Make WordPress Core

Changeset 49451


Ignore:
Timestamp:
10/30/2020 04:57:16 AM (4 years ago)
Author:
peterwilsoncc
Message:

Taxonomy: Revert Light-weight/partial term counts.

Partial revert of [49141], [49171], [49316].

All functional changes are removed, appropriate term counting unit tests are retained.

See #40351.

Location:
trunk
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-includes/class-wp-taxonomy.php

    r49171 r49451  
    180180     */
    181181    public $update_count_callback;
    182 
    183     /**
    184      * Function that will be called when the count is modified by an amount.
    185      *
    186      * @since 5.6.0
    187      * @var callable
    188      */
    189     public $update_count_by_callback;
    190182
    191183    /**
     
    286278
    287279        $defaults = array(
    288             'labels'                   => array(),
    289             'description'              => '',
    290             'public'                   => true,
    291             'publicly_queryable'       => null,
    292             'hierarchical'             => false,
    293             'show_ui'                  => null,
    294             'show_in_menu'             => null,
    295             'show_in_nav_menus'        => null,
    296             'show_tagcloud'            => null,
    297             'show_in_quick_edit'       => null,
    298             'show_admin_column'        => false,
    299             'meta_box_cb'              => null,
    300             'meta_box_sanitize_cb'     => null,
    301             'capabilities'             => array(),
    302             'rewrite'                  => true,
    303             'query_var'                => $this->name,
    304             'update_count_callback'    => '',
    305             'update_count_by_callback' => '',
    306             'show_in_rest'             => false,
    307             'rest_base'                => false,
    308             'rest_controller_class'    => false,
    309             'default_term'             => null,
    310             '_builtin'                 => false,
     280            'labels'                => array(),
     281            'description'           => '',
     282            'public'                => true,
     283            'publicly_queryable'    => null,
     284            'hierarchical'          => false,
     285            'show_ui'               => null,
     286            'show_in_menu'          => null,
     287            'show_in_nav_menus'     => null,
     288            'show_tagcloud'         => null,
     289            'show_in_quick_edit'    => null,
     290            'show_admin_column'     => false,
     291            'meta_box_cb'           => null,
     292            'meta_box_sanitize_cb'  => null,
     293            'capabilities'          => array(),
     294            'rewrite'               => true,
     295            'query_var'             => $this->name,
     296            'update_count_callback' => '',
     297            'show_in_rest'          => false,
     298            'rest_base'             => false,
     299            'rest_controller_class' => false,
     300            'default_term'          => null,
     301            '_builtin'              => false,
    311302        );
    312303
     
    421412        }
    422413
    423         // If generic update callback is defined but increment/decrement callback is not.
    424         if (
    425             ! empty( $args['update_count_callback'] ) &&
    426             is_callable( $args['update_count_callback'] ) &&
    427             empty( $args['update_count_by_callback'] )
    428         ) {
    429             $args['update_count_by_callback'] = function( $tt_ids, $taxonomy ) use ( $args ) {
    430                 return call_user_func( $args['update_count_callback'], $tt_ids, $taxonomy );
    431             };
    432         }
    433 
    434414        foreach ( $args as $property_name => $property_value ) {
    435415            $this->$property_name = $property_value;
  • trunk/src/wp-includes/post.php

    r49328 r49451  
    40754075    }
    40764076
    4077     // Allow term counts to be handled by transitioning post type.
    4078     _wp_prevent_term_counting( true );
    40794077    if ( is_object_in_taxonomy( $post_type, 'category' ) ) {
    40804078        wp_set_post_categories( $post_ID, $post_category );
     
    41334131        }
    41344132    }
    4135     // Restore term counting.
    4136     _wp_prevent_term_counting( false );
    41374133
    41384134    if ( ! empty( $postarr['meta_input'] ) ) {
     
    44514447            continue;
    44524448        }
    4453         _wp_prevent_term_counting( true );
    44544449        wp_set_post_terms( $post->ID, array( $default_term_id ), $taxonomy );
    4455         _wp_prevent_term_counting( false );
    44564450    }
    44574451
     
    73617355 */
    73627356function _update_term_count_on_transition_post_status( $new_status, $old_status, $post ) {
    7363     if ( 'inherit' === $new_status ) {
    7364         $new_status = get_post_status( $post->post_parent );
    7365     }
    7366 
    7367     if ( 'inherit' === $old_status ) {
    7368         $old_status = get_post_status( $post->post_parent );
    7369     }
    7370 
    7371     $count_new = 'publish' === $new_status;
    7372     $count_old = 'publish' === $old_status;
    7373 
    7374     if ( $count_new === $count_old ) {
    7375         // Nothing to do.
    7376         return;
    7377     }
    7378 
    7379     /*
    7380      * Update counts for the post's terms.
    7381      *
    7382      * Term counting is deferred while incrementing/decrementing the counts to
    7383      * reduce the number of database queries required. Once the counts are
    7384      * complete the updates are performed if term counting wasn't previously
    7385      * deferred.
    7386      */
    7387     $previous_deferred_setting = wp_defer_term_counting();
    7388     wp_defer_term_counting( true );
     7357    // Update counts for the post's terms.
    73897358    foreach ( (array) get_object_taxonomies( $post->post_type ) as $taxonomy ) {
    73907359        $tt_ids = wp_get_object_terms( $post->ID, $taxonomy, array( 'fields' => 'tt_ids' ) );
    7391 
    7392         if ( empty( $tt_ids ) ) {
    7393             // No terms for this taxonomy on object.
    7394             continue;
    7395         }
    7396 
    7397         $object_types = (array) get_taxonomy( $taxonomy )->object_type;
    7398 
    7399         foreach ( $object_types as &$object_type ) {
    7400             list( $object_type ) = explode( ':', $object_type );
    7401         }
    7402 
    7403         $object_types = array_unique( $object_types );
    7404 
    7405         if ( ! in_array( $post->post_type, $object_types, true ) ) {
    7406             $modify_by = 0;
    7407         } elseif ( $count_new && ! $count_old ) {
    7408             $modify_by = 1;
    7409         } elseif ( $count_old && ! $count_new ) {
    7410             $modify_by = -1;
    7411         }
    7412 
    7413         if ( 'attachment' === $post->post_type ) {
    7414             wp_modify_term_count_by( $tt_ids, $taxonomy, $modify_by );
    7415             continue;
    7416         }
    7417 
    7418         $check_attachments = array_search( 'attachment', $object_types, true );
    7419         if ( false !== $check_attachments ) {
    7420             unset( $object_types[ $check_attachments ] );
    7421             $check_attachments = true;
    7422         }
    7423 
    7424         wp_modify_term_count_by( $tt_ids, $taxonomy, $modify_by );
    7425         if ( ! $check_attachments ) {
    7426             continue;
    7427         }
    7428 
    7429         /*
    7430          * For non-attachments, check if there are any attachment children
    7431          * with 'inherited' post status -- if so those will need to be counted.
    7432          */
    7433         $attachments = get_children(
    7434             array(
    7435                 'post_parent'            => $post->ID,
    7436                 'post_status'            => 'inherit',
    7437                 'post_type'              => 'attachment',
    7438                 'update_post_meta_cache' => false,
    7439                 'update_post_term_cache' => true,
    7440             )
    7441         );
    7442 
    7443         foreach ( $attachments as $attachment ) {
    7444             _update_term_count_on_transition_post_status( $new_status, $old_status, $attachment );
    7445         }
    7446     }
    7447     wp_defer_term_counting( $previous_deferred_setting );
     7360        wp_update_term_count( $tt_ids, $taxonomy );
     7361    }
    74487362}
    74497363
  • trunk/src/wp-includes/taxonomy.php

    r49316 r49451  
    337337 * @since 5.4.0 Added the registered taxonomy object as a return value.
    338338 * @since 5.5.0 Introduced `default_term` argument.
    339  * @since 5.6.0 Introduced `update_count_by_callback` argument.
    340339 *
    341340 * @global array $wp_taxonomies Registered taxonomies.
     
    346345 *     Optional. Array or query string of arguments for registering a taxonomy.
    347346 *
    348  *     @type array         $labels                   An array of labels for this taxonomy. By default, Tag labels are
    349  *                                                   used for non-hierarchical taxonomies, and Category labels are used
    350  *                                                   for hierarchical taxonomies. See accepted values in
    351  *                                                   get_taxonomy_labels(). Default empty array.
    352  *     @type string        $description              A short descriptive summary of what the taxonomy is for. Default empty.
    353  *     @type bool          $public                   Whether a taxonomy is intended for use publicly either via
    354  *                                                   the admin interface or by front-end users. The default settings
    355  *                                                   of `$publicly_queryable`, `$show_ui`, and `$show_in_nav_menus`
    356  *                                                   are inherited from `$public`.
    357  *     @type bool          $publicly_queryable       Whether the taxonomy is publicly queryable.
    358  *                                                   If not set, the default is inherited from `$public`
    359  *     @type bool          $hierarchical             Whether the taxonomy is hierarchical. Default false.
    360  *     @type bool          $show_ui                  Whether to generate and allow a UI for managing terms in this taxonomy in
    361  *                                                   the admin. If not set, the default is inherited from `$public`
    362  *                                                   (default true).
    363  *     @type bool          $show_in_menu             Whether to show the taxonomy in the admin menu. If true, the taxonomy is
    364  *                                                   shown as a submenu of the object type menu. If false, no menu is shown.
    365  *                                                   `$show_ui` must be true. If not set, default is inherited from `$show_ui`
    366  *                                                   (default true).
    367  *     @type bool          $show_in_nav_menus        Makes this taxonomy available for selection in navigation menus. If not
    368  *                                                   set, the default is inherited from `$public` (default true).
    369  *     @type bool          $show_in_rest             Whether to include the taxonomy in the REST API. Set this to true
    370  *                                                   for the taxonomy to be available in the block editor.
    371  *     @type string        $rest_base                To change the base url of REST API route. Default is $taxonomy.
    372  *     @type string        $rest_controller_class    REST API Controller class name. Default is 'WP_REST_Terms_Controller'.
    373  *     @type bool          $show_tagcloud            Whether to list the taxonomy in the Tag Cloud Widget controls. If not set,
    374  *                                                   the default is inherited from `$show_ui` (default true).
    375  *     @type bool          $show_in_quick_edit       Whether to show the taxonomy in the quick/bulk edit panel. It not set,
    376  *                                                   the default is inherited from `$show_ui` (default true).
    377  *     @type bool          $show_admin_column        Whether to display a column for the taxonomy on its post type listing
    378  *                                                   screens. Default false.
    379  *     @type bool|callable $meta_box_cb              Provide a callback function for the meta box display. If not set,
    380  *                                                   post_categories_meta_box() is used for hierarchical taxonomies, and
    381  *                                                   post_tags_meta_box() is used for non-hierarchical. If false, no meta
    382  *                                                   box is shown.
    383  *     @type callable      $meta_box_sanitize_cb     Callback function for sanitizing taxonomy data saved from a meta
    384  *                                                   box. If no callback is defined, an appropriate one is determined
    385  *                                                   based on the value of `$meta_box_cb`.
     347 *     @type array         $labels                An array of labels for this taxonomy. By default, Tag labels are
     348 *                                                used for non-hierarchical taxonomies, and Category labels are used
     349 *                                                for hierarchical taxonomies. See accepted values in
     350 *                                                get_taxonomy_labels(). Default empty array.
     351 *     @type string        $description           A short descriptive summary of what the taxonomy is for. Default empty.
     352 *     @type bool          $public                Whether a taxonomy is intended for use publicly either via
     353 *                                                the admin interface or by front-end users. The default settings
     354 *                                                of `$publicly_queryable`, `$show_ui`, and `$show_in_nav_menus`
     355 *                                                are inherited from `$public`.
     356 *     @type bool          $publicly_queryable    Whether the taxonomy is publicly queryable.
     357 *                                                If not set, the default is inherited from `$public`
     358 *     @type bool          $hierarchical          Whether the taxonomy is hierarchical. Default false.
     359 *     @type bool          $show_ui               Whether to generate and allow a UI for managing terms in this taxonomy in
     360 *                                                the admin. If not set, the default is inherited from `$public`
     361 *                                                (default true).
     362 *     @type bool          $show_in_menu          Whether to show the taxonomy in the admin menu. If true, the taxonomy is
     363 *                                                shown as a submenu of the object type menu. If false, no menu is shown.
     364 *                                                `$show_ui` must be true. If not set, default is inherited from `$show_ui`
     365 *                                                (default true).
     366 *     @type bool          $show_in_nav_menus     Makes this taxonomy available for selection in navigation menus. If not
     367 *                                                set, the default is inherited from `$public` (default true).
     368 *     @type bool          $show_in_rest          Whether to include the taxonomy in the REST API. Set this to true
     369 *                                                for the taxonomy to be available in the block editor.
     370 *     @type string        $rest_base             To change the base url of REST API route. Default is $taxonomy.
     371 *     @type string        $rest_controller_class REST API Controller class name. Default is 'WP_REST_Terms_Controller'.
     372 *     @type bool          $show_tagcloud         Whether to list the taxonomy in the Tag Cloud Widget controls. If not set,
     373 *                                                the default is inherited from `$show_ui` (default true).
     374 *     @type bool          $show_in_quick_edit    Whether to show the taxonomy in the quick/bulk edit panel. It not set,
     375 *                                                the default is inherited from `$show_ui` (default true).
     376 *     @type bool          $show_admin_column     Whether to display a column for the taxonomy on its post type listing
     377 *                                                screens. Default false.
     378 *     @type bool|callable $meta_box_cb           Provide a callback function for the meta box display. If not set,
     379 *                                                post_categories_meta_box() is used for hierarchical taxonomies, and
     380 *                                                post_tags_meta_box() is used for non-hierarchical. If false, no meta
     381 *                                                box is shown.
     382 *     @type callable      $meta_box_sanitize_cb  Callback function for sanitizing taxonomy data saved from a meta
     383 *                                                box. If no callback is defined, an appropriate one is determined
     384 *                                                based on the value of `$meta_box_cb`.
    386385 *     @type array         $capabilities {
    387386 *         Array of capabilities for this taxonomy.
     
    401400 *         @type int    $ep_mask      Assign an endpoint mask. Default `EP_NONE`.
    402401 *     }
    403  *     @type string|bool   $query_var                Sets the query var key for this taxonomy. Default `$taxonomy` key. If
    404  *                                                   false, a taxonomy cannot be loaded at `?{query_var}={term_slug}`. If a
    405  *                                                   string, the query `?{query_var}={term_slug}` will be valid.
    406  *     @type callable      $update_count_callback    Works much like a hook, in that it will be called when the count is
    407  *                                                   updated. Default _update_post_term_count() for taxonomies attached
    408  *                                                   to post types, which confirms that the objects are published before
    409  *                                                   counting them. Default _update_generic_term_count() for taxonomies
    410  *                                                   attached to other object types, such as users.
    411  *     @type callable      $update_count_by_callback Works much like a hook, in that it will be called when the count is
    412  *                                                   incremented or decremented. Defaults to the value of `$update_count_callback` if
    413  *                                                   a custom callack is defined, otherwise uses wp_modify_term_count_by().
     402 *     @type string|bool   $query_var             Sets the query var key for this taxonomy. Default `$taxonomy` key. If
     403 *                                                false, a taxonomy cannot be loaded at `?{query_var}={term_slug}`. If a
     404 *                                                string, the query `?{query_var}={term_slug}` will be valid.
     405 *     @type callable      $update_count_callback Works much like a hook, in that it will be called when the count is
     406 *                                                updated. Default _update_post_term_count() for taxonomies attached
     407 *                                                to post types, which confirms that the objects are published before
     408 *                                                counting them. Default _update_generic_term_count() for taxonomies
     409 *                                                attached to other object types, such as users.
    414410 *     @type string|array  $default_term {
    415411 *         Default term to be used for the taxonomy.
     
    419415 *         @type string $description  Description for default term. Default empty.
    420416 *     }
    421  *     @type bool          $_builtin                 This taxonomy is a "built-in" taxonomy. INTERNAL USE ONLY!
    422  *                                                   Default false.
     417 *     @type bool          $_builtin              This taxonomy is a "built-in" taxonomy. INTERNAL USE ONLY!
     418 *                                                Default false.
    423419 * }
    424420 * @return WP_Taxonomy|WP_Error The registered taxonomy object on success, WP_Error object on failure.
     
    25662562    }
    25672563
    2568     $taxonomy_object = get_taxonomy( $taxonomy );
    2569 
    2570     $object_types = (array) $taxonomy_object->object_type;
    2571     foreach ( $object_types as &$object_type ) {
    2572         if ( 0 === strpos( $object_type, 'attachment:' ) ) {
    2573             list( $object_type ) = explode( ':', $object_type );
    2574         }
    2575     }
    2576 
    2577     if ( array_filter( $object_types, 'post_type_exists' ) !== $object_types ) {
    2578         // This taxonomy applies to non-posts, count changes now.
    2579         $do_recount = ! _wp_prevent_term_counting();
    2580     } elseif ( 'publish' === get_post_status( $object_id ) ) {
    2581         // Published post, count changes now.
    2582         $do_recount = ! _wp_prevent_term_counting();
    2583     } else {
    2584         $do_recount = false;
    2585     }
    2586 
    25872564    if ( ! is_array( $terms ) ) {
    25882565        $terms = array( $terms );
     
    26702647    }
    26712648
    2672     if ( $new_tt_ids && $do_recount ) {
    2673         wp_increment_term_count( $new_tt_ids, $taxonomy );
     2649    if ( $new_tt_ids ) {
     2650        wp_update_term_count( $new_tt_ids, $taxonomy );
    26742651    }
    26752652
     
    26892666    }
    26902667
    2691     if ( ! $append && isset( $taxonomy_object->sort ) && $taxonomy_object->sort ) {
     2668    $t = get_taxonomy( $taxonomy );
     2669
     2670    if ( ! $append && isset( $t->sort ) && $t->sort ) {
    26922671        $values     = array();
    26932672        $term_order = 0;
     
    27682747    if ( ! taxonomy_exists( $taxonomy ) ) {
    27692748        return new WP_Error( 'invalid_taxonomy', __( 'Invalid taxonomy.' ) );
    2770     }
    2771 
    2772     $taxonomy_object = get_taxonomy( $taxonomy );
    2773 
    2774     $object_types = (array) $taxonomy_object->object_type;
    2775     foreach ( $object_types as &$object_type ) {
    2776         if ( 0 === strpos( $object_type, 'attachment:' ) ) {
    2777             list( $object_type ) = explode( ':', $object_type );
    2778         }
    2779     }
    2780 
    2781     if ( array_filter( $object_types, 'post_type_exists' ) !== $object_types ) {
    2782         // This taxonomy applies to non-posts, count changes now.
    2783         $do_recount = ! _wp_prevent_term_counting();
    2784     } elseif (
    2785         'publish' === get_post_status( $object_id ) ||
    2786         (
    2787             'inherit' === get_post_status( $object_id ) &&
    2788             'publish' === get_post_status( wp_get_post_parent_id( $object_id ) )
    2789         )
    2790     ) {
    2791         // Published post, count changes now.
    2792         $do_recount = ! _wp_prevent_term_counting();
    2793     } else {
    2794         $do_recount = false;
    27952749    }
    27962750
     
    28532807        do_action( 'deleted_term_relationships', $object_id, $tt_ids, $taxonomy );
    28542808
    2855         if ( $do_recount ) {
    2856             wp_decrement_term_count( $tt_ids, $taxonomy );
    2857         }
     2809        wp_update_term_count( $tt_ids, $taxonomy );
    28582810
    28592811        return (bool) $deleted;
     
    32753227        // Flush any deferred counts.
    32763228        if ( ! $defer ) {
    3277             wp_modify_term_count_by( null, null, null, true );
    32783229            wp_update_term_count( null, null, true );
    32793230        }
     
    32813232
    32823233    return $_defer;
    3283 }
    3284 
    3285 /**
    3286  * Prevents add/removing a term from modifying a term count.
    3287  *
    3288  * This is used by functions calling wp_transition_post_status() to indicate the
    3289  * term count will be handled during the post's transition.
    3290  *
    3291  * @private
    3292  * @since 5.6.0
    3293  *
    3294  * @param bool $new_setting The new setting for preventing term counts.
    3295  * @return bool Whether term count prevention is enabled or disabled.
    3296  */
    3297 function _wp_prevent_term_counting( $new_setting = null ) {
    3298     static $prevent = false;
    3299 
    3300     if ( is_bool( $new_setting ) ) {
    3301         $prevent = $new_setting;
    3302     }
    3303 
    3304     return $prevent;
    3305 }
    3306 
    3307 /**
    3308  * Increments the amount of terms in taxonomy.
    3309  *
    3310  * If there is a taxonomy callback applied, then it will be called for updating
    3311  * the count.
    3312  *
    3313  * The default action is to increment the count by one and update the database.
    3314  *
    3315  * @since 5.6.0
    3316  *
    3317  * @param int|array $tt_ids       The term_taxonomy_id of the terms.
    3318  * @param string    $taxonomy     The context of the term.
    3319  * @param int       $increment_by By how many the term count is to be incremented. Default 1.
    3320  * @param bool      $do_deferred  Whether to flush the deferred term counts too. Default false.
    3321  * @return bool If no terms will return false, and if successful will return true.
    3322  */
    3323 function wp_increment_term_count( $tt_ids, $taxonomy, $increment_by = 1, $do_deferred = false ) {
    3324     return wp_modify_term_count_by( $tt_ids, $taxonomy, $increment_by, $do_deferred );
    3325 }
    3326 
    3327 /**
    3328  * Decrements the amount of terms in taxonomy.
    3329  *
    3330  * If there is a taxonomy callback applied, then it will be called for updating
    3331  * the count.
    3332  *
    3333  * The default action is to decrement the count by one and update the database.
    3334  *
    3335  * @since 5.6.0
    3336  *
    3337  * @param int|array $tt_ids       The term_taxonomy_id of the terms.
    3338  * @param string    $taxonomy     The context of the term.
    3339  * @param int       $decrement_by By how many the term count is to be decremented. Default 1.
    3340  * @param bool      $do_deferred  Whether to flush the deferred term counts too. Default false.
    3341  * @return bool If no terms will return false, and if successful will return true.
    3342  */
    3343 function wp_decrement_term_count( $tt_ids, $taxonomy, $decrement_by = 1, $do_deferred = false ) {
    3344     return wp_modify_term_count_by( $tt_ids, $taxonomy, $decrement_by * -1, $do_deferred );
    3345 }
    3346 
    3347 /**
    3348  * Modifies the amount of terms in taxonomy.
    3349  *
    3350  * If there is a taxonomy callback applied, then it will be called for updating
    3351  * the count.
    3352  *
    3353  * The default action is to decrement the count by one and update the database.
    3354  *
    3355  * @since 5.6.0
    3356  *
    3357  * @param int|array $tt_ids      The term_taxonomy_id of the terms.
    3358  * @param string    $taxonomy    The context of the term.
    3359  * @param int       $modify_by   By how many the term count is to be modified.
    3360  * @param bool      $do_deferred Whether to flush the deferred term counts too. Default false.
    3361  * @return bool If no terms will return false, and if successful will return true.
    3362  */
    3363 function wp_modify_term_count_by( $tt_ids, $taxonomy, $modify_by, $do_deferred = false ) {
    3364     static $_deferred = array();
    3365 
    3366     if ( $do_deferred ) {
    3367         foreach ( (array) $_deferred as $taxonomy_name => $modifications ) {
    3368             $tax_by_count = array_reduce(
    3369                 array_keys( $modifications ),
    3370                 function( $by_count, $tt_id ) use ( $modifications ) {
    3371                     if ( ! isset( $by_count[ $modifications[ $tt_id ] ] ) ) {
    3372                         $by_count[ $modifications[ $tt_id ] ] = array();
    3373                     }
    3374                     $by_count[ $modifications[ $tt_id ] ][] = $tt_id;
    3375                     return $by_count;
    3376                 },
    3377                 array()
    3378             );
    3379 
    3380             foreach ( $tax_by_count as $_modify_by => $_tt_ids ) {
    3381                 wp_modify_term_count_by_now( $_tt_ids, $taxonomy_name, $_modify_by );
    3382             }
    3383             unset( $_deferred[ $taxonomy_name ] );
    3384         }
    3385     }
    3386 
    3387     if ( empty( $tt_ids ) ) {
    3388         return false;
    3389     }
    3390 
    3391     if ( ! is_array( $tt_ids ) ) {
    3392         $tt_ids = array( $tt_ids );
    3393     }
    3394 
    3395     if ( wp_defer_term_counting() ) {
    3396         foreach ( $tt_ids as $tt_id ) {
    3397             if ( ! isset( $_deferred[ $taxonomy ][ $tt_id ] ) ) {
    3398                 $_deferred[ $taxonomy ][ $tt_id ] = 0;
    3399             }
    3400             $_deferred[ $taxonomy ][ $tt_id ] += $modify_by;
    3401         }
    3402         return true;
    3403     }
    3404 
    3405     return wp_modify_term_count_by_now( $tt_ids, $taxonomy, $modify_by );
    3406 }
    3407 
    3408 /**
    3409  * Modifies the amount of terms in taxonomy immediately
    3410  *
    3411  * If there is a taxonomy callback applied, then it will be called for updating
    3412  * the count.
    3413  *
    3414  * The default action is to decrement the count by one and update the database.
    3415  *
    3416  * @since 5.6.0
    3417  *
    3418  * @param int|array $tt_ids      The term_taxonomy_id of the terms.
    3419  * @param string    $taxonomy    The context of the term.
    3420  * @param int       $modify_by   By how many the term count is to be modified.
    3421  * @return bool If no terms will return false, and if successful will return true.
    3422  */
    3423 function wp_modify_term_count_by_now( $tt_ids, $taxonomy, $modify_by ) {
    3424     global $wpdb;
    3425 
    3426     if ( 0 === $modify_by ) {
    3427         return false;
    3428     }
    3429 
    3430     $tt_ids = array_filter( array_map( 'intval', (array) $tt_ids ) );
    3431 
    3432     if ( empty( $tt_ids ) ) {
    3433         return false;
    3434     }
    3435 
    3436     $taxonomy = get_taxonomy( $taxonomy );
    3437     if ( ! empty( $taxonomy->update_count_by_callback ) ) {
    3438         call_user_func( $taxonomy->update_count_by_callback, $tt_ids, $taxonomy, $modify_by );
    3439         clean_term_cache( $tt_ids, '', false );
    3440         return true;
    3441     }
    3442 
    3443     $tt_ids_string = '(' . implode( ',', $tt_ids ) . ')';
    3444 
    3445     foreach ( $tt_ids as $tt_id ) {
    3446         /** This action is documented in wp-includes/taxonomy.php */
    3447         do_action( 'edit_term_taxonomy', $tt_id, $taxonomy->name );
    3448     }
    3449 
    3450     $result = $wpdb->query(
    3451         $wpdb->prepare(
    3452             // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
    3453             "UPDATE {$wpdb->term_taxonomy} AS tt SET tt.count = GREATEST( 0, tt.count + %d ) WHERE tt.term_taxonomy_id IN $tt_ids_string",
    3454             $modify_by
    3455         )
    3456     );
    3457 
    3458     if ( ! $result ) {
    3459         return false;
    3460     }
    3461 
    3462     foreach ( $tt_ids as $tt_id ) {
    3463         /** This action is documented in wp-includes/taxonomy.php */
    3464         do_action( 'edited_term_taxonomy', $tt_id, $taxonomy->name );
    3465     }
    3466 
    3467     clean_term_cache( $tt_ids, '', false );
    3468 
    3469     return true;
    34703234}
    34713235
  • trunk/tests/phpunit/tests/taxonomy.php

    r49328 r49451  
    55 */
    66class Tests_Taxonomy extends WP_UnitTestCase {
    7 
    8     /**
    9      * Number of times full count callback has been called.
    10      *
    11      * @var int
    12      */
    13     public $full_count_cb_called = 0;
    14 
    15     /**
    16      * Number of times partial count callback has been called.
    17      *
    18      * @var int
    19      */
    20     public $partial_count_cb_called = 0;
    21 
    227    function test_get_post_taxonomies() {
    238        $this->assertSame( array( 'category', 'post_tag', 'post_format' ), get_object_taxonomies( 'post' ) );
     
    10681053        $this->assertContains( $tax2, $taxonomies );
    10691054    }
    1070 
    1071     /**
    1072      * Ensure custom callbacks are used when registered.
    1073      *
    1074      * @covers ::register_taxonomy
    1075      * @ticket 40351
    1076      */
    1077     function test_register_taxonomy_counting_callbacks() {
    1078         $post_id = self::factory()->post->create();
    1079 
    1080         register_taxonomy(
    1081             'wp_tax_40351_full_only',
    1082             'post',
    1083             array(
    1084                 'update_count_callback' => array( $this, 'cb_register_taxonomy_full_count_callback' ),
    1085             )
    1086         );
    1087         $full_term    = self::factory()->term->create_and_get(
    1088             array(
    1089                 'taxonomy' => 'wp_tax_40351_full_only',
    1090             )
    1091         );
    1092         $full_term_id = $full_term->term_id;
    1093 
    1094         register_taxonomy(
    1095             'wp_tax_40351_partial_only',
    1096             'post',
    1097             array(
    1098                 'update_count_by_callback' => array( $this, 'cb_register_taxonomy_partial_count_callback' ),
    1099             )
    1100         );
    1101         $partial_term    = self::factory()->term->create_and_get(
    1102             array(
    1103                 'taxonomy' => 'wp_tax_40351_partial_only',
    1104             )
    1105         );
    1106         $partial_term_id = $partial_term->term_id;
    1107 
    1108         register_taxonomy(
    1109             'wp_tax_40351_both',
    1110             'post',
    1111             array(
    1112                 'update_count_callback'    => array( $this, 'cb_register_taxonomy_full_count_callback' ),
    1113                 'update_count_by_callback' => array( $this, 'cb_register_taxonomy_partial_count_callback' ),
    1114             )
    1115         );
    1116         $both_term      = self::factory()->term->create_and_get(
    1117             array(
    1118                 'taxonomy' => 'wp_tax_40351_both',
    1119             )
    1120         );
    1121         $both_term_id   = $both_term->term_id;
    1122         $both_term_ttid = $both_term->term_taxonomy_id;
    1123 
    1124         wp_set_post_terms( $post_id, $full_term_id, 'wp_tax_40351_full_only' );
    1125         $this->assertSame( 0, $this->partial_count_cb_called );
    1126         $this->assertSame( 1, $this->full_count_cb_called );
    1127 
    1128         wp_set_post_terms( $post_id, $partial_term_id, 'wp_tax_40351_partial_only' );
    1129         $this->assertSame( 1, $this->partial_count_cb_called );
    1130         $this->assertSame( 1, $this->full_count_cb_called );
    1131 
    1132         wp_set_post_terms( $post_id, $both_term_id, 'wp_tax_40351_both' );
    1133         $this->assertSame( 2, $this->partial_count_cb_called );
    1134         $this->assertSame( 1, $this->full_count_cb_called );
    1135 
    1136         // Force a full recount `$both_term` to ensure callback is called.
    1137         wp_update_term_count( $both_term_ttid, 'wp_tax_40351_both' );
    1138         $this->assertSame( 2, $this->full_count_cb_called );
    1139     }
    1140 
    1141     /**
    1142      * Custom full count callback for `test_register_taxonomy_counting_callbacks()`.
    1143      *
    1144      * For the purpose of this test no database modifications are required, therefore
    1145      * the parameters passed are unused.
    1146      *
    1147      * @param int|array $tt_ids   The term_taxonomy_id of the terms.
    1148      * @param string    $taxonomy The context of the term.
    1149      */
    1150     function cb_register_taxonomy_full_count_callback( $tt_ids, $taxonomy ) {
    1151         $this->full_count_cb_called++;
    1152     }
    1153 
    1154     /**
    1155      * Custom partial count callback for `test_register_taxonomy_counting_callbacks()`.
    1156      *
    1157      * For the purpose of this test no database modifications are required, therefore
    1158      * the parameters passed are unused.
    1159      *
    1160      * @param int|array $tt_ids    The term_taxonomy_id of the terms.
    1161      * @param string    $taxonomy  The context of the term.
    1162      * @param int       $modify_by By how many the term count is to be modified.
    1163      */
    1164     function cb_register_taxonomy_partial_count_callback( $tt_ids, $taxonomy, $modify_by ) {
    1165         $this->partial_count_cb_called++;
    1166     }
    11671055}
  • trunk/tests/phpunit/tests/term/termCounts.php

    r49305 r49451  
    8080
    8181    /**
    82      * Term counts are not double incremented when post created.
    83      *
    84      * @covers ::wp_modify_term_count_by
     82     * Term counts are incremented when post created.
     83     *
     84     * @covers ::wp_update_term_count
    8585     * @dataProvider data_term_count_changes_for_post_statuses
    86      * @ticket 40351
    8786     *
    8887     * @param string $post_status New post status.
     
    123122     *
    124123     * @covers ::wp_publish_post
    125      * @covers ::wp_modify_term_count_by
     124     * @covers ::wp_update_term_count
    126125     * @dataProvider data_term_counts_incremented_on_publish
    127      * @ticket 40351
    128126     * @ticket 51292
    129127     *
     
    165163     * Test post status transition update term counts correctly.
    166164     *
    167      * @covers ::wp_modify_term_count_by
     165     * @covers ::wp_update_term_count
    168166     * @dataProvider data_term_count_transitions_update_term_counts
    169      * @ticket 40351
    170167     *
    171168     * @param string $original_post_status Post status upon create.
     
    229226
    230227    /**
    231      * Term counts are not double incremented when post created.
    232      *
    233      * @covers ::wp_modify_term_count_by
     228     * Term counts incremented correctly for posts with attachment.
     229     *
     230     * @covers ::wp_update_term_count
    234231     * @dataProvider data_term_count_changes_for_post_statuses_with_attachments
    235      * @ticket 40351
    236232     *
    237233     * @param string $post_status New post status.
     
    278274
    279275    /**
    280      * Term counts increments correctly when post status becomes published.
     276     * Term counts increments correctly when post with attachment becomes published.
    281277     *
    282278     * @covers ::wp_publish_post
    283      * @covers ::wp_modify_term_count_by
     279     * @covers ::wp_update_term_count
    284280     * @dataProvider data_term_counts_incremented_on_publish_with_attachments
    285      * @ticket 40351
    286281     * @ticket 51292
    287282     *
     
    330325
    331326    /**
    332      * Test post status transition update term counts correctly.
    333      *
    334      * @covers ::wp_modify_term_count_by
     327     * Test post status transition update term counts correctly for posts with attachments.
     328     *
     329     * @covers ::wp_update_term_count
    335330     * @dataProvider data_term_count_transitions_update_term_counts_with_attachments
    336      * @ticket 40351
    337331     *
    338332     * @param string $original_post_status Post status upon create.
     
    405399
    406400    /**
    407      * Term counts are not double incremented when post created.
    408      *
    409      * @covers ::wp_modify_term_count_by
    410      * @dataProvider data_term_count_changes_for_post_statuses_with_untermed_attachments
    411      * @ticket 40351
    412      *
    413      * @param string $post_status New post status.
    414      * @param int    $change      Expected change.
    415      */
    416     public function test_term_count_changes_for_post_statuses_with_untermed_attachments( $post_status, $change ) {
    417         $term_count = get_term( self::$attachment_term )->count;
    418         // Do not use shared fixture for this test as it relies on a new post.
    419         $post_id = $this->factory()->post->create( array( 'post_status' => $post_status ) );
    420         wp_add_object_terms( $post_id, self::$attachment_term, 'wp_test_tax_counts' );
    421         $attachment_id = self::factory()->attachment->create_object(
    422             array(
    423                 'file'        => 'image.jpg',
    424                 'post_parent' => $post_id,
    425                 'post_status' => 'inherit',
    426             )
    427         );
    428 
    429         $expected = $term_count + $change;
    430         $this->assertSame( $expected, get_term( self::$attachment_term )->count );
    431     }
    432 
    433     /**
    434      * Data provider for test_term_count_changes_for_post_statuses_with_untermed_attachments.
    435      *
    436      * @return array[] {
    437      *     @type string $post_status New post status.
    438      *     @type int    $change      Expected change.
    439      * }
    440      */
    441     function data_term_count_changes_for_post_statuses_with_untermed_attachments() {
    442         return array(
    443             // 0. Published post
    444             array( 'publish', 1 ),
    445             // 1. Auto draft
    446             array( 'auto-draft', 0 ),
    447             // 2. Draft
    448             array( 'draft', 0 ),
    449             // 3. Private post
    450             array( 'private', 0 ),
    451         );
    452     }
    453 
    454     /**
    455      * Term counts increments correctly when post status becomes published.
    456      *
    457      * @covers ::wp_modify_term_count_by
     401     * Term counts increments correctly when post with attachment becomes published.
     402     *
     403     * @covers ::wp_update_term_count
    458404     * @covers ::wp_publish_post
    459405     * @dataProvider data_term_counts_incremented_on_publish_with_untermed_attachments
    460      * @ticket 40351
    461406     * @ticket 51292
    462407     *
     
    504449
    505450    /**
    506      * Test post status transition update term counts correctly.
    507      *
    508      * @covers ::wp_modify_term_count_by
     451     * Test post status transition update term counts correctly on post with attachment.
     452     *
     453     * @covers ::wp_update_term_count
    509454     * @dataProvider data_term_count_transitions_update_term_counts_with_untermed_attachments
    510      * @ticket 40351
    511455     *
    512456     * @param string $original_post_status Post status upon create.
     
    580524     * User taxonomy term counts increments when added to an account.
    581525     *
    582      * @covers ::wp_modify_term_count_by
     526     * @covers ::wp_update_term_count
    583527     * @ticket 51292
    584528     */
     
    594538     * User taxonomy term counts decrement when term deleted from user.
    595539     *
    596      * @covers ::wp_modify_term_count_by
     540     * @covers ::wp_update_term_count
    597541     * @ticket 51292
    598542     */
     
    605549        $this->assertSame( $expected, get_term( self::$user_term )->count );
    606550    }
    607 
    608     /**
    609      * Ensure DB queries for deferred counts are nullified for net zero gain.
    610      *
    611      * @covers ::wp_modify_term_count_by
    612      * @covers ::wp_defer_term_counting
    613      * @ticket 51292
    614      */
    615     public function test_counts_after_deferral_net_zero() {
    616         $post_one = self::$post_ids['publish'];
    617         $post_two = self::$post_ids['publish_two'];
    618         $terms    = self::$tag_ids;
    619 
    620         wp_set_object_terms( $post_one, $terms[0], 'post_tag', true );
    621 
    622         // Net gain 0;
    623         wp_defer_term_counting( true );
    624         wp_remove_object_terms( $post_one, $terms[0], 'post_tag' );
    625         wp_set_object_terms( $post_two, $terms[0], 'post_tag', true );
    626         $num_queries = get_num_queries();
    627         wp_defer_term_counting( false );
    628         // Ensure number of queries unchanged.
    629         $this->assertSame( $num_queries, get_num_queries() );
    630     }
    631 
    632     /**
    633      * Ensure full recounts follow modify by X recounts to avoid miscounts.
    634      *
    635      * @covers ::wp_modify_term_count_by
    636      * @covers ::wp_update_term_count
    637      * @covers ::wp_defer_term_counting
    638      * @ticket 51292
    639      */
    640     public function test_counts_after_deferral_full_before_partial() {
    641         $post_one   = self::$post_ids['publish'];
    642         $terms      = self::$tag_ids;
    643         $term_count = get_term( $terms[0] )->count;
    644 
    645         // Net gain 1;
    646         wp_defer_term_counting( true );
    647         wp_set_object_terms( $post_one, $terms[0], 'post_tag', true );
    648         wp_update_term_count( get_term( $terms[0] )->term_taxonomy_id, 'post_tag' );
    649         wp_defer_term_counting( false );
    650 
    651         // Ensure term count is correct.
    652         $expected = $term_count + 1;
    653         $this->assertSame( $expected, get_term( $terms[0] )->count );
    654     }
    655 
    656     /**
    657      * Ensure DB queries for deferred counts are combined.
    658      *
    659      * @covers ::wp_modify_term_count_by
    660      * @covers ::wp_defer_term_counting
    661      * @ticket 51292
    662      */
    663     public function test_counts_after_deferral_matching_changes() {
    664         $post_one = self::$post_ids['publish'];
    665         $post_two = self::$post_ids['publish_two'];
    666         $terms    = self::$tag_ids;
    667 
    668         wp_set_object_terms( $post_one, $terms[0], 'post_tag', true );
    669 
    670         // Net gain 0:
    671         wp_defer_term_counting( true );
    672         wp_remove_object_terms( $post_one, $terms[0], 'post_tag' );
    673         wp_set_object_terms( $post_two, $terms[0], 'post_tag', true );
    674 
    675         // Net gain 1:
    676         wp_set_object_terms( $post_one, $terms[1], 'post_tag', true );
    677         wp_set_object_terms( $post_two, $terms[2], 'post_tag', true );
    678 
    679         // Net gain 2:
    680         wp_set_object_terms( $post_one, array( $terms[3], $terms[4] ), 'post_tag', true );
    681         wp_set_object_terms( $post_two, array( $terms[3], $terms[4] ), 'post_tag', true );
    682 
    683         $num_queries = get_num_queries();
    684         wp_defer_term_counting( false );
    685 
    686         /*
    687          * Each count is expected to produce two queries:
    688          * 1) The count update
    689          * 2) The SELECT in `clean_term_cache()`.
    690          */
    691         $expected = $num_queries + ( 2 * 2 );
    692         // Ensure number of queries correct.
    693         $this->assertSame( $expected, get_num_queries() );
    694     }
    695551}
Note: See TracChangeset for help on using the changeset viewer.