| 1 |
<?php |
| 2 |
/** |
| 3 |
* Widget Types: server-side registry and REST exposure. |
| 4 |
* |
| 5 |
* Hydrates `WP_Widget_Type_Registry` from the build manifest at `init`, |
| 6 |
* and exposes the registry to the client through the |
| 7 |
* `/wp/v2/widget-modules` REST endpoint. The JS layer reads the endpoint |
| 8 |
* via core-data and dynamically imports each widget's render module on |
| 9 |
* the consumer side. |
| 10 |
* |
| 11 |
* @package gutenberg |
| 12 |
*/ |
| 13 |
|
| 14 |
require_once __DIR__ . '/class-wp-widget-type.php'; |
| 15 |
require_once __DIR__ . '/class-wp-widget-type-registry.php'; |
| 16 |
require_once __DIR__ . '/class-wp-rest-widget-modules-controller.php'; |
| 17 |
|
| 18 |
/** |
| 19 |
* Hydrates the widget type registry from the build manifest. |
| 20 |
* |
| 21 |
* Iterates the widgets discovered by the build pipeline (via |
| 22 |
* `gutenberg_get_registered_widget_modules()`) and registers each one in |
| 23 |
* `WP_Widget_Type_Registry`. The manifest is the single source of widget |
| 24 |
* authorship in this codebase; this loop is a deterministic copy of it |
| 25 |
* into the in-memory registry, with no filters in between. |
| 26 |
*/ |
| 27 |
function gutenberg_register_widget_types() { |
| 28 |
if ( ! function_exists( 'gutenberg_get_registered_widget_modules' ) ) { |
| 29 |
return; |
| 30 |
} |
| 31 |
|
| 32 |
$registry = WP_Widget_Type_Registry::get_instance(); |
| 33 |
|
| 34 |
foreach ( gutenberg_get_registered_widget_modules() as $widget ) { |
| 35 |
if ( empty( $widget['name'] ) || $registry->is_registered( $widget['name'] ) ) { |
| 36 |
continue; |
| 37 |
} |
| 38 |
|
| 39 |
$registry->register( |
| 40 |
$widget['name'], |
| 41 |
array( |
| 42 |
'render_module' => $widget['render_module'] ?? null, |
| 43 |
'widget_module' => $widget['widget_module'] ?? null, |
| 44 |
'presentation' => $widget['presentation'] ?? null, |
| 45 |
) |
| 46 |
); |
| 47 |
} |
| 48 |
} |
| 49 |
|
| 50 |
if ( did_action( 'init' ) ) { |
| 51 |
gutenberg_register_widget_types(); |
| 52 |
} else { |
| 53 |
add_action( 'init', 'gutenberg_register_widget_types' ); |
| 54 |
} |
| 55 |
|
| 56 |
/** |
| 57 |
* Returns all widget types registered in the widget type registry. |
| 58 |
* |
| 59 |
* Convenience accessor around `WP_Widget_Type_Registry::get_all_registered()` |
| 60 |
* for callers that prefer a function-based API. |
| 61 |
* |
| 62 |
* @return WP_Widget_Type[] Associative array of `$name => $widget_type` |
| 63 |
* pairs. |
| 64 |
*/ |
| 65 |
function gutenberg_get_registered_widget_types() { |
| 66 |
return WP_Widget_Type_Registry::get_instance()->get_all_registered(); |
| 67 |
} |
| 68 |
|
| 69 |
/** |
| 70 |
* Registers the REST controller that exposes the widget type registry. |
| 71 |
*/ |
| 72 |
function gutenberg_register_widget_modules_rest_controller() { |
| 73 |
$controller = new WP_REST_Widget_Modules_Controller(); |
| 74 |
$controller->register_routes(); |
| 75 |
} |
| 76 |
add_action( 'rest_api_init', 'gutenberg_register_widget_modules_rest_controller' ); |
| 77 |
|
| 78 |
/** |
| 79 |
* Adds the registered widget modules to the dashboard page's boot |
| 80 |
* dependencies. |
| 81 |
* |
| 82 |
* The wp-build page templates expose a generic |
| 83 |
* `{page-id}-wp-admin_boot_dependencies` filter. The dashboard surface |
| 84 |
* hooks it to make every registered widget render and metadata module |
| 85 |
* available in the page's import map for dynamic `import()` calls. |
| 86 |
* |
| 87 |
* Both the render module and the metadata module are added as |
| 88 |
* 'dynamic' dependencies so they are reachable from the import map but |
| 89 |
* not eagerly executed. |
| 90 |
* |
| 91 |
* @param array $boot_dependencies Boot dependencies for the page. |
| 92 |
* @return array Updated boot dependencies. |
| 93 |
*/ |
| 94 |
function gutenberg_add_widget_modules_to_dashboard_boot_deps( $boot_dependencies ) { |
| 95 |
foreach ( gutenberg_get_registered_widget_types() as $widget_type ) { |
| 96 |
if ( $widget_type->render_module ) { |
| 97 |
$boot_dependencies[] = array( |
| 98 |
'import' => 'dynamic', |
| 99 |
'id' => $widget_type->render_module, |
| 100 |
); |
| 101 |
} |
| 102 |
if ( $widget_type->widget_module ) { |
| 103 |
$boot_dependencies[] = array( |
| 104 |
'import' => 'dynamic', |
| 105 |
'id' => $widget_type->widget_module, |
| 106 |
); |
| 107 |
} |
| 108 |
} |
| 109 |
|
| 110 |
return $boot_dependencies; |
| 111 |
} |
| 112 |
add_filter( 'dashboard-wp-admin_boot_dependencies', 'gutenberg_add_widget_modules_to_dashboard_boot_deps' ); |
| 113 |
|