PluginProbe
Gutenberg / trunk
Gutenberg vtrunk
24.1.0 24.0.0 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 All 404 releases
← All changes | lib/compat/wordpress-7.1/view-config-api.php +205 -228 23.5.2 → trunk View file →
@@ -3,19 +3,121 @@
3 3 * Entity view configuration API.
4 4 *
5 5 * Builds the default view configuration for an entity and exposes it through
6 6 * the dynamic `get_entity_view_config_{$kind}_{$name}` filter so core and third
7 - * parties can provide the configuration for a specific entity.
7 + * parties can provide the configuration for a specific entity. The dynamic
8 + * portions of the hook name are lowercased, e.g.
9 + * `get_entity_view_config_posttype_page` for the `page` post type.
8 10 *
9 11 * @package gutenberg
10 12 */
11 13
12 14 /**
15 + * Builds the name of the dynamic filter that provides the view configuration
16 + * for an entity.
17 + *
18 + * The entity kind and name are embedded in the hook name lowercased, so the
19 + * hook follows the WordPress convention of lowercase hook names regardless of
20 + * how the entity identifiers are spelled: the `postType`/`page` entity maps to
21 + * the `get_entity_view_config_posttype_page` hook.
22 + *
23 + * @param string $kind The entity kind (e.g. `postType`).
24 + * @param string $name The entity name (e.g. `page`).
25 + * @return string The filter name.
26 + */
27 +function gutenberg_get_entity_view_config_hook_name( $kind, $name ) {
28 + return strtolower( "get_entity_view_config_{$kind}_{$name}" );
29 +}
30 +
31 +/**
32 + * Builds the default `form` configuration for post types that don't provide their own.
33 + *
34 + * It is a sensible default for `post`, `page`, and custom post types alike rather
35 + * than being tailored per type. Post types that need a different shape can replace
36 + * it entirely with a dedicated `form` through their own filter callback.
37 + *
38 + * It is intentionally NOT gated by `supports`. The registered fields are the
39 + * single source of truth for what applies: each field is registered for a post
40 + * type based on its `supports` (and related flags such as `theme_supports`), and
41 + * the editor drops any form field whose definition is absent or whose `isVisible`
42 + * returns `false`.
43 + *
44 + * @return array The default form configuration.
45 + */
46 +function _gutenberg_get_default_posttype_form() {
47 + return array(
48 + 'layout' => array( 'type' => 'panel' ),
49 + 'fields' => array(
50 + array(
51 + 'id' => 'featured_media',
52 + 'layout' => array(
53 + 'type' => 'regular',
54 + 'labelPosition' => 'none',
55 + ),
56 + ),
57 + array(
58 + 'id' => 'post-content-info',
59 + 'layout' => array(
60 + 'type' => 'regular',
61 + 'labelPosition' => 'none',
62 + ),
63 + ),
64 + array(
65 + 'id' => 'excerpt',
66 + 'layout' => array(
67 + 'type' => 'panel',
68 + 'labelPosition' => 'top',
69 + ),
70 + ),
71 + array(
72 + 'id' => 'status',
73 + 'label' => __( 'Status', 'gutenberg' ),
74 + 'children' => array(
75 + array(
76 + 'id' => 'status',
77 + 'layout' => array(
78 + 'type' => 'regular',
79 + 'labelPosition' => 'none',
80 + ),
81 + ),
82 + 'scheduled_date',
83 + 'password',
84 + 'sticky',
85 + ),
86 + ),
87 + 'date',
88 + 'slug',
89 + 'author',
90 + 'template',
91 + array(
92 + 'id' => 'discussion',
93 + 'label' => __( 'Discussion', 'gutenberg' ),
94 + 'children' => array(
95 + array(
96 + 'id' => 'comment_status',
97 + 'layout' => array(
98 + 'type' => 'regular',
99 + 'labelPosition' => 'none',
100 + ),
101 + ),
102 + 'ping_status',
103 + ),
104 + ),
105 + 'parent',
106 + 'format',
107 + 'revisions',
108 + ),
109 + );
110 +}
111 +
112 +/**
13 113 * Returns the view configuration for the given entity.
14 114 *
15 115 * Builds the default configuration shared by all entities and then exposes it
16 - * through the dynamic `get_entity_view_config_{$kind}_{$name}` filter so that core
17 - * and third parties can provide the configuration for a specific entity.
116 + * through the dynamic `get_entity_view_config_{$kind}_{$name}` filter — with the
117 + * dynamic portions lowercased, see gutenberg_get_entity_view_config_hook_name()
118 + * — so that core and third parties can provide the configuration for a
119 + * specific entity.
18 120 *
19 121 * @param string $kind The entity kind (e.g. `postType`).
20 122 * @param string $name The entity name (e.g. `page`).
21 123 * @return array {
@@ -61,61 +163,24 @@
61 163 $config = array(
62 164 'default_view' => $default_view,
63 165 'default_layouts' => $default_layouts,
64 166 'view_list' => $view_list,
65 - 'form' => array(),
167 + 'form' => 'postType' === $kind ? _gutenberg_get_default_posttype_form() : array(),
66 168 );
67 169
68 - /**
69 - * Filters the view configuration for a given entity.
70 - *
71 - * The dynamic portions of the hook name, `$kind` and `$name`, refer to the
72 - * entity kind (e.g. `postType`) and the entity name (e.g. `page`).
73 - *
74 - * @param array $config {
75 - * The view configuration for the entity.
76 - *
77 - * @type array $default_view Default view configuration.
78 - * @type array $default_layouts Default layouts configuration.
79 - * @type array $view_list List of available views.
80 - * @type array $form Form configuration.
81 - * }
82 - * @param array $entity {
83 - * The entity the configuration is built for.
84 - *
85 - * @type string $kind The entity kind.
86 - * @type string $name The entity name.
87 - * }
88 - */
89 - $filtered_config = apply_filters(
90 - "get_entity_view_config_{$kind}_{$name}",
91 - $config,
92 - array(
93 - 'kind' => $kind,
94 - 'name' => $name,
95 - )
96 - );
170 + $data = new Gutenberg_View_Config_Data( $config );
97 171
98 - if ( ! is_array( $filtered_config ) ) {
99 - return $config;
100 - }
101 -
102 - // Backfill any dropped keys with their defaults, then discard any keys the
103 - // filter introduced that are not part of the documented configuration shape.
104 - $filtered_config = array_merge( $config, $filtered_config );
105 - return array_intersect_key( $filtered_config, $config );
172 + return $data->apply_filters( $kind, $name );
106 173 }
107 174
108 175 /**
109 176 * Provides the view configuration for the `page` post type.
110 177 *
111 - * @param array $config {
112 - * The view configuration for the entity.
113 - * }
114 - * @return array The filtered view configuration.
178 + * @param Gutenberg_View_Config_Data $data The view configuration container for the entity.
179 + * @return Gutenberg_View_Config_Data The updated view configuration container.
115 180 */
116 -function _gutenberg_get_entity_view_config_post_type_page( $config ) {
117 - $config['default_layouts'] = array(
181 +function _gutenberg_get_entity_view_config_posttype_page( $data ) {
182 + $default_layouts = array(
118 183 'table' => array(
119 184 'layout' => array(
120 185 'styles' => array(
121 186 'author' => array(
@@ -127,9 +192,9 @@
127 192 'grid' => array(),
128 193 'list' => array(),
129 194 );
130 195
131 - $config['default_view'] = array(
196 + $default_view = array(
132 197 'type' => 'list',
133 198 'filters' => array(),
134 199 'perPage' => 20,
135 200 'sort' => array(
@@ -141,12 +206,9 @@
141 206 'mediaField' => 'featured_media',
142 207 'fields' => array( 'author', 'status' ),
143 208 );
144 209
145 - $config['view_list'] = array(
146 - // Reuse the base "all items" view, whose title is derived from the post
147 - // type's `all_items` label in gutenberg_get_entity_view_config().
148 - $config['view_list'][0],
210 + $view_list = array(
149 211 array(
150 212 'title' => __( 'Published', 'gutenberg' ),
151 213 'slug' => 'published',
152 214 'view' => array(
@@ -220,9 +282,9 @@
220 282 'title' => __( 'Trash', 'gutenberg' ),
221 283 'slug' => 'trash',
222 284 'view' => array(
223 285 'type' => 'table',
224 - 'layout' => $config['default_layouts']['table']['layout'],
286 + 'layout' => $default_layouts['table']['layout'],
225 287 'filters' => array(
226 288 array(
227 289 'field' => 'status',
228 290 'operator' => 'isAny',
@@ -233,161 +295,30 @@
233 295 ),
234 296 ),
235 297 );
236 298
237 - $config['form'] = array(
238 - 'layout' => array( 'type' => 'panel' ),
239 - 'fields' => array(
240 - array(
241 - 'id' => 'featured_media',
242 - 'layout' => array(
243 - 'type' => 'regular',
244 - 'labelPosition' => 'none',
245 - ),
246 - ),
247 - array(
248 - 'id' => 'post-content-info',
249 - 'layout' => array(
250 - 'type' => 'regular',
251 - 'labelPosition' => 'none',
252 - ),
253 - ),
254 - array(
255 - 'id' => 'excerpt',
256 - 'layout' => array(
257 - 'type' => 'panel',
258 - 'labelPosition' => 'top',
259 - ),
260 - ),
261 - array(
262 - 'id' => 'status',
263 - 'label' => __( 'Status', 'gutenberg' ),
264 - 'children' => array(
265 - array(
266 - 'id' => 'status',
267 - 'layout' => array(
268 - 'type' => 'regular',
269 - 'labelPosition' => 'none',
270 - ),
271 - ),
272 - 'scheduled_date',
273 - 'password',
274 - 'sticky',
275 - ),
276 - ),
277 - 'date',
278 - 'slug',
279 - 'author',
280 - 'template',
281 - array(
282 - 'id' => 'discussion',
283 - 'label' => __( 'Discussion', 'gutenberg' ),
284 - 'children' => array(
285 - array(
286 - 'id' => 'comment_status',
287 - 'layout' => array(
288 - 'type' => 'regular',
289 - 'labelPosition' => 'none',
290 - ),
291 - ),
292 - 'ping_status',
293 - ),
294 - ),
295 - 'parent',
296 - 'format',
297 - 'revisions',
299 + $data->set(
300 + array(
301 + 'default_view' => $default_view,
302 + 'default_layouts' => $default_layouts,
298 303 ),
304 + 1
299 305 );
306 + // Append the status views, thereby preserving the base "all items" view,
307 + // so its post-type-specific title is kept.
308 + $data->merge( array( 'view_list' => $view_list ), 1 );
300 309
301 - return $config;
310 + return $data;
302 311 }
303 312
304 313 /**
305 - * Provides the view configuration for the `post` post type.
306 - *
307 - * @param array $config {
308 - * The view configuration for the entity.
309 - * }
310 - * @return array The filtered view configuration.
311 - */
312 -function _gutenberg_get_entity_view_config_post_type_post( $config ) {
313 - $config['form'] = array(
314 - 'layout' => array( 'type' => 'panel' ),
315 - 'fields' => array(
316 - array(
317 - 'id' => 'featured_media',
318 - 'layout' => array(
319 - 'type' => 'regular',
320 - 'labelPosition' => 'none',
321 - ),
322 - ),
323 - array(
324 - 'id' => 'post-content-info',
325 - 'layout' => array(
326 - 'type' => 'regular',
327 - 'labelPosition' => 'none',
328 - ),
329 - ),
330 - array(
331 - 'id' => 'excerpt',
332 - 'layout' => array(
333 - 'type' => 'panel',
334 - 'labelPosition' => 'top',
335 - ),
336 - ),
337 - array(
338 - 'id' => 'status',
339 - 'label' => __( 'Status', 'gutenberg' ),
340 - 'children' => array(
341 - array(
342 - 'id' => 'status',
343 - 'layout' => array(
344 - 'type' => 'regular',
345 - 'labelPosition' => 'none',
346 - ),
347 - ),
348 - 'scheduled_date',
349 - 'password',
350 - 'sticky',
351 - ),
352 - ),
353 - 'date',
354 - 'slug',
355 - 'author',
356 - 'template',
357 - array(
358 - 'id' => 'discussion',
359 - 'label' => __( 'Discussion', 'gutenberg' ),
360 - 'children' => array(
361 - array(
362 - 'id' => 'comment_status',
363 - 'layout' => array(
364 - 'type' => 'regular',
365 - 'labelPosition' => 'none',
366 - ),
367 - ),
368 - 'ping_status',
369 - ),
370 - ),
371 - 'parent',
372 - 'format',
373 - 'revisions',
374 - ),
375 - );
376 -
377 - return $config;
378 -}
379 -
380 -/**
381 314 * Provides the view configuration for the `wp_block` post type.
382 315 *
383 - * @param array $config {
384 - * The view configuration for the entity.
385 - * }
386 - * @return array The filtered view configuration.
316 + * @param Gutenberg_View_Config_Data $data The view configuration container for the entity.
317 + * @return Gutenberg_View_Config_Data The updated view configuration container.
387 318 */
388 -function _gutenberg_get_entity_view_config_post_type_wp_block( $config ) {
389 - $config['default_layouts'] = array(
319 +function _gutenberg_get_entity_view_config_posttype_wp_block( $data ) {
320 + $default_layouts = array(
390 321 'table' => array(
391 322 'layout' => array(
392 323 'styles' => array(
393 324 'author' => array(
@@ -402,9 +333,9 @@
402 333 ),
403 334 ),
404 335 );
405 336
406 - $config['default_view'] = array(
337 + $default_view = array(
407 338 'type' => 'grid',
408 339 'perPage' => 20,
409 340 'titleField' => 'title',
410 341 'mediaField' => 'preview',
@@ -409,9 +340,9 @@
409 340 'titleField' => 'title',
410 341 'mediaField' => 'preview',
411 342 'fields' => array( 'sync-status' ),
412 343 'filters' => array(),
413 - 'layout' => $config['default_layouts']['grid']['layout'],
344 + 'layout' => $default_layouts['grid']['layout'],
414 345 );
415 346
416 347 $view_list = array(
417 348 array(
@@ -459,23 +390,51 @@
459 390 'slug' => $category_name,
460 391 );
461 392 }
462 393
463 - $config['view_list'] = $view_list;
394 + $form = array(
395 + 'layout' => array( 'type' => 'panel' ),
396 + 'fields' => array(
397 + array(
398 + 'id' => 'excerpt',
399 + 'layout' => array(
400 + 'type' => 'panel',
401 + 'labelPosition' => 'top',
402 + ),
403 + ),
404 + array(
405 + 'id' => 'post-content-info',
406 + 'layout' => array(
407 + 'type' => 'regular',
408 + 'labelPosition' => 'none',
409 + ),
410 + ),
411 + 'sync-status',
412 + 'revisions',
413 + ),
414 + );
464 415
465 - return $config;
416 + $data->set(
417 + array(
418 + 'default_view' => $default_view,
419 + 'default_layouts' => $default_layouts,
420 + 'view_list' => $view_list,
421 + 'form' => $form,
422 + ),
423 + 1
424 + );
425 +
426 + return $data;
466 427 }
467 428
468 429 /**
469 430 * Provides the view configuration for the `wp_template_part` post type.
470 431 *
471 - * @param array $config {
472 - * The view configuration for the entity.
473 - * }
474 - * @return array The filtered view configuration.
432 + * @param Gutenberg_View_Config_Data $data The view configuration container for the entity.
433 + * @return Gutenberg_View_Config_Data The updated view configuration container.
475 434 */
476 -function _gutenberg_get_entity_view_config_post_type_wp_template_part( $config ) {
477 - $config['default_layouts'] = array(
435 +function _gutenberg_get_entity_view_config_posttype_wp_template_part( $data ) {
436 + $default_layouts = array(
478 437 'table' => array(
479 438 'layout' => array(
480 439 'styles' => array(
481 440 'author' => array(
@@ -488,9 +447,9 @@
488 447 'layout' => array(),
489 448 ),
490 449 );
491 450
492 - $config['default_view'] = array(
451 + $default_view = array(
493 452 'type' => 'grid',
494 453 'perPage' => 20,
495 454 'titleField' => 'title',
496 455 'mediaField' => 'preview',
@@ -495,9 +454,9 @@
495 454 'titleField' => 'title',
496 455 'mediaField' => 'preview',
497 456 'fields' => array( 'author' ),
498 457 'filters' => array(),
499 - 'layout' => $config['default_layouts']['grid']['layout'],
458 + 'layout' => $default_layouts['grid']['layout'],
500 459 );
501 460
502 461 $view_list = array(
503 462 array(
@@ -539,11 +498,9 @@
539 498 ),
540 499 );
541 500 }
542 501
543 - $config['view_list'] = $view_list;
544 -
545 - $config['form'] = array(
502 + $form = array(
546 503 'layout' => array( 'type' => 'panel' ),
547 504 'fields' => array(
548 505 array(
549 506 'id' => 'last_edited_date',
@@ -555,21 +512,29 @@
555 512 'revisions',
556 513 ),
557 514 );
558 515
559 - return $config;
516 + $data->set(
517 + array(
518 + 'default_view' => $default_view,
519 + 'default_layouts' => $default_layouts,
520 + 'view_list' => $view_list,
521 + 'form' => $form,
522 + ),
523 + 1
524 + );
525 +
526 + return $data;
560 527 }
561 528
562 529 /**
563 530 * Provides the view configuration for the `wp_template` post type.
564 531 *
565 - * @param array $config {
566 - * The view configuration for the entity.
567 - * }
568 - * @return array The filtered view configuration.
532 + * @param Gutenberg_View_Config_Data $data The view configuration container for the entity.
533 + * @return Gutenberg_View_Config_Data The updated view configuration container.
569 534 */
570 -function _gutenberg_get_entity_view_config_post_type_wp_template( $config ) {
571 - $config['default_view'] = array(
535 +function _gutenberg_get_entity_view_config_posttype_wp_template( $data ) {
536 + $default_view = array(
572 537 'type' => 'grid',
573 538 'perPage' => 20,
574 539 'sort' => array(
575 540 'field' => 'title',
@@ -582,9 +547,9 @@
582 547 'filters' => array(),
583 548 'showMedia' => true,
584 549 );
585 550
586 - $config['default_layouts'] = array(
551 + $default_layouts = array(
587 552 'table' => array( 'showMedia' => false ),
588 553 'grid' => array( 'showMedia' => true ),
589 554 'list' => array( 'showMedia' => false ),
590 555 );
@@ -726,11 +691,9 @@
726 691 }
727 692 }
728 693 }
729 694
730 - $config['view_list'] = array_merge( $view_list, $registered_authors, $user_authors );
731 -
732 - $config['form'] = array(
695 + $form = array(
733 696 'layout' => array( 'type' => 'panel' ),
734 697 'fields' => array(
735 698 array(
736 699 'id' => 'description',
@@ -763,9 +726,19 @@
763 726 'default_comment_status',
764 727 ),
765 728 );
766 729
767 - return $config;
730 + $data->set(
731 + array(
732 + 'default_view' => $default_view,
733 + 'default_layouts' => $default_layouts,
734 + 'view_list' => array_merge( $view_list, $registered_authors, $user_authors ),
735 + 'form' => $form,
736 + ),
737 + 1
738 + );
739 +
740 + return $data;
768 741 }
769 742
770 743 /**
771 744 * Registers the Gutenberg entity view configuration filters, overriding any
@@ -770,13 +743,17 @@
770 743 /**
771 744 * Registers the Gutenberg entity view configuration filters, overriding any
772 745 * defaults that WordPress core may have already registered.
773 746 *
774 - * Core registers its own `_wp_get_entity_view_config_post_type_*` callbacks on
747 + * Core registers its own `_wp_get_entity_view_config_posttype_*` callbacks on
775 748 * the shared `get_entity_view_config_{$kind}_{$name}` hooks. The Gutenberg
776 749 * plugin always ships the newest configuration, so it removes the core defaults
777 750 * and installs its own `_gutenberg_*` callbacks instead.
778 751 *
752 + * Post types without a dedicated `_gutenberg_*` callback (e.g. `post`) still have
753 + * the core callback removed so they fall back to the default configuration
754 + * built in gutenberg_get_entity_view_config().
755 + *
779 756 * This runs on `init` rather than at file include time so that the core
780 757 * defaults are guaranteed to be registered first, regardless of whether core
781 758 * registers them at include time or lazily on a hook.
782 759 */
@@ -783,11 +760,11 @@
783 760 function gutenberg_register_entity_view_config_filters() {
784 761 $post_types = array( 'page', 'post', 'wp_block', 'wp_template_part', 'wp_template' );
785 762
786 763 foreach ( $post_types as $post_type ) {
787 - $hook = "get_entity_view_config_postType_{$post_type}";
788 - $wp_callback = "_wp_get_entity_view_config_post_type_{$post_type}";
789 - $gb_callback = "_gutenberg_get_entity_view_config_post_type_{$post_type}";
764 + $hook = gutenberg_get_entity_view_config_hook_name( 'postType', $post_type );
765 + $wp_callback = "_wp_get_entity_view_config_posttype_{$post_type}";
766 + $gb_callback = "_gutenberg_get_entity_view_config_posttype_{$post_type}";
790 767
791 768 // has_filter() returns the priority the callback was registered at.
792 769 $wp_priority = has_filter( $hook, $wp_callback );
793 770 if ( false !== $wp_priority ) {