Skip to:
Content

bbPress.org


Ignore:
Timestamp:
11/09/2019 05:35:42 AM (5 years ago)
Author:
johnjamesjacoby
Message:

Counts (meta-data): full audit of forum/topic/reply, public/non-public counts.

This commit is the result of a full count audit, exposing multiple inconsistencies and voids in relation to how public and non-public counts are (re)calculated.

For instance, hidden forum replies are not counted at all, until now. By introducing a new Repair tool, hidden forum reply counts are now counted.

In addition, there were multiple bugs with topic & reply moderation, where the act of approving or unapproving topics or replies would cause the numbers to be inaccurate, or where topics & replies being caught in moderation were still increasing public counts.

It was also possible to, as a Key Master, publicly reply to unapproved topics, which was a completely unanticipated side-effect of allowing Key Masters to do pretty much anything. Going forward, the default reply status is the topic status, but is still beholden to all existing moderation settings and user role capabilities. This results in a more sane user experience, and prevents the unusual circumstance of there being "0 topics and 30 replies" in public-facing forums.

Certain count increase/decrease actions have been reprioritized to avoid collisions and race conditions, proving once again that ya gotta get up to get down.

See #2838. Fixes #1799.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/includes/forums/functions.php

    r6922 r6923  
    11351135        $forum_id = bbp_get_topic_forum_id( $topic_id );
    11361136
    1137         // Bail if not public.
     1137        // Update inverse based on item status
    11381138        if ( ! bbp_is_topic_public( $topic_id ) ) {
    11391139            bbp_increase_forum_topic_count_hidden( $forum_id );
     
    11421142    }
    11431143
     1144    // Bump up
    11441145    bbp_bump_forum_topic_count( $forum_id );
    11451146}
     
    11631164    // If it's a topic, get the forum id.
    11641165    if ( bbp_is_topic( $forum_id ) ) {
    1165         $forum_id = bbp_get_topic_forum_id( $forum_id );
    1166     }
    1167 
     1166        $topic_id = $forum_id;
     1167        $forum_id = bbp_get_topic_forum_id( $topic_id );
     1168
     1169        // Update inverse based on item status
     1170        if ( ! bbp_is_topic_public( $topic_id ) ) {
     1171            bbp_decrease_forum_topic_count_hidden( $forum_id );
     1172            return;
     1173        }
     1174    }
     1175
     1176    // Bump down
    11681177    bbp_bump_forum_topic_count( $forum_id, -1 );
    11691178}
    11701179
    11711180/**
    1172  * Bump the total hidden topic count of a forum
     1181 * Bump the total topic count of a forum
    11731182 *
    11741183 * @since 2.1.0 bbPress (r3825)
     
    11761185 * @param int $forum_id Optional. Forum id.
    11771186 * @param int $difference Optional. Default 1
    1178  *
    1179  * @return int Forum hidden topic count
    1180  */
    1181 function bbp_bump_forum_topic_count_hidden( $forum_id = 0, $difference = 1 ) {
     1187 * @param bool $update_ancestors Optional. Default true
     1188 *
     1189 * @return int Forum topic count
     1190 */
     1191function bbp_bump_forum_topic_count_hidden( $forum_id = 0, $difference = 1, $update_ancestors = true ) {
    11821192
    11831193    // Bail if no bump
     
    11871197
    11881198    // Get some counts
    1189     $forum_id    = bbp_get_forum_id( $forum_id );
    1190     $topic_count = bbp_get_forum_topic_count_hidden( $forum_id, true );
    1191     $difference  = (int) $difference;
    1192     $new_count   = (int) ( $topic_count + $difference );
     1199    $forum_id          = bbp_get_forum_id( $forum_id );
     1200    $reply_count       = bbp_get_forum_topic_count_hidden( $forum_id, false, true );
     1201    $total_topic_count = bbp_get_forum_topic_count_hidden( $forum_id, true,  true );
     1202    $difference        = (int) $difference;
    11931203
    11941204    // Update this forum id
    1195     update_post_meta( $forum_id, '_bbp_topic_count_hidden', $new_count );
     1205    update_post_meta( $forum_id, '_bbp_topic_count_hidden',       (int) ( $reply_count       + $difference ) );
     1206    update_post_meta( $forum_id, '_bbp_total_topic_count_hidden', (int) ( $total_topic_count + $difference ) );
     1207
     1208    // Check for ancestors
     1209    if ( true === $update_ancestors ) {
     1210
     1211        // Get post ancestors
     1212        $forum     = get_post( $forum_id );
     1213        $ancestors = get_post_ancestors( $forum );
     1214
     1215        // If has ancestors, loop through them...
     1216        if ( ! empty( $ancestors ) ) {
     1217            foreach ( (array) $ancestors as $parent_forum_id ) {
     1218
     1219                // Only update topic count when an ancestor is not a category.
     1220                if ( ! bbp_is_forum_category( $parent_forum_id ) ) {
     1221
     1222                    $parent_topic_count = bbp_get_forum_topic_count_hidden( $parent_forum_id, false, true );
     1223                    update_post_meta( $parent_forum_id, '_bbp_topic_count_hidden', (int) ( $parent_topic_count + $difference ) );
     1224                }
     1225
     1226                // Update the total topic count.
     1227                $parent_total_topic_count = bbp_get_forum_topic_count_hidden( $parent_forum_id, true, true );
     1228                update_post_meta( $parent_forum_id, '_bbp_total_topic_count_hidden', (int) ( $parent_total_topic_count + $difference ) );
     1229            }
     1230        }
     1231    }
     1232
     1233    $forum_topic_count = (int) ( $total_topic_count + $difference );
    11961234
    11971235    // Filter & return
    1198     return (int) apply_filters( 'bbp_bump_forum_topic_count_hidden', $new_count, $forum_id, $difference );
     1236    return (int) apply_filters( 'bbp_bump_forum_topic_count_hidden', $forum_topic_count, $forum_id, $difference, $update_ancestors );
    11991237}
    12001238
     
    12171255    // If it's a topic, get the forum id.
    12181256    if ( bbp_is_topic( $forum_id ) ) {
    1219         $forum_id = bbp_get_topic_forum_id( $forum_id );
    1220     }
    1221 
     1257        $topic_id = $forum_id;
     1258        $forum_id = bbp_get_topic_forum_id( $topic_id );
     1259
     1260        // Update inverse based on item status
     1261        if ( bbp_is_topic_public( $topic_id ) ) {
     1262            bbp_increase_forum_topic_count( $forum_id );
     1263            return;
     1264        }
     1265    }
     1266
     1267    // Bump up
    12221268    bbp_bump_forum_topic_count_hidden( $forum_id );
    12231269}
     
    12411287    // If it's a topic, get the forum id.
    12421288    if ( bbp_is_topic( $forum_id ) ) {
    1243         $forum_id = bbp_get_topic_forum_id( $forum_id );
    1244     }
    1245 
     1289        $topic_id = $forum_id;
     1290        $forum_id = bbp_get_topic_forum_id( $topic_id );
     1291
     1292        // Update inverse based on item status
     1293        if ( bbp_is_topic_public( $topic_id ) ) {
     1294            bbp_decrease_forum_topic_count( $forum_id );
     1295            return;
     1296        }
     1297    }
     1298
     1299    // Bump down
    12461300    bbp_bump_forum_topic_count_hidden( $forum_id, -1 );
    12471301}
     
    12671321    // Get some counts
    12681322    $forum_id          = bbp_get_forum_id( $forum_id );
    1269     $topic_count       = bbp_get_forum_reply_count( $forum_id, false, true );
     1323    $reply_count       = bbp_get_forum_reply_count( $forum_id, false, true );
    12701324    $total_reply_count = bbp_get_forum_reply_count( $forum_id, true,  true );
    12711325    $difference        = (int) $difference;
    12721326
    12731327    // Update this forum id
    1274     update_post_meta( $forum_id, '_bbp_reply_count',       (int) ( $topic_count       + $difference ) );
     1328    update_post_meta( $forum_id, '_bbp_reply_count',       (int) ( $reply_count       + $difference ) );
    12751329    update_post_meta( $forum_id, '_bbp_total_reply_count', (int) ( $total_reply_count + $difference ) );
    12761330
     
    13071361
    13081362/**
     1363 * Bump the total topic count of a forum
     1364 *
     1365 * @since 2.6.0 bbPress (r6922)
     1366 *
     1367 * @param int $forum_id Optional. Forum id.
     1368 * @param int $difference Optional. Default 1
     1369 * @param bool $update_ancestors Optional. Default true
     1370 *
     1371 * @return int Forum topic count
     1372 */
     1373function bbp_bump_forum_reply_count_hidden( $forum_id = 0, $difference = 1, $update_ancestors = true ) {
     1374
     1375    // Bail if no bump
     1376    if ( empty( $difference ) ) {
     1377        return false;
     1378    }
     1379
     1380    // Get some counts
     1381    $forum_id          = bbp_get_forum_id( $forum_id );
     1382    $reply_count       = bbp_get_forum_reply_count_hidden( $forum_id, false, true );
     1383    $total_reply_count = bbp_get_forum_reply_count_hidden( $forum_id, true,  true );
     1384    $difference        = (int) $difference;
     1385
     1386    // Update this forum id
     1387    update_post_meta( $forum_id, '_bbp_reply_count_hidden',       (int) ( $reply_count       + $difference ) );
     1388    update_post_meta( $forum_id, '_bbp_total_reply_count_hidden', (int) ( $total_reply_count + $difference ) );
     1389
     1390    // Check for ancestors
     1391    if ( true === $update_ancestors ) {
     1392
     1393        // Get post ancestors
     1394        $forum     = get_post( $forum_id );
     1395        $ancestors = get_post_ancestors( $forum );
     1396
     1397        // If has ancestors, loop through them...
     1398        if ( ! empty( $ancestors ) ) {
     1399            foreach ( (array) $ancestors as $parent_forum_id ) {
     1400
     1401                // Only update reply count when an ancestor is not a category.
     1402                if ( ! bbp_is_forum_category( $parent_forum_id ) ) {
     1403
     1404                    $parent_reply_count = bbp_get_forum_reply_count_hidden( $parent_forum_id, false, true );
     1405                    update_post_meta( $parent_forum_id, '_bbp_reply_count_hidden', (int) ( $parent_reply_count + $difference ) );
     1406                }
     1407
     1408                // Update the total reply count.
     1409                $parent_total_reply_count = bbp_get_forum_reply_count_hidden( $parent_forum_id, true,  true );
     1410                update_post_meta( $parent_forum_id, '_bbp_total_reply_count_hidden', (int) ( $parent_total_reply_count + $difference ) );
     1411            }
     1412        }
     1413    }
     1414
     1415    $forum_reply_count = (int) ( $total_reply_count + $difference );
     1416
     1417    // Filter & return
     1418    return (int) apply_filters( 'bbp_bump_forum_reply_count_hidden', $forum_reply_count, $forum_id, $difference, $update_ancestors );
     1419}
     1420
     1421/**
    13091422 * Increase the total reply count of a forum by one.
    13101423 *
     
    13241437    // If it's a reply, get the forum id.
    13251438    if ( bbp_is_reply( $forum_id ) ) {
    1326         $forum_id = bbp_get_reply_forum_id( $forum_id );
    1327     }
    1328 
     1439        $reply_id = $forum_id;
     1440        $forum_id = bbp_get_reply_forum_id( $reply_id );
     1441
     1442        // Update inverse based on item status
     1443        if ( ! bbp_is_reply_public( $reply_id ) ) {
     1444            bbp_increase_forum_reply_count_hidden( $forum_id );
     1445            return;
     1446        }
     1447    }
     1448
     1449    // Bump up
    13291450    bbp_bump_forum_reply_count( $forum_id );
    13301451}
     
    13481469    // If it's a reply, get the forum id.
    13491470    if ( bbp_is_reply( $forum_id ) ) {
    1350         $forum_id = bbp_get_reply_forum_id( $forum_id );
    1351     }
    1352 
     1471        $reply_id = $forum_id;
     1472        $forum_id = bbp_get_reply_forum_id( $reply_id );
     1473
     1474        // Update inverse based on item status
     1475        if ( ! bbp_is_reply_public( $reply_id ) ) {
     1476            bbp_decrease_forum_reply_count_hidden( $forum_id );
     1477            return;
     1478        }
     1479    }
     1480
     1481    // Bump down
    13531482    bbp_bump_forum_reply_count( $forum_id, -1 );
     1483}
     1484
     1485/**
     1486 * Increase the total hidden reply count of a forum by one.
     1487 *
     1488 * @since 2.6.0 bbPress (r6036)
     1489 *
     1490 * @param int $forum_id The forum id.
     1491 *
     1492 * @return void
     1493 */
     1494function bbp_increase_forum_reply_count_hidden( $forum_id = 0 ) {
     1495
     1496    // Bail early if no id is passed.
     1497    if ( empty( $forum_id ) ) {
     1498        return;
     1499    }
     1500
     1501    // If it's a reply, get the forum id.
     1502    if ( bbp_is_reply( $forum_id ) ) {
     1503        $reply_id = $forum_id;
     1504        $forum_id = bbp_get_reply_forum_id( $reply_id );
     1505
     1506        // Update inverse based on item status
     1507        if ( bbp_is_reply_public( $reply_id ) ) {
     1508            bbp_increase_forum_reply_count( $forum_id );
     1509            return;
     1510        }
     1511    }
     1512
     1513    // Bump up
     1514    bbp_bump_forum_reply_count_hidden( $forum_id );
     1515}
     1516
     1517/**
     1518 * Decrease the total hidden reply count of a forum by one.
     1519 *
     1520 * @since 2.6.0 bbPress (r6036)
     1521 *
     1522 * @param int $forum_id The forum id.
     1523 *
     1524 * @return void
     1525 */
     1526function bbp_decrease_forum_reply_count_hidden( $forum_id = 0 ) {
     1527
     1528    // Bail early if no id is passed.
     1529    if ( empty( $forum_id ) ) {
     1530        return;
     1531    }
     1532
     1533    // If it's a reply, get the forum id.
     1534    if ( bbp_is_reply( $forum_id ) ) {
     1535        $reply_id = $forum_id;
     1536        $forum_id = bbp_get_reply_forum_id( $reply_id );
     1537
     1538        // Update inverse based on item status
     1539        if ( bbp_is_reply_public( $reply_id ) ) {
     1540            bbp_decrease_forum_reply_count( $forum_id );
     1541            return;
     1542        }
     1543    }
     1544
     1545    // Bump down
     1546    bbp_bump_forum_reply_count_hidden( $forum_id, -1 );
    13541547}
    13551548
     
    13781571    }
    13791572
    1380     // Update counts.
     1573    // Bump up or down
    13811574    bbp_bump_forum_reply_count( bbp_get_topic_forum_id( $topic_id ), $count );
    13821575}
     
    14371630
    14381631    // Update the last public topic ID
    1439     if ( bbp_is_topic_published( $topic_id ) ) {
    1440         update_post_meta( $forum_id, '_bbp_last_topic_id', $topic_id );
    1441     }
     1632    update_post_meta( $forum_id, '_bbp_last_topic_id', $topic_id );
    14421633
    14431634    // Filter & return
     
    14791670
    14801671            // ...and compare it to the most recent topic id...
    1481             $reply_id = ( $reply_id > max( $topic_ids ) ) ? $reply_id : max( $topic_ids );
     1672            $reply_id = ( $reply_id > max( $topic_ids ) )
     1673                ? $reply_id
     1674                : max( $topic_ids );
    14821675        }
    14831676    }
     
    14931686
    14941687    // Update the last public reply ID
    1495     if ( bbp_is_reply_published( $reply_id ) ) {
    1496         update_post_meta( $forum_id, '_bbp_last_reply_id', $reply_id );
    1497     }
     1688    update_post_meta( $forum_id, '_bbp_last_reply_id', $reply_id );
    14981689
    14991690    // Filter & return
     
    15201711    if ( empty( $active_id ) ) {
    15211712
    1522         // Loop through children and add together forum reply counts
     1713        // Loop through children and get the last active ID
    15231714        $children = bbp_forum_query_subforum_ids( $forum_id );
    15241715        if ( ! empty( $children ) ) {
     
    15281719        }
    15291720
    1530         // Don't count replies if the forum is a category
     1721        // Get topic IDs and only accept larger IDs
    15311722        $topic_ids = bbp_forum_query_topic_ids( $forum_id );
    15321723        if ( ! empty( $topic_ids ) ) {
     1724
     1725            // Make sure ID is larger
    15331726            $active_id = bbp_forum_query_last_reply_id( $forum_id, $topic_ids );
    1534             $active_id = $active_id > max( $topic_ids ) ? $active_id : max( $topic_ids );
     1727            $active_id = $active_id > max( $topic_ids )
     1728                ? $active_id
     1729                : max( $topic_ids );
    15351730
    15361731        // Forum has no topics
     
    15441739    $children_last_active = (int) $children_last_active;
    15451740
    1546     // If child forums have higher id, use that instead
     1741    // If child forums have higher ID, use that instead
    15471742    if ( ! empty( $children ) && ( $children_last_active > $active_id ) ) {
    15481743        $active_id = $children_last_active;
    15491744    }
    15501745
    1551     // Update only if published
    1552     if ( bbp_get_public_status_id() === get_post_status( $active_id ) ) {
    1553         update_post_meta( $forum_id, '_bbp_last_active_id', $active_id );
    1554     }
     1746    update_post_meta( $forum_id, '_bbp_last_active_id', $active_id );
    15551747
    15561748    // Filter & return
     
    15911783 *
    15921784 * @param int $forum_id Optional. Forum id
     1785 * @param int $subforums Optional. Number of subforums
    15931786 * @return bool True on success, false on failure
    15941787 */
    1595 function bbp_update_forum_subforum_count( $forum_id = 0, $subforums = 0 ) {
     1788function bbp_update_forum_subforum_count( $forum_id = 0, $subforums = false ) {
    15961789    $forum_id = bbp_get_forum_id( $forum_id );
    15971790
    15981791    // Maybe query for counts
    1599     if ( empty( $subforums ) ) {
    1600         $subforums = bbp_get_public_child_count( $forum_id, bbp_get_forum_post_type() );
    1601     }
    1602 
    1603     $subforums = (int) $subforums;
     1792    $subforums = ! is_int( $subforums )
     1793        ? bbp_get_public_child_count( $forum_id, bbp_get_forum_post_type() )
     1794        : (int) $subforums;
    16041795
    16051796    update_post_meta( $forum_id, '_bbp_forum_subforum_count', $subforums );
     
    16581849 * @return int Topic hidden topic count
    16591850 */
    1660 function bbp_update_forum_topic_count_hidden( $forum_id = 0, $topic_count = 0 ) {
     1851function bbp_update_forum_topic_count_hidden( $forum_id = 0, $topic_count = false ) {
    16611852
    16621853    // If topic_id was passed as $forum_id, then get its forum
     
    16741865
    16751866        // Get topics of forum
    1676         if ( empty( $topic_count ) ) {
     1867        if ( ! is_int( $topic_count ) ) {
    16771868            $query = new WP_Query( array(
    16781869                'fields'         => 'ids',
     
    17301921
    17311922    // Don't count replies if the forum is a category
    1732     $reply_count = 0;
    1733     $topic_ids   = bbp_forum_query_topic_ids( $forum_id );
    1734     if ( ! empty( $topic_ids ) ) {
    1735         $reply_count = bbp_get_public_child_count( $forum_id, bbp_get_reply_post_type() );
    1736     }
     1923    $reply_count = ! bbp_is_forum_category( $forum_id )
     1924        ? bbp_get_public_child_count( $forum_id, bbp_get_reply_post_type() )
     1925        : 0;
    17371926
    17381927    // Calculate total replies in this forum
    17391928    $total_replies = (int) ( $reply_count + $children_reply_count );
    17401929
    1741     // Update the count
     1930    // Update the counts
    17421931    update_post_meta( $forum_id, '_bbp_reply_count',       $reply_count   );
    17431932    update_post_meta( $forum_id, '_bbp_total_reply_count', $total_replies );
     
    17451934    // Filter & return
    17461935    return (int) apply_filters( 'bbp_update_forum_reply_count', $total_replies, $forum_id );
     1936}
     1937
     1938/**
     1939 * Adjust the total hidden reply count of a forum
     1940 *
     1941 * @since 2.6.0 bbPress (r6922)
     1942 *
     1943 * @param int  $forum_id Optional. Forum id or topic id. It is checked whether it
     1944 *                       is a topic or a forum. If it's a topic, its parent,
     1945 *                       i.e. the forum is automatically retrieved.
     1946 *
     1947 * @return int Forum reply count
     1948 */
     1949function bbp_update_forum_reply_count_hidden( $forum_id = 0 ) {
     1950
     1951    $forum_id = bbp_get_forum_id( $forum_id );
     1952    $children_reply_count = 0;
     1953
     1954    // Loop through children and add together forum reply counts
     1955    $children = bbp_forum_query_subforum_ids( $forum_id );
     1956    if ( ! empty( $children ) ) {
     1957        foreach ( (array) $children as $child ) {
     1958            $children_reply_count += bbp_update_forum_reply_count_hidden( $child );
     1959        }
     1960    }
     1961
     1962    // Don't count replies if the forum is a category
     1963    $reply_count = ! bbp_is_forum_category( $forum_id )
     1964        ? bbp_get_non_public_child_count( $forum_id, bbp_get_reply_post_type() )
     1965        : 0;
     1966
     1967    // Calculate total replies in this forum
     1968    $total_replies = (int) ( $reply_count + $children_reply_count );
     1969
     1970    // Update the counts
     1971    update_post_meta( $forum_id, '_bbp_reply_count_hidden',       $reply_count   );
     1972    update_post_meta( $forum_id, '_bbp_total_reply_count_hidden', $total_replies );
     1973
     1974    // Filter & return
     1975    return (int) apply_filters( 'bbp_update_forum_reply_count_hidden', $total_replies, $forum_id );
    17471976}
    17481977
     
    17982027    bbp_update_forum_subforum_count( $r['forum_id'] );
    17992028
    1800     // Only update topic count if we're deleting a topic, or in the dashboard.
    1801     if ( in_array( current_filter(), array( 'bbp_delete_topic', 'save_post' ), true ) ) {
     2029    // Only update topic count if we've deleted a topic
     2030    if ( in_array( current_filter(), array( 'bbp_deleted_topic', 'save_post' ), true ) ) {
    18022031        bbp_update_forum_reply_count(        $r['forum_id'] );
    18032032        bbp_update_forum_topic_count(        $r['forum_id'] );
    18042033        bbp_update_forum_topic_count_hidden( $r['forum_id'] );
     2034        bbp_update_forum_reply_count_hidden( $r['forum_id'] );
    18052035    }
    18062036
Note: See TracChangeset for help on using the changeset viewer.