Make WordPress Core


Ignore:
Timestamp:
05/17/2022 06:59:24 PM (4 years ago)
Author:
SergeyBiryukov
Message:

Users: Fail gracefully when checking mapped capabilities without providing the required object ID.

This avoids an Undefined array key 0 PHP warning for current_user_can() capability checks that require a specific object to check against but an object ID was not passed.

A _doing_it_wrong() notice is also added, so that developers and site administrators are aware that the capability mapping is failing in the absence of the required object ID.

The list of mapped capabilities that require an object ID:

  • delete_post / delete_page
  • edit_post / edit_page
  • read_post / read_page
  • publish_post
  • edit_(post|comment|term|user)_meta / delete_*_meta / add_*_meta
  • edit_comment
  • edit_term / delete_term / assign_term

Follow-up to [34091], [34113], [47178].

Props jeherve, peterwilsoncc, henry.wright, johnbillion, mattheweppelsheimer, hellofromTonya, JeffPaul, azouamauriac, Ninos Ego, TobiasBg, wpsmith, GaryJ, nacin, johnstonphilip, azaozz, SergeyBiryukov.
Fixes #44591.

File:
1 edited

Legend:

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

    r53249 r53408  
    7474                case 'delete_post':
    7575                case 'delete_page':
     76                        if ( ! isset( $args[0] ) ) {
     77                                if ( 'delete_post' === $cap ) {
     78                                        /* translators: %s: Capability name. */
     79                                        $message = __( 'When checking for the %s capability, you must always check it against a specific post.' );
     80                                } else {
     81                                        /* translators: %s: Capability name. */
     82                                        $message = __( 'When checking for the %s capability, you must always check it against a specific page.' );
     83                                }
     84
     85                                _doing_it_wrong(
     86                                        __FUNCTION__,
     87                                        sprintf( $message, '<code>' . $cap . '</code>' ),
     88                                        '6.1.0'
     89                                );
     90
     91                                $caps[] = 'do_not_allow';
     92                                break;
     93                        }
     94
    7695                        $post = get_post( $args[0] );
    7796                        if ( ! $post ) {
     
    93112                        if ( ! $post_type ) {
    94113                                /* translators: 1: Post type, 2: Capability name. */
    95                                 _doing_it_wrong( __FUNCTION__, sprintf( __( 'The post type %1$s is not registered, so it may not be reliable to check the capability "%2$s" against a post of that type.' ), $post->post_type, $cap ), '4.4.0' );
     114                                $message = __( 'The post type %1$s is not registered, so it may not be reliable to check the capability %2$s against a post of that type.' );
     115
     116                                _doing_it_wrong(
     117                                        __FUNCTION__,
     118                                        sprintf(
     119                                                $message,
     120                                                '<code>' . $post->post_type . '</code>',
     121                                                '<code>' . $cap . '</code>'
     122                                        ),
     123                                        '4.4.0'
     124                                );
     125
    96126                                $caps[] = 'edit_others_posts';
    97127                                break;
     
    147177                case 'edit_post':
    148178                case 'edit_page':
     179                        if ( ! isset( $args[0] ) ) {
     180                                if ( 'edit_post' === $cap ) {
     181                                        /* translators: %s: Capability name. */
     182                                        $message = __( 'When checking for the %s capability, you must always check it against a specific post.' );
     183                                } else {
     184                                        /* translators: %s: Capability name. */
     185                                        $message = __( 'When checking for the %s capability, you must always check it against a specific page.' );
     186                                }
     187
     188                                _doing_it_wrong(
     189                                        __FUNCTION__,
     190                                        sprintf( $message, '<code>' . $cap . '</code>' ),
     191                                        '6.1.0'
     192                                );
     193
     194                                $caps[] = 'do_not_allow';
     195                                break;
     196                        }
     197
    149198                        $post = get_post( $args[0] );
    150199                        if ( ! $post ) {
     
    164213                        if ( ! $post_type ) {
    165214                                /* translators: 1: Post type, 2: Capability name. */
    166                                 _doing_it_wrong( __FUNCTION__, sprintf( __( 'The post type %1$s is not registered, so it may not be reliable to check the capability "%2$s" against a post of that type.' ), $post->post_type, $cap ), '4.4.0' );
     215                                $message = __( 'The post type %1$s is not registered, so it may not be reliable to check the capability %2$s against a post of that type.' );
     216
     217                                _doing_it_wrong(
     218                                        __FUNCTION__,
     219                                        sprintf(
     220                                                $message,
     221                                                '<code>' . $post->post_type . '</code>',
     222                                                '<code>' . $cap . '</code>'
     223                                        ),
     224                                        '4.4.0'
     225                                );
     226
    167227                                $caps[] = 'edit_others_posts';
    168228                                break;
     
    216276                case 'read_post':
    217277                case 'read_page':
     278                        if ( ! isset( $args[0] ) ) {
     279                                if ( 'read_post' === $cap ) {
     280                                        /* translators: %s: Capability name. */
     281                                        $message = __( 'When checking for the %s capability, you must always check it against a specific post.' );
     282                                } else {
     283                                        /* translators: %s: Capability name. */
     284                                        $message = __( 'When checking for the %s capability, you must always check it against a specific page.' );
     285                                }
     286
     287                                _doing_it_wrong(
     288                                        __FUNCTION__,
     289                                        sprintf( $message, '<code>' . $cap . '</code>' ),
     290                                        '6.1.0'
     291                                );
     292
     293                                $caps[] = 'do_not_allow';
     294                                break;
     295                        }
     296
    218297                        $post = get_post( $args[0] );
    219298                        if ( ! $post ) {
     
    233312                        if ( ! $post_type ) {
    234313                                /* translators: 1: Post type, 2: Capability name. */
    235                                 _doing_it_wrong( __FUNCTION__, sprintf( __( 'The post type %1$s is not registered, so it may not be reliable to check the capability "%2$s" against a post of that type.' ), $post->post_type, $cap ), '4.4.0' );
     314                                $message = __( 'The post type %1$s is not registered, so it may not be reliable to check the capability %2$s against a post of that type.' );
     315
     316                                _doing_it_wrong(
     317                                        __FUNCTION__,
     318                                        sprintf(
     319                                                $message,
     320                                                '<code>' . $post->post_type . '</code>',
     321                                                '<code>' . $cap . '</code>'
     322                                        ),
     323                                        '4.4.0'
     324                                );
     325
    236326                                $caps[] = 'edit_others_posts';
    237327                                break;
     
    250340                        if ( ! $status_obj ) {
    251341                                /* translators: 1: Post status, 2: Capability name. */
    252                                 _doing_it_wrong( __FUNCTION__, sprintf( __( 'The post status %1$s is not registered, so it may not be reliable to check the capability "%2$s" against a post with that status.' ), get_post_status( $post ), $cap ), '5.4.0' );
     342                                $message = __( 'The post status %1$s is not registered, so it may not be reliable to check the capability %2$s against a post with that status.' );
     343
     344                                _doing_it_wrong(
     345                                        __FUNCTION__,
     346                                        sprintf(
     347                                                $message,
     348                                                '<code>' . get_post_status( $post ) . '</code>',
     349                                                '<code>' . $cap . '</code>'
     350                                        ),
     351                                        '5.4.0'
     352                                );
     353
    253354                                $caps[] = 'edit_others_posts';
    254355                                break;
     
    269370                        break;
    270371                case 'publish_post':
     372                        if ( ! isset( $args[0] ) ) {
     373                                /* translators: %s: Capability name. */
     374                                $message = __( 'When checking for the %s capability, you must always check it against a specific post.' );
     375
     376                                _doing_it_wrong(
     377                                        __FUNCTION__,
     378                                        sprintf( $message, '<code>' . $cap . '</code>' ),
     379                                        '6.1.0'
     380                                );
     381
     382                                $caps[] = 'do_not_allow';
     383                                break;
     384                        }
     385
    271386                        $post = get_post( $args[0] );
    272387                        if ( ! $post ) {
     
    278393                        if ( ! $post_type ) {
    279394                                /* translators: 1: Post type, 2: Capability name. */
    280                                 _doing_it_wrong( __FUNCTION__, sprintf( __( 'The post type %1$s is not registered, so it may not be reliable to check the capability "%2$s" against a post of that type.' ), $post->post_type, $cap ), '4.4.0' );
     395                                $message = __( 'The post type %1$s is not registered, so it may not be reliable to check the capability %2$s against a post of that type.' );
     396
     397                                _doing_it_wrong(
     398                                        __FUNCTION__,
     399                                        sprintf(
     400                                                $message,
     401                                                '<code>' . $post->post_type . '</code>',
     402                                                '<code>' . $cap . '</code>'
     403                                        ),
     404                                        '4.4.0'
     405                                );
     406
    281407                                $caps[] = 'edit_others_posts';
    282408                                break;
     
    298424                case 'add_user_meta':
    299425                        $object_type = explode( '_', $cap )[1];
    300                         $object_id   = (int) $args[0];
     426
     427                        if ( ! isset( $args[0] ) ) {
     428                                if ( 'post' === $object_type ) {
     429                                        /* translators: %s: Capability name. */
     430                                        $message = __( 'When checking for the %s capability, you must always check it against a specific post.' );
     431                                } elseif ( 'comment' === $object_type ) {
     432                                        /* translators: %s: Capability name. */
     433                                        $message = __( 'When checking for the %s capability, you must always check it against a specific comment.' );
     434                                } elseif ( 'term' === $object_type ) {
     435                                        /* translators: %s: Capability name. */
     436                                        $message = __( 'When checking for the %s capability, you must always check it against a specific term.' );
     437                                } else {
     438                                        /* translators: %s: Capability name. */
     439                                        $message = __( 'When checking for the %s capability, you must always check it against a specific user.' );
     440                                }
     441
     442                                _doing_it_wrong(
     443                                        __FUNCTION__,
     444                                        sprintf( $message, '<code>' . $cap . '</code>' ),
     445                                        '6.1.0'
     446                                );
     447
     448                                $caps[] = 'do_not_allow';
     449                                break;
     450                        }
     451
     452                        $object_id = (int) $args[0];
    301453
    302454                        $object_subtype = get_object_subtype( $object_type, $object_id );
     
    393545                        break;
    394546                case 'edit_comment':
     547                        if ( ! isset( $args[0] ) ) {
     548                                /* translators: %s: Capability name. */
     549                                $message = __( 'When checking for the %s capability, you must always check it against a specific comment.' );
     550
     551                                _doing_it_wrong(
     552                                        __FUNCTION__,
     553                                        sprintf( $message, '<code>' . $cap . '</code>' ),
     554                                        '6.1.0'
     555                                );
     556
     557                                $caps[] = 'do_not_allow';
     558                                break;
     559                        }
     560
    395561                        $comment = get_comment( $args[0] );
    396562                        if ( ! $comment ) {
     
    533699                case 'delete_term':
    534700                case 'assign_term':
     701                        if ( ! isset( $args[0] ) ) {
     702                                /* translators: %s: Capability name. */
     703                                $message = __( 'When checking for the %s capability, you must always check it against a specific term.' );
     704
     705                                _doing_it_wrong(
     706                                        __FUNCTION__,
     707                                        sprintf( $message, '<code>' . $cap . '</code>' ),
     708                                        '6.1.0'
     709                                );
     710
     711                                $caps[] = 'do_not_allow';
     712                                break;
     713                        }
     714
    535715                        $term_id = (int) $args[0];
    536716                        $term    = get_term( $term_id );
Note: See TracChangeset for help on using the changeset viewer.