WordPress.org

Make WordPress Core

Ticket #38323: 38323.10.diff

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

     
    281281                        list( $_, $object_type, $_ ) = explode( '_', $cap );
    282282                        $object_id                   = (int) $args[0];
    283283
    284                         switch ( $object_type ) {
    285                                 case 'post':
    286                                         $post = get_post( $object_id );
    287                                         if ( ! $post ) {
    288                                                 break;
    289                                         }
    290 
    291                                         $sub_type = get_post_type( $post );
    292                                         break;
    293 
    294                                 case 'comment':
    295                                         $comment = get_comment( $object_id );
    296                                         if ( ! $comment ) {
    297                                                 break;
    298                                         }
    299 
    300                                         $sub_type = empty( $comment->comment_type ) ? 'comment' : $comment->comment_type;
    301                                         break;
    302 
    303                                 case 'term':
    304                                         $term = get_term( $object_id );
    305                                         if ( ! $term instanceof WP_Term ) {
    306                                                 break;
    307                                         }
    308 
    309                                         $sub_type = $term->taxonomy;
    310                                         break;
    311 
    312                                 case 'user':
    313                                         $user = get_user_by( 'id', $object_id );
    314                                         if ( ! $user ) {
    315                                                 break;
    316                                         }
     284                        $object_subtype = get_object_subtype( $object_type, $object_id );
    317285
    318                                         $sub_type = 'user';
    319                                         break;
    320                         }
    321 
    322                         if ( empty( $sub_type ) ) {
     286                        if ( empty( $object_subtype ) ) {
    323287                                $caps[] = 'do_not_allow';
    324288                                break;
    325289                        }
     
    328292
    329293                        $meta_key = isset( $args[1] ) ? $args[1] : false;
    330294
    331                         $has_filter = has_filter( "auth_{$object_type}_meta_{$meta_key}" ) || has_filter( "auth_{$object_type}_{$sub_type}_meta_{$meta_key}" );
    332                         if ( $meta_key && $has_filter ) {
     295                        if ( $meta_key ) {
     296                                $allowed = ! is_protected_meta( $meta_key, $object_type );
    333297
    334                                 /**
    335                                  * Filters whether the user is allowed to edit meta for specific object types.
    336                                  *
    337                                  * Return true to have the mapped meta caps from `edit_{$object_type}` apply.
    338                                  *
    339                                  * The dynamic portion of the hook name, `$object_type` refers to the object type being filtered.
    340                                  * The dynamic portion of the hook name, `$meta_key`, refers to the meta key passed to map_meta_cap().
    341                                  *
    342                                  * @since 3.3.0 As `auth_post_meta_{$meta_key}`.
    343                                  * @since 4.6.0
    344                                  *
    345                                  * @param bool     $allowed   Whether the user can add the object meta. Default false.
    346                                  * @param string   $meta_key  The meta key.
    347                                  * @param int      $object_id Object ID.
    348                                  * @param int      $user_id   User ID.
    349                                  * @param string   $cap       Capability name.
    350                                  * @param string[] $caps      Array of the user's capabilities.
    351                                  */
    352                                 $allowed = apply_filters( "auth_{$object_type}_meta_{$meta_key}", false, $meta_key, $object_id, $user_id, $cap, $caps );
    353 
    354                                 /**
    355                                  * Filters whether the user is allowed to edit meta for specific object types/subtypes.
    356                                  *
    357                                  * Return true to have the mapped meta caps from `edit_{$object_type}` apply.
    358                                  *
    359                                  * The dynamic portion of the hook name, `$object_type` refers to the object type being filtered.
    360                                  * The dynamic portion of the hook name, `$sub_type` refers to the object subtype being filtered.
    361                                  * The dynamic portion of the hook name, `$meta_key`, refers to the meta key passed to map_meta_cap().
    362                                  *
    363                                  * @since 4.6.0 As `auth_post_{$post_type}_meta_{$meta_key}`.
    364                                  * @since 4.7.0
    365                                  *
    366                                  * @param bool     $allowed   Whether the user can add the object meta. Default false.
    367                                  * @param string   $meta_key  The meta key.
    368                                  * @param int      $object_id Object ID.
    369                                  * @param int      $user_id   User ID.
    370                                  * @param string   $cap       Capability name.
    371                                  * @param string[] $caps      Array of the user's capabilities.
    372                                  */
    373                                 $allowed = apply_filters( "auth_{$object_type}_{$sub_type}_meta_{$meta_key}", $allowed, $meta_key, $object_id, $user_id, $cap, $caps );
     298                                if ( ! empty( $object_subtype ) && has_filter( "auth_{$object_type}_meta_{$meta_key}_for_{$object_subtype}" ) ) {
     299
     300                                        /**
     301                                         * Filters whether the user is allowed to edit a specific meta key of a specific object type and subtype.
     302                                         *
     303                                         * The dynamic portions of the hook name, `$object_type`, `$meta_key`,
     304                                         * and `$object_subtype`, refer to the metadata object type (comment, post, term or user),
     305                                         * the meta key value, and the object subtype respectively.
     306                                         *
     307                                         * @since 5.0.0
     308                                         *
     309                                         * @param bool     $allowed   Whether the user can add the object meta. Default false.
     310                                         * @param string   $meta_key  The meta key.
     311                                         * @param int      $object_id Object ID.
     312                                         * @param int      $user_id   User ID.
     313                                         * @param string   $cap       Capability name.
     314                                         * @param string[] $caps      Array of the user's capabilities.
     315                                         */
     316                                        $allowed = apply_filters( "auth_{$object_type}_meta_{$meta_key}_for_{$object_subtype}", $allowed, $meta_key, $object_id, $user_id, $cap, $caps );
     317                                } else {
     318
     319                                        /**
     320                                         * Filters whether the user is allowed to edit a specific meta key of a specific object type.
     321                                         *
     322                                         * Return true to have the mapped meta caps from `edit_{$object_type}` apply.
     323                                         *
     324                                         * The dynamic portion of the hook name, `$object_type` refers to the object type being filtered.
     325                                         * The dynamic portion of the hook name, `$meta_key`, refers to the meta key passed to map_meta_cap().
     326                                         *
     327                                         * @since 3.3.0 As `auth_post_meta_{$meta_key}`.
     328                                         * @since 4.6.0
     329                                         *
     330                                         * @param bool     $allowed   Whether the user can add the object meta. Default false.
     331                                         * @param string   $meta_key  The meta key.
     332                                         * @param int      $object_id Object ID.
     333                                         * @param int      $user_id   User ID.
     334                                         * @param string   $cap       Capability name.
     335                                         * @param string[] $caps      Array of the user's capabilities.
     336                                         */
     337                                        $allowed = apply_filters( "auth_{$object_type}_meta_{$meta_key}", $allowed, $meta_key, $object_id, $user_id, $cap, $caps );
     338                                }
     339
     340                                if ( ! empty( $object_subtype ) ) {
     341
     342                                        /**
     343                                         * Filters whether the user is allowed to edit meta for specific object types/subtypes.
     344                                         *
     345                                         * Return true to have the mapped meta caps from `edit_{$object_type}` apply.
     346                                         *
     347                                         * The dynamic portion of the hook name, `$object_type` refers to the object type being filtered.
     348                                         * The dynamic portion of the hook name, `$object_subtype` refers to the object subtype being filtered.
     349                                         * The dynamic portion of the hook name, `$meta_key`, refers to the meta key passed to map_meta_cap().
     350                                         *
     351                                         * @since 4.6.0 As `auth_post_{$post_type}_meta_{$meta_key}`.
     352                                         * @since 4.7.0
     353                                         * @deprecated 5.0.0 Use `auth_{$object_type}_meta_{$meta_key}_for_{$object_subtype}`
     354                                         *
     355                                         * @param bool     $allowed   Whether the user can add the object meta. Default false.
     356                                         * @param string   $meta_key  The meta key.
     357                                         * @param int      $object_id Object ID.
     358                                         * @param int      $user_id   User ID.
     359                                         * @param string   $cap       Capability name.
     360                                         * @param string[] $caps      Array of the user's capabilities.
     361                                         */
     362                                        $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}" );
     363                                }
    374364
    375365                                if ( ! $allowed ) {
    376366                                        $caps[] = $cap;
    377367                                }
    378                         } elseif ( $meta_key && is_protected_meta( $meta_key, $object_type ) ) {
    379                                 $caps[] = $cap;
    380368                        }
    381369                        break;
    382370                case 'edit_comment':
  • 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 'term':
     1324                        $term = get_term( $object_id );
     1325                        if ( ! $term instanceof WP_Term ) {
     1326                                break;
     1327                        }
     1328
     1329                        $object_subtype = $term->taxonomy;
     1330                        break;
     1331
     1332                case 'comment':
     1333                        $comment = get_comment( $object_id );
     1334                        if ( ! $comment ) {
     1335                                break;
     1336                        }
     1337
     1338                        $object_subtype = 'comment';
     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 'comment' There are no subtypes.
     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 'user' There are no subtypes.
     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.
  • tests/phpunit/tests/meta/registerMeta.php

     
    33 * @group meta
    44 */
    55class Tests_Meta_Register_Meta extends WP_UnitTestCase {
     6
    67        protected static $post_id;
     8        protected static $term_id;
     9        protected static $comment_id;
     10        protected static $user_id;
    711
    812        public static function wpSetUpBeforeClass( $factory ) {
    9                 self::$post_id = $factory->post->create();
     13                self::$post_id    = $factory->post->create( array( 'post_type' => 'page' ) );
     14                self::$term_id    = $factory->term->create( array( 'taxonomy' => 'category' ) );
     15                self::$comment_id = $factory->comment->create();
     16                self::$user_id    = $factory->user->create();
     17        }
     18
     19        public static function wpTearDownAfterClass() {
     20                wp_delete_post( self::$post_id, true );
     21                wp_delete_term( self::$term_id, 'category' );
     22                wp_delete_comment( self::$comment_id, true );
     23                self::delete_user( self::$user_id );
    1024        }
    1125
    1226        public function _old_sanitize_meta_cb( $meta_value, $meta_key, $meta_type ) {
     
    7488
    7589                $expected = array(
    7690                        '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,
     91                                '' => array(
     92                                        'flight_number' => array(
     93                                                'type'              => 'string',
     94                                                'description'       => '',
     95                                                'single'            => false,
     96                                                'sanitize_callback' => null,
     97                                                'auth_callback'     => '__return_true',
     98                                                'show_in_rest'      => false,
     99                                        ),
    84100                                ),
    85101                        ),
    86102                );
    87103
    88                 $this->assertEquals( $actual, $expected );
     104                $this->assertEquals( $expected, $actual );
    89105        }
    90106
    91107        public function test_register_meta_with_term_object_type_populates_wp_meta_keys() {
     
    96112
    97113                $expected = array(
    98114                        '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,
     115                                '' => array(
     116                                        'category_icon' => array(
     117                                                'type'              => 'string',
     118                                                'description'       => '',
     119                                                'single'            => false,
     120                                                'sanitize_callback' => null,
     121                                                'auth_callback'     => '__return_true',
     122                                                'show_in_rest'      => false,
     123                                        ),
    106124                                ),
    107125                        ),
    108126                );
    109127
    110                 $this->assertEquals( $actual, $expected );
     128                $this->assertEquals( $expected, $actual );
    111129        }
    112130
    113131        public function test_register_meta_with_deprecated_sanitize_callback_does_not_populate_wp_meta_keys() {
     
    148166
    149167                $expected = array(
    150168                        '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,
     169                                '' => array(
     170                                        'flight_number' => array(
     171                                                'type'              => 'string',
     172                                                'description'       => '',
     173                                                'single'            => false,
     174                                                'sanitize_callback' => array( $this, '_new_sanitize_meta_cb' ),
     175                                                'auth_callback'     => '__return_true',
     176                                                'show_in_rest'      => false,
     177                                        ),
    158178                                ),
    159179                        ),
    160180                );
     
    301321
    302322                $this->assertEmpty( $meta );
    303323        }
     324
     325        /**
     326         * @ticket 38323
     327         * @dataProvider data_get_types_and_subtypes
     328         */
     329        public function test_register_meta_with_subtype_populates_wp_meta_keys( $type, $subtype ) {
     330                global $wp_meta_keys;
     331
     332                register_meta( $type, 'flight_number', array( 'object_subtype' => $subtype ) );
     333
     334                $expected = array(
     335                        $type => array(
     336                                $subtype => array(
     337                                        'flight_number' => array(
     338                                                'type'              => 'string',
     339                                                'description'       => '',
     340                                                'single'            => false,
     341                                                'sanitize_callback' => null,
     342                                                'auth_callback'     => '__return_true',
     343                                                'show_in_rest'      => false,
     344                                        ),
     345                                ),
     346                        ),
     347                );
     348
     349                $actual = $wp_meta_keys;
     350
     351                // Reset global so subsequent data tests do not get polluted.
     352                $wp_meta_keys = array();
     353
     354                $this->assertEquals( $expected, $actual );
     355        }
     356
     357        /**
     358         * @ticket 38323
     359         * @dataProvider data_get_types_and_subtypes
     360         */
     361        public function test_unregister_meta_with_subtype_unpopulates_wp_meta_keys( $type, $subtype ) {
     362                global $wp_meta_keys;
     363
     364                register_meta( $type, 'flight_number', array( 'object_subtype' => $subtype ) );
     365                unregister_meta_key( $type, 'flight_number', $subtype );
     366
     367                $actual = $wp_meta_keys;
     368
     369                // Reset global so subsequent data tests do not get polluted.
     370                $wp_meta_keys = array();
     371
     372                $this->assertEmpty( $actual );
     373        }
     374
     375        /**
     376         * @ticket 38323
     377         * @dataProvider data_get_types_and_subtypes
     378         */
     379        public function test_unregister_meta_without_subtype_keeps_subtype_meta_key( $type, $subtype ) {
     380                global $wp_meta_keys;
     381
     382                register_meta( $type, 'flight_number', array( 'object_subtype' => $subtype ) );
     383
     384                // Unregister meta key without subtype.
     385                unregister_meta_key( $type, 'flight_number' );
     386
     387                $expected = array(
     388                        $type => array(
     389                                $subtype => array(
     390                                        'flight_number' => array(
     391                                                'type'              => 'string',
     392                                                'description'       => '',
     393                                                'single'            => false,
     394                                                'sanitize_callback' => null,
     395                                                'auth_callback'     => '__return_true',
     396                                                'show_in_rest'      => false,
     397                                        ),
     398                                ),
     399                        ),
     400                );
     401
     402                $actual = $wp_meta_keys;
     403
     404                // Reset global so subsequent data tests do not get polluted.
     405                $wp_meta_keys = array();
     406
     407                $this->assertEquals( $expected, $actual );
     408        }
     409
     410        /**
     411         * @ticket 38323
     412         * @dataProvider data_get_types_and_subtypes
     413         */
     414        public function test_get_registered_meta_keys_with_subtype( $type, $subtype ) {
     415                register_meta( $type, 'registered_key1', array( 'object_subtype' => $subtype ) );
     416                register_meta( $type, 'registered_key2', array( 'object_subtype' => $subtype ) );
     417
     418                $meta_keys = get_registered_meta_keys( $type, $subtype );
     419
     420                $this->assertArrayHasKey( 'registered_key1', $meta_keys );
     421                $this->assertArrayHasKey( 'registered_key2', $meta_keys );
     422                $this->assertEmpty( get_registered_meta_keys( $type ) );
     423        }
     424
     425        /**
     426         * @ticket 38323
     427         * @dataProvider data_get_types_and_subtypes
     428         */
     429        public function test_get_registered_metadata_with_subtype( $type, $subtype ) {
     430                register_meta( $type, 'registered_key1', array() );
     431
     432                // This will override the above registration for objects of $subtype.
     433                register_meta( $type, 'registered_key1', array(
     434                        'object_subtype' => $subtype,
     435                        'single'         => true,
     436                ) );
     437
     438                // For testing with $single => false.
     439                register_meta( $type, 'registered_key2', array(
     440                        'object_subtype' => $subtype,
     441                ) );
     442
     443                // Register another meta key for a different subtype.
     444                register_meta( $type, 'registered_key3', array(
     445                        'object_subtype' => 'other_subtype',
     446                ) );
     447
     448                $object_property_name = $type . '_id';
     449                $object_id = self::$$object_property_name;
     450
     451                add_metadata( $type, $object_id, 'registered_key1', 'value1' );
     452                add_metadata( $type, $object_id, 'registered_key2', 'value2' );
     453                add_metadata( $type, $object_id, 'registered_key3', 'value3' );
     454
     455                $meta = get_registered_metadata( $type, $object_id );
     456
     457                $key1 = get_registered_metadata( $type, $object_id, 'registered_key1' );
     458                $key2 = get_registered_metadata( $type, $object_id, 'registered_key2' );
     459                $key3 = get_registered_metadata( $type, $object_id, 'registered_key3' );
     460
     461                $this->assertSame( array( 'registered_key1', 'registered_key2' ), array_keys( $meta ) );
     462                $this->assertSame( 'value1', $meta['registered_key1'][0] );
     463                $this->assertSame( 'value2', $meta['registered_key2'][0] );
     464
     465                $this->assertSame( 'value1', $key1 );
     466                $this->assertSame( array( 'value2' ), $key2 );
     467                $this->assertFalse( $key3 );
     468        }
     469
     470        /**
     471         * @ticket 38323
     472         * @dataProvider data_get_types_and_subtypes
     473         */
     474        public function test_get_object_subtype( $type, $expected_subtype ) {
     475                $object_property_name = $type . '_id';
     476                $object_id = self::$$object_property_name;
     477
     478                $this->assertSame( $expected_subtype, get_object_subtype( $type, $object_id ) );
     479        }
     480
     481        /**
     482         * @ticket 38323
     483         */
     484        public function test_get_object_subtype_custom() {
     485                add_filter( 'get_object_subtype_customtype', array( $this, 'filter_get_object_subtype_for_customtype' ), 10, 2 );
     486
     487                $subtype_for_3 = get_object_subtype( 'customtype', 3 );
     488                $subtype_for_4 = get_object_subtype( 'customtype', 4 );
     489
     490                $this->assertSame( 'odd', $subtype_for_3 );
     491                $this->assertSame( 'even', $subtype_for_4 );
     492        }
     493
     494        public function filter_get_object_subtype_for_customtype( $subtype, $object_id ) {
     495                if ( $object_id % 2 === 1 ) {
     496                        return 'odd';
     497                }
     498
     499                return 'even';
     500        }
     501
     502        public function data_get_types_and_subtypes() {
     503                return array(
     504                        array( 'post', 'page' ),
     505                        array( 'term', 'category' ),
     506                        array( 'comment', 'comment' ),
     507                        array( 'user', 'user' ),
     508                );
     509        }
    304510}
  • tests/phpunit/tests/post/meta.php

     
    55 * @group meta
    66 */
    77class Tests_Post_Meta extends WP_UnitTestCase {
    8         function setUp() {
    9                 parent::setUp();
    108
    11                 $this->author = new WP_User( self::factory()->user->create( array( 'role' => 'editor' ) ) );
     9        private $last_register_meta_call = array(
     10                'object_type' => '',
     11                'meta_key'    => '',
     12                'args'        => array(),
     13        );
     14
     15        protected static $author;
     16        protected static $post_id;
     17        protected static $post_id_2;
    1218
    13                 $post = array(
    14                         'post_author'  => $this->author->ID,
     19        public static function wpSetUpBeforeClass( $factory ) {
     20                self::$author = $factory->user->create_and_get( array( 'role' => 'editor' ) );
     21
     22                self::$post_id = $factory->post->create( array(
     23                        'post_author'  => self::$author->ID,
    1524                        'post_status'  => 'publish',
    1625                        'post_content' => rand_str(),
    1726                        'post_title'   => rand_str(),
    18                 );
     27                ) );
    1928
    20                 // insert a post
    21                 $this->post_id = wp_insert_post( $post );
    22 
    23                 $post = array(
    24                         'post_author'  => $this->author->ID,
     29                self::$post_id_2 = $factory->post->create( array(
     30                        'post_author'  => self::$author->ID,
    2531                        'post_status'  => 'publish',
    2632                        'post_content' => rand_str(),
    2733                        'post_title'   => rand_str(),
    28                 );
     34                ) );
     35        }
    2936
    30                 // insert a post
    31                 $this->post_id_2 = wp_insert_post( $post );
     37        public static function wpTearDownAfterClass() {
     38                wp_delete_post( self::$post_id, true );
     39                wp_delete_post( self::$post_id_2, true );
     40                self::delete_user( self::$author );
    3241        }
    3342
    3443        function test_unique_postmeta() {
    3544                // Add a unique post meta item
    36                 $this->assertInternalType( 'integer', add_post_meta( $this->post_id, 'unique', 'value', true ) );
     45                $this->assertInternalType( 'integer', add_post_meta( self::$post_id, 'unique', 'value', true ) );
    3746
    3847                // Check unique is enforced
    39                 $this->assertFalse( add_post_meta( $this->post_id, 'unique', 'another value', true ) );
     48                $this->assertFalse( add_post_meta( self::$post_id, 'unique', 'another value', true ) );
    4049
    4150                //Check it exists
    42                 $this->assertEquals( 'value', get_post_meta( $this->post_id, 'unique', true ) );
    43                 $this->assertEquals( array( 'value' ), get_post_meta( $this->post_id, 'unique', false ) );
     51                $this->assertEquals( 'value', get_post_meta( self::$post_id, 'unique', true ) );
     52                $this->assertEquals( array( 'value' ), get_post_meta( self::$post_id, 'unique', false ) );
    4453
    4554                //Fail to delete the wrong value
    46                 $this->assertFalse( delete_post_meta( $this->post_id, 'unique', 'wrong value' ) );
     55                $this->assertFalse( delete_post_meta( self::$post_id, 'unique', 'wrong value' ) );
    4756
    4857                //Delete it
    49                 $this->assertTrue( delete_post_meta( $this->post_id, 'unique', 'value' ) );
     58                $this->assertTrue( delete_post_meta( self::$post_id, 'unique', 'value' ) );
    5059
    5160                //Check it is deleted
    52                 $this->assertEquals( '', get_post_meta( $this->post_id, 'unique', true ) );
    53                 $this->assertEquals( array(), get_post_meta( $this->post_id, 'unique', false ) );
     61                $this->assertEquals( '', get_post_meta( self::$post_id, 'unique', true ) );
     62                $this->assertEquals( array(), get_post_meta( self::$post_id, 'unique', false ) );
    5463
    5564        }
    5665
    5766        function test_nonunique_postmeta() {
    5867                // Add two non unique post meta item
    59                 $this->assertInternalType( 'integer', add_post_meta( $this->post_id, 'nonunique', 'value' ) );
    60                 $this->assertInternalType( 'integer', add_post_meta( $this->post_id, 'nonunique', 'another value' ) );
     68                $this->assertInternalType( 'integer', add_post_meta( self::$post_id, 'nonunique', 'value' ) );
     69                $this->assertInternalType( 'integer', add_post_meta( self::$post_id, 'nonunique', 'another value' ) );
    6170
    6271                //Check they exists
    63                 $this->assertEquals( 'value', get_post_meta( $this->post_id, 'nonunique', true ) );
    64                 $this->assertEquals( array( 'value', 'another value' ), get_post_meta( $this->post_id, 'nonunique', false ) );
     72                $this->assertEquals( 'value', get_post_meta( self::$post_id, 'nonunique', true ) );
     73                $this->assertEquals( array( 'value', 'another value' ), get_post_meta( self::$post_id, 'nonunique', false ) );
    6574
    6675                //Fail to delete the wrong value
    67                 $this->assertFalse( delete_post_meta( $this->post_id, 'nonunique', 'wrong value' ) );
     76                $this->assertFalse( delete_post_meta( self::$post_id, 'nonunique', 'wrong value' ) );
    6877
    6978                //Delete the first one
    70                 $this->assertTrue( delete_post_meta( $this->post_id, 'nonunique', 'value' ) );
     79                $this->assertTrue( delete_post_meta( self::$post_id, 'nonunique', 'value' ) );
    7180
    7281                //Check the remainder exists
    73                 $this->assertEquals( 'another value', get_post_meta( $this->post_id, 'nonunique', true ) );
    74                 $this->assertEquals( array( 'another value' ), get_post_meta( $this->post_id, 'nonunique', false ) );
     82                $this->assertEquals( 'another value', get_post_meta( self::$post_id, 'nonunique', true ) );
     83                $this->assertEquals( array( 'another value' ), get_post_meta( self::$post_id, 'nonunique', false ) );
    7584
    7685                //Add a third one
    77                 $this->assertInternalType( 'integer', add_post_meta( $this->post_id, 'nonunique', 'someother value' ) );
     86                $this->assertInternalType( 'integer', add_post_meta( self::$post_id, 'nonunique', 'someother value' ) );
    7887
    7988                //Check they exists
    8089                $expected = array(
     
    8291                        'another value',
    8392                );
    8493                sort( $expected );
    85                 $this->assertTrue( in_array( get_post_meta( $this->post_id, 'nonunique', true ), $expected ) );
    86                 $actual = get_post_meta( $this->post_id, 'nonunique', false );
     94                $this->assertTrue( in_array( get_post_meta( self::$post_id, 'nonunique', true ), $expected ) );
     95                $actual = get_post_meta( self::$post_id, 'nonunique', false );
    8796                sort( $actual );
    8897                $this->assertEquals( $expected, $actual );
    8998
     
    93102
    94103        function test_update_post_meta() {
    95104                // Add a unique post meta item
    96                 $this->assertInternalType( 'integer', add_post_meta( $this->post_id, 'unique_update', 'value', true ) );
     105                $this->assertInternalType( 'integer', add_post_meta( self::$post_id, 'unique_update', 'value', true ) );
    97106
    98107                // Add two non unique post meta item
    99                 $this->assertInternalType( 'integer', add_post_meta( $this->post_id, 'nonunique_update', 'value' ) );
    100                 $this->assertInternalType( 'integer', add_post_meta( $this->post_id, 'nonunique_update', 'another value' ) );
     108                $this->assertInternalType( 'integer', add_post_meta( self::$post_id, 'nonunique_update', 'value' ) );
     109                $this->assertInternalType( 'integer', add_post_meta( self::$post_id, 'nonunique_update', 'another value' ) );
    101110
    102111                //Check they exists
    103                 $this->assertEquals( 'value', get_post_meta( $this->post_id, 'unique_update', true ) );
    104                 $this->assertEquals( array( 'value' ), get_post_meta( $this->post_id, 'unique_update', false ) );
    105                 $this->assertEquals( 'value', get_post_meta( $this->post_id, 'nonunique_update', true ) );
    106                 $this->assertEquals( array( 'value', 'another value' ), get_post_meta( $this->post_id, 'nonunique_update', false ) );
     112                $this->assertEquals( 'value', get_post_meta( self::$post_id, 'unique_update', true ) );
     113                $this->assertEquals( array( 'value' ), get_post_meta( self::$post_id, 'unique_update', false ) );
     114                $this->assertEquals( 'value', get_post_meta( self::$post_id, 'nonunique_update', true ) );
     115                $this->assertEquals( array( 'value', 'another value' ), get_post_meta( self::$post_id, 'nonunique_update', false ) );
    107116
    108117                // Update them
    109                 $this->assertTrue( update_post_meta( $this->post_id, 'unique_update', 'new', 'value' ) );
    110                 $this->assertTrue( update_post_meta( $this->post_id, 'nonunique_update', 'new', 'value' ) );
    111                 $this->assertTrue( update_post_meta( $this->post_id, 'nonunique_update', 'another new', 'another value' ) );
     118                $this->assertTrue( update_post_meta( self::$post_id, 'unique_update', 'new', 'value' ) );
     119                $this->assertTrue( update_post_meta( self::$post_id, 'nonunique_update', 'new', 'value' ) );
     120                $this->assertTrue( update_post_meta( self::$post_id, 'nonunique_update', 'another new', 'another value' ) );
    112121
    113122                //Check they updated
    114                 $this->assertEquals( 'new', get_post_meta( $this->post_id, 'unique_update', true ) );
    115                 $this->assertEquals( array( 'new' ), get_post_meta( $this->post_id, 'unique_update', false ) );
    116                 $this->assertEquals( 'new', get_post_meta( $this->post_id, 'nonunique_update', true ) );
    117                 $this->assertEquals( array( 'new', 'another new' ), get_post_meta( $this->post_id, 'nonunique_update', false ) );
     123                $this->assertEquals( 'new', get_post_meta( self::$post_id, 'unique_update', true ) );
     124                $this->assertEquals( array( 'new' ), get_post_meta( self::$post_id, 'unique_update', false ) );
     125                $this->assertEquals( 'new', get_post_meta( self::$post_id, 'nonunique_update', true ) );
     126                $this->assertEquals( array( 'new', 'another new' ), get_post_meta( self::$post_id, 'nonunique_update', false ) );
    118127
    119128        }
    120129
    121130        function test_delete_post_meta() {
    122131                // Add a unique post meta item
    123                 $this->assertInternalType( 'integer', add_post_meta( $this->post_id, 'unique_delete', 'value', true ) );
    124                 $this->assertInternalType( 'integer', add_post_meta( $this->post_id_2, 'unique_delete', 'value', true ) );
     132                $this->assertInternalType( 'integer', add_post_meta( self::$post_id, 'unique_delete', 'value', true ) );
     133                $this->assertInternalType( 'integer', add_post_meta( self::$post_id_2, 'unique_delete', 'value', true ) );
    125134
    126135                //Check they exists
    127                 $this->assertEquals( 'value', get_post_meta( $this->post_id, 'unique_delete', true ) );
    128                 $this->assertEquals( 'value', get_post_meta( $this->post_id_2, 'unique_delete', true ) );
     136                $this->assertEquals( 'value', get_post_meta( self::$post_id, 'unique_delete', true ) );
     137                $this->assertEquals( 'value', get_post_meta( self::$post_id_2, 'unique_delete', true ) );
    129138
    130139                //Delete one of them
    131                 $this->assertTrue( delete_post_meta( $this->post_id, 'unique_delete', 'value' ) );
     140                $this->assertTrue( delete_post_meta( self::$post_id, 'unique_delete', 'value' ) );
    132141
    133142                //Check the other still exitsts
    134                 $this->assertEquals( 'value', get_post_meta( $this->post_id_2, 'unique_delete', true ) );
     143                $this->assertEquals( 'value', get_post_meta( self::$post_id_2, 'unique_delete', true ) );
    135144
    136145        }
    137146
    138147        function test_delete_post_meta_by_key() {
    139148                // Add a unique post meta item
    140                 $this->assertInternalType( 'integer', add_post_meta( $this->post_id, 'unique_delete_by_key', 'value', true ) );
    141                 $this->assertInternalType( 'integer', add_post_meta( $this->post_id_2, 'unique_delete_by_key', 'value', true ) );
     149                $this->assertInternalType( 'integer', add_post_meta( self::$post_id, 'unique_delete_by_key', 'value', true ) );
     150                $this->assertInternalType( 'integer', add_post_meta( self::$post_id_2, 'unique_delete_by_key', 'value', true ) );
    142151
    143152                //Check they exist
    144                 $this->assertEquals( 'value', get_post_meta( $this->post_id, 'unique_delete_by_key', true ) );
    145                 $this->assertEquals( 'value', get_post_meta( $this->post_id_2, 'unique_delete_by_key', true ) );
     153                $this->assertEquals( 'value', get_post_meta( self::$post_id, 'unique_delete_by_key', true ) );
     154                $this->assertEquals( 'value', get_post_meta( self::$post_id_2, 'unique_delete_by_key', true ) );
    146155
    147156                //Delete one of them
    148157                $this->assertTrue( delete_post_meta_by_key( 'unique_delete_by_key' ) );
    149158
    150159                //Check the other still exists
    151                 $this->assertEquals( '', get_post_meta( $this->post_id_2, 'unique_delete_by_key', true ) );
    152                 $this->assertEquals( '', get_post_meta( $this->post_id_2, 'unique_delete_by_key', true ) );
     160                $this->assertEquals( '', get_post_meta( self::$post_id_2, 'unique_delete_by_key', true ) );
     161                $this->assertEquals( '', get_post_meta( self::$post_id_2, 'unique_delete_by_key', true ) );
    153162        }
    154163
    155164        function test_get_post_meta_by_id() {
    156                 $mid = add_post_meta( $this->post_id, 'get_post_meta_by_key', 'get_post_meta_by_key_value', true );
     165                $mid = add_post_meta( self::$post_id, 'get_post_meta_by_key', 'get_post_meta_by_key_value', true );
    157166                $this->assertInternalType( 'integer', $mid );
    158167
    159168                $mobj             = new stdClass;
    160169                $mobj->meta_id    = $mid;
    161                 $mobj->post_id    = $this->post_id;
     170                $mobj->post_id    = self::$post_id;
    162171                $mobj->meta_key   = 'get_post_meta_by_key';
    163172                $mobj->meta_value = 'get_post_meta_by_key_value';
    164173                $this->assertEquals( $mobj, get_post_meta_by_id( $mid ) );
    165174                delete_metadata_by_mid( 'post', $mid );
    166175
    167                 $mid = add_post_meta( $this->post_id, 'get_post_meta_by_key', array( 'foo', 'bar' ), true );
     176                $mid = add_post_meta( self::$post_id, 'get_post_meta_by_key', array( 'foo', 'bar' ), true );
    168177                $this->assertInternalType( 'integer', $mid );
    169178                $mobj->meta_id    = $mid;
    170179                $mobj->meta_value = array( 'foo', 'bar' );
     
    173182        }
    174183
    175184        function test_delete_meta() {
    176                 $mid = add_post_meta( $this->post_id, 'delete_meta', 'delete_meta_value', true );
     185                $mid = add_post_meta( self::$post_id, 'delete_meta', 'delete_meta_value', true );
    177186                $this->assertInternalType( 'integer', $mid );
    178187
    179188                $this->assertTrue( delete_meta( $mid ) );
     
    184193
    185194        function test_update_meta() {
    186195                // Add a unique post meta item
    187                 $this->assertInternalType( 'integer', $mid1 = add_post_meta( $this->post_id, 'unique_update', 'value', true ) );
     196                $this->assertInternalType( 'integer', $mid1 = add_post_meta( self::$post_id, 'unique_update', 'value', true ) );
    188197
    189198                // Add two non unique post meta item
    190                 $this->assertInternalType( 'integer', $mid2 = add_post_meta( $this->post_id, 'nonunique_update', 'value' ) );
    191                 $this->assertInternalType( 'integer', $mid3 = add_post_meta( $this->post_id, 'nonunique_update', 'another value' ) );
     199                $this->assertInternalType( 'integer', $mid2 = add_post_meta( self::$post_id, 'nonunique_update', 'value' ) );
     200                $this->assertInternalType( 'integer', $mid3 = add_post_meta( self::$post_id, 'nonunique_update', 'another value' ) );
    192201
    193202                //Check they exist
    194                 $this->assertEquals( 'value', get_post_meta( $this->post_id, 'unique_update', true ) );
    195                 $this->assertEquals( array( 'value' ), get_post_meta( $this->post_id, 'unique_update', false ) );
    196                 $this->assertEquals( 'value', get_post_meta( $this->post_id, 'nonunique_update', true ) );
    197                 $this->assertEquals( array( 'value', 'another value' ), get_post_meta( $this->post_id, 'nonunique_update', false ) );
     203                $this->assertEquals( 'value', get_post_meta( self::$post_id, 'unique_update', true ) );
     204                $this->assertEquals( array( 'value' ), get_post_meta( self::$post_id, 'unique_update', false ) );
     205                $this->assertEquals( 'value', get_post_meta( self::$post_id, 'nonunique_update', true ) );
     206                $this->assertEquals( array( 'value', 'another value' ), get_post_meta( self::$post_id, 'nonunique_update', false ) );
    198207
    199208                // Update them
    200209                $this->assertTrue( update_meta( $mid1, 'unique_update', 'new' ) );
     
    202211                $this->assertTrue( update_meta( $mid3, 'nonunique_update', 'another new' ) );
    203212
    204213                //Check they updated
    205                 $this->assertEquals( 'new', get_post_meta( $this->post_id, 'unique_update', true ) );
    206                 $this->assertEquals( array( 'new' ), get_post_meta( $this->post_id, 'unique_update', false ) );
    207                 $this->assertEquals( 'new', get_post_meta( $this->post_id, 'nonunique_update', true ) );
    208                 $this->assertEquals( array( 'new', 'another new' ), get_post_meta( $this->post_id, 'nonunique_update', false ) );
     214                $this->assertEquals( 'new', get_post_meta( self::$post_id, 'unique_update', true ) );
     215                $this->assertEquals( array( 'new' ), get_post_meta( self::$post_id, 'unique_update', false ) );
     216                $this->assertEquals( 'new', get_post_meta( self::$post_id, 'nonunique_update', true ) );
     217                $this->assertEquals( array( 'new', 'another new' ), get_post_meta( self::$post_id, 'nonunique_update', false ) );
    209218
    210219                // Slashed update
    211220                $data = "'quote and \slash";
     
    229238                $funky_meta[]    = $classy;
    230239
    231240                // Add a post meta item
    232                 $this->assertInternalType( 'integer', add_post_meta( $this->post_id, 'test_funky_post_meta', $funky_meta, true ) );
     241                $this->assertInternalType( 'integer', add_post_meta( self::$post_id, 'test_funky_post_meta', $funky_meta, true ) );
    233242
    234243                //Check they exists
    235                 $this->assertEquals( $funky_meta, get_post_meta( $this->post_id, 'test_funky_post_meta', true ) );
     244                $this->assertEquals( $funky_meta, get_post_meta( self::$post_id, 'test_funky_post_meta', true ) );
     245
     246        }
     247
     248        /**
     249         * @ticket 38323
     250         * @dataProvider data_register_post_meta
     251         */
     252        public function test_register_post_meta( $post_type, $meta_key, $args ) {
     253                add_filter( 'register_meta_args', array( $this, 'filter_register_meta_args_set_last_register_meta_call' ), 10, 4 );
     254
     255                register_post_meta( $post_type, $meta_key, $args );
     256
     257                $args['object_subtype'] = $post_type;
     258
     259                // Reset global so subsequent data tests do not get polluted.
     260                $GLOBALS['wp_meta_keys'] = array();
     261
     262                $this->assertEquals( 'post', $this->last_register_meta_call['object_type'] );
     263                $this->assertEquals( $meta_key, $this->last_register_meta_call['meta_key'] );
     264                $this->assertEquals( $args, $this->last_register_meta_call['args'] );
     265        }
    236266
     267        public function data_register_post_meta() {
     268                return array(
     269                        array( 'post', 'registered_key1', array( 'single' => true ) ),
     270                        array( 'page', 'registered_key2', array() ),
     271                        array( '', 'registered_key3', array( 'sanitize_callback' => 'absint' ) ),
     272                );
     273        }
     274
     275        public function filter_register_meta_args_set_last_register_meta_call( $args, $defaults, $object_type, $meta_key ) {
     276                $this->last_register_meta_call['object_type'] = $object_type;
     277                $this->last_register_meta_call['meta_key']    = $meta_key;
     278                $this->last_register_meta_call['args']        = $args;
     279
     280                return $args;
     281        }
     282
     283        /**
     284         * @ticket 38323
     285         * @dataProvider data_unregister_post_meta
     286         */
     287        public function test_unregister_post_meta( $post_type, $meta_key ) {
     288                global $wp_meta_keys;
     289
     290                register_post_meta( $post_type, $meta_key, array() );
     291                unregister_post_meta( $post_type, $meta_key );
     292
     293                $actual = $wp_meta_keys;
     294
     295                // Reset global so subsequent data tests do not get polluted.
     296                $wp_meta_keys = array();
     297
     298                $this->assertEmpty( $actual );
     299        }
     300
     301        public function data_unregister_post_meta() {
     302                return array(
     303                        array( 'post', 'registered_key1' ),
     304                        array( 'page', 'registered_key2' ),
     305                        array( '', 'registered_key3' ),
     306                );
    237307        }
    238308}
  • tests/phpunit/tests/rest-api/rest-post-meta-fields.php

     
    1212class WP_Test_REST_Post_Meta_Fields extends WP_Test_REST_TestCase {
    1313        protected static $wp_meta_keys_saved;
    1414        protected static $post_id;
     15        protected static $custom_post_type_id;
    1516
    1617        public static function wpSetUpBeforeClass( $factory ) {
    1718                self::$wp_meta_keys_saved = $GLOBALS['wp_meta_keys'];
    1819                self::$post_id            = $factory->post->create();
     20
     21                self::$custom_post_type_id = $factory->post->create( array( 'post_type' => 'cpt' ) );
    1922        }
    2023
    2124        public static function wpTearDownAfterClass() {
    2225                $GLOBALS['wp_meta_keys'] = self::$wp_meta_keys_saved;
    2326                wp_delete_post( self::$post_id, true );
     27                wp_delete_post( self::$custom_post_type_id, true );
    2428        }
    2529
    2630        public function setUp() {
     
    120124                        )
    121125                );
    122126
     127                $args = array(
     128                        'show_in_rest' => true,
     129                        'supports'     => array( 'custom-fields' ),
     130                );
     131                register_post_type( 'cpt', $args );
     132
     133                register_post_meta( 'cpt', 'test_cpt_single', array(
     134                        'show_in_rest'   => true,
     135                        'single'         => true,
     136                        'object_subtype' => 'cpt',
     137                ) );
     138
     139                register_post_meta( 'cpt', 'test_cpt_bad_auth', array(
     140                        'show_in_rest'   => true,
     141                        'single'         => true,
     142                        'auth_callback'  => '__return_false',
     143                        'object_subtype' => 'cpt',
     144                ) );
     145
     146                // registering the key 'test_single' on the cpt post type
     147                register_post_meta( 'cpt', 'test_single', array(
     148                        'show_in_rest'   => true,
     149                        'single'         => true,
     150                        'auth_callback'  => '__return_false',
     151                        'object_subtype' => 'cpt',
     152                ) );
     153
    123154                /** @var WP_REST_Server $wp_rest_server */
    124155                global $wp_rest_server;
    125156                $wp_rest_server = new Spy_REST_Server;
     
    10481079        }
    10491080
    10501081        /**
     1082         * @ticket 38323
     1083         */
     1084        public function test_register_custom_post_meta_get_value () {
     1085                add_post_meta( self::$custom_post_type_id, 'test_cpt_single', 'testcptvalue' );
     1086
     1087                $request = new WP_REST_Request( 'GET', sprintf( '/wp/v2/cpt/%d', self::$custom_post_type_id ) );
     1088                $response = rest_get_server()->dispatch( $request );
     1089
     1090                $this->assertEquals( 200, $response->get_status() );
     1091
     1092                $data = $response->get_data();
     1093                $this->assertArrayHasKey( 'meta', $data );
     1094
     1095                $meta = (array) $data['meta'];
     1096                $this->assertArrayHasKey( 'test_cpt_single', $meta );
     1097                $this->assertEquals( 'testcptvalue', $meta['test_cpt_single'] );
     1098        }
     1099
     1100        /**
     1101         * @ticket 38323
     1102         */
     1103        public function test_register_custom_post_meta_not_in_post () {
     1104                add_post_meta( self::$post_id, 'test_cpt_single', 'testcptvalue' );
     1105
     1106                $request = new WP_REST_Request( 'GET', sprintf( '/wp/v2/posts/%d', self::$post_id ) );
     1107                $response = rest_get_server()->dispatch( $request );
     1108
     1109                $this->assertEquals( 200, $response->get_status() );
     1110
     1111                $data = $response->get_data();
     1112                $this->assertArrayHasKey( 'meta', $data );
     1113
     1114                $meta = (array) $data['meta'];
     1115                $this->assertArrayNotHasKey( 'test_cpt_single', $meta );
     1116        }
     1117
     1118        /**
     1119         * @ticket 38323
     1120         */
     1121        public function test_set_value_unregistered_custom_post_type_registered_object() {
     1122                // Ensure no data exists currently.
     1123                $values = get_post_meta( self::$custom_post_type_id, 'test_multi', false );
     1124                $this->assertEmpty( $values );
     1125
     1126                $this->grant_write_permission();
     1127
     1128                $data    = array(
     1129                        'meta' => array(
     1130                                'test_multi' => 'test_value',
     1131                        ),
     1132                );
     1133                $request = new WP_REST_Request( 'POST', sprintf( '/wp/v2/cpt/%d', self::$custom_post_type_id ) );
     1134                $request->set_body_params( $data );
     1135
     1136                $response = rest_get_server()->dispatch( $request );
     1137                $this->assertEquals( 200, $response->get_status() );
     1138
     1139                $meta = get_post_meta( self::$custom_post_type_id, 'test_multi', false );
     1140                $this->assertNotEmpty( $meta );
     1141                $this->assertCount( 1, $meta );
     1142                $this->assertEquals( 'test_value', $meta[0] );
     1143
     1144                $data = $response->get_data();
     1145                $meta = (array) $data['meta'];
     1146                $this->assertArrayHasKey( 'test_multi', $meta );
     1147                $this->assertEquals( 'test_value', $meta['test_multi'][0] );
     1148        }
     1149
     1150        /**
     1151         * @ticket 38323
     1152         */
     1153        public function test_set_value_custom_post_type() {
     1154                // Ensure no data exists currently.
     1155                $values = get_post_meta( self::$custom_post_type_id, 'test_cpt_single', false );
     1156                $this->assertEmpty( $values );
     1157
     1158                $this->grant_write_permission();
     1159
     1160                $data    = array(
     1161                        'meta' => array(
     1162                                'test_cpt_single' => 'test_value',
     1163                        ),
     1164                );
     1165                $request = new WP_REST_Request( 'POST', sprintf( '/wp/v2/cpt/%d', self::$custom_post_type_id ) );
     1166                $request->set_body_params( $data );
     1167
     1168                $response = rest_get_server()->dispatch( $request );
     1169                $this->assertEquals( 200, $response->get_status() );
     1170
     1171                $meta = get_post_meta( self::$custom_post_type_id, 'test_cpt_single', false );
     1172                $this->assertNotEmpty( $meta );
     1173                $this->assertCount( 1, $meta );
     1174                $this->assertEquals( 'test_value', $meta[0] );
     1175
     1176                $data = $response->get_data();
     1177                $meta = (array) $data['meta'];
     1178                $this->assertArrayHasKey( 'test_cpt_single', $meta );
     1179                $this->assertEquals( 'test_value', $meta['test_cpt_single'] );
     1180        }
     1181
     1182        /**
     1183         * @ticket 38323
     1184         */
     1185        public function test_set_value_custom_post_type_blocked() {
     1186                $data = array(
     1187                        'meta' => array(
     1188                                'test_cpt_bad_auth' => 'test_value',
     1189                        ),
     1190                );
     1191
     1192                $this->grant_write_permission();
     1193
     1194                $request = new WP_REST_Request( 'POST', sprintf( '/wp/v2/cpt/%d', self::$custom_post_type_id ) );
     1195                $request->set_body_params( $data );
     1196
     1197                $response = rest_get_server()->dispatch( $request );
     1198                $this->assertErrorResponse( 'rest_cannot_update', $response, 403 );
     1199                $this->assertEmpty( get_post_meta( self::$custom_post_type_id, 'test_cpt_bad_auth', false ) );
     1200        }
     1201
     1202        /**
     1203         * @ticket 38323
     1204         */
     1205        public function test_set_value_custom_post_type_duplicate_key_blocked() {
     1206                $data = array(
     1207                        'meta' => array(
     1208                                'test_single' => 'test_value',
     1209                        ),
     1210                );
     1211
     1212                $this->grant_write_permission();
     1213
     1214                $request = new WP_REST_Request( 'POST', sprintf( '/wp/v2/posts/%d', self::$post_id ) );
     1215                $request->set_body_params( $data );
     1216
     1217                $response = rest_get_server()->dispatch( $request );
     1218                $this->assertEquals( get_post_meta( self::$post_id, 'test_single', true ), 'test_value' );
     1219
     1220                $request_cpt = new WP_REST_Request( 'POST', sprintf( '/wp/v2/cpt/%d', self::$custom_post_type_id ) );
     1221                $request_cpt->set_body_params( $data );
     1222
     1223                $response_cpt = rest_get_server()->dispatch( $request_cpt );
     1224
     1225                $this->assertErrorResponse( 'rest_cannot_update', $response_cpt, 403 );
     1226                $this->assertEmpty( get_post_meta( self::$custom_post_type_id, 'test_single', true ) );
     1227        }
     1228
     1229        /**
    10511230         * Internal function used to disable an insert query which
    10521231         * will trigger a wpdb error for testing purposes.
    10531232         */
  • tests/phpunit/tests/term/meta.php

     
    66 * @ticket 10142
    77 */
    88class Tests_Term_Meta extends WP_UnitTestCase {
     9
     10        private $last_register_meta_call = array(
     11                'object_type' => '',
     12                'meta_key'    => '',
     13                'args'        => array(),
     14        );
     15
    916        public function setUp() {
    1017                parent::setUp();
    1118                register_taxonomy( 'wptests_tax', 'post' );
     
    463470        public static function set_cache_results( $q ) {
    464471                $q->set( 'cache_results', true );
    465472        }
     473
     474        /**
     475         * @ticket 38323
     476         * @dataProvider data_register_term_meta
     477         */
     478        public function test_register_term_meta( $taxonomy, $meta_key, $args ) {
     479                add_filter( 'register_meta_args', array( $this, 'filter_register_meta_args_set_last_register_meta_call' ), 10, 4 );
     480
     481                register_term_meta( $taxonomy, $meta_key, $args );
     482
     483                $args['object_subtype'] = $taxonomy;
     484
     485                // Reset global so subsequent data tests do not get polluted.
     486                $GLOBALS['wp_meta_keys'] = array();
     487
     488                $this->assertEquals( 'term', $this->last_register_meta_call['object_type'] );
     489                $this->assertEquals( $meta_key, $this->last_register_meta_call['meta_key'] );
     490                $this->assertEquals( $args, $this->last_register_meta_call['args'] );
     491        }
     492
     493        public function data_register_term_meta() {
     494                return array(
     495                        array( 'wptests_tax', 'registered_key1', array( 'single' => true ) ),
     496                        array( 'category', 'registered_key2', array() ),
     497                        array( '', 'registered_key3', array( 'sanitize_callback' => 'absint' ) ),
     498                );
     499        }
     500
     501        public function filter_register_meta_args_set_last_register_meta_call( $args, $defaults, $object_type, $meta_key ) {
     502                $this->last_register_meta_call['object_type'] = $object_type;
     503                $this->last_register_meta_call['meta_key']    = $meta_key;
     504                $this->last_register_meta_call['args']        = $args;
     505
     506                return $args;
     507        }
     508
     509        /**
     510         * @ticket 38323
     511         * @dataProvider data_unregister_term_meta
     512         */
     513        public function test_unregister_term_meta( $taxonomy, $meta_key ) {
     514                global $wp_meta_keys;
     515
     516                register_term_meta( $taxonomy, $meta_key, array() );
     517                unregister_term_meta( $taxonomy, $meta_key );
     518
     519                $actual = $wp_meta_keys;
     520
     521                // Reset global so subsequent data tests do not get polluted.
     522                $wp_meta_keys = array();
     523
     524                $this->assertEmpty( $actual );
     525        }
     526
     527        public function data_unregister_term_meta() {
     528                return array(
     529                        array( 'wptests_tax', 'registered_key1' ),
     530                        array( 'category', 'registered_key2' ),
     531                        array( '', 'registered_key3' ),
     532                );
     533        }
    466534}