WordPress.org

Make WordPress Core

Ticket #38323: 38323.5.diff

File 38323.5.diff, 20.8 KB (added by flixos90, 2 years ago)
  • src/wp-includes/capabilities.php

     
    263263                        list( $_, $object_type, $_ ) = explode( '_', $cap );
    264264                        $object_id                   = (int) $args[0];
    265265
    266                         switch ( $object_type ) {
    267                                 case 'post':
    268                                         $post = get_post( $object_id );
    269                                         if ( ! $post ) {
    270                                                 break;
    271                                         }
    272 
    273                                         $sub_type = get_post_type( $post );
    274                                         break;
    275 
    276                                 case 'comment':
    277                                         $comment = get_comment( $object_id );
    278                                         if ( ! $comment ) {
    279                                                 break;
    280                                         }
    281 
    282                                         $sub_type = empty( $comment->comment_type ) ? 'comment' : $comment->comment_type;
    283                                         break;
    284 
    285                                 case 'term':
    286                                         $term = get_term( $object_id );
    287                                         if ( ! $term instanceof WP_Term ) {
    288                                                 break;
    289                                         }
    290 
    291                                         $sub_type = $term->taxonomy;
    292                                         break;
    293 
    294                                 case 'user':
    295                                         $user = get_user_by( 'id', $object_id );
    296                                         if ( ! $user ) {
    297                                                 break;
    298                                         }
    299 
    300                                         $sub_type = 'user';
    301                                         break;
    302                         }
     266                        $sub_type = get_object_subtype( $object_type, $object_id );
    303267
    304268                        if ( empty( $sub_type ) ) {
    305269                                $caps[] = 'do_not_allow';
  • src/wp-includes/meta.php

     
    4444                return false;
    4545        }
    4646
     47        $meta_subtype = get_object_subtype( $meta_type, $object_id );
     48
    4749        $column = sanitize_key( $meta_type . '_id' );
    4850
    4951        // expected_slashed ($meta_key)
    5052        $meta_key   = wp_unslash( $meta_key );
    5153        $meta_value = wp_unslash( $meta_value );
    52         $meta_value = sanitize_meta( $meta_key, $meta_value, $meta_type );
     54        $meta_value = sanitize_meta( $meta_key, $meta_value, $meta_type, $meta_subtype );
    5355
    5456        /**
    5557         * Filters whether to add metadata of a specific type.
     
    165167                return false;
    166168        }
    167169
     170        $meta_subtype = get_object_subtype( $meta_type, $object_id );
     171
    168172        $column    = sanitize_key( $meta_type . '_id' );
    169173        $id_column = 'user' == $meta_type ? 'umeta_id' : 'meta_id';
    170174
     
    173177        $meta_key     = wp_unslash( $meta_key );
    174178        $passed_value = $meta_value;
    175179        $meta_value   = wp_unslash( $meta_value );
    176         $meta_value   = sanitize_meta( $meta_key, $meta_value, $meta_type );
     180        $meta_value   = sanitize_meta( $meta_key, $meta_value, $meta_type, $meta_subtype );
    177181
    178182        /**
    179183         * Filters whether to update metadata of a specific type.
     
    666670                        return false;
    667671                }
    668672
     673                $meta_subtype = get_object_subtype( $meta_type, $object_id );
     674
    669675                // Sanitize the meta
    670676                $_meta_value = $meta_value;
    671                 $meta_value  = sanitize_meta( $meta_key, $meta_value, $meta_type );
     677                $meta_value  = sanitize_meta( $meta_key, $meta_value, $meta_type, $meta_subtype );
    672678                $meta_value  = maybe_serialize( $meta_value );
    673679
    674680                // Format the data query arguments.
     
    968974 * Sanitize meta value.
    969975 *
    970976 * @since 3.1.3
     977 * @since 5.0.0 The `$object_subtype` parameter was added.
    971978 *
    972979 * @param string $meta_key       Meta key.
    973980 * @param mixed  $meta_value     Meta value to sanitize.
     
    975982 *
    976983 * @return mixed Sanitized $meta_value.
    977984 */
    978 function sanitize_meta( $meta_key, $meta_value, $object_type ) {
     985function sanitize_meta( $meta_key, $meta_value, $object_type, $object_subtype = '' ) {
     986        if ( ! empty( $object_subtype ) ) {
     987                /**
     988                 * Filters the sanitization of a specific meta key of a specific meta type and subtype.
     989                 *
     990                 * The dynamic portions of the hook name, `$object_type`, `$object_subtype`
     991                 * and `$meta_key`, refer to the metadata object type (comment, post, term or user),
     992                 * the object subtype and the meta key value, respectively.
     993                 *
     994                 * @since 5.0.0
     995                 *
     996                 * @param mixed  $meta_value     Meta value to sanitize.
     997                 * @param string $meta_key       Meta key.
     998                 * @param string $object_type    Object type.
     999                 * @param string $object_subtype Object subtype.
     1000                 */
     1001                $meta_value = apply_filters( "sanitize_{$object_type}_{$object_subtype}_meta_{$meta_key}", $meta_value, $meta_key, $object_type, $object_subtype );
     1002        }
     1003
    9791004        /**
    9801005         * Filters the sanitization of a specific meta key of a specific meta type.
    9811006         *
     
    9991024 * @since 4.6.0 {@link https://core.trac.wordpress.org/ticket/35658 Modified
    10001025 *              to support an array of data to attach to registered meta keys}. Previous arguments for
    10011026 *              `$sanitize_callback` and `$auth_callback` have been folded into this array.
     1027 * @since 5.0.0 The `$object_subtype` argument was added to the arguments array.
    10021028 *
    10031029 * @param string $object_type    Type of object this meta is registered to.
    10041030 * @param string $meta_key       Meta key to register.
    10051031 * @param array  $args {
    10061032 *     Data used to describe the meta key when registered.
    10071033 *
     1034 *     @type string $object_subtype    A subtype; e.g. if the object type is "post", the post type. If left empty,
     1035 *                                     the meta key will be registered on the entire object type. Default empty.
    10081036 *     @type string $type              The type of data associated with this meta key.
    10091037 *                                     Valid values are 'string', 'boolean', 'integer', and 'number'.
    10101038 *     @type string $description       A description of the data attached to this meta key.
     
    10271055        }
    10281056
    10291057        $defaults = array(
     1058                'object_subtype'    => '',
    10301059                'type'              => 'string',
    10311060                'description'       => '',
    10321061                'single'            => false,
     
    10671096        $args = apply_filters( 'register_meta_args', $args, $defaults, $object_type, $meta_key );
    10681097        $args = wp_parse_args( $args, $defaults );
    10691098
     1099        $object_subtype = ! empty( $args['object_subtype'] ) ? $args['object_subtype'] : '';
     1100
    10701101        // If `auth_callback` is not provided, fall back to `is_protected_meta()`.
    10711102        if ( empty( $args['auth_callback'] ) ) {
    10721103                if ( is_protected_meta( $meta_key, $object_type ) ) {
     
    10781109
    10791110        // Back-compat: old sanitize and auth callbacks are applied to all of an object type.
    10801111        if ( is_callable( $args['sanitize_callback'] ) ) {
    1081                 add_filter( "sanitize_{$object_type}_meta_{$meta_key}", $args['sanitize_callback'], 10, 3 );
     1112                if ( ! empty( $object_subtype ) ) {
     1113                        add_filter( "sanitize_{$object_type}_{$object_subtype}_meta_{$meta_key}", $args['sanitize_callback'], 10, 4 );
     1114                } else {
     1115                        add_filter( "sanitize_{$object_type}_meta_{$meta_key}", $args['sanitize_callback'], 10, 3 );
     1116                }
    10821117        }
    10831118
    10841119        if ( is_callable( $args['auth_callback'] ) ) {
    1085                 add_filter( "auth_{$object_type}_meta_{$meta_key}", $args['auth_callback'], 10, 6 );
     1120                if ( ! empty( $object_subtype ) ) {
     1121                        add_filter( "auth_{$object_type}_{$object_subtype}_meta_{$meta_key}", $args['auth_callback'], 10, 6 );
     1122                } else {
     1123                        add_filter( "auth_{$object_type}_meta_{$meta_key}", $args['auth_callback'], 10, 6 );
     1124                }
    10861125        }
    10871126
    10881127        // Global registry only contains meta keys registered with the array of arguments added in 4.6.0.
    10891128        if ( ! $has_old_auth_cb && ! $has_old_sanitize_cb ) {
    1090                 $wp_meta_keys[ $object_type ][ $meta_key ] = $args;
     1129                unset( $args['object_subtype'] );
     1130
     1131                $wp_meta_keys[ $object_type ][ $object_subtype ][ $meta_key ] = $args;
    10911132
    10921133                return true;
    10931134        }
     
    10991140 * Checks if a meta key is registered.
    11001141 *
    11011142 * @since 4.6.0
     1143 * @since 5.0.0 The `$object_subtype` parameter was added.
    11021144 *
    11031145 * @param string $object_type    The type of object.
    11041146 * @param string $meta_key       The meta key.
     1147 * @param string $object_subtype Optional. The subtype of the object type.
    11051148 *
    1106  * @return bool True if the meta key is registered to the object type. False if not.
     1149 * @return bool True if the meta key is registered to the object type and, if provided,
     1150 *              the object subtype. False if not.
    11071151 */
    1108 function registered_meta_key_exists( $object_type, $meta_key ) {
    1109         global $wp_meta_keys;
    1110 
    1111         if ( ! is_array( $wp_meta_keys ) ) {
    1112                 return false;
    1113         }
    1114 
    1115         if ( ! isset( $wp_meta_keys[ $object_type ] ) ) {
    1116                 return false;
    1117         }
    1118 
    1119         if ( isset( $wp_meta_keys[ $object_type ][ $meta_key ] ) ) {
    1120                 return true;
    1121         }
     1152function registered_meta_key_exists( $object_type, $meta_key, $object_subtype = '' ) {
     1153        $meta_keys = get_registered_meta_keys( $object_type, $object_subtype );
    11221154
    1123         return false;
     1155        return isset( $meta_keys[ $meta_key ] );
    11241156}
    11251157
    11261158/**
    11271159 * Unregisters a meta key from the list of registered keys.
    11281160 *
    11291161 * @since 4.6.0
     1162 * @since 5.0.0 The `$object_subtype` parameter was added.
    11301163 *
    1131  * @param string $object_type The type of object.
    1132  * @param string $meta_key    The meta key.
     1164 * @param string $object_type    The type of object.
     1165 * @param string $meta_key       The meta key.
     1166 * @param string $object_subtype Optional. The subtype of the object type.
    11331167 * @return bool True if successful. False if the meta key was not registered.
    11341168 */
    1135 function unregister_meta_key( $object_type, $meta_key ) {
     1169function unregister_meta_key( $object_type, $meta_key, $object_subtype = '' ) {
    11361170        global $wp_meta_keys;
    11371171
    1138         if ( ! registered_meta_key_exists( $object_type, $meta_key ) ) {
     1172        if ( ! registered_meta_key_exists( $object_type, $meta_key, $object_subtype ) ) {
    11391173                return false;
    11401174        }
    11411175
    1142         $args = $wp_meta_keys[ $object_type ][ $meta_key ];
     1176        $args = $wp_meta_keys[ $object_type ][ $object_subtype ][ $meta_key ];
    11431177
    11441178        if ( isset( $args['sanitize_callback'] ) && is_callable( $args['sanitize_callback'] ) ) {
    1145                 remove_filter( "sanitize_{$object_type}_meta_{$meta_key}", $args['sanitize_callback'] );
     1179                if ( ! empty( $object_subtype ) ) {
     1180                        remove_filter( "sanitize_{$object_type}_{$object_subtype}_meta_{$meta_key}", $args['sanitize_callback'] );
     1181                } else {
     1182                        remove_filter( "sanitize_{$object_type}_meta_{$meta_key}", $args['sanitize_callback'] );
     1183                }
    11461184        }
    11471185
    11481186        if ( isset( $args['auth_callback'] ) && is_callable( $args['auth_callback'] ) ) {
    1149                 remove_filter( "auth_{$object_type}_meta_{$meta_key}", $args['auth_callback'] );
     1187                if ( ! empty( $object_subtype ) ) {
     1188                        remove_filter( "auth_{$object_type}_{$object_subtype}_meta_{$meta_key}", $args['auth_callback'] );
     1189                } else {
     1190                        remove_filter( "auth_{$object_type}_meta_{$meta_key}", $args['auth_callback'] );
     1191                }
    11501192        }
    11511193
    1152         unset( $wp_meta_keys[ $object_type ][ $meta_key ] );
     1194        unset( $wp_meta_keys[ $object_type ][ $object_subtype ][ $meta_key ] );
    11531195
    11541196        // Do some clean up
     1197        if ( empty( $wp_meta_keys[ $object_type ][ $object_subtype ] ) ) {
     1198                unset( $wp_meta_keys[ $object_type ][ $object_subtype ] );
     1199        }
    11551200        if ( empty( $wp_meta_keys[ $object_type ] ) ) {
    11561201                unset( $wp_meta_keys[ $object_type ] );
    11571202        }
     
    11631208 * Retrieves a list of registered meta keys for an object type.
    11641209 *
    11651210 * @since 4.6.0
     1211 * @since 5.0.0 The `$object_subtype` parameter was added.
    11661212 *
    1167  * @param string $object_type The type of object. Post, comment, user, term.
     1213 * @param string $object_type    The type of object. Post, comment, user, term.
     1214 * @param string $object_subtype Optional. The subtype of the object type.
    11681215 * @return array List of registered meta keys.
    11691216 */
    1170 function get_registered_meta_keys( $object_type ) {
     1217function get_registered_meta_keys( $object_type, $object_subtype = '' ) {
    11711218        global $wp_meta_keys;
    11721219
    1173         if ( ! is_array( $wp_meta_keys ) || ! isset( $wp_meta_keys[ $object_type ] ) ) {
     1220        if ( ! is_array( $wp_meta_keys ) || ! isset( $wp_meta_keys[ $object_type ] ) || ! isset( $wp_meta_keys[ $object_type ][ $object_subtype ] ) ) {
    11741221                return array();
    11751222        }
    11761223
    1177         return $wp_meta_keys[ $object_type ];
     1224        return $wp_meta_keys[ $object_type ][ $object_subtype ];
    11781225}
    11791226
    11801227/**
    11811228 * Retrieves registered metadata for a specified object.
    11821229 *
     1230 * The results include both meta that is registered specifically for the
     1231 * object's subtype and meta that is registered for the entire object type.
     1232 *
    11831233 * @since 4.6.0
    11841234 *
    11851235 * @param string $object_type Type of object to request metadata for. (e.g. comment, post, term, user)
     
    11871237 * @param string $meta_key    Optional. Registered metadata key. If not specified, retrieve all registered
    11881238 *                            metadata for the specified object.
    11891239 * @return mixed A single value or array of values for a key if specified. An array of all registered keys
    1190  *               and values for an object ID if not.
     1240 *               and values for an object ID if not. False if a given $meta_key is not registered.
    11911241 */
    11921242function get_registered_metadata( $object_type, $object_id, $meta_key = '' ) {
     1243        $object_subtype = get_object_subtype( $object_type, $object_id );
     1244
    11931245        if ( ! empty( $meta_key ) ) {
    1194                 if ( ! registered_meta_key_exists( $object_type, $meta_key ) ) {
     1246                if ( ! empty( $object_subtype ) && ! registered_meta_key_exists( $object_type, $meta_key, $object_subtype ) ) {
     1247                        $object_subtype = '';
     1248                }
     1249
     1250                if ( ! registered_meta_key_exists( $object_type, $meta_key, $object_subtype ) ) {
    11951251                        return false;
    11961252                }
    1197                 $meta_keys     = get_registered_meta_keys( $object_type );
     1253
     1254                $meta_keys     = get_registered_meta_keys( $object_type, $object_subtype );
    11981255                $meta_key_data = $meta_keys[ $meta_key ];
    11991256
    12001257                $data = get_metadata( $object_type, $object_id, $meta_key, $meta_key_data['single'] );
     
    12141271                }
    12151272        }
    12161273
     1274        if ( ! empty( $object_subtype ) ) {
     1275                $meta_keys = get_registered_meta_keys( $object_type, $object_subtype );
     1276
     1277                foreach ( $meta_keys as $k => $v ) {
     1278                        if ( isset( $data[ $k ] ) ) {
     1279                                $registered_data[ $k ] = $data[ $k ];
     1280                        }
     1281                }
     1282        }
     1283
    12171284        return $registered_data;
    12181285}
    12191286
     
    12421309
    12431310        return $args;
    12441311}
     1312
     1313/**
     1314 * Returns the object subtype for a given object ID of a specific type.
     1315 *
     1316 * @since 5.0.0
     1317 *
     1318 * @param string $object_type Type of object to request metadata for. (e.g. comment, post, term, user)
     1319 * @param int    $object_id   ID of the object to retrieve its subtype.
     1320 * @return string The object subtype or an empty string if unspecified subtype.
     1321 */
     1322function get_object_subtype( $object_type, $object_id ) {
     1323        $object_id = (int) $object_id;
     1324        $object_subtype = '';
     1325
     1326        switch ( $object_type ) {
     1327                case 'post':
     1328                        $post = get_post( $object_id );
     1329                        if ( ! $post ) {
     1330                                break;
     1331                        }
     1332
     1333                        $object_subtype = get_post_type( $post );
     1334                        break;
     1335
     1336                case 'comment':
     1337                        $comment = get_comment( $object_id );
     1338                        if ( ! $comment ) {
     1339                                break;
     1340                        }
     1341
     1342                        $object_subtype = 'comment';
     1343                        break;
     1344
     1345                case 'term':
     1346                        $term = get_term( $object_id );
     1347                        if ( ! $term instanceof WP_Term ) {
     1348                                break;
     1349                        }
     1350
     1351                        $object_subtype = $term->taxonomy;
     1352                        break;
     1353
     1354                case 'user':
     1355                        $user = get_user_by( 'id', $object_id );
     1356                        if ( ! $user ) {
     1357                                break;
     1358                        }
     1359
     1360                        $object_subtype = 'user';
     1361                        break;
     1362                default:
     1363
     1364                        /**
     1365                         * Filters the object subtype identifier for a non standard object type.
     1366                         *
     1367                         * The dynamic portion of the hook, `$object_type`, refers to the object
     1368                         * type (post, comment, term, or user).
     1369                         *
     1370                         * @since 5.0.0
     1371                         *
     1372                         * @param string $object_subtype Empty string to override.
     1373                         * @param int    $object_id      ID of the object to get the subtype for.
     1374                         */
     1375                        $object_subtype = apply_filters( "get_object_subtype_{$object_type}", $object_subtype, $object_id );
     1376        }
     1377
     1378        return $object_subtype;
     1379}
  • src/wp-includes/rest-api/fields/class-wp-rest-comment-meta-fields.php

     
    2828        }
    2929
    3030        /**
     31         * Retrieves the object meta subtype.
     32         *
     33         * @since 5.0.0
     34         *
     35         * @return string Subtype for the meta type, or empty string if no specific subtype.
     36         */
     37        protected function get_meta_subtype() {
     38                return 'comment';
     39        }
     40
     41        /**
    3142         * Retrieves the type for register_rest_field() in the context of comments.
    3243         *
    3344         * @since 4.7.0
  • src/wp-includes/rest-api/fields/class-wp-rest-meta-fields.php

     
    2525        abstract protected function get_meta_type();
    2626
    2727        /**
     28         * Retrieves the object meta subtype.
     29         *
     30         * @since 5.0.0
     31         *
     32         * @return string Subtype for the meta type, or empty string if no specific subtype.
     33         */
     34        protected function get_meta_subtype() {
     35                return '';
     36        }
     37
     38        /**
    2839         * Retrieves the object type for register_rest_field().
    2940         *
    3041         * @since 4.7.0
     
    340351        protected function get_registered_fields() {
    341352                $registered = array();
    342353
    343                 foreach ( get_registered_meta_keys( $this->get_meta_type() ) as $name => $args ) {
     354                $meta_type    = $this->get_meta_type();
     355                $meta_subtype = $this->get_meta_subtype();
     356
     357                $meta_keys = get_registered_meta_keys( $meta_type );
     358                if ( ! empty( $meta_subtype ) ) {
     359                        $meta_keys = array_merge( $meta_keys, get_registered_meta_keys( $meta_type, $meta_subtype ) );
     360                }
     361
     362                foreach ( $meta_keys as $name => $args ) {
    344363                        if ( empty( $args['show_in_rest'] ) ) {
    345364                                continue;
    346365                        }
  • src/wp-includes/rest-api/fields/class-wp-rest-post-meta-fields.php

     
    4747        }
    4848
    4949        /**
     50         * Retrieves the object meta subtype.
     51         *
     52         * @since 5.0.0
     53         *
     54         * @return string Subtype for the meta type, or empty string if no specific subtype.
     55         */
     56        protected function get_meta_subtype() {
     57                return $this->post_type;
     58        }
     59
     60        /**
    5061         * Retrieves the type for register_rest_field().
    5162         *
    5263         * @since 4.7.0
  • src/wp-includes/rest-api/fields/class-wp-rest-term-meta-fields.php

     
    4747        }
    4848
    4949        /**
     50         * Retrieves the object meta subtype.
     51         *
     52         * @since 5.0.0
     53         *
     54         * @return string Subtype for the meta type, or empty string if no specific subtype.
     55         */
     56        protected function get_meta_subtype() {
     57                return $this->taxonomy;
     58        }
     59
     60        /**
    5061         * Retrieves the type for register_rest_field().
    5162         *
    5263         * @since 4.7.0
  • src/wp-includes/rest-api/fields/class-wp-rest-user-meta-fields.php

     
    2828        }
    2929
    3030        /**
     31         * Retrieves the object meta subtype.
     32         *
     33         * @since 5.0.0
     34         *
     35         * @return string Subtype for the meta type, or empty string if no specific subtype.
     36         */
     37        protected function get_meta_subtype() {
     38                return 'user';
     39        }
     40
     41        /**
    3142         * Retrieves the type for register_rest_field().
    3243         *
    3344         * @since 4.7.0
  • tests/phpunit/tests/meta/registerMeta.php

     
    7474
    7575                $expected = array(
    7676                        'post' => array(
    77                                 'flight_number' => array(
    78                                         'type'              => 'string',
    79                                         'description'       => '',
    80                                         'single'            => false,
    81                                         'sanitize_callback' => null,
    82                                         'auth_callback'     => '__return_true',
    83                                         'show_in_rest'      => false,
     77                                '' => array(
     78                                        'flight_number' => array(
     79                                                'type'              => 'string',
     80                                                'description'       => '',
     81                                                'single'            => false,
     82                                                'sanitize_callback' => null,
     83                                                'auth_callback'     => '__return_true',
     84                                                'show_in_rest'      => false,
     85                                        ),
    8486                                ),
    8587                        ),
    8688                );
     
    9698
    9799                $expected = array(
    98100                        'term' => array(
    99                                 'category_icon' => array(
    100                                         'type'              => 'string',
    101                                         'description'       => '',
    102                                         'single'            => false,
    103                                         'sanitize_callback' => null,
    104                                         'auth_callback'     => '__return_true',
    105                                         'show_in_rest'      => false,
     101                                '' => array(
     102                                        'category_icon' => array(
     103                                                'type'              => 'string',
     104                                                'description'       => '',
     105                                                'single'            => false,
     106                                                'sanitize_callback' => null,
     107                                                'auth_callback'     => '__return_true',
     108                                                'show_in_rest'      => false,
     109                                        ),
    106110                                ),
    107111                        ),
    108112                );
     
    148152
    149153                $expected = array(
    150154                        'post' => array(
    151                                 'flight_number' => array(
    152                                         'type'              => 'string',
    153                                         'description'       => '',
    154                                         'single'            => false,
    155                                         'sanitize_callback' => array( $this, '_new_sanitize_meta_cb' ),
    156                                         'auth_callback'     => '__return_true',
    157                                         'show_in_rest'      => false,
     155                                '' => array(
     156                                        'flight_number' => array(
     157                                                'type'              => 'string',
     158                                                'description'       => '',
     159                                                'single'            => false,
     160                                                'sanitize_callback' => array( $this, '_new_sanitize_meta_cb' ),
     161                                                'auth_callback'     => '__return_true',
     162                                                'show_in_rest'      => false,
     163                                        ),
    158164                                ),
    159165                        ),
    160166                );