Changeset 64686
- Timestamp:
- 10/23/2026 07:31:51 AM (7 hours ago)
- Location:
- trunk
- Files:
-
- 1 added
- 15 edited
-
src/wp-includes/class-wp-entity-actions-registry.php (modified) (2 diffs)
-
src/wp-includes/class-wp-entity-fields-registry.php (modified) (3 diffs)
-
src/wp-includes/entity-actions.php (modified) (5 diffs)
-
src/wp-includes/entity-fields.php (modified) (6 diffs)
-
src/wp-includes/entity-utils.php (added)
-
src/wp-includes/rest-api/endpoints/class-wp-rest-entity-actions-controller.php (modified) (1 diff)
-
src/wp-includes/rest-api/endpoints/class-wp-rest-entity-fields-controller.php (modified) (1 diff)
-
src/wp-settings.php (modified) (1 diff)
-
tests/phpunit/tests/entity-actions.php (modified) (9 diffs)
-
tests/phpunit/tests/entity-actions/registerCoreEntityActions.php (modified) (4 diffs)
-
tests/phpunit/tests/entity-fields/wpAddEntityFieldModulesToEditorScript.php (modified) (1 diff)
-
tests/phpunit/tests/entity-fields/wpEntityFieldsRegistry.php (modified) (8 diffs)
-
tests/phpunit/tests/entity-fields/wpPreloadEntityFields.php (modified) (3 diffs)
-
tests/phpunit/tests/entity-fields/wpRegisterCoreFieldCollections.php (modified) (8 diffs)
-
tests/phpunit/tests/entity-fields/wpRegisterEntityFieldCollection.php (modified) (1 diff)
-
tests/phpunit/tests/rest-api/rest-entity-fields-controller.php (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/wp-includes/class-wp-entity-actions-registry.php
r64601 r64686 405 405 * @param string $kind The entity kind (e.g. `postType`). 406 406 * @param string $name The entity name (e.g. `page`). 407 * @return array<string, string[]> The ids of the actions each module 408 * applies to, keyed by module id, in 409 * registration order. Empty when the 410 * entity is invalid. 407 * @return array[] { 408 * The script modules, in registration order. Empty when the entity 409 * is invalid. 410 * 411 * @type array ...$0 { 412 * @type string $id The id of the script module. 413 * @type string[] $actions The ids of the actions the module 414 * applies to, in registration order. 415 * } 416 * } 411 417 */ 412 418 public function get_registered_action_modules( $kind, $name ) { … … 415 421 } 416 422 $this->initialize(); 417 return $this->action_modules[ $kind ][ $name ] ?? array(); 423 $modules = array(); 424 foreach ( $this->action_modules[ $kind ][ $name ] ?? array() as $module => $action_ids ) { 425 $modules[] = array( 426 // A numeric module id is an integer as an array key. 427 'id' => (string) $module, 428 'actions' => $action_ids, 429 ); 430 } 431 return $modules; 418 432 } 419 433 -
trunk/src/wp-includes/class-wp-entity-fields-registry.php
r64528 r64686 478 478 * @param string $kind The entity kind (e.g. `postType`). 479 479 * @param string $name The entity name (e.g. `page`). 480 * @return array<string, string[]> The ids of the fields each module 481 * applies to, keyed by module id, in 482 * registration order. 480 * @return array[] { 481 * The script modules, in registration order. 482 * 483 * @type array ...$0 { 484 * @type string $id The id of the script module. 485 * @type string[] $fields The ids of the fields the module applies 486 * to, in registration order. 487 * } 488 * } 483 489 */ 484 490 public function get_registered_field_modules( $kind, $name ) { 485 491 $this->initialize(); 486 return $this->field_modules[ $kind ][ $name ] ?? array(); 492 $modules = array(); 493 foreach ( $this->field_modules[ $kind ][ $name ] ?? array() as $module => $field_ids ) { 494 $modules[] = array( 495 // A numeric module id is an integer as an array key. 496 'id' => (string) $module, 497 'fields' => $field_ids, 498 ); 499 } 500 return $modules; 487 501 } 488 502 … … 498 512 public function get_all_registered_field_modules() { 499 513 $this->initialize(); 514 /* 515 * Keeps the module ids and drops the field ids they apply to, e.g.: 516 * 517 * array( 518 * 'postType' => array( 519 * 'page' => array( 'my-plugin/fields', '123' ), 520 * 'post' => array( 'my-plugin/fields' ), 521 * ), 522 * ) 523 */ 500 524 return array_map( 501 525 static function ( $entities ) { 502 return array_map( 'array_keys', $entities ); 526 return array_map( 527 static function ( $modules ) { 528 // A numeric module id is an integer as an array key. 529 return array_map( 'strval', array_keys( $modules ) ); 530 }, 531 $entities 532 ); 503 533 }, 504 534 $this->field_modules … … 732 762 $invalid = array(); 733 763 foreach ( $fields as $position => $field ) { 734 if ( is_array( $field ) && ! empty( $field['id'] ) && is_string( $field['id'] )) {764 if ( is_array( $field ) && isset( $field['id'] ) && is_string( $field['id'] ) && '' !== $field['id'] ) { 735 765 $valid[] = $field; 736 766 } else { -
trunk/src/wp-includes/entity-actions.php
r64595 r64686 81 81 82 82 /** 83 * Returns the ids of thescript modules registered for the given entity.83 * Returns the script modules registered for the given entity. 84 84 * 85 85 * @since 7.2.0 … … 87 87 * @param string $kind The entity kind (e.g. `postType`). 88 88 * @param string $name The entity name (e.g. `page`). 89 * @return array<string, string[]> The ids of the actions each module 90 * applies to, keyed by module id, in 91 * registration order. Empty until the 92 * `init` action has completed: a read 93 * before then is refused. 89 * @return array[] { 90 * The script modules, in registration order. Empty until the `init` 91 * action has completed: a read before then is refused. 92 * 93 * @type array ...$0 { 94 * @type string $id The id of the script module. 95 * @type string[] $actions The ids of the actions the module applies 96 * to, in registration order. 97 * } 98 * } 94 99 */ 95 100 function wp_get_registered_entity_action_modules( $kind, $name ) { … … 115 120 /** 116 121 * Declares the script modules of the entity actions as dependencies of the 117 * editor script .122 * editor script, see _wp_add_entity_modules_to_editor_script(). 118 123 * 119 * The editor imports the script modules of an entity on demand, with a dynamic 120 * `import()` the browser resolves through the import map of the page. Listing 121 * the modules as dynamic `module_dependencies` of the `wp-editor` script adds 122 * them to the import map of every page that loads the editor script: the post 123 * editor, the site editor, and the pages booted by `@wordpress/boot`, whose 124 * prerequisites depend on it. A dynamic dependency is only listed in the 125 * import map; the module is fetched when it is imported. 126 * 127 * Reading the registry fires `wp_entity_actions_api_init`, so the actions and their 128 * script modules are registered on demand. It only reads the registry on the 129 * pages that load the editor script, not on every admin request (heartbeat, 130 * Ajax, other screens). It runs on `admin_footer`, the last action before the 131 * import map is printed that fires both in the admin template and in the pages 132 * rendered outside it, which print the import map themselves. By then `init` 133 * has completed, so the post types and supports the actions derive from are 134 * final. 135 * The registry only accepts registrations while the action fires, so the 136 * modules declared here are the modules of every action the page can show. 124 * The actions are loaded by `usePostActions()` of the editor script, so every 125 * screen showing them loads it. 137 126 * 138 127 * The `admin_footer` action passes it no argument, so the global registry is … … 140 129 * 141 130 * @since 7.2.0 131 * @access private 142 132 * 143 133 * @param WP_Scripts|null $scripts The scripts registry. Defaults to the global one. 144 134 */ 145 135 function _wp_add_entity_action_modules_to_editor_script( $scripts = null ) { 146 if ( ! $scripts instanceof WP_Scripts ) { 147 $scripts = wp_scripts(); 148 } 149 150 // The actions are loaded by `usePostActions()` of the editor script, so 151 // every screen showing them loads it. 152 if ( ! $scripts->query( 'wp-editor', 'enqueued' ) && ! $scripts->query( 'wp-editor', 'done' ) ) { 153 return; 154 } 155 156 $kinds = wp_get_all_registered_entity_action_modules(); 157 if ( empty( $kinds ) ) { 158 return; 159 } 160 161 $dependencies = $scripts->get_data( 'wp-editor', 'module_dependencies' ); 162 $dependencies = is_array( $dependencies ) ? $dependencies : array(); 163 164 $declared = array(); 165 foreach ( $dependencies as $dependency ) { 166 $declared[] = is_array( $dependency ) ? $dependency['id'] : $dependency; 167 } 168 169 $added = false; 170 foreach ( $kinds as $entities ) { 171 foreach ( $entities as $modules ) { 172 foreach ( $modules as $module ) { 173 if ( ! in_array( $module, $declared, true ) ) { 174 $dependencies[] = array( 175 'id' => $module, 176 'import' => 'dynamic', 177 ); 178 $declared[] = $module; 179 $added = true; 180 } 181 } 182 } 183 } 184 185 if ( $added ) { 186 // `add_data()` replaces the value, hence the merge above. 187 $scripts->add_data( 'wp-editor', 'module_dependencies', $dependencies ); 188 } 136 _wp_add_entity_modules_to_editor_script( $scripts, 'wp_get_all_registered_entity_action_modules' ); 189 137 } 190 138 … … 202 150 * 203 151 * @since 7.2.0 152 * @access private 204 153 * 205 * @param array$paths REST API paths to preload.206 * @param WP_Block_Editor_Context $context Block editor context.207 * @return array Filtered preload paths.154 * @param mixed $paths REST API paths to preload. 155 * @param mixed $context Optional. Block editor context. Default null. 156 * @return mixed Filtered preload paths. See _wp_add_entity_preload_paths(). 208 157 */ 209 function _wp_preload_entity_actions( $paths, $context ) { 210 $post_types = array(); 211 if ( 'core/edit-post' === $context->name && isset( $context->post ) ) { 212 $post_types[] = $context->post->post_type; 213 } elseif ( 'core/edit-site' === $context->name ) { 214 if ( isset( $context->post ) ) { 215 $post_types[] = $context->post->post_type; 216 } 217 $post_types = array_merge( $post_types, _wp_get_site_editor_screen_post_types() ); 218 } 219 220 foreach ( array_unique( $post_types ) as $post_type ) { 221 if ( ! post_type_exists( $post_type ) ) { 222 continue; 223 } 224 $paths[] = add_query_arg( 225 array( 226 'kind' => 'postType', 227 'name' => $post_type, 228 ), 229 '/wp/v2/entity-actions' 230 ); 231 } 232 233 return $paths; 158 function _wp_preload_entity_actions( $paths, $context = null ) { 159 return _wp_add_entity_preload_paths( $paths, $context, '/wp/v2/entity-actions' ); 234 160 } -
trunk/src/wp-includes/entity-fields.php
r64595 r64686 112 112 113 113 /** 114 * Returns the ids of thescript modules registered for the given entity.114 * Returns the script modules registered for the given entity. 115 115 * 116 116 * @since 7.2.0 … … 118 118 * @param string $kind The entity kind (e.g. `postType`). 119 119 * @param string $name The entity name (e.g. `page`). 120 * @return array<string, string[]> The ids of the fields each module applies 121 * to, keyed by module id, in registration 122 * order. Empty until the `init` action has 123 * completed: a read before then is refused. 120 * @return array[] { 121 * The script modules, in registration order. Empty until the `init` 122 * action has completed: a read before then is refused. 123 * 124 * @type array ...$0 { 125 * @type string $id The id of the script module. 126 * @type string[] $fields The ids of the fields the module applies to, 127 * in registration order. 128 * } 129 * } 124 130 */ 125 131 function wp_get_registered_entity_field_modules( $kind, $name ) { … … 145 151 /** 146 152 * Declares the script modules of the entity fields as dependencies of the 147 * editor script. 148 * 149 * The editor imports the script modules of an entity on demand, with a dynamic 150 * `import()` the browser resolves through the import map of the page. Listing 151 * the modules as dynamic `module_dependencies` of the `wp-editor` script adds 152 * them to the import map of every page that loads the editor script: the post 153 * editor, the site editor, and the pages booted by `@wordpress/boot`, whose 154 * prerequisites depend on it. A dynamic dependency is only listed in the 155 * import map; the module is fetched when it is imported. 156 * 157 * Reading the registry fires `wp_entity_fields_api_init`, so the fields and their 158 * script modules are registered on demand. It only reads the registry on the 159 * pages that load the editor script, not on every admin request (heartbeat, 160 * Ajax, other screens). It runs on `admin_footer`, the last action before the 161 * import map is printed that fires both in the admin template and in the pages 162 * rendered outside it, which print the import map themselves. By then `init` 163 * has completed, so the supports the default fields derive from are final. 164 * The registry only accepts registrations while the action fires, so the 165 * modules declared here are the modules of every field the page can show. 153 * editor script, see _wp_add_entity_modules_to_editor_script(). 154 * 155 * The fields are loaded by the editor package, see 156 * packages/editor/src/dataviews/store/private-resolvers.ts in Gutenberg, which 157 * means any screen that wants to use this mechanism needs to load the editor 158 * script. 166 159 * 167 160 * It is hooked to `admin_footer` without arguments, so the global scripts … … 175 168 */ 176 169 function _wp_add_entity_field_modules_to_editor_script( $scripts = null ) { 177 if ( ! $scripts instanceof WP_Scripts ) { 178 $scripts = wp_scripts(); 179 } 180 181 /* 182 * The fields are loaded by the editor package, see 183 * packages/editor/src/dataviews/store/private-resolvers.ts in Gutenberg, 184 * which means any screen that wants to use this mechanism needs to load 185 * the editor script. 186 */ 187 if ( ! $scripts->query( 'wp-editor', 'enqueued' ) && ! $scripts->query( 'wp-editor', 'done' ) ) { 188 return; 189 } 190 191 $kinds = wp_get_all_registered_entity_field_modules(); 192 if ( empty( $kinds ) ) { 193 return; 194 } 195 196 $dependencies = $scripts->get_data( 'wp-editor', 'module_dependencies' ); 197 $dependencies = is_array( $dependencies ) ? $dependencies : array(); 198 199 $declared = array(); 200 foreach ( $dependencies as $dependency ) { 201 $declared[] = is_array( $dependency ) ? $dependency['id'] : $dependency; 202 } 203 204 $added = false; 205 foreach ( $kinds as $entities ) { 206 foreach ( $entities as $modules ) { 207 foreach ( $modules as $module ) { 208 if ( ! in_array( $module, $declared, true ) ) { 209 $dependencies[] = array( 210 'id' => $module, 211 'import' => 'dynamic', 212 ); 213 $declared[] = $module; 214 $added = true; 215 } 216 } 217 } 218 } 219 220 if ( $added ) { 221 // `add_data()` replaces the value, hence the merge above. 222 $scripts->add_data( 'wp-editor', 'module_dependencies', $dependencies ); 223 } 170 _wp_add_entity_modules_to_editor_script( $scripts, 'wp_get_all_registered_entity_field_modules' ); 224 171 } 225 172 … … 254 201 function wp_register_entity_field_collection( $directory ) { 255 202 return WP_Entity_Fields_Registry::get_instance()->register_collection( $directory ); 256 }257 258 /**259 * Returns the paths that serve the fields of the given post types, skipping260 * the post types that are not registered.261 *262 * A path must match the request of the `getFieldsConfig` core data resolver,263 * see packages/core-data/src/resolvers.js in Gutenberg.264 *265 * @since 7.2.0266 * @access private267 *268 * @param string[] $post_types The post types.269 * @return string[] One path of the `/wp/v2/entity-fields` route per post type,270 * in the order the post types are given, without duplicates.271 */272 function _wp_get_post_type_fields_preload_paths( $post_types ) {273 $paths = array();274 foreach ( array_unique( $post_types ) as $post_type ) {275 if ( ! post_type_exists( $post_type ) ) {276 continue;277 }278 $paths[] = add_query_arg(279 array(280 'kind' => 'postType',281 'name' => $post_type,282 ),283 '/wp/v2/entity-fields'284 );285 }286 287 return $paths;288 }289 290 /**291 * Returns the post types whose items the screen of the site editor being292 * loaded lists or edits, from its `p` query arg.293 *294 * The screens are the routes in295 * packages/edit-site/src/components/site-editor-routes in Gutenberg: the296 * lists and the editors of pages, templates, patterns, and template parts.297 * The patterns screen lists both patterns and template parts.298 *299 * @since 7.2.0300 * @access private301 *302 * @return string[] The post types, empty for any other screen.303 */304 function _wp_get_site_editor_screen_post_types() {305 // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Only picks what to preload.306 $path = isset( $_GET['p'] ) && is_string( $_GET['p'] ) ? sanitize_text_field( wp_unslash( $_GET['p'] ) ) : '';307 $segments = explode( '/', trim( $path, '/' ) );308 309 switch ( $segments[0] ) {310 case 'page':311 return array( 'page' );312 case 'template':313 case 'wp_template':314 return array( 'wp_template' );315 case 'pattern':316 return array( 'wp_block', 'wp_template_part' );317 case 'wp_block':318 return array( 'wp_block' );319 case 'wp_template_part':320 return array( 'wp_template_part' );321 }322 return array();323 203 } 324 204 … … 330 210 * post editor reads those of the edited post in the post summary of its 331 211 * inspector. The site editor reads those of the edited post, if any, and of 332 * the post types of the screen it opens on. 212 * the post types of the screen it opens on. A path must match the request of 213 * the `getFieldsConfig` core data resolver, see 214 * packages/core-data/src/resolvers.js in Gutenberg. 333 215 * 334 216 * @since 7.2.0 335 217 * @access private 336 218 * 337 * @param array $paths REST API paths to preload. 338 * @param WP_Block_Editor_Context $context Block editor context. 339 * @return array Filtered preload paths. 340 */ 341 function _wp_preload_entity_fields( $paths, $context ) { 342 $post_types = array(); 343 if ( 'core/edit-post' === $context->name && isset( $context->post ) ) { 344 $post_types[] = $context->post->post_type; 345 } elseif ( 'core/edit-site' === $context->name ) { 346 if ( isset( $context->post ) ) { 347 $post_types[] = $context->post->post_type; 348 } 349 $post_types = array_merge( $post_types, _wp_get_site_editor_screen_post_types() ); 350 } 351 352 return array_merge( 353 $paths, 354 _wp_get_post_type_fields_preload_paths( $post_types ) 355 ); 356 } 219 * @param mixed $paths REST API paths to preload. 220 * @param mixed $context Optional. Block editor context. Default null. 221 * @return mixed Filtered preload paths. See _wp_add_entity_preload_paths(). 222 */ 223 function _wp_preload_entity_fields( $paths, $context = null ) { 224 return _wp_add_entity_preload_paths( $paths, $context, '/wp/v2/entity-fields' ); 225 } -
trunk/src/wp-includes/rest-api/endpoints/class-wp-rest-entity-actions-controller.php
r64517 r64686 198 198 $name = $request->get_param( 'name' ); 199 199 200 $script_modules = array();201 foreach ( wp_get_registered_entity_action_modules( $kind, $name ) as $module => $action_ids ) {202 $script_modules[] = array(203 // A numeric module id is an integer as an array key.204 'id' => (string) $module,205 'actions' => array_values( $action_ids ),206 );207 }208 209 200 $response = array( 210 201 'kind' => $kind, 211 202 'name' => $name, 212 203 'actions' => wp_get_registered_entity_actions( $kind, $name ), 213 'script_modules' => $script_modules,204 'script_modules' => wp_get_registered_entity_action_modules( $kind, $name ), 214 205 ); 215 206 -
trunk/src/wp-includes/rest-api/endpoints/class-wp-rest-entity-fields-controller.php
r64602 r64686 160 160 } 161 161 162 $script_modules = array();163 foreach ( wp_get_registered_entity_field_modules( $kind, $name ) as $module => $field_ids ) {164 $script_modules[] = array(165 'id' => $module,166 'fields' => array_values( $field_ids ),167 );168 }169 170 162 $response = array( 171 163 'kind' => $kind, 172 164 'name' => $name, 173 165 'fields' => $fields, 174 'script_modules' => $script_modules,166 'script_modules' => wp_get_registered_entity_field_modules( $kind, $name ), 175 167 ); 176 168 -
trunk/src/wp-settings.php
r64581 r64686 207 207 require ABSPATH . WPINC . '/class-wp-view-config-data.php'; 208 208 require ABSPATH . WPINC . '/view-config.php'; 209 require ABSPATH . WPINC . '/entity-utils.php'; 209 210 require ABSPATH . WPINC . '/class-wp-entity-actions-registry.php'; 210 211 require ABSPATH . WPINC . '/entity-actions.php'; -
trunk/tests/phpunit/tests/entity-actions.php
r64601 r64686 9 9 * 10 10 * @covers ::_wp_add_entity_action_modules_to_editor_script 11 * @covers ::_wp_add_entity_modules_to_editor_script 12 * @covers ::_wp_add_entity_preload_paths 11 13 * @covers ::_wp_preload_entity_actions 12 14 * @covers ::wp_get_all_registered_entity_action_modules … … 672 674 'The removed action is gone, and the replaced one has the new definition and origin.' 673 675 ); 674 $this->assertSame( array( 'core/defaults' => array( 'move-to-trash' ) ), $modules, 'The replaced action keeps the script module of the default.' ); 676 $this->assertSame( 677 array( 678 array( 679 'id' => 'core/defaults', 680 'actions' => array( 'move-to-trash' ), 681 ), 682 ), 683 $modules, 684 'The replaced action keeps the script module of the default.' 685 ); 675 686 } 676 687 … … 718 729 $this->assertSame( 'Rename…', $actions['rename-post']['label'], 'The registered action is left untouched.' ); 719 730 $this->assertSame( 'core', $actions['rename-post']['origin']['registeredBy'] ); 720 $this->assertSame( array( 'feature' ), wp_get_registered_entity_action_modules( 'postType', 'page' )['plugin/actions'], 'The script module only applies to the actions registered.' );731 $this->assertSame( array( 'feature' ), array_column( wp_get_registered_entity_action_modules( 'postType', 'page' ), 'actions', 'id' )['plugin/actions'], 'The script module only applies to the actions registered.' ); 721 732 $this->assertCount( 1, $reported ); 722 733 $this->assertStringContainsString( 'postType "page"', $reported[0], 'The notice names the entity.' ); … … 814 825 $this->assertSame( 815 826 array( 816 'core/defaults' => array( 'rename-post', 'move-to-trash' ), 817 'plugin/actions' => array( 'feature', 'archive' ), 818 'other-plugin/actions' => array( 'share' ), 827 array( 828 'id' => 'core/defaults', 829 'actions' => array( 'rename-post', 'move-to-trash' ), 830 ), 831 array( 832 'id' => 'plugin/actions', 833 'actions' => array( 'feature', 'archive' ), 834 ), 835 array( 836 'id' => 'other-plugin/actions', 837 'actions' => array( 'share' ), 838 ), 819 839 ), 820 840 wp_get_registered_entity_action_modules( 'postType', 'page' ), … … 845 865 $this->assertSame( array(), wp_get_registered_entity_actions( 'a/b', 'c' ) ); 846 866 $this->assertSame( array( 'feature', 'archive' ), array_column( wp_get_registered_entity_actions( 'a', 'b/c' ), 'id' ), 'The second entity keeps its actions.' ); 847 $this->assertSame( array( 'plugin/second' => array( 'feature', 'archive' ) ), wp_get_registered_entity_action_modules( 'a', 'b/c' ), 'The second entity keeps only its own module.' ); 867 $this->assertSame( 868 array( 869 array( 870 'id' => 'plugin/second', 871 'actions' => array( 'feature', 'archive' ), 872 ), 873 ), 874 wp_get_registered_entity_action_modules( 'a', 'b/c' ), 875 'The second entity keeps only its own module.' 876 ); 848 877 $this->assertSame( array( 'b/c' => array( 'plugin/second' ) ), wp_get_all_registered_entity_action_modules()['a'], 'Only the second entity has modules under its kind.' ); 849 878 $this->assertArrayNotHasKey( 'a/b', wp_get_all_registered_entity_action_modules(), 'The kind of the first entity, emptied, is forgotten.' ); … … 882 911 'The actions unregistered by id are returned in registration order.' 883 912 ); 884 $this->assertSame( array( 'plugin/first' => array( 'b' ) ), $modules['by_id'], 'The unregistered actions leave their modules, and an emptied module is forgotten.' ); 913 $this->assertSame( 914 array( 915 array( 916 'id' => 'plugin/first', 917 'actions' => array( 'b' ), 918 ), 919 ), 920 $modules['by_id'], 921 'The unregistered actions leave their modules, and an emptied module is forgotten.' 922 ); 885 923 $this->assertSame( array(), $unregistered['missing'], 'Nothing is returned when no action is registered.' ); 886 924 $this->assertSame( … … 989 1027 $this->assertCount( 3, $reported ); 990 1028 $this->assertNotContains( 'feature', array_column( wp_get_registered_entity_actions( 'postType', 'page' ), 'id' ) ); 991 $this->assert ArrayNotHasKey( 'plugin/actions', wp_get_registered_entity_action_modules( 'postType', 'page' ) );1029 $this->assertNotContains( 'plugin/actions', array_column( wp_get_registered_entity_action_modules( 'postType', 'page' ), 'id' ) ); 992 1030 } 993 1031 … … 1085 1123 1086 1124 $this->assertSame( array( 'core/defaults', '123' ), wp_get_all_registered_entity_action_modules()['postType']['page'] ); 1125 $this->assertSame( array( 'core/defaults', '123' ), array_column( wp_get_registered_entity_action_modules( 'postType', 'page' ), 'id' ) ); 1087 1126 } 1088 1127 … … 1103 1142 $this->assertSame( $fired, did_action( 'wp_entity_actions_api_init' ), 'Refusing does not fire the action.' ); 1104 1143 $this->assertNotContains( 'feature', array_column( wp_get_registered_entity_actions( 'postType', 'page' ), 'id' ) ); 1105 $this->assert ArrayNotHasKey( 'plugin/feature', wp_get_registered_entity_action_modules( 'postType', 'page' ) );1144 $this->assertNotContains( 'plugin/feature', array_column( wp_get_registered_entity_action_modules( 'postType', 'page' ), 'id' ) ); 1106 1145 } 1107 1146 -
trunk/tests/phpunit/tests/entity-actions/registerCoreEntityActions.php
r64566 r64686 165 165 self::PAGE => self::PAGE_ACTIONS, 166 166 ), 167 wp_get_registered_entity_action_modules( 'postType', 'page' ),167 array_column( wp_get_registered_entity_action_modules( 'postType', 'page' ), 'actions', 'id' ), 168 168 'Each action of pages is registered with the module of its folder.' 169 169 ); … … 206 206 self::WP_BLOCK => array( 'duplicate-pattern', 'export-pattern' ), 207 207 ), 208 wp_get_registered_entity_action_modules( 'postType', 'wp_block' ),208 array_column( wp_get_registered_entity_action_modules( 'postType', 'wp_block' ), 'actions', 'id' ), 209 209 'The actions of patterns come from the `wp_block` module.' 210 210 ); … … 244 244 $this->assertSame( 245 245 array( 'duplicate-template-part' ), 246 wp_get_registered_entity_action_modules( 'postType', 'wp_template_part' )[ self::WP_TEMPLATE_PART ],246 array_column( wp_get_registered_entity_action_modules( 'postType', 'wp_template_part' ), 'actions', 'id' )[ self::WP_TEMPLATE_PART ], 247 247 'The action comes from the `wp_template_part` module.' 248 248 ); … … 523 523 self::PAGE => self::PAGE_ACTIONS, 524 524 ), 525 wp_get_registered_entity_action_modules( 'postType', 'page' ),525 array_column( wp_get_registered_entity_action_modules( 'postType', 'page' ), 'actions', 'id' ), 526 526 'The replaced action keeps the module of the core action.' 527 527 ); -
trunk/tests/phpunit/tests/entity-fields/wpAddEntityFieldModulesToEditorScript.php
r64566 r64686 13 13 * 14 14 * @covers ::_wp_add_entity_field_modules_to_editor_script 15 * @covers ::_wp_add_entity_modules_to_editor_script 15 16 */ 16 17 class Tests_Entity_Fields_WpAddEntityFieldModulesToEditorScript extends WP_Entity_Fields_UnitTestCase { -
trunk/tests/phpunit/tests/entity-fields/wpEntityFieldsRegistry.php
r64528 r64686 130 130 $this->assertSame( 'Author', $fields['author']['label'], 'The registered field is left untouched.' ); 131 131 $this->assertSame( 'core', $fields['author']['origin']['registeredBy'] ); 132 $this->assertSame( array( 'color' ), wp_get_registered_entity_field_modules( 'postType', 'page' )['plugin/fields'], 'The script module only applies to the fields registered.' );132 $this->assertSame( array( 'color' ), array_column( wp_get_registered_entity_field_modules( 'postType', 'page' ), 'fields', 'id' )['plugin/fields'], 'The script module only applies to the fields registered.' ); 133 133 $this->assertCount( 1, $reported ); 134 134 $this->assertStringContainsString( 'postType "page"', $reported[0], 'The notice names the entity.' ); … … 218 218 $this->assertSame( array(), wp_get_registered_entity_fields( 'a/b', 'c' ) ); 219 219 $this->assertSame( array( 'color', 'size' ), array_column( wp_get_registered_entity_fields( 'a', 'b/c' ), 'id' ), 'The second entity keeps its fields.' ); 220 $this->assertSame( array( 'plugin/second' => array( 'color', 'size' ) ), wp_get_registered_entity_field_modules( 'a', 'b/c' ), 'The second entity keeps only its own module.' ); 220 $this->assertSame( 221 array( 222 array( 223 'id' => 'plugin/second', 224 'fields' => array( 'color', 'size' ), 225 ), 226 ), 227 wp_get_registered_entity_field_modules( 'a', 'b/c' ), 228 'The second entity keeps only its own module.' 229 ); 221 230 $this->assertSame( array( 'b/c' => array( 'plugin/second' ) ), wp_get_all_registered_entity_field_modules()['a'], 'Only the second entity has modules under its kind.' ); 222 231 $this->assertArrayNotHasKey( 'a/b', wp_get_all_registered_entity_field_modules(), 'The kind of the first entity, emptied, is forgotten.' ); 232 } 233 234 /** 235 * A numeric module id is listed as a string, as it was registered, not 236 * as the integer its array key becomes. 237 * 238 * @ticket 66229 239 */ 240 public function test_all_registered_field_modules_lists_a_numeric_module_id_as_a_string() { 241 $this->register_fields( 'postType', 'post', array( $this->field( 'color' ) ), '42' ); 242 243 $this->assertSame( array( '42' ), wp_get_all_registered_entity_field_modules()['postType']['post'] ); 244 $this->assertSame( array( '42' ), array_column( wp_get_registered_entity_field_modules( 'postType', 'post' ), 'id' ) ); 223 245 } 224 246 … … 323 345 $fields[0]['origin'] 324 346 ); 325 $modules = wp_get_registered_entity_field_modules( 'postType', 'page' );347 $modules = array_column( wp_get_registered_entity_field_modules( 'postType', 'page' ), 'fields', 'id' ); 326 348 $this->assertContains( 'author', $modules['test/defaults'], 'The field keeps its modules.' ); 327 349 $this->assertSame( array( 'author' ), $modules['plugin/author'], 'The module applies to the field.' ); … … 397 419 $this->assertSame( 'Writer', $fields['author']['label'], 'The rest of the fields of the call are updated.' ); 398 420 $this->assertSame( array( 'test-plugin' ), $fields['author']['origin']['updatedBy'] ); 399 $this->assertSame( array( 'author' ), wp_get_registered_entity_field_modules( 'postType', 'page' )['plugin/fields'], 'The script module only applies to the fields updated.' );421 $this->assertSame( array( 'author' ), array_column( wp_get_registered_entity_field_modules( 'postType', 'page' ), 'fields', 'id' )['plugin/fields'], 'The script module only applies to the fields updated.' ); 400 422 $this->assertCount( 1, $reported ); 401 423 $this->assertStringContainsString( 'postType "page"', $reported[0], 'The notice names the entity.' ); … … 431 453 ), 432 454 $this->field( 'weight' ), 455 $this->field( '0' ), 433 456 ) 434 457 ); … … 443 466 'label' => 'Colour', 444 467 ), 468 array( 469 'id' => '0', 470 'label' => 'Zero', 471 ), 445 472 ) 446 473 ); … … 448 475 ); 449 476 450 $this->assertSame( array( 'color', 'weight' ), $registered, 'The valid definitions are registered.' );451 $this->assertSame( array( 'color' ), $updated, 'The valid definitions are updated.' );477 $this->assertSame( array( 'color', 'weight', '0' ), $registered, 'The valid definitions are registered, `0` included.' ); 478 $this->assertSame( array( 'color', '0' ), $updated, 'The valid definitions are updated, `0` included.' ); 452 479 $fields = array_column( wp_get_registered_entity_fields( 'postType', 'page' ), null, 'id' ); 453 480 $this->assertSame( 'Colour', $fields['color']['label'] ); 481 $this->assertSame( 'Zero', $fields['0']['label'] ); 454 482 $this->assertArrayHasKey( 'weight', $fields ); 455 483 $this->assertCount( 1, $reported ); … … 558 586 $this->assertSame( $fired, did_action( 'wp_entity_fields_api_init' ), 'Refusing does not fire the action.' ); 559 587 $this->assertNotContains( 'color', array_column( wp_get_registered_entity_fields( 'postType', 'page' ), 'id' ) ); 560 $this->assert ArrayNotHasKey( 'plugin/color', wp_get_registered_entity_field_modules( 'postType', 'page' ) );588 $this->assertNotContains( 'plugin/color', array_column( wp_get_registered_entity_field_modules( 'postType', 'page' ), 'id' ) ); 561 589 } 562 590 -
trunk/tests/phpunit/tests/entity-fields/wpPreloadEntityFields.php
r64595 r64686 12 12 * @group entity-fields 13 13 * 14 * @covers ::_wp_add_entity_preload_paths 14 15 * @covers ::_wp_preload_entity_fields 15 * @covers ::_wp_get_post_type_fields_preload_paths16 * @covers ::_wp_get_site_editor_screen_post_types17 16 */ 18 17 class Tests_Entity_Fields_WpPreloadEntityFields extends WP_Entity_Fields_UnitTestCase { … … 141 140 */ 142 141 public function test_unregistered_post_types_are_not_preloaded() { 143 $this->assertSame( 144 array( '/wp/v2/entity-fields?kind=postType&name=page' ), 145 _wp_get_post_type_fields_preload_paths( array( 'page', 'not_a_post_type', 'page' ) ) 146 ); 142 $context = new WP_Block_Editor_Context( 143 array( 144 'name' => 'core/edit-post', 145 'post' => new WP_Post( (object) array( 'post_type' => 'not_a_post_type' ) ), 146 ) 147 ); 148 149 $this->assertSame( array(), _wp_preload_entity_fields( array(), $context ) ); 147 150 } 148 151 … … 162 165 $this->assertSame( array(), _wp_preload_entity_fields( array(), $widgets ) ); 163 166 } 167 168 /** 169 * Empty paths that are not an array become an array the fields are added 170 * to. Other paths that are not an array are returned unchanged. 171 * 172 * @ticket 66229 173 * 174 * @dataProvider data_non_array_paths 175 * 176 * @param mixed $paths The paths passed to the filter. 177 * @param mixed $expected The filtered paths, or null for the fields path 178 * only. 179 */ 180 public function test_non_array_paths( $paths, $expected ) { 181 $post = self::factory()->post->create_and_get( array( 'post_type' => 'page' ) ); 182 $context = new WP_Block_Editor_Context( 183 array( 184 'name' => 'core/edit-post', 185 'post' => $post, 186 ) 187 ); 188 189 if ( null === $expected ) { 190 $expected = array( '/wp/v2/entity-fields?kind=postType&name=page' ); 191 } 192 193 $this->assertSame( $expected, _wp_preload_entity_fields( $paths, $context ) ); 194 } 195 196 /** 197 * Data provider for test_non_array_paths(). 198 * 199 * @return array[] 200 */ 201 public function data_non_array_paths() { 202 $object = new stdClass(); 203 204 return array( 205 'null' => array( null, null ), 206 'false' => array( false, null ), 207 'empty string' => array( '', null ), 208 'string' => array( '/wp/v2/types', '/wp/v2/types' ), 209 'object' => array( $object, $object ), 210 ); 211 } 212 213 /** 214 * Called with the paths only, as by a filter added with one accepted 215 * argument, the paths are returned unchanged. 216 * 217 * @ticket 66229 218 */ 219 public function test_the_paths_are_unchanged_without_a_context() { 220 $this->assertSame( array( '/wp/v2/types' ), _wp_preload_entity_fields( array( '/wp/v2/types' ) ) ); 221 $this->assertSame( array(), _wp_preload_entity_fields( null ) ); 222 } 164 223 } -
trunk/tests/phpunit/tests/entity-fields/wpRegisterCoreFieldCollections.php
r64581 r64686 210 210 $this->assertSame( 211 211 array( self::POST_TYPE_SUPPORTS => array_column( $fields, 'id' ) ), 212 wp_get_registered_entity_field_modules( 'postType', 'test_book' ),212 array_column( wp_get_registered_entity_field_modules( 'postType', 'test_book' ), 'fields', 'id' ), 213 213 'Every default field is registered with the module of its folder.' 214 214 ); … … 364 364 public function test_pages_get_their_own_title_field() { 365 365 $fields = self::get_fields( 'postType', 'page' ); 366 $modules = wp_get_registered_entity_field_modules( 'postType', 'page' );366 $modules = array_column( wp_get_registered_entity_field_modules( 'postType', 'page' ), 'fields', 'id' ); 367 367 368 368 $this->assertFalse( $fields['title']['enableHiding'], 'The page title is the one of the collection.' ); … … 391 391 $this->assertSame( 392 392 $ids, 393 wp_get_registered_entity_field_modules( 'postType', 'wp_template' )['@wordpress/core-fields/wp_template'],393 array_column( wp_get_registered_entity_field_modules( 'postType', 'wp_template' ), 'fields', 'id' )['@wordpress/core-fields/wp_template'], 394 394 'The fields of templates ship their JavaScript parts in the module of the collection.' 395 395 ); … … 413 413 $this->assertSame( 414 414 array( 'author', 'title' ), 415 wp_get_registered_entity_field_modules( 'postType', 'wp_template_part' )['@wordpress/core-fields/wp_template_part'],415 array_column( wp_get_registered_entity_field_modules( 'postType', 'wp_template_part' ), 'fields', 'id' )['@wordpress/core-fields/wp_template_part'], 416 416 'The fields of template parts ship their JavaScript parts in the module of the collection.' 417 417 ); … … 426 426 public function test_patterns_get_their_own_fields() { 427 427 $fields = self::get_fields( 'postType', 'wp_block' ); 428 $modules = wp_get_registered_entity_field_modules( 'postType', 'wp_block' );428 $modules = array_column( wp_get_registered_entity_field_modules( 'postType', 'wp_block' ), 'fields', 'id' ); 429 429 430 430 $this->assertTrue( post_type_supports( 'wp_block', 'excerpt' ), 'The post type supports excerpts.' ); … … 487 487 $this->assertSame( 488 488 array( '@wordpress/core-fields/attachment' => $ids ), 489 wp_get_registered_entity_field_modules( 'postType', 'attachment' ),489 array_column( wp_get_registered_entity_field_modules( 'postType', 'attachment' ), 'fields', 'id' ), 490 490 'Every media field is registered with the module of the collection.' 491 491 ); … … 509 509 $this->assertSame( 510 510 array( '@wordpress/core-fields/root_site' => $ids ), 511 wp_get_registered_entity_field_modules( 'root', 'site' ),511 array_column( wp_get_registered_entity_field_modules( 'root', 'site' ), 'fields', 'id' ), 512 512 'Every field of the site is registered with the module of the collection.' 513 513 ); … … 714 714 ); 715 715 716 $modules = wp_get_registered_entity_field_modules( 'postType', 'wp_template' );716 $modules = array_column( wp_get_registered_entity_field_modules( 'postType', 'wp_template' ), 'fields', 'id' ); 717 717 718 718 $this->assertSame( 'my-plugin', self::get_fields( 'postType', 'wp_template' )['author']['origin']['registeredBy'], 'The author field is the one of the plugin.' ); -
trunk/tests/phpunit/tests/entity-fields/wpRegisterEntityFieldCollection.php
r64528 r64686 101 101 $this->assertSame( array( 'subtitle', 'isbn' ), array_column( $book, 'id' ), 'The fields registered first come first: the fixture collections run at priority 0.' ); 102 102 $this->assertSame( 'fixture', $book[0]['origin']['registeredBy'], 'The fields carry the origin of their collection.' ); 103 $this->assertSame( array( 'fixture/book' => array( 'subtitle' ) ), wp_get_registered_entity_field_modules( 'postType', 'test_book' ), 'Each field is registered with the module of its collection.' ); 103 $this->assertSame( 104 array( 105 array( 106 'id' => 'fixture/book', 107 'fields' => array( 'subtitle' ), 108 ), 109 ), 110 wp_get_registered_entity_field_modules( 'postType', 'test_book' ), 111 'Each field is registered with the module of its collection.' 112 ); 104 113 105 114 $this->assertSame( array( 'issue' ), array_column( wp_get_registered_entity_fields( 'postType', 'test_magazine' ), 'id' ) ); -
trunk/tests/phpunit/tests/rest-api/rest-entity-fields-controller.php
r64581 r64686 595 595 596 596 /** 597 * A numeric script module id is returned as a string, like any other. 598 * 599 * @covers ::get_items 600 * 601 * @ticket 66229 602 */ 603 public function test_get_items_returns_a_numeric_module_id_as_a_string() { 604 $this->register_fields( 605 'customKind', 606 'customName', 607 array( 608 array( 609 'id' => 'color', 610 'type' => 'text', 611 'label' => 'Color', 612 ), 613 ), 614 '123' 615 ); 616 617 wp_set_current_user( self::$editor_id ); 618 $data = $this->dispatch_request( 'customKind', 'customName' )->get_data(); 619 620 $this->assertSame( 621 array( 622 array( 623 'id' => '123', 624 'fields' => array( 'color' ), 625 ), 626 ), 627 $data['script_modules'] 628 ); 629 } 630 631 /** 597 632 * Fields registered without a script module have none listed. 598 633 *
Note:
See TracChangeset
for help on using the changeset viewer.
![(please configure the [header_logo] section in trac.ini)](/chrome/site/your_project_logo.png)