PluginProbe
Gutenberg / 23.5.3
Gutenberg v23.5.3
23.9.1 23.9.0 23.8.0 23.7.2 23.7.1 23.7.0 23.6.1 23.6.2 23.6.0 23.5.3 23.5.2 23.5.1 23.5.0 23.4.0 23.3.2 23.3.1 23.3.0 23.2.0 23.2.1 23.2.2 23.1.1 23.1.0 23.0.1 12.6.0 7.4.0 All 402 releases
gutenberg / lib / experimental / dashboard-widgets / dashboard-layout.php

dashboard-layout.php in Gutenberg 23.5.3, at lib/experimental/dashboard-widgets/dashboard-layout.php

155 lines 5.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Dashboard Layout: server-side defaults.
4 *
5 * Allows plugins and themes to register a default dashboard layout
6 * that surfaces transparently through the `@wordpress/preferences`
7 * store for users who have not customized theirs.
8 *
9 * @package gutenberg
10 */
11
12 /**
13 * Preferences scope under which the dashboard layout is stored.
14 * Mirrors the scope read by the dashboard's JS layer.
15 */
16 const GUTENBERG_DASHBOARD_LAYOUT_SCOPE = 'core/dashboard';
17
18 /**
19 * Preferences key under `GUTENBERG_DASHBOARD_LAYOUT_SCOPE` that holds
20 * the layout array.
21 */
22 const GUTENBERG_DASHBOARD_LAYOUT_KEY = 'dashboardLayout';
23
24 /**
25 * Identifier of the bundled dashboard, formatted as `<plugin>_<page>`
26 * to match the underscore form produced by the wp-build pipeline
27 * (mirrors the `{{PREFIX}}_{{PAGE_SLUG_UNDERSCORE}}` pair used in
28 * generated page templates).
29 *
30 * Passed as context to `gutenberg_dashboard_default_layout` and used
31 * as the `{name}` segment of the REST default-layout route.
32 */
33 const GUTENBERG_DASHBOARD_NAME = 'gutenberg_dashboard';
34
35 /**
36 * Injects a registered default dashboard layout into the user's
37 * `persisted_preferences` read when the stored layout is empty.
38 *
39 * Hooks into `get_user_metadata` so the default propagates through
40 * the same persistence layer the dashboard's JS layer reads from.
41 * The JS side stays oblivious: a default and a user-saved layout
42 * look identical at the preferences-store boundary.
43 *
44 * @global wpdb $wpdb WordPress database abstraction object.
45 *
46 * @param mixed $value The pre-fetched value, or null to let the
47 * meta API resolve normally.
48 * @param int $user_id User ID.
49 * @param string $meta_key Meta key being read.
50 * @return mixed The original value, or a single-element array
51 * containing the extended persisted preferences.
52 */
53 function gutenberg_inject_dashboard_default_layout( $value, $user_id, $meta_key ) {
54 global $wpdb;
55
56 $expected_key = $wpdb->get_blog_prefix() . 'persisted_preferences';
57 if ( $meta_key !== $expected_key ) {
58 return $value;
59 }
60
61 // Avoid recursion when reading the user meta.
62 remove_filter( 'get_user_metadata', __FUNCTION__, 99 );
63 $base = get_user_meta( $user_id, $meta_key, true );
64 add_filter( 'get_user_metadata', __FUNCTION__, 99, 3 );
65
66 if ( ! is_array( $base ) ) {
67 $base = array();
68 }
69
70 $committed = isset( $base[ GUTENBERG_DASHBOARD_LAYOUT_SCOPE ][ GUTENBERG_DASHBOARD_LAYOUT_KEY ] )
71 ? $base[ GUTENBERG_DASHBOARD_LAYOUT_SCOPE ][ GUTENBERG_DASHBOARD_LAYOUT_KEY ]
72 : array();
73
74 if ( ! empty( $committed ) ) {
75 return $value;
76 }
77
78 /**
79 * Filters the default dashboard layout served to users who have
80 * not customized theirs.
81 *
82 * Each entry should match the dashboard's widget instance shape:
83 * `uuid`, `type`, optional `attributes`, optional `placement`.
84 *
85 * @param array $default_layout Default array of widget instances.
86 * @param string $dashboard_name Identifier of the dashboard
87 * receiving the default. Callbacks
88 * targeting a specific dashboard
89 * should switch on this value.
90 */
91 $default = apply_filters( 'gutenberg_dashboard_default_layout', array(), GUTENBERG_DASHBOARD_NAME );
92
93 if ( empty( $default ) || ! is_array( $default ) ) {
94 return $value;
95 }
96
97 if ( ! isset( $base[ GUTENBERG_DASHBOARD_LAYOUT_SCOPE ] ) || ! is_array( $base[ GUTENBERG_DASHBOARD_LAYOUT_SCOPE ] ) ) {
98 $base[ GUTENBERG_DASHBOARD_LAYOUT_SCOPE ] = array();
99 }
100
101 $base[ GUTENBERG_DASHBOARD_LAYOUT_SCOPE ][ GUTENBERG_DASHBOARD_LAYOUT_KEY ] = $default;
102
103 return array( $base );
104 }
105
106 add_filter( 'get_user_metadata', 'gutenberg_inject_dashboard_default_layout', 99, 3 );
107
108 /**
109 * Returns the default layout registered for a dashboard.
110 *
111 * Resolves `gutenberg_dashboard_default_layout` for the supplied
112 * dashboard name, returning a fresh evaluation of the filter chain
113 * each call. Used by the dashboard's JS layer to back a "reset to
114 * default" action without depending on the user-meta hydration path.
115 *
116 * @param WP_REST_Request $request REST request carrying the
117 * dashboard name segment.
118 * @return WP_REST_Response Response wrapping the default layout
119 * array.
120 */
121 function gutenberg_get_dashboard_default_layout( $request ) {
122 $name = $request['name'];
123 $default = apply_filters( 'gutenberg_dashboard_default_layout', array(), $name );
124
125 if ( ! is_array( $default ) ) {
126 $default = array();
127 }
128
129 return rest_ensure_response( array_values( $default ) );
130 }
131
132 /**
133 * Registers the REST route that exposes per-dashboard default layouts.
134 */
135 function gutenberg_register_dashboard_default_layout_route() {
136 register_rest_route(
137 'wp/v2',
138 '/dashboards/(?P<name>[a-z][a-z0-9]*(?:_[a-z0-9]+)+)/default-layout',
139 array(
140 'methods' => WP_REST_Server::READABLE,
141 'callback' => 'gutenberg_get_dashboard_default_layout',
142 'permission_callback' => function () {
143 return current_user_can( 'read' );
144 },
145 'args' => array(
146 'name' => array(
147 'description' => __( 'Dashboard identifier as produced by the build pipeline.', 'gutenberg' ),
148 'type' => 'string',
149 ),
150 ),
151 )
152 );
153 }
154 add_action( 'rest_api_init', 'gutenberg_register_dashboard_default_layout_route' );
155