WordPress.org

Make WordPress Core

Ticket #38323: 38323.6.diff

File 38323.6.diff, 35.0 KB (added by flixos90, 16 months 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                                         }
     266                        $object_subtype = get_object_subtype( $object_type, $object_id );
    299267
    300                                         $sub_type = 'user';
    301                                         break;
    302                         }
    303 
    304                         if ( empty( $sub_type ) ) {
     268                        if ( empty( $object_subtype ) ) {
    305269                                $caps[] = 'do_not_allow';
    306270                                break;
    307271                        }
     
    310274
    311275                        $meta_key = isset( $args[1] ) ? $args[1] : false;
    312276
    313                         $has_filter = has_filter( "auth_{$object_type}_meta_{$meta_key}" ) || has_filter( "auth_{$object_type}_{$sub_type}_meta_{$meta_key}" );
    314                         if ( $meta_key && $has_filter ) {
     277                        if ( $meta_key ) {
     278                                $allowed = ! is_protected_meta( $meta_key, $object_type );
     279
     280                                if ( ! empty( $object_subtype ) && has_filter( "auth_{$object_type}_meta_{$meta_key}_for_{$object_subtype}" ) ) {
     281
     282                                        /**
     283                                         * Filters whether the user is allowed to edit a specific meta key of a specific object type and subtype.
     284                                         *
     285                                         * The dynamic portions of the hook name, `$object_type`, `$meta_key`,
     286                                         * and `$object_subtype`, refer to the metadata object type (comment, post, term or user),
     287                                         * the meta key value, and the object subtype respectively.
     288                                         *
     289                                         * @since 5.0.0
     290                                         *
     291                                         * @param bool     $allowed   Whether the user can add the object meta. Default false.
     292                                         * @param string   $meta_key  The meta key.
     293                                         * @param int      $object_id Object ID.
     294                                         * @param int      $user_id   User ID.
     295                                         * @param string   $cap       Capability name.
     296                                         * @param string[] $caps      Array of the user's capabilities.
     297                                         */
     298                                        $meta_value = apply_filters( "auth_{$object_type}_meta_{$meta_key}_for_{$object_subtype}", $allowed, $meta_key, $object_id, $user_id, $cap, $caps );
     299                                } else {
     300
     301                                        /**
     302                                         * Filters whether the user is allowed to edit a specific meta key of a specific object type.
     303                                         *
     304                                         * Return true to have the mapped meta caps from `edit_{$object_type}` apply.
     305                                         *
     306                                         * The dynamic portion of the hook name, `$object_type` refers to the object type being filtered.
     307                                         * The dynamic portion of the hook name, `$meta_key`, refers to the meta key passed to map_meta_cap().
     308                                         *
     309                                         * @since 3.3.0 As `auth_post_meta_{$meta_key}`.
     310                                         * @since 4.6.0
     311                                         *
     312                                         * @param bool     $allowed   Whether the user can add the object meta. Default false.
     313                                         * @param string   $meta_key  The meta key.
     314                                         * @param int      $object_id Object ID.
     315                                         * @param int      $user_id   User ID.
     316                                         * @param string   $cap       Capability name.
     317                                         * @param string[] $caps      Array of the user's capabilities.
     318                                         */
     319                                        $allowed = apply_filters( "auth_{$object_type}_meta_{$meta_key}", $allowed, $meta_key, $object_id, $user_id, $cap, $caps );
     320                                }
     321
     322                                if ( ! empty( $object_subtype ) ) {
    315323
    316                                 /**
    317                                  * Filters whether the user is allowed to edit meta for specific object types.
    318                                  *
    319                                  * Return true to have the mapped meta caps from `edit_{$object_type}` apply.
    320                                  *
    321                                  * The dynamic portion of the hook name, `$object_type` refers to the object type being filtered.
    322                                  * The dynamic portion of the hook name, `$meta_key`, refers to the meta key passed to map_meta_cap().
    323                                  *
    324                                  * @since 3.3.0 As `auth_post_meta_{$meta_key}`.
    325                                  * @since 4.6.0
    326                                  *
    327                                  * @param bool     $allowed   Whether the user can add the object meta. Default false.
    328                                  * @param string   $meta_key  The meta key.
    329                                  * @param int      $object_id Object ID.
    330                                  * @param int      $user_id   User ID.
    331                                  * @param string   $cap       Capability name.
    332                                  * @param string[] $caps      Array of the user's capabilities.
    333                                  */
    334                                 $allowed = apply_filters( "auth_{$object_type}_meta_{$meta_key}", false, $meta_key, $object_id, $user_id, $cap, $caps );
    335 
    336                                 /**
    337                                  * Filters whether the user is allowed to edit meta for specific object types/subtypes.
    338                                  *
    339                                  * Return true to have the mapped meta caps from `edit_{$object_type}` apply.
    340                                  *
    341                                  * The dynamic portion of the hook name, `$object_type` refers to the object type being filtered.
    342                                  * The dynamic portion of the hook name, `$sub_type` refers to the object subtype being filtered.
    343                                  * The dynamic portion of the hook name, `$meta_key`, refers to the meta key passed to map_meta_cap().
    344                                  *
    345                                  * @since 4.6.0 As `auth_post_{$post_type}_meta_{$meta_key}`.
    346                                  * @since 4.7.0
    347                                  *
    348                                  * @param bool     $allowed   Whether the user can add the object meta. Default false.
    349                                  * @param string   $meta_key  The meta key.
    350                                  * @param int      $object_id Object ID.
    351                                  * @param int      $user_id   User ID.
    352                                  * @param string   $cap       Capability name.
    353                                  * @param string[] $caps      Array of the user's capabilities.
    354                                  */
    355                                 $allowed = apply_filters( "auth_{$object_type}_{$sub_type}_meta_{$meta_key}", $allowed, $meta_key, $object_id, $user_id, $cap, $caps );
     324                                        /**
     325                                         * Filters whether the user is allowed to edit meta for specific object types/subtypes.
     326                                         *
     327                                         * Return true to have the mapped meta caps from `edit_{$object_type}` apply.
     328                                         *
     329                                         * The dynamic portion of the hook name, `$object_type` refers to the object type being filtered.
     330                                         * The dynamic portion of the hook name, `$object_subtype` refers to the object subtype being filtered.
     331                                         * The dynamic portion of the hook name, `$meta_key`, refers to the meta key passed to map_meta_cap().
     332                                         *
     333                                         * @since 4.6.0 As `auth_post_{$post_type}_meta_{$meta_key}`.
     334                                         * @since 4.7.0
     335                                         * @deprecated 5.0.0 Use `auth_{$object_type}_meta_{$meta_key}_for_{$object_subtype}`
     336                                         *
     337                                         * @param bool     $allowed   Whether the user can add the object meta. Default false.
     338                                         * @param string   $meta_key  The meta key.
     339                                         * @param int      $object_id Object ID.
     340                                         * @param int      $user_id   User ID.
     341                                         * @param string   $cap       Capability name.
     342                                         * @param string[] $caps      Array of the user's capabilities.
     343                                         */
     344                                        $allowed = apply_filters_deprecated( "auth_{$object_type}_{$object_subtype}_meta_{$meta_key}", array( $allowed, $meta_key, $object_id, $user_id, $cap, $caps ), '5.0.0', "auth_{$object_type}_meta_{$meta_key}_for_{$object_subtype}" );
     345                                }
    356346
    357347                                if ( ! $allowed ) {
    358348                                        $caps[] = $cap;
    359349                                }
    360                         } elseif ( $meta_key && is_protected_meta( $meta_key, $object_type ) ) {
    361                                 $caps[] = $cap;
    362350                        }
    363351                        break;
    364352                case 'edit_comment':
  • src/wp-includes/comment.php

     
    513513}
    514514
    515515/**
     516 * Registers a meta key for comments.
     517 *
     518 * @since 5.0.0
     519 *
     520 * @param string $comment_type Comment type to register a meta key for. Pass an empty string
     521 *                             to register the meta key across all existing comment types.
     522 * @param string $meta_key     The meta key to register.
     523 * @param array  $args         Data used to describe the meta key when registered. See
     524 *                             {@see register_meta()} for a list of supported arguments.
     525 * @return bool True if the meta key was successfully registered, false if not.
     526 */
     527function register_comment_meta( $comment_type, $meta_key, array $args ) {
     528        $args['object_subtype'] = $comment_type;
     529
     530        return register_meta( 'comment', $meta_key, $args );
     531}
     532
     533/**
     534 * Unregisters a meta key for comments.
     535 *
     536 * @since 5.0.0
     537 *
     538 * @param string $comment_type Comment type the meta key is currently registered for. Pass
     539 *                             an empty string if the meta key is registered across all
     540 *                             existing comment types.
     541 * @param string $meta_key     The meta key to unregister.
     542 * @return bool True on success, false if the meta key was not previously registered.
     543 */
     544function unregister_comment_meta( $comment_type, $meta_key ) {
     545        return unregister_meta_key( 'comment', $meta_key, $comment_type );
     546}
     547
     548/**
    516549 * Queues comments for metadata lazy-loading.
    517550 *
    518551 * @since 4.5.0
  • 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 ) && has_filter( "sanitize_{$object_type}_meta_{$meta_key}_for_{$object_subtype}" ) ) {
     987
     988                /**
     989                 * Filters the sanitization of a specific meta key of a specific meta type and subtype.
     990                 *
     991                 * The dynamic portions of the hook name, `$object_type`, `$meta_key`,
     992                 * and `$object_subtype`, refer to the metadata object type (comment, post, term or user),
     993                 * the meta key value, and the object subtype respectively.
     994                 *
     995                 * @since 5.0.0
     996                 *
     997                 * @param mixed  $meta_value     Meta value to sanitize.
     998                 * @param string $meta_key       Meta key.
     999                 * @param string $object_type    Object type.
     1000                 * @param string $object_subtype Object subtype.
     1001                 */
     1002                return apply_filters( "sanitize_{$object_type}_meta_{$meta_key}_for_{$object_subtype}", $meta_value, $meta_key, $object_type, $object_subtype );
     1003        }
     1004
    9791005        /**
    9801006         * Filters the sanitization of a specific meta key of a specific meta type.
    9811007         *
     
    9951021/**
    9961022 * Registers a meta key.
    9971023 *
     1024 * It is recommended to register meta keys for a specific combination of object type and object subtype. If passing
     1025 * an object subtype is omitted, the meta key will be registered for the entire object type, however it can be partly
     1026 * overridden in case a more specific meta key of the same name exists for the same object type and a subtype.
     1027 *
     1028 * If an object type does not support any subtypes, such as users or comments, you should commonly call this function
     1029 * without passing a subtype.
     1030 *
    9981031 * @since 3.3.0
    9991032 * @since 4.6.0 {@link https://core.trac.wordpress.org/ticket/35658 Modified
    10001033 *              to support an array of data to attach to registered meta keys}. Previous arguments for
    10011034 *              `$sanitize_callback` and `$auth_callback` have been folded into this array.
     1035 * @since 5.0.0 The `$object_subtype` argument was added to the arguments array.
    10021036 *
    10031037 * @param string $object_type    Type of object this meta is registered to.
    10041038 * @param string $meta_key       Meta key to register.
    10051039 * @param array  $args {
    10061040 *     Data used to describe the meta key when registered.
    10071041 *
     1042 *     @type string $object_subtype    A subtype; e.g. if the object type is "post", the post type. If left empty,
     1043 *                                     the meta key will be registered on the entire object type. Default empty.
    10081044 *     @type string $type              The type of data associated with this meta key.
    10091045 *                                     Valid values are 'string', 'boolean', 'integer', and 'number'.
    10101046 *     @type string $description       A description of the data attached to this meta key.
     
    10271063        }
    10281064
    10291065        $defaults = array(
     1066                'object_subtype'    => '',
    10301067                'type'              => 'string',
    10311068                'description'       => '',
    10321069                'single'            => false,
     
    10671104        $args = apply_filters( 'register_meta_args', $args, $defaults, $object_type, $meta_key );
    10681105        $args = wp_parse_args( $args, $defaults );
    10691106
     1107        $object_subtype = ! empty( $args['object_subtype'] ) ? $args['object_subtype'] : '';
     1108
    10701109        // If `auth_callback` is not provided, fall back to `is_protected_meta()`.
    10711110        if ( empty( $args['auth_callback'] ) ) {
    10721111                if ( is_protected_meta( $meta_key, $object_type ) ) {
     
    10781117
    10791118        // Back-compat: old sanitize and auth callbacks are applied to all of an object type.
    10801119        if ( is_callable( $args['sanitize_callback'] ) ) {
    1081                 add_filter( "sanitize_{$object_type}_meta_{$meta_key}", $args['sanitize_callback'], 10, 3 );
     1120                if ( ! empty( $object_subtype ) ) {
     1121                        add_filter( "sanitize_{$object_type}_meta_{$meta_key}_for_{$object_subtype}", $args['sanitize_callback'], 10, 4 );
     1122                } else {
     1123                        add_filter( "sanitize_{$object_type}_meta_{$meta_key}", $args['sanitize_callback'], 10, 3 );
     1124                }
    10821125        }
    10831126
    10841127        if ( is_callable( $args['auth_callback'] ) ) {
    1085                 add_filter( "auth_{$object_type}_meta_{$meta_key}", $args['auth_callback'], 10, 6 );
     1128                if ( ! empty( $object_subtype ) ) {
     1129                        add_filter( "auth_{$object_type}_meta_{$meta_key}_for_{$object_subtype}", $args['auth_callback'], 10, 6 );
     1130                } else {
     1131                        add_filter( "auth_{$object_type}_meta_{$meta_key}", $args['auth_callback'], 10, 6 );
     1132                }
    10861133        }
    10871134
    10881135        // Global registry only contains meta keys registered with the array of arguments added in 4.6.0.
    10891136        if ( ! $has_old_auth_cb && ! $has_old_sanitize_cb ) {
    1090                 $wp_meta_keys[ $object_type ][ $meta_key ] = $args;
     1137                unset( $args['object_subtype'] );
     1138
     1139                $wp_meta_keys[ $object_type ][ $object_subtype ][ $meta_key ] = $args;
    10911140
    10921141                return true;
    10931142        }
     
    10991148 * Checks if a meta key is registered.
    11001149 *
    11011150 * @since 4.6.0
     1151 * @since 5.0.0 The `$object_subtype` parameter was added.
    11021152 *
    11031153 * @param string $object_type    The type of object.
    11041154 * @param string $meta_key       The meta key.
     1155 * @param string $object_subtype Optional. The subtype of the object type.
    11051156 *
    1106  * @return bool True if the meta key is registered to the object type. False if not.
     1157 * @return bool True if the meta key is registered to the object type and, if provided,
     1158 *              the object subtype. False if not.
    11071159 */
    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         }
     1160function registered_meta_key_exists( $object_type, $meta_key, $object_subtype = '' ) {
     1161        $meta_keys = get_registered_meta_keys( $object_type, $object_subtype );
    11181162
    1119         if ( isset( $wp_meta_keys[ $object_type ][ $meta_key ] ) ) {
    1120                 return true;
    1121         }
    1122 
    1123         return false;
     1163        return isset( $meta_keys[ $meta_key ] );
    11241164}
    11251165
    11261166/**
    11271167 * Unregisters a meta key from the list of registered keys.
    11281168 *
    11291169 * @since 4.6.0
     1170 * @since 5.0.0 The `$object_subtype` parameter was added.
    11301171 *
    1131  * @param string $object_type The type of object.
    1132  * @param string $meta_key    The meta key.
     1172 * @param string $object_type    The type of object.
     1173 * @param string $meta_key       The meta key.
     1174 * @param string $object_subtype Optional. The subtype of the object type.
    11331175 * @return bool True if successful. False if the meta key was not registered.
    11341176 */
    1135 function unregister_meta_key( $object_type, $meta_key ) {
     1177function unregister_meta_key( $object_type, $meta_key, $object_subtype = '' ) {
    11361178        global $wp_meta_keys;
    11371179
    1138         if ( ! registered_meta_key_exists( $object_type, $meta_key ) ) {
     1180        if ( ! registered_meta_key_exists( $object_type, $meta_key, $object_subtype ) ) {
    11391181                return false;
    11401182        }
    11411183
    1142         $args = $wp_meta_keys[ $object_type ][ $meta_key ];
     1184        $args = $wp_meta_keys[ $object_type ][ $object_subtype ][ $meta_key ];
    11431185
    11441186        if ( isset( $args['sanitize_callback'] ) && is_callable( $args['sanitize_callback'] ) ) {
    1145                 remove_filter( "sanitize_{$object_type}_meta_{$meta_key}", $args['sanitize_callback'] );
     1187                if ( ! empty( $object_subtype ) ) {
     1188                        remove_filter( "sanitize_{$object_type}_meta_{$meta_key}_for_{$object_subtype}", $args['sanitize_callback'] );
     1189                } else {
     1190                        remove_filter( "sanitize_{$object_type}_meta_{$meta_key}", $args['sanitize_callback'] );
     1191                }
    11461192        }
    11471193
    11481194        if ( isset( $args['auth_callback'] ) && is_callable( $args['auth_callback'] ) ) {
    1149                 remove_filter( "auth_{$object_type}_meta_{$meta_key}", $args['auth_callback'] );
     1195                if ( ! empty( $object_subtype ) ) {
     1196                        remove_filter( "auth_{$object_type}_meta_{$meta_key}_for_{$object_subtype}", $args['auth_callback'] );
     1197                } else {
     1198                        remove_filter( "auth_{$object_type}_meta_{$meta_key}", $args['auth_callback'] );
     1199                }
    11501200        }
    11511201
    1152         unset( $wp_meta_keys[ $object_type ][ $meta_key ] );
     1202        unset( $wp_meta_keys[ $object_type ][ $object_subtype ][ $meta_key ] );
    11531203
    11541204        // Do some clean up
     1205        if ( empty( $wp_meta_keys[ $object_type ][ $object_subtype ] ) ) {
     1206                unset( $wp_meta_keys[ $object_type ][ $object_subtype ] );
     1207        }
    11551208        if ( empty( $wp_meta_keys[ $object_type ] ) ) {
    11561209                unset( $wp_meta_keys[ $object_type ] );
    11571210        }
     
    11631216 * Retrieves a list of registered meta keys for an object type.
    11641217 *
    11651218 * @since 4.6.0
     1219 * @since 5.0.0 The `$object_subtype` parameter was added.
    11661220 *
    1167  * @param string $object_type The type of object. Post, comment, user, term.
     1221 * @param string $object_type    The type of object. Post, comment, user, term.
     1222 * @param string $object_subtype Optional. The subtype of the object type.
    11681223 * @return array List of registered meta keys.
    11691224 */
    1170 function get_registered_meta_keys( $object_type ) {
     1225function get_registered_meta_keys( $object_type, $object_subtype = '' ) {
    11711226        global $wp_meta_keys;
    11721227
    1173         if ( ! is_array( $wp_meta_keys ) || ! isset( $wp_meta_keys[ $object_type ] ) ) {
     1228        if ( ! is_array( $wp_meta_keys ) || ! isset( $wp_meta_keys[ $object_type ] ) || ! isset( $wp_meta_keys[ $object_type ][ $object_subtype ] ) ) {
    11741229                return array();
    11751230        }
    11761231
    1177         return $wp_meta_keys[ $object_type ];
     1232        return $wp_meta_keys[ $object_type ][ $object_subtype ];
    11781233}
    11791234
    11801235/**
    11811236 * Retrieves registered metadata for a specified object.
    11821237 *
     1238 * The results include both meta that is registered specifically for the
     1239 * object's subtype and meta that is registered for the entire object type.
     1240 *
    11831241 * @since 4.6.0
    11841242 *
    11851243 * @param string $object_type Type of object to request metadata for. (e.g. comment, post, term, user)
     
    11871245 * @param string $meta_key    Optional. Registered metadata key. If not specified, retrieve all registered
    11881246 *                            metadata for the specified object.
    11891247 * @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.
     1248 *               and values for an object ID if not. False if a given $meta_key is not registered.
    11911249 */
    11921250function get_registered_metadata( $object_type, $object_id, $meta_key = '' ) {
     1251        $object_subtype = get_object_subtype( $object_type, $object_id );
     1252
    11931253        if ( ! empty( $meta_key ) ) {
    1194                 if ( ! registered_meta_key_exists( $object_type, $meta_key ) ) {
     1254                if ( ! empty( $object_subtype ) && ! registered_meta_key_exists( $object_type, $meta_key, $object_subtype ) ) {
     1255                        $object_subtype = '';
     1256                }
     1257
     1258                if ( ! registered_meta_key_exists( $object_type, $meta_key, $object_subtype ) ) {
    11951259                        return false;
    11961260                }
    1197                 $meta_keys     = get_registered_meta_keys( $object_type );
     1261
     1262                $meta_keys     = get_registered_meta_keys( $object_type, $object_subtype );
    11981263                $meta_key_data = $meta_keys[ $meta_key ];
    11991264
    12001265                $data = get_metadata( $object_type, $object_id, $meta_key, $meta_key_data['single'] );
     
    12031268        }
    12041269
    12051270        $data = get_metadata( $object_type, $object_id );
     1271        if ( ! $data ) {
     1272                return array();
     1273        }
    12061274
    1207         $meta_keys       = get_registered_meta_keys( $object_type );
    1208         $registered_data = array();
    1209 
    1210         // Someday, array_filter()
    1211         foreach ( $meta_keys as $k => $v ) {
    1212                 if ( isset( $data[ $k ] ) ) {
    1213                         $registered_data[ $k ] = $data[ $k ];
    1214                 }
     1275        $meta_keys = get_registered_meta_keys( $object_type );
     1276        if ( ! empty( $object_subtype ) ) {
     1277                $meta_keys = array_merge( $meta_keys, get_registered_meta_keys( $object_type, $object_subtype ) );
    12151278        }
    12161279
    1217         return $registered_data;
     1280        return array_intersect_key( $data, $meta_keys );
    12181281}
    12191282
    12201283/**
     
    12231286 * to be explicitly turned off is a warranty seal of sorts.
    12241287 *
    12251288 * @access private
    1226  * @since  4.6.0
     1289 * @since 4.6.0
    12271290 *
    1228  * @param  array $args         Arguments from `register_meta()`.
    1229  * @param  array $default_args Default arguments for `register_meta()`.
     1291 * @param array $args         Arguments from `register_meta()`.
     1292 * @param array $default_args Default arguments for `register_meta()`.
    12301293 *
    12311294 * @return array Filtered arguments.
    12321295 */
    12331296function _wp_register_meta_args_whitelist( $args, $default_args ) {
    1234         $whitelist = array_keys( $default_args );
     1297        return array_intersect_key( $args, $default_args );
     1298}
    12351299
    1236         // In an anonymous function world, this would be better as an array_filter()
    1237         foreach ( $args as $key => $value ) {
    1238                 if ( ! in_array( $key, $whitelist ) ) {
    1239                         unset( $args[ $key ] );
    1240                 }
     1300/**
     1301 * Returns the object subtype for a given object ID of a specific type.
     1302 *
     1303 * @since 5.0.0
     1304 *
     1305 * @param string $object_type Type of object to request metadata for. (e.g. comment, post, term, user)
     1306 * @param int    $object_id   ID of the object to retrieve its subtype.
     1307 * @return string The object subtype or an empty string if unspecified subtype.
     1308 */
     1309function get_object_subtype( $object_type, $object_id ) {
     1310        $object_id      = (int) $object_id;
     1311        $object_subtype = '';
     1312
     1313        switch ( $object_type ) {
     1314                case 'post':
     1315                        $post = get_post( $object_id );
     1316                        if ( ! $post ) {
     1317                                break;
     1318                        }
     1319
     1320                        $object_subtype = get_post_type( $post );
     1321                        break;
     1322
     1323                case 'comment':
     1324                        $comment = get_comment( $object_id );
     1325                        if ( ! $comment ) {
     1326                                break;
     1327                        }
     1328
     1329                        $object_subtype = 'comment';
     1330                        break;
     1331
     1332                case 'term':
     1333                        $term = get_term( $object_id );
     1334                        if ( ! $term instanceof WP_Term ) {
     1335                                break;
     1336                        }
     1337
     1338                        $object_subtype = $term->taxonomy;
     1339                        break;
     1340
     1341                case 'user':
     1342                        $user = get_user_by( 'id', $object_id );
     1343                        if ( ! $user ) {
     1344                                break;
     1345                        }
     1346
     1347                        $object_subtype = 'user';
     1348                        break;
     1349                default:
     1350
     1351                        /**
     1352                         * Filters the object subtype identifier for a non standard object type.
     1353                         *
     1354                         * The dynamic portion of the hook, `$object_type`, refers to the object
     1355                         * type (post, comment, term, or user).
     1356                         *
     1357                         * @since 5.0.0
     1358                         *
     1359                         * @param string $object_subtype Empty string to override.
     1360                         * @param int    $object_id      ID of the object to get the subtype for.
     1361                         */
     1362                        $object_subtype = apply_filters( "get_object_subtype_{$object_type}", $object_subtype, $object_id );
    12411363        }
    12421364
    1243         return $args;
     1365        return $object_subtype;
    12441366}
  • src/wp-includes/post.php

     
    19901990}
    19911991
    19921992/**
     1993 * Registers a meta key for posts.
     1994 *
     1995 * @since 5.0.0
     1996 *
     1997 * @param string $post_type Post type to register a meta key for. Pass an empty string
     1998 *                          to register the meta key across all existing post types.
     1999 * @param string $meta_key  The meta key to register.
     2000 * @param array  $args      Data used to describe the meta key when registered. See
     2001 *                          {@see register_meta()} for a list of supported arguments.
     2002 * @return bool True if the meta key was successfully registered, false if not.
     2003 */
     2004function register_post_meta( $post_type, $meta_key, array $args ) {
     2005        $args['object_subtype'] = $post_type;
     2006
     2007        return register_meta( 'post', $meta_key, $args );
     2008}
     2009
     2010/**
     2011 * Unregisters a meta key for posts.
     2012 *
     2013 * @since 5.0.0
     2014 *
     2015 * @param string $post_type Post type the meta key is currently registered for. Pass
     2016 *                          an empty string if the meta key is registered across all
     2017 *                          existing post types.
     2018 * @param string $meta_key  The meta key to unregister.
     2019 * @return bool True on success, false if the meta key was not previously registered.
     2020 */
     2021function unregister_post_meta( $post_type, $meta_key ) {
     2022        return unregister_meta_key( 'post', $meta_key, $post_type );
     2023}
     2024
     2025/**
    19932026 * Retrieve post meta fields, based on post ID.
    19942027 *
    19952028 * The post meta fields are retrieved from the cache where possible,
  • 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
  • src/wp-includes/taxonomy.php

     
    13231323}
    13241324
    13251325/**
     1326 * Registers a meta key for terms.
     1327 *
     1328 * @since 5.0.0
     1329 *
     1330 * @param string $taxonomy Taxonomy to register a meta key for. Pass an empty string
     1331 *                         to register the meta key across all existing taxonomies.
     1332 * @param string $meta_key The meta key to register.
     1333 * @param array  $args     Data used to describe the meta key when registered. See
     1334 *                         {@see register_meta()} for a list of supported arguments.
     1335 * @return bool True if the meta key was successfully registered, false if not.
     1336 */
     1337function register_term_meta( $taxonomy, $meta_key, array $args ) {
     1338        $args['object_subtype'] = $taxonomy;
     1339
     1340        return register_meta( 'term', $meta_key, $args );
     1341}
     1342
     1343/**
     1344 * Unregisters a meta key for terms.
     1345 *
     1346 * @since 5.0.0
     1347 *
     1348 * @param string $taxonomy Taxonomy the meta key is currently registered for. Pass
     1349 *                         an empty string if the meta key is registered across all
     1350 *                         existing taxonomies.
     1351 * @param string $meta_key The meta key to unregister.
     1352 * @return bool True on success, false if the meta key was not previously registered.
     1353 */
     1354function unregister_term_meta( $taxonomy, $meta_key ) {
     1355        return unregister_meta_key( 'term', $meta_key, $taxonomy );
     1356}
     1357
     1358/**
    13261359 * Determines whether a term exists.
    13271360 *
    13281361 * Formerly is_term(), introduced in 2.3.0.
  • src/wp-includes/user.php

     
    857857}
    858858
    859859/**
     860 * Registers a meta key for users.
     861 *
     862 * @since 5.0.0
     863 *
     864 * @param string $user_type User type to register a meta key for. Pass an empty string
     865 *                          to register the meta key across all existing user types.
     866 * @param string $meta_key  The meta key to register.
     867 * @param array  $args      Data used to describe the meta key when registered. See
     868 *                          {@see register_meta()} for a list of supported arguments.
     869 * @return bool True if the meta key was successfully registered, false if not.
     870 */
     871function register_user_meta( $user_type, $meta_key, array $args ) {
     872        $args['object_subtype'] = $user_type;
     873
     874        return register_meta( 'user', $meta_key, $args );
     875}
     876
     877/**
     878 * Unregisters a meta key for users.
     879 *
     880 * @since 5.0.0
     881 *
     882 * @param string $user_type User type the meta key is currently registered for. Pass
     883 *                          an empty string if the meta key is registered across all
     884 *                          existing user types.
     885 * @param string $meta_key  The meta key to unregister.
     886 * @return bool True on success, false if the meta key was not previously registered.
     887 */
     888function unregister_user_meta( $user_type, $meta_key ) {
     889        return unregister_meta_key( 'user', $meta_key, $user_type );
     890}
     891
     892/**
    860893 * Count number of users who have each of the user roles.
    861894 *
    862895 * Assumes there are neither duplicated nor orphaned capabilities meta_values.
  • 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                );