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 +283 -239 23.4.0 → 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 {
@@ -30,15 +132,15 @@
30 132 function gutenberg_get_entity_view_config( $kind, $name ) {
31 133 $default_view = array(
32 134 'type' => 'table',
33 135 'filters' => array(),
34 - 'perPage' => 20,
35 136 'sort' => array(
36 137 'field' => 'title',
37 138 'direction' => 'asc',
38 139 ),
140 + 'perPage' => 20,
141 + 'fields' => array( 'author', 'status' ),
39 142 'titleField' => 'title',
40 - 'fields' => array( 'author', 'status' ),
41 143 );
42 144 $default_layouts = array(
43 145 'table' => array(),
44 146 'grid' => 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,167 +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',
299 + $data->set(
300 + array(
301 + 'default_view' => $default_view,
302 + 'default_layouts' => $default_layouts,
297 303 ),
304 + 1
298 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 );
299 309
300 - return $config;
310 + return $data;
301 311 }
302 -if ( has_filter( 'get_entity_view_config_postType_page', '_wp_get_entity_view_config_post_type_page' ) ) {
303 - remove_filter( 'get_entity_view_config_postType_page', '_wp_get_entity_view_config_post_type_page' );
304 -}
305 -add_filter( 'get_entity_view_config_postType_page', '_gutenberg_get_entity_view_config_post_type_page', 10, 1 );
306 312
307 313 /**
308 - * Provides the view configuration for the `post` post type.
309 - *
310 - * @param array $config {
311 - * The view configuration for the entity.
312 - * }
313 - * @return array The filtered view configuration.
314 - */
315 -function _gutenberg_get_entity_view_config_post_type_post( $config ) {
316 - $config['form'] = array(
317 - 'layout' => array( 'type' => 'panel' ),
318 - 'fields' => array(
319 - array(
320 - 'id' => 'featured_media',
321 - 'layout' => array(
322 - 'type' => 'regular',
323 - 'labelPosition' => 'none',
324 - ),
325 - ),
326 - array(
327 - 'id' => 'post-content-info',
328 - 'layout' => array(
329 - 'type' => 'regular',
330 - 'labelPosition' => 'none',
331 - ),
332 - ),
333 - array(
334 - 'id' => 'excerpt',
335 - 'layout' => array(
336 - 'type' => 'panel',
337 - 'labelPosition' => 'top',
338 - ),
339 - ),
340 - array(
341 - 'id' => 'status',
342 - 'label' => __( 'Status', 'gutenberg' ),
343 - 'children' => array(
344 - array(
345 - 'id' => 'status',
346 - 'layout' => array(
347 - 'type' => 'regular',
348 - 'labelPosition' => 'none',
349 - ),
350 - ),
351 - 'scheduled_date',
352 - 'password',
353 - 'sticky',
354 - ),
355 - ),
356 - 'date',
357 - 'slug',
358 - 'author',
359 - 'template',
360 - array(
361 - 'id' => 'discussion',
362 - 'label' => __( 'Discussion', 'gutenberg' ),
363 - 'children' => array(
364 - array(
365 - 'id' => 'comment_status',
366 - 'layout' => array(
367 - 'type' => 'regular',
368 - 'labelPosition' => 'none',
369 - ),
370 - ),
371 - 'ping_status',
372 - ),
373 - ),
374 - 'parent',
375 - 'format',
376 - ),
377 - );
378 -
379 - return $config;
380 -}
381 -if ( has_filter( 'get_entity_view_config_postType_post', '_wp_get_entity_view_config_post_type_post' ) ) {
382 - remove_filter( 'get_entity_view_config_postType_post', '_wp_get_entity_view_config_post_type_post' );
383 -}
384 -add_filter( 'get_entity_view_config_postType_post', '_gutenberg_get_entity_view_config_post_type_post', 10, 1 );
385 -
386 -/**
387 314 * Provides the view configuration for the `wp_block` post type.
388 315 *
389 - * @param array $config {
390 - * The view configuration for the entity.
391 - * }
392 - * @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.
393 318 */
394 -function _gutenberg_get_entity_view_config_post_type_wp_block( $config ) {
395 - $config['default_layouts'] = array(
319 +function _gutenberg_get_entity_view_config_posttype_wp_block( $data ) {
320 + $default_layouts = array(
396 321 'table' => array(
397 322 'layout' => array(
398 323 'styles' => array(
399 324 'author' => array(
@@ -408,9 +333,9 @@
408 333 ),
409 334 ),
410 335 );
411 336
412 - $config['default_view'] = array(
337 + $default_view = array(
413 338 'type' => 'grid',
414 339 'perPage' => 20,
415 340 'titleField' => 'title',
416 341 'mediaField' => 'preview',
@@ -415,9 +340,9 @@
415 340 'titleField' => 'title',
416 341 'mediaField' => 'preview',
417 342 'fields' => array( 'sync-status' ),
418 343 'filters' => array(),
419 - 'layout' => $config['default_layouts']['grid']['layout'],
344 + 'layout' => $default_layouts['grid']['layout'],
420 345 );
421 346
422 347 $view_list = array(
423 348 array(
@@ -465,27 +390,51 @@
465 390 'slug' => $category_name,
466 391 );
467 392 }
468 393
469 - $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 + );
470 415
471 - 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;
472 427 }
473 -if ( has_filter( 'get_entity_view_config_postType_wp_block', '_wp_get_entity_view_config_post_type_wp_block' ) ) {
474 - remove_filter( 'get_entity_view_config_postType_wp_block', '_wp_get_entity_view_config_post_type_wp_block' );
475 -}
476 -add_filter( 'get_entity_view_config_postType_wp_block', '_gutenberg_get_entity_view_config_post_type_wp_block', 10, 1 );
477 428
478 429 /**
479 430 * Provides the view configuration for the `wp_template_part` post type.
480 431 *
481 - * @param array $config {
482 - * The view configuration for the entity.
483 - * }
484 - * @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.
485 434 */
486 -function _gutenberg_get_entity_view_config_post_type_wp_template_part( $config ) {
487 - $config['default_layouts'] = array(
435 +function _gutenberg_get_entity_view_config_posttype_wp_template_part( $data ) {
436 + $default_layouts = array(
488 437 'table' => array(
489 438 'layout' => array(
490 439 'styles' => array(
491 440 'author' => array(
@@ -498,9 +447,9 @@
498 447 'layout' => array(),
499 448 ),
500 449 );
501 450
502 - $config['default_view'] = array(
451 + $default_view = array(
503 452 'type' => 'grid',
504 453 'perPage' => 20,
505 454 'titleField' => 'title',
506 455 'mediaField' => 'preview',
@@ -505,9 +454,9 @@
505 454 'titleField' => 'title',
506 455 'mediaField' => 'preview',
507 456 'fields' => array( 'author' ),
508 457 'filters' => array(),
509 - 'layout' => $config['default_layouts']['grid']['layout'],
458 + 'layout' => $default_layouts['grid']['layout'],
510 459 );
511 460
512 461 $view_list = array(
513 462 array(
@@ -549,27 +498,43 @@
549 498 ),
550 499 );
551 500 }
552 501
553 - $config['view_list'] = $view_list;
502 + $form = array(
503 + 'layout' => array( 'type' => 'panel' ),
504 + 'fields' => array(
505 + array(
506 + 'id' => 'last_edited_date',
507 + 'layout' => array(
508 + 'type' => 'panel',
509 + 'labelPosition' => 'none',
510 + ),
511 + ),
512 + 'revisions',
513 + ),
514 + );
554 515
555 - 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;
556 527 }
557 -if ( has_filter( 'get_entity_view_config_postType_wp_template_part', '_wp_get_entity_view_config_post_type_wp_template_part' ) ) {
558 - remove_filter( 'get_entity_view_config_postType_wp_template_part', '_wp_get_entity_view_config_post_type_wp_template_part' );
559 -}
560 -add_filter( 'get_entity_view_config_postType_wp_template_part', '_gutenberg_get_entity_view_config_post_type_wp_template_part', 10, 1 );
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,12 +691,91 @@
726 691 }
727 692 }
728 693 }
729 694
730 - $config['view_list'] = array_merge( $view_list, $registered_authors, $user_authors );
695 + $form = array(
696 + 'layout' => array( 'type' => 'panel' ),
697 + 'fields' => array(
698 + array(
699 + 'id' => 'description',
700 + 'layout' => array(
701 + 'type' => 'panel',
702 + 'labelPosition' => 'top',
703 + ),
704 + ),
705 + array(
706 + 'id' => 'description_readonly',
707 + 'layout' => array(
708 + 'type' => 'regular',
709 + 'labelPosition' => 'none',
710 + ),
711 + ),
712 + array(
713 + 'id' => 'last_edited_date',
714 + 'layout' => array(
715 + 'type' => 'panel',
716 + 'labelPosition' => 'none',
717 + ),
718 + ),
719 + 'revisions',
720 + // The following fields are only meaningful in the `home`/`index`
721 + // template summary. They edit other entities (`root/site` and the
722 + // posts page); the editor merges those records into the form data
723 + // under a namespace and controls when the fields are shown.
724 + 'posts_page_title',
725 + 'posts_per_page',
726 + 'default_comment_status',
727 + ),
728 + );
731 729
732 - 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;
733 741 }
734 -if ( has_filter( 'get_entity_view_config_postType_wp_template', '_wp_get_entity_view_config_post_type_wp_template' ) ) {
735 - remove_filter( 'get_entity_view_config_postType_wp_template', '_wp_get_entity_view_config_post_type_wp_template' );
742 +
743 +/**
744 + * Registers the Gutenberg entity view configuration filters, overriding any
745 + * defaults that WordPress core may have already registered.
746 + *
747 + * Core registers its own `_wp_get_entity_view_config_posttype_*` callbacks on
748 + * the shared `get_entity_view_config_{$kind}_{$name}` hooks. The Gutenberg
749 + * plugin always ships the newest configuration, so it removes the core defaults
750 + * and installs its own `_gutenberg_*` callbacks instead.
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 + *
756 + * This runs on `init` rather than at file include time so that the core
757 + * defaults are guaranteed to be registered first, regardless of whether core
758 + * registers them at include time or lazily on a hook.
759 + */
760 +function gutenberg_register_entity_view_config_filters() {
761 + $post_types = array( 'page', 'post', 'wp_block', 'wp_template_part', 'wp_template' );
762 +
763 + foreach ( $post_types as $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}";
767 +
768 + // has_filter() returns the priority the callback was registered at.
769 + $wp_priority = has_filter( $hook, $wp_callback );
770 + if ( false !== $wp_priority ) {
771 + remove_filter( $hook, $wp_callback, $wp_priority );
772 + }
773 + if ( function_exists( $gb_callback ) ) {
774 + // Base definitions run before the default priority, so third-party
775 + // callbacks registered at the default compose on top of them
776 + // regardless of registration order.
777 + add_filter( $hook, $gb_callback, 5, 1 );
778 + }
779 + }
736 780 }
737 -add_filter( 'get_entity_view_config_postType_wp_template', '_gutenberg_get_entity_view_config_post_type_wp_template', 10, 1 );
781 +add_action( 'init', 'gutenberg_register_entity_view_config_filters' );