Ticket #38323: 38323.5.diff
File 38323.5.diff, 20.8 KB (added by , 6 years ago) |
---|
-
src/wp-includes/capabilities.php
263 263 list( $_, $object_type, $_ ) = explode( '_', $cap ); 264 264 $object_id = (int) $args[0]; 265 265 266 switch ( $object_type ) { 267 case 'post': 268 $post = get_post( $object_id ); 269 if ( ! $post ) { 270 break; 271 } 272 273 $sub_type = get_post_type( $post ); 274 break; 275 276 case 'comment': 277 $comment = get_comment( $object_id ); 278 if ( ! $comment ) { 279 break; 280 } 281 282 $sub_type = empty( $comment->comment_type ) ? 'comment' : $comment->comment_type; 283 break; 284 285 case 'term': 286 $term = get_term( $object_id ); 287 if ( ! $term instanceof WP_Term ) { 288 break; 289 } 290 291 $sub_type = $term->taxonomy; 292 break; 293 294 case 'user': 295 $user = get_user_by( 'id', $object_id ); 296 if ( ! $user ) { 297 break; 298 } 299 300 $sub_type = 'user'; 301 break; 302 } 266 $sub_type = get_object_subtype( $object_type, $object_id ); 303 267 304 268 if ( empty( $sub_type ) ) { 305 269 $caps[] = 'do_not_allow'; -
src/wp-includes/meta.php
44 44 return false; 45 45 } 46 46 47 $meta_subtype = get_object_subtype( $meta_type, $object_id ); 48 47 49 $column = sanitize_key( $meta_type . '_id' ); 48 50 49 51 // expected_slashed ($meta_key) 50 52 $meta_key = wp_unslash( $meta_key ); 51 53 $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 ); 53 55 54 56 /** 55 57 * Filters whether to add metadata of a specific type. … … 165 167 return false; 166 168 } 167 169 170 $meta_subtype = get_object_subtype( $meta_type, $object_id ); 171 168 172 $column = sanitize_key( $meta_type . '_id' ); 169 173 $id_column = 'user' == $meta_type ? 'umeta_id' : 'meta_id'; 170 174 … … 173 177 $meta_key = wp_unslash( $meta_key ); 174 178 $passed_value = $meta_value; 175 179 $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 ); 177 181 178 182 /** 179 183 * Filters whether to update metadata of a specific type. … … 666 670 return false; 667 671 } 668 672 673 $meta_subtype = get_object_subtype( $meta_type, $object_id ); 674 669 675 // Sanitize the meta 670 676 $_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 ); 672 678 $meta_value = maybe_serialize( $meta_value ); 673 679 674 680 // Format the data query arguments. … … 968 974 * Sanitize meta value. 969 975 * 970 976 * @since 3.1.3 977 * @since 5.0.0 The `$object_subtype` parameter was added. 971 978 * 972 979 * @param string $meta_key Meta key. 973 980 * @param mixed $meta_value Meta value to sanitize. … … 975 982 * 976 983 * @return mixed Sanitized $meta_value. 977 984 */ 978 function sanitize_meta( $meta_key, $meta_value, $object_type ) { 985 function sanitize_meta( $meta_key, $meta_value, $object_type, $object_subtype = '' ) { 986 if ( ! empty( $object_subtype ) ) { 987 /** 988 * Filters the sanitization of a specific meta key of a specific meta type and subtype. 989 * 990 * The dynamic portions of the hook name, `$object_type`, `$object_subtype` 991 * and `$meta_key`, refer to the metadata object type (comment, post, term or user), 992 * the object subtype and the meta key value, respectively. 993 * 994 * @since 5.0.0 995 * 996 * @param mixed $meta_value Meta value to sanitize. 997 * @param string $meta_key Meta key. 998 * @param string $object_type Object type. 999 * @param string $object_subtype Object subtype. 1000 */ 1001 $meta_value = apply_filters( "sanitize_{$object_type}_{$object_subtype}_meta_{$meta_key}", $meta_value, $meta_key, $object_type, $object_subtype ); 1002 } 1003 979 1004 /** 980 1005 * Filters the sanitization of a specific meta key of a specific meta type. 981 1006 * … … 999 1024 * @since 4.6.0 {@link https://core.trac.wordpress.org/ticket/35658 Modified 1000 1025 * to support an array of data to attach to registered meta keys}. Previous arguments for 1001 1026 * `$sanitize_callback` and `$auth_callback` have been folded into this array. 1027 * @since 5.0.0 The `$object_subtype` argument was added to the arguments array. 1002 1028 * 1003 1029 * @param string $object_type Type of object this meta is registered to. 1004 1030 * @param string $meta_key Meta key to register. 1005 1031 * @param array $args { 1006 1032 * Data used to describe the meta key when registered. 1007 1033 * 1034 * @type string $object_subtype A subtype; e.g. if the object type is "post", the post type. If left empty, 1035 * the meta key will be registered on the entire object type. Default empty. 1008 1036 * @type string $type The type of data associated with this meta key. 1009 1037 * Valid values are 'string', 'boolean', 'integer', and 'number'. 1010 1038 * @type string $description A description of the data attached to this meta key. … … 1027 1055 } 1028 1056 1029 1057 $defaults = array( 1058 'object_subtype' => '', 1030 1059 'type' => 'string', 1031 1060 'description' => '', 1032 1061 'single' => false, … … 1067 1096 $args = apply_filters( 'register_meta_args', $args, $defaults, $object_type, $meta_key ); 1068 1097 $args = wp_parse_args( $args, $defaults ); 1069 1098 1099 $object_subtype = ! empty( $args['object_subtype'] ) ? $args['object_subtype'] : ''; 1100 1070 1101 // If `auth_callback` is not provided, fall back to `is_protected_meta()`. 1071 1102 if ( empty( $args['auth_callback'] ) ) { 1072 1103 if ( is_protected_meta( $meta_key, $object_type ) ) { … … 1078 1109 1079 1110 // Back-compat: old sanitize and auth callbacks are applied to all of an object type. 1080 1111 if ( is_callable( $args['sanitize_callback'] ) ) { 1081 add_filter( "sanitize_{$object_type}_meta_{$meta_key}", $args['sanitize_callback'], 10, 3 ); 1112 if ( ! empty( $object_subtype ) ) { 1113 add_filter( "sanitize_{$object_type}_{$object_subtype}_meta_{$meta_key}", $args['sanitize_callback'], 10, 4 ); 1114 } else { 1115 add_filter( "sanitize_{$object_type}_meta_{$meta_key}", $args['sanitize_callback'], 10, 3 ); 1116 } 1082 1117 } 1083 1118 1084 1119 if ( is_callable( $args['auth_callback'] ) ) { 1085 add_filter( "auth_{$object_type}_meta_{$meta_key}", $args['auth_callback'], 10, 6 ); 1120 if ( ! empty( $object_subtype ) ) { 1121 add_filter( "auth_{$object_type}_{$object_subtype}_meta_{$meta_key}", $args['auth_callback'], 10, 6 ); 1122 } else { 1123 add_filter( "auth_{$object_type}_meta_{$meta_key}", $args['auth_callback'], 10, 6 ); 1124 } 1086 1125 } 1087 1126 1088 1127 // Global registry only contains meta keys registered with the array of arguments added in 4.6.0. 1089 1128 if ( ! $has_old_auth_cb && ! $has_old_sanitize_cb ) { 1090 $wp_meta_keys[ $object_type ][ $meta_key ] = $args; 1129 unset( $args['object_subtype'] ); 1130 1131 $wp_meta_keys[ $object_type ][ $object_subtype ][ $meta_key ] = $args; 1091 1132 1092 1133 return true; 1093 1134 } … … 1099 1140 * Checks if a meta key is registered. 1100 1141 * 1101 1142 * @since 4.6.0 1143 * @since 5.0.0 The `$object_subtype` parameter was added. 1102 1144 * 1103 1145 * @param string $object_type The type of object. 1104 1146 * @param string $meta_key The meta key. 1147 * @param string $object_subtype Optional. The subtype of the object type. 1105 1148 * 1106 * @return bool True if the meta key is registered to the object type. False if not. 1149 * @return bool True if the meta key is registered to the object type and, if provided, 1150 * the object subtype. False if not. 1107 1151 */ 1108 function registered_meta_key_exists( $object_type, $meta_key ) { 1109 global $wp_meta_keys; 1110 1111 if ( ! is_array( $wp_meta_keys ) ) { 1112 return false; 1113 } 1114 1115 if ( ! isset( $wp_meta_keys[ $object_type ] ) ) { 1116 return false; 1117 } 1118 1119 if ( isset( $wp_meta_keys[ $object_type ][ $meta_key ] ) ) { 1120 return true; 1121 } 1152 function registered_meta_key_exists( $object_type, $meta_key, $object_subtype = '' ) { 1153 $meta_keys = get_registered_meta_keys( $object_type, $object_subtype ); 1122 1154 1123 return false;1155 return isset( $meta_keys[ $meta_key ] ); 1124 1156 } 1125 1157 1126 1158 /** 1127 1159 * Unregisters a meta key from the list of registered keys. 1128 1160 * 1129 1161 * @since 4.6.0 1162 * @since 5.0.0 The `$object_subtype` parameter was added. 1130 1163 * 1131 * @param string $object_type The type of object. 1132 * @param string $meta_key The meta key. 1164 * @param string $object_type The type of object. 1165 * @param string $meta_key The meta key. 1166 * @param string $object_subtype Optional. The subtype of the object type. 1133 1167 * @return bool True if successful. False if the meta key was not registered. 1134 1168 */ 1135 function unregister_meta_key( $object_type, $meta_key ) {1169 function unregister_meta_key( $object_type, $meta_key, $object_subtype = '' ) { 1136 1170 global $wp_meta_keys; 1137 1171 1138 if ( ! registered_meta_key_exists( $object_type, $meta_key ) ) {1172 if ( ! registered_meta_key_exists( $object_type, $meta_key, $object_subtype ) ) { 1139 1173 return false; 1140 1174 } 1141 1175 1142 $args = $wp_meta_keys[ $object_type ][ $ meta_key ];1176 $args = $wp_meta_keys[ $object_type ][ $object_subtype ][ $meta_key ]; 1143 1177 1144 1178 if ( isset( $args['sanitize_callback'] ) && is_callable( $args['sanitize_callback'] ) ) { 1145 remove_filter( "sanitize_{$object_type}_meta_{$meta_key}", $args['sanitize_callback'] ); 1179 if ( ! empty( $object_subtype ) ) { 1180 remove_filter( "sanitize_{$object_type}_{$object_subtype}_meta_{$meta_key}", $args['sanitize_callback'] ); 1181 } else { 1182 remove_filter( "sanitize_{$object_type}_meta_{$meta_key}", $args['sanitize_callback'] ); 1183 } 1146 1184 } 1147 1185 1148 1186 if ( isset( $args['auth_callback'] ) && is_callable( $args['auth_callback'] ) ) { 1149 remove_filter( "auth_{$object_type}_meta_{$meta_key}", $args['auth_callback'] ); 1187 if ( ! empty( $object_subtype ) ) { 1188 remove_filter( "auth_{$object_type}_{$object_subtype}_meta_{$meta_key}", $args['auth_callback'] ); 1189 } else { 1190 remove_filter( "auth_{$object_type}_meta_{$meta_key}", $args['auth_callback'] ); 1191 } 1150 1192 } 1151 1193 1152 unset( $wp_meta_keys[ $object_type ][ $ meta_key ] );1194 unset( $wp_meta_keys[ $object_type ][ $object_subtype ][ $meta_key ] ); 1153 1195 1154 1196 // Do some clean up 1197 if ( empty( $wp_meta_keys[ $object_type ][ $object_subtype ] ) ) { 1198 unset( $wp_meta_keys[ $object_type ][ $object_subtype ] ); 1199 } 1155 1200 if ( empty( $wp_meta_keys[ $object_type ] ) ) { 1156 1201 unset( $wp_meta_keys[ $object_type ] ); 1157 1202 } … … 1163 1208 * Retrieves a list of registered meta keys for an object type. 1164 1209 * 1165 1210 * @since 4.6.0 1211 * @since 5.0.0 The `$object_subtype` parameter was added. 1166 1212 * 1167 * @param string $object_type The type of object. Post, comment, user, term. 1213 * @param string $object_type The type of object. Post, comment, user, term. 1214 * @param string $object_subtype Optional. The subtype of the object type. 1168 1215 * @return array List of registered meta keys. 1169 1216 */ 1170 function get_registered_meta_keys( $object_type ) {1217 function get_registered_meta_keys( $object_type, $object_subtype = '' ) { 1171 1218 global $wp_meta_keys; 1172 1219 1173 if ( ! is_array( $wp_meta_keys ) || ! isset( $wp_meta_keys[ $object_type ] ) ) {1220 if ( ! is_array( $wp_meta_keys ) || ! isset( $wp_meta_keys[ $object_type ] ) || ! isset( $wp_meta_keys[ $object_type ][ $object_subtype ] ) ) { 1174 1221 return array(); 1175 1222 } 1176 1223 1177 return $wp_meta_keys[ $object_type ] ;1224 return $wp_meta_keys[ $object_type ][ $object_subtype ]; 1178 1225 } 1179 1226 1180 1227 /** 1181 1228 * Retrieves registered metadata for a specified object. 1182 1229 * 1230 * The results include both meta that is registered specifically for the 1231 * object's subtype and meta that is registered for the entire object type. 1232 * 1183 1233 * @since 4.6.0 1184 1234 * 1185 1235 * @param string $object_type Type of object to request metadata for. (e.g. comment, post, term, user) … … 1187 1237 * @param string $meta_key Optional. Registered metadata key. If not specified, retrieve all registered 1188 1238 * metadata for the specified object. 1189 1239 * @return mixed A single value or array of values for a key if specified. An array of all registered keys 1190 * and values for an object ID if not. 1240 * and values for an object ID if not. False if a given $meta_key is not registered. 1191 1241 */ 1192 1242 function get_registered_metadata( $object_type, $object_id, $meta_key = '' ) { 1243 $object_subtype = get_object_subtype( $object_type, $object_id ); 1244 1193 1245 if ( ! empty( $meta_key ) ) { 1194 if ( ! registered_meta_key_exists( $object_type, $meta_key ) ) { 1246 if ( ! empty( $object_subtype ) && ! registered_meta_key_exists( $object_type, $meta_key, $object_subtype ) ) { 1247 $object_subtype = ''; 1248 } 1249 1250 if ( ! registered_meta_key_exists( $object_type, $meta_key, $object_subtype ) ) { 1195 1251 return false; 1196 1252 } 1197 $meta_keys = get_registered_meta_keys( $object_type ); 1253 1254 $meta_keys = get_registered_meta_keys( $object_type, $object_subtype ); 1198 1255 $meta_key_data = $meta_keys[ $meta_key ]; 1199 1256 1200 1257 $data = get_metadata( $object_type, $object_id, $meta_key, $meta_key_data['single'] ); … … 1214 1271 } 1215 1272 } 1216 1273 1274 if ( ! empty( $object_subtype ) ) { 1275 $meta_keys = get_registered_meta_keys( $object_type, $object_subtype ); 1276 1277 foreach ( $meta_keys as $k => $v ) { 1278 if ( isset( $data[ $k ] ) ) { 1279 $registered_data[ $k ] = $data[ $k ]; 1280 } 1281 } 1282 } 1283 1217 1284 return $registered_data; 1218 1285 } 1219 1286 … … 1242 1309 1243 1310 return $args; 1244 1311 } 1312 1313 /** 1314 * Returns the object subtype for a given object ID of a specific type. 1315 * 1316 * @since 5.0.0 1317 * 1318 * @param string $object_type Type of object to request metadata for. (e.g. comment, post, term, user) 1319 * @param int $object_id ID of the object to retrieve its subtype. 1320 * @return string The object subtype or an empty string if unspecified subtype. 1321 */ 1322 function get_object_subtype( $object_type, $object_id ) { 1323 $object_id = (int) $object_id; 1324 $object_subtype = ''; 1325 1326 switch ( $object_type ) { 1327 case 'post': 1328 $post = get_post( $object_id ); 1329 if ( ! $post ) { 1330 break; 1331 } 1332 1333 $object_subtype = get_post_type( $post ); 1334 break; 1335 1336 case 'comment': 1337 $comment = get_comment( $object_id ); 1338 if ( ! $comment ) { 1339 break; 1340 } 1341 1342 $object_subtype = 'comment'; 1343 break; 1344 1345 case 'term': 1346 $term = get_term( $object_id ); 1347 if ( ! $term instanceof WP_Term ) { 1348 break; 1349 } 1350 1351 $object_subtype = $term->taxonomy; 1352 break; 1353 1354 case 'user': 1355 $user = get_user_by( 'id', $object_id ); 1356 if ( ! $user ) { 1357 break; 1358 } 1359 1360 $object_subtype = 'user'; 1361 break; 1362 default: 1363 1364 /** 1365 * Filters the object subtype identifier for a non standard object type. 1366 * 1367 * The dynamic portion of the hook, `$object_type`, refers to the object 1368 * type (post, comment, term, or user). 1369 * 1370 * @since 5.0.0 1371 * 1372 * @param string $object_subtype Empty string to override. 1373 * @param int $object_id ID of the object to get the subtype for. 1374 */ 1375 $object_subtype = apply_filters( "get_object_subtype_{$object_type}", $object_subtype, $object_id ); 1376 } 1377 1378 return $object_subtype; 1379 } -
src/wp-includes/rest-api/fields/class-wp-rest-comment-meta-fields.php
28 28 } 29 29 30 30 /** 31 * Retrieves the object meta subtype. 32 * 33 * @since 5.0.0 34 * 35 * @return string Subtype for the meta type, or empty string if no specific subtype. 36 */ 37 protected function get_meta_subtype() { 38 return 'comment'; 39 } 40 41 /** 31 42 * Retrieves the type for register_rest_field() in the context of comments. 32 43 * 33 44 * @since 4.7.0 -
src/wp-includes/rest-api/fields/class-wp-rest-meta-fields.php
25 25 abstract protected function get_meta_type(); 26 26 27 27 /** 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 /** 28 39 * Retrieves the object type for register_rest_field(). 29 40 * 30 41 * @since 4.7.0 … … 340 351 protected function get_registered_fields() { 341 352 $registered = array(); 342 353 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 ) { 344 363 if ( empty( $args['show_in_rest'] ) ) { 345 364 continue; 346 365 } -
src/wp-includes/rest-api/fields/class-wp-rest-post-meta-fields.php
47 47 } 48 48 49 49 /** 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 /** 50 61 * Retrieves the type for register_rest_field(). 51 62 * 52 63 * @since 4.7.0 -
src/wp-includes/rest-api/fields/class-wp-rest-term-meta-fields.php
47 47 } 48 48 49 49 /** 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 /** 50 61 * Retrieves the type for register_rest_field(). 51 62 * 52 63 * @since 4.7.0 -
src/wp-includes/rest-api/fields/class-wp-rest-user-meta-fields.php
28 28 } 29 29 30 30 /** 31 * Retrieves the object meta subtype. 32 * 33 * @since 5.0.0 34 * 35 * @return string Subtype for the meta type, or empty string if no specific subtype. 36 */ 37 protected function get_meta_subtype() { 38 return 'user'; 39 } 40 41 /** 31 42 * Retrieves the type for register_rest_field(). 32 43 * 33 44 * @since 4.7.0 -
tests/phpunit/tests/meta/registerMeta.php
74 74 75 75 $expected = array( 76 76 'post' => array( 77 'flight_number' => array( 78 'type' => 'string', 79 'description' => '', 80 'single' => false, 81 'sanitize_callback' => null, 82 'auth_callback' => '__return_true', 83 'show_in_rest' => false, 77 '' => array( 78 'flight_number' => array( 79 'type' => 'string', 80 'description' => '', 81 'single' => false, 82 'sanitize_callback' => null, 83 'auth_callback' => '__return_true', 84 'show_in_rest' => false, 85 ), 84 86 ), 85 87 ), 86 88 ); … … 96 98 97 99 $expected = array( 98 100 'term' => array( 99 'category_icon' => array( 100 'type' => 'string', 101 'description' => '', 102 'single' => false, 103 'sanitize_callback' => null, 104 'auth_callback' => '__return_true', 105 'show_in_rest' => false, 101 '' => array( 102 'category_icon' => array( 103 'type' => 'string', 104 'description' => '', 105 'single' => false, 106 'sanitize_callback' => null, 107 'auth_callback' => '__return_true', 108 'show_in_rest' => false, 109 ), 106 110 ), 107 111 ), 108 112 ); … … 148 152 149 153 $expected = array( 150 154 'post' => array( 151 'flight_number' => array( 152 'type' => 'string', 153 'description' => '', 154 'single' => false, 155 'sanitize_callback' => array( $this, '_new_sanitize_meta_cb' ), 156 'auth_callback' => '__return_true', 157 'show_in_rest' => false, 155 '' => array( 156 'flight_number' => array( 157 'type' => 'string', 158 'description' => '', 159 'single' => false, 160 'sanitize_callback' => array( $this, '_new_sanitize_meta_cb' ), 161 'auth_callback' => '__return_true', 162 'show_in_rest' => false, 163 ), 158 164 ), 159 165 ), 160 166 );