Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 19 additions & 5 deletions src/wp-includes/class-wp-entity-actions-registry.php
Original file line number Diff line number Diff line change
Expand Up @@ -404,17 +404,31 @@ static function ( $entities ) {
*
* @param string $kind The entity kind (e.g. `postType`).
* @param string $name The entity name (e.g. `page`).
* @return array<string, string[]> The ids of the actions each module
* applies to, keyed by module id, in
* registration order. Empty when the
* entity is invalid.
* @return array[] {
* The script modules, in registration order. Empty when the entity
* is invalid.
*
* @type array ...$0 {
* @type string $id The id of the script module.
* @type string[] $actions The ids of the actions the module
* applies to, in registration order.
* }
* }
*/
public function get_registered_action_modules( $kind, $name ) {
if ( ! $this->validate_entity( __METHOD__, $kind, $name ) ) {
return array();
}
$this->initialize();
return $this->action_modules[ $kind ][ $name ] ?? array();
$modules = array();
foreach ( $this->action_modules[ $kind ][ $name ] ?? array() as $module => $action_ids ) {
$modules[] = array(
// A numeric module id is an integer as an array key.
'id' => (string) $module,
'actions' => $action_ids,
);
}
return $modules;
}

/**
Expand Down
42 changes: 36 additions & 6 deletions src/wp-includes/class-wp-entity-fields-registry.php
Original file line number Diff line number Diff line change
Expand Up @@ -477,13 +477,27 @@ static function ( $entities ) {
*
* @param string $kind The entity kind (e.g. `postType`).
* @param string $name The entity name (e.g. `page`).
* @return array<string, string[]> The ids of the fields each module
* applies to, keyed by module id, in
* registration order.
* @return array[] {
* The script modules, in registration order.
*
* @type array ...$0 {
* @type string $id The id of the script module.
* @type string[] $fields The ids of the fields the module applies
* to, in registration order.
* }
* }
*/
public function get_registered_field_modules( $kind, $name ) {
$this->initialize();
return $this->field_modules[ $kind ][ $name ] ?? array();
$modules = array();
foreach ( $this->field_modules[ $kind ][ $name ] ?? array() as $module => $field_ids ) {
$modules[] = array(
// A numeric module id is an integer as an array key.
'id' => (string) $module,
'fields' => $field_ids,
);
}
return $modules;
}

/**
Expand All @@ -497,9 +511,25 @@ public function get_registered_field_modules( $kind, $name ) {
*/
public function get_all_registered_field_modules() {
$this->initialize();
/*
* Keeps the module ids and drops the field ids they apply to, e.g.:
*
* array(
* 'postType' => array(
* 'page' => array( 'my-plugin/fields', '123' ),
* 'post' => array( 'my-plugin/fields' ),
* ),
* )
*/
return array_map(
Comment thread
oandregal marked this conversation as resolved.
static function ( $entities ) {
return array_map( 'array_keys', $entities );
return array_map(
static function ( $modules ) {
// A numeric module id is an integer as an array key.
return array_map( 'strval', array_keys( $modules ) );
Comment thread
oandregal marked this conversation as resolved.
},
$entities
);
},
$this->field_modules
);
Expand Down Expand Up @@ -731,7 +761,7 @@ protected function skip_invalid_definitions( $method, $kind, $name, $fields ) {
$valid = array();
$invalid = array();
foreach ( $fields as $position => $field ) {
if ( is_array( $field ) && ! empty( $field['id'] ) && is_string( $field['id'] ) ) {
if ( is_array( $field ) && isset( $field['id'] ) && is_string( $field['id'] ) && '' !== $field['id'] ) {
$valid[] = $field;
} else {
$invalid[] = '#' . ( $position + 1 );
Expand Down
120 changes: 23 additions & 97 deletions src/wp-includes/entity-actions.php
Original file line number Diff line number Diff line change
Expand Up @@ -80,17 +80,22 @@ function wp_get_registered_entity_actions( $kind, $name ) {
}

/**
* Returns the ids of the script modules registered for the given entity.
* Returns the script modules registered for the given entity.
*
* @since 7.2.0
*
* @param string $kind The entity kind (e.g. `postType`).
* @param string $name The entity name (e.g. `page`).
* @return array<string, string[]> The ids of the actions each module
* applies to, keyed by module id, in
* registration order. Empty until the
* `init` action has completed: a read
* before then is refused.
* @return array[] {
* The script modules, in registration order. Empty until the `init`
* action has completed: a read before then is refused.
*
* @type array ...$0 {
* @type string $id The id of the script module.
* @type string[] $actions The ids of the actions the module applies
* to, in registration order.
* }
* }
*/
function wp_get_registered_entity_action_modules( $kind, $name ) {
return WP_Entity_Actions_Registry::get_instance()->get_registered_action_modules( $kind, $name );
Expand All @@ -114,78 +119,21 @@ function wp_get_all_registered_entity_action_modules() {

/**
* Declares the script modules of the entity actions as dependencies of the
* editor script.
*
* The editor imports the script modules of an entity on demand, with a dynamic
* `import()` the browser resolves through the import map of the page. Listing
* the modules as dynamic `module_dependencies` of the `wp-editor` script adds
* them to the import map of every page that loads the editor script: the post
* editor, the site editor, and the pages booted by `@wordpress/boot`, whose
* prerequisites depend on it. A dynamic dependency is only listed in the
* import map; the module is fetched when it is imported.
*
* Reading the registry fires `wp_entity_actions_api_init`, so the actions and their
* script modules are registered on demand. It only reads the registry on the
* pages that load the editor script, not on every admin request (heartbeat,
* Ajax, other screens). It runs on `admin_footer`, the last action before the
* import map is printed that fires both in the admin template and in the pages
* rendered outside it, which print the import map themselves. By then `init`
* has completed, so the post types and supports the actions derive from are
* final.
* The registry only accepts registrations while the action fires, so the
* modules declared here are the modules of every action the page can show.
* editor script, see _wp_add_entity_modules_to_editor_script().
*
* The actions are loaded by `usePostActions()` of the editor script, so every
* screen showing them loads it.
*
* The `admin_footer` action passes it no argument, so the global registry is
* used. In other scenarios (tests), the scripts are given directly.
*
* @since 7.2.0
* @access private
*
* @param WP_Scripts|null $scripts The scripts registry. Defaults to the global one.
*/
function _wp_add_entity_action_modules_to_editor_script( $scripts = null ) {
Comment thread
oandregal marked this conversation as resolved.
if ( ! $scripts instanceof WP_Scripts ) {
$scripts = wp_scripts();
}

// The actions are loaded by `usePostActions()` of the editor script, so
// every screen showing them loads it.
if ( ! $scripts->query( 'wp-editor', 'enqueued' ) && ! $scripts->query( 'wp-editor', 'done' ) ) {
return;
}

$kinds = wp_get_all_registered_entity_action_modules();
if ( empty( $kinds ) ) {
return;
}

$dependencies = $scripts->get_data( 'wp-editor', 'module_dependencies' );
$dependencies = is_array( $dependencies ) ? $dependencies : array();

$declared = array();
foreach ( $dependencies as $dependency ) {
$declared[] = is_array( $dependency ) ? $dependency['id'] : $dependency;
}

$added = false;
foreach ( $kinds as $entities ) {
foreach ( $entities as $modules ) {
foreach ( $modules as $module ) {
if ( ! in_array( $module, $declared, true ) ) {
$dependencies[] = array(
'id' => $module,
'import' => 'dynamic',
);
$declared[] = $module;
$added = true;
}
}
}
}

if ( $added ) {
// `add_data()` replaces the value, hence the merge above.
$scripts->add_data( 'wp-editor', 'module_dependencies', $dependencies );
}
_wp_add_entity_modules_to_editor_script( $scripts, 'wp_get_all_registered_entity_action_modules' );
}

/**
Expand All @@ -201,34 +149,12 @@ function _wp_add_entity_action_modules_to_editor_script( $scripts = null ) {
* packages/core-data/src/resolvers.js in Gutenberg.
*
* @since 7.2.0
* @access private
*
* @param array $paths REST API paths to preload.
* @param WP_Block_Editor_Context $context Block editor context.
* @return array Filtered preload paths.
* @param mixed $paths REST API paths to preload.
* @param mixed $context Optional. Block editor context. Default null.
* @return mixed Filtered preload paths. See _wp_add_entity_preload_paths().
*/
function _wp_preload_entity_actions( $paths, $context ) {
$post_types = array();
if ( 'core/edit-post' === $context->name && isset( $context->post ) ) {
$post_types[] = $context->post->post_type;
} elseif ( 'core/edit-site' === $context->name ) {
if ( isset( $context->post ) ) {
$post_types[] = $context->post->post_type;
}
$post_types = array_merge( $post_types, _wp_get_site_editor_screen_post_types() );
}

foreach ( array_unique( $post_types ) as $post_type ) {
if ( ! post_type_exists( $post_type ) ) {
continue;
}
$paths[] = add_query_arg(
array(
'kind' => 'postType',
'name' => $post_type,
),
'/wp/v2/entity-actions'
);
}

return $paths;
function _wp_preload_entity_actions( $paths, $context = null ) {
Comment thread
oandregal marked this conversation as resolved.
return _wp_add_entity_preload_paths( $paths, $context, '/wp/v2/entity-actions' );
}
Loading
Loading