Make WordPress Core

Changeset 54269


Ignore:
Timestamp:
09/20/2022 09:19:10 PM (22 months ago)
Author:
hellofromTonya
Message:

Editor: Adds template types, is_wp_suggestion, and fallback template content.

This commit improves site editor templates by:

  • Adds a post meta is_wp_suggestion to templates created from the site editor.

Why? To differentiate the templates created from the post editor in the Template panel in inspector controls and the templates suggested in site editor.

See Gutenberg PR 41387 for more details.

  • Expands the template types that can be added to the site editor to include single custom post type and specific posts templates.

See Gutenberg PR 41189 for more details.

  • Adds fallback template content on creation in site editor:
    • Introduces get_template_hierarchy() to get the template hierarchy for a given template slug to be created.
    • Adds a lookup route to WP_REST_Templates_Controller to get the fallback template content.

See Gutenberg PR 42520 for more details.

  • Fixes a typo in default category template's description within get_default_block_template_types().

See Gutenberg PR 42586 for more details.

  • Changes field checks from in_array() to rest_is_field_included() in WP_REST_Post_Types_Controller.
  • Adds an icon field to WP_REST_Post_Types_Controller

Follow-up to [53129], [52331], [52275], [52062], [51962], [43087].

Props ntsekouras, spacedmonkey, mamaduka, mburridge, jameskoster, bernhard-reiter, mcsf, hellofromTonya.
See #56467.

Location:
trunk
Files:
3 added
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/phpcs.xml.dist

    r53800 r54269  
    238238                <!-- Test case parent classes outside of the "includes" folder. -->
    239239                <element value="Tests_Query_Conditionals"/>
     240                <element value="WP_Block_Templates_UnitTestCase"/>
    240241                <element value="WP_Filesystem_UnitTestCase"/>
    241242                <element value="WP_HTTP_UnitTestCase"/>
  • trunk/src/wp-includes/block-template-utils.php

    r54210 r54269  
    148148        'category'       => array(
    149149            'title'       => _x( 'Category', 'Template name' ),
    150             'description' => __( 'Displays latest posts in single post category.' ),
     150            'description' => __( 'Displays latest posts from a single post category.' ),
    151151        ),
    152152        'taxonomy'       => array(
     
    556556    $has_theme_file = wp_get_theme()->get_stylesheet() === $theme && null !== $template_file;
    557557
    558     $origin = get_post_meta( $post->ID, 'origin', true );
     558    $origin           = get_post_meta( $post->ID, 'origin', true );
     559    $is_wp_suggestion = get_post_meta( $post->ID, 'is_wp_suggestion', true );
    559560
    560561    $template                 = new WP_Block_Template();
     
    571572    $template->status         = $post->post_status;
    572573    $template->has_theme_file = $has_theme_file;
    573     $template->is_custom      = true;
     574    $template->is_custom      = empty( $is_wp_suggestion );
    574575    $template->author         = $post->post_author;
    575576
     
    680681        }
    681682
    682         if ( $post_type &&
     683        if (
     684            $post_type &&
    683685            isset( $template->post_types ) &&
    684686            ! in_array( $post_type, $template->post_types, true )
     
    913915 */
    914916function wp_is_theme_directory_ignored( $path ) {
    915     $directories_to_ignore = array( '.svn', '.git', '.hg', '.bzr', 'node_modules', 'vendor' );
     917    $directories_to_ignore = array( '.DS_Store', '.svn', '.git', '.hg', '.bzr', 'node_modules', 'vendor' );
     918
    916919    foreach ( $directories_to_ignore as $directory ) {
    917         if ( strpos( $path, $directory ) === 0 ) {
     920        if ( str_starts_with( $path, $directory ) ) {
    918921            return true;
    919922        }
     
    10241027    return $filename;
    10251028}
     1029
     1030/**
     1031 * Gets the template hierarchy for the given template slug to be created.
     1032 *
     1033 *
     1034 * Note: Always add `index` as the last fallback template.
     1035 *
     1036 * @since 6.1.0
     1037 *
     1038 * @param string  $slug           The template slug to be created.
     1039 * @param boolean $is_custom      Optional. Indicates if a template is custom or
     1040 *                                part of the template hierarchy. Default false.
     1041 * @param string $template_prefix Optional. The template prefix for the created template.
     1042 *                                Used to extract the main template type, e.g.
     1043 *                                in `taxonomy-books` the `taxonomy` is extracted.
     1044 *                                Default empty string.
     1045 * @return string[] The template hierarchy.
     1046 */
     1047function get_template_hierarchy( $slug, $is_custom = false, $template_prefix = '' ) {
     1048    if ( 'index' === $slug ) {
     1049        return array( 'index' );
     1050    }
     1051    if ( $is_custom ) {
     1052        return array( 'page', 'singular', 'index' );
     1053    }
     1054    if ( 'front-page' === $slug ) {
     1055        return array( 'front-page', 'home', 'index' );
     1056    }
     1057
     1058    $template_hierarchy = array( $slug );
     1059
     1060    // Most default templates don't have `$template_prefix` assigned.
     1061    if ( $template_prefix ) {
     1062        list( $type ) = explode( '-', $template_prefix );
     1063        // These checks are needed because the `$slug` above is always added.
     1064        if ( ! in_array( $template_prefix, array( $slug, $type ), true ) ) {
     1065            $template_hierarchy[] = $template_prefix;
     1066        }
     1067        if ( $slug !== $type ) {
     1068            $template_hierarchy[] = $type;
     1069        }
     1070    }
     1071
     1072    // Handle `archive` template.
     1073    if (
     1074        str_starts_with( $slug, 'author' ) ||
     1075        str_starts_with( $slug, 'taxonomy' ) ||
     1076        str_starts_with( $slug, 'category' ) ||
     1077        str_starts_with( $slug, 'tag' ) ||
     1078        'date' === $slug
     1079    ) {
     1080        $template_hierarchy[] = 'archive';
     1081    }
     1082    // Handle `single` template.
     1083    if ( 'attachment' === $slug ) {
     1084        $template_hierarchy[] = 'single';
     1085    }
     1086
     1087    // Handle `singular` template.
     1088    if (
     1089        str_starts_with( $slug, 'single' ) ||
     1090        str_starts_with( $slug, 'page' ) ||
     1091        'attachment' === $slug
     1092    ) {
     1093        $template_hierarchy[] = 'singular';
     1094    }
     1095
     1096    $template_hierarchy[] = 'index';
     1097
     1098    return $template_hierarchy;
     1099};
  • trunk/src/wp-includes/rest-api/endpoints/class-wp-rest-post-types-controller.php

    r53760 r54269  
    187187        $data   = array();
    188188
    189         if ( in_array( 'capabilities', $fields, true ) ) {
     189        if ( rest_is_field_included( 'capabilities', $fields ) ) {
    190190            $data['capabilities'] = $post_type->cap;
    191191        }
    192192
    193         if ( in_array( 'description', $fields, true ) ) {
     193        if ( rest_is_field_included( 'description', $fields ) ) {
    194194            $data['description'] = $post_type->description;
    195195        }
    196196
    197         if ( in_array( 'hierarchical', $fields, true ) ) {
     197        if ( rest_is_field_included( 'hierarchical', $fields ) ) {
    198198            $data['hierarchical'] = $post_type->hierarchical;
    199199        }
    200200
    201         if ( in_array( 'visibility', $fields, true ) ) {
     201        if ( rest_is_field_included( 'visibility', $fields ) ) {
    202202            $data['visibility'] = array(
    203203                'show_in_nav_menus' => (bool) $post_type->show_in_nav_menus,
     
    206206        }
    207207
    208         if ( in_array( 'viewable', $fields, true ) ) {
     208        if ( rest_is_field_included( 'viewable', $fields ) ) {
    209209            $data['viewable'] = is_post_type_viewable( $post_type );
    210210        }
    211211
    212         if ( in_array( 'labels', $fields, true ) ) {
     212        if ( rest_is_field_included( 'labels', $fields ) ) {
    213213            $data['labels'] = $post_type->labels;
    214214        }
    215215
    216         if ( in_array( 'name', $fields, true ) ) {
     216        if ( rest_is_field_included( 'name', $fields ) ) {
    217217            $data['name'] = $post_type->label;
    218218        }
    219219
    220         if ( in_array( 'slug', $fields, true ) ) {
     220        if ( rest_is_field_included( 'slug', $fields ) ) {
    221221            $data['slug'] = $post_type->name;
    222222        }
    223223
    224         if ( in_array( 'supports', $fields, true ) ) {
     224        if ( rest_is_field_included( 'icon', $fields ) ) {
     225            $data['icon'] = $post_type->menu_icon;
     226        }
     227
     228        if ( rest_is_field_included( 'supports', $fields ) ) {
    225229            $data['supports'] = $supports;
    226230        }
    227231
    228         if ( in_array( 'taxonomies', $fields, true ) ) {
     232        if ( rest_is_field_included( 'taxonomies', $fields ) ) {
    229233            $data['taxonomies'] = array_values( $taxonomies );
    230234        }
    231235
    232         if ( in_array( 'rest_base', $fields, true ) ) {
     236        if ( rest_is_field_included( 'rest_base', $fields ) ) {
    233237            $data['rest_base'] = $base;
    234238        }
    235239
    236         if ( in_array( 'rest_namespace', $fields, true ) ) {
     240        if ( rest_is_field_included( 'rest_namespace', $fields ) ) {
    237241            $data['rest_namespace'] = $namespace;
    238242        }
     
    288292     * @since 4.8.0 The `supports` property was added.
    289293     * @since 5.9.0 The `visibility` and `rest_namespace` properties were added.
     294     * @since 6.1.0 The `icon` property was added.
    290295     *
    291296     * @return array Item schema data.
     
    386391                    ),
    387392                ),
     393                'icon'           => array(
     394                    'description' => __( 'The icon for the post type.' ),
     395                    'type'        => array( 'string', 'null' ),
     396                    'context'     => array( 'view', 'edit', 'embed' ),
     397                    'readonly'    => true,
     398                ),
    388399            ),
    389400        );
  • trunk/src/wp-includes/rest-api/endpoints/class-wp-rest-templates-controller.php

    r54121 r54269  
    4343     *
    4444     * @since 5.8.0
     45     * @since 6.1.0 Endpoint for fallback template content.
    4546     */
    4647    public function register_routes() {
     
    6364                ),
    6465                'schema' => array( $this, 'get_public_item_schema' ),
     66            )
     67        );
     68
     69        // Get fallback template content.
     70        register_rest_route(
     71            $this->namespace,
     72            '/' . $this->rest_base . '/lookup',
     73            array(
     74                array(
     75                    'methods'             => WP_REST_Server::READABLE,
     76                    'callback'            => array( $this, 'get_template_fallback' ),
     77                    'permission_callback' => array( $this, 'get_item_permissions_check' ),
     78                    'args'                => array(
     79                        'slug'            => array(
     80                            'description' => __( 'The slug of the template to get the fallback for' ),
     81                            'type'        => 'string',
     82                            'required'    => true,
     83                        ),
     84                        'is_custom'       => array(
     85                            'description' => __( ' Indicates if a template is custom or part of the template hierarchy' ),
     86                            'type'        => 'boolean',
     87                        ),
     88                        'template_prefix' => array(
     89                            'description' => __( 'The template prefix for the created template. This is used to extract the main template type, e.g. in `taxonomy-books` extracts the `taxonomy`' ),
     90                            'type'        => 'string',
     91                        ),
     92                    ),
     93                ),
    6594            )
    6695        );
     
    116145            )
    117146        );
     147    }
     148
     149    /**
     150     * Returns the fallback template for the given slug.
     151     *
     152     * @since 6.1.0
     153     *
     154     * @param WP_REST_Request $request The request instance.
     155     * @return WP_REST_Response|WP_Error
     156     */
     157    public function get_template_fallback( $request ) {
     158        $hierarchy         = get_template_hierarchy( $request['slug'], $request['is_custom'], $request['template_prefix'] );
     159        $fallback_template = resolve_block_template( $request['slug'], $hierarchy, '' );
     160        $response          = $this->prepare_item_for_response( $fallback_template, $request );
     161        return rest_ensure_response( $response );
    118162    }
    119163
     
    526570        }
    527571
     572        if ( 'wp_template' === $this->post_type && isset( $request['is_wp_suggestion'] ) ) {
     573            $changes->meta_input     = wp_parse_args(
     574                array(
     575                    'is_wp_suggestion' => $request['is_wp_suggestion'],
     576                ),
     577                $changes->meta_input = array()
     578            );
     579        }
     580
    528581        if ( 'wp_template_part' === $this->post_type ) {
    529582            if ( isset( $request['area'] ) ) {
  • trunk/tests/phpunit/tests/rest-api/rest-post-types-controller.php

    r54090 r54269  
    157157    }
    158158
     159    /**
     160     * @ticket 56467
     161     *
     162     * @covers WP_REST_Post_Types_Controller::get_item_schema
     163     */
    159164    public function test_get_item_schema() {
    160165        $request    = new WP_REST_Request( 'OPTIONS', '/wp/v2/types' );
     
    162167        $data       = $response->get_data();
    163168        $properties = $data['schema']['properties'];
    164         $this->assertCount( 12, $properties );
    165         $this->assertArrayHasKey( 'capabilities', $properties );
    166         $this->assertArrayHasKey( 'description', $properties );
    167         $this->assertArrayHasKey( 'hierarchical', $properties );
    168         $this->assertArrayHasKey( 'viewable', $properties );
    169         $this->assertArrayHasKey( 'labels', $properties );
    170         $this->assertArrayHasKey( 'name', $properties );
    171         $this->assertArrayHasKey( 'slug', $properties );
    172         $this->assertArrayHasKey( 'supports', $properties );
    173         $this->assertArrayHasKey( 'taxonomies', $properties );
    174         $this->assertArrayHasKey( 'rest_base', $properties );
    175         $this->assertArrayHasKey( 'rest_namespace', $properties );
    176         $this->assertArrayHasKey( 'visibility', $properties );
     169
     170        $this->assertCount( 13, $properties, 'Schema should have 13 properties' );
     171        $this->assertArrayHasKey( 'capabilities', $properties, '`capabilities` should be included in the schema' );
     172        $this->assertArrayHasKey( 'description', $properties, '`description` should be included in the schema' );
     173        $this->assertArrayHasKey( 'hierarchical', $properties, '`hierarchical` should be included in the schema' );
     174        $this->assertArrayHasKey( 'viewable', $properties, '`viewable` should be included in the schema' );
     175        $this->assertArrayHasKey( 'labels', $properties, '`labels` should be included in the schema' );
     176        $this->assertArrayHasKey( 'name', $properties, '`name` should be included in the schema' );
     177        $this->assertArrayHasKey( 'slug', $properties, '`slug` should be included in the schema' );
     178        $this->assertArrayHasKey( 'supports', $properties, '`supports` should be included in the schema' );
     179        $this->assertArrayHasKey( 'taxonomies', $properties, '`taxonomies` should be included in the schema' );
     180        $this->assertArrayHasKey( 'rest_base', $properties, '`rest_base` should be included in the schema' );
     181        $this->assertArrayHasKey( 'rest_namespace', $properties, '`rest_namespace` should be included in the schema' );
     182        $this->assertArrayHasKey( 'visibility', $properties, '`visibility` should be included in the schema' );
     183        $this->assertArrayHasKey( 'icon', $properties, '`icon` should be included in the schema' );
    177184    }
    178185
  • trunk/tests/phpunit/tests/rest-api/rest-schema-setup.php

    r54090 r54269  
    151151            '/wp/v2/template-parts/(?P<parent>[\d]+)/revisions',
    152152            '/wp/v2/template-parts/(?P<parent>[\d]+)/revisions/(?P<id>[\d]+)',
     153            '/wp/v2/template-parts/lookup',
    153154            '/wp/v2/templates',
    154155            '/wp/v2/templates/(?P<id>[\d]+)/autosaves',
     
    157158            '/wp/v2/templates/(?P<parent>[\d]+)/revisions',
    158159            '/wp/v2/templates/(?P<parent>[\d]+)/revisions/(?P<id>[\d]+)',
     160            '/wp/v2/templates/lookup',
    159161            '/wp/v2/themes',
    160162            '/wp/v2/themes/(?P<stylesheet>[^\/:<>\*\?"\|]+(?:\/[^\/:<>\*\?"\|]+)?)',
  • trunk/tests/phpunit/tests/rest-api/wpRestTemplatesController.php

    r54058 r54269  
    5757     * @covers WP_REST_Templates_Controller::register_routes
    5858     * @ticket 54596
     59     * @ticket 56467
    5960     */
    6061    public function test_register_routes() {
     
    6970            $routes,
    7071            'Single template based on the given ID route does not exist'
     72        );
     73        $this->assertArrayHasKey(
     74            '/wp/v2/templates/lookup',
     75            $routes,
     76            'Get template fallback content route does not exist'
    7177        );
    7278    }
     
    679685    }
    680686
     687    /**
     688     * @dataProvider data_create_item_with_is_wp_suggestion
     689     * @ticket 56467
     690     * @covers WP_REST_Templates_Controller::create_item
     691     *
     692     * @param array $body_params Data set to test.
     693     * @param array $expected    Expected results.
     694     */
     695    public function test_create_item_with_is_wp_suggestion( array $body_params, array $expected ) {
     696        // Set up the user.
     697        $body_params['author'] = self::$admin_id;
     698        $expected['author']    = self::$admin_id;
     699        wp_set_current_user( self::$admin_id );
     700
     701        $request = new WP_REST_Request( 'POST', '/wp/v2/templates' );
     702        $request->set_body_params( $body_params );
     703        $response = rest_get_server()->dispatch( $request );
     704        $data     = $response->get_data();
     705        unset( $data['_links'] );
     706        unset( $data['wp_id'] );
     707
     708        $this->assertSame( $expected, $data );
     709    }
     710
     711    /**
     712     * Data provider.
     713     *
     714     * @return array
     715     */
     716    public function data_create_item_with_is_wp_suggestion() {
     717        $expected = array(
     718            'id'             => 'default//page-rigas',
     719            'theme'          => 'default',
     720            'content'        => array(
     721                'raw' => 'Content',
     722            ),
     723            'slug'           => 'page-rigas',
     724            'source'         => 'custom',
     725            'origin'         => null,
     726            'type'           => 'wp_template',
     727            'description'    => 'Just a description',
     728            'title'          => array(
     729                'raw'      => 'My Template',
     730                'rendered' => 'My Template',
     731            ),
     732            'status'         => 'publish',
     733            'has_theme_file' => false,
     734            'is_custom'      => false,
     735            'author'         => null,
     736        );
     737
     738        return array(
     739            'is_wp_suggestion: true'  => array(
     740                'body_params' => array(
     741                    'slug'             => 'page-rigas',
     742                    'description'      => 'Just a description',
     743                    'title'            => 'My Template',
     744                    'content'          => 'Content',
     745                    'is_wp_suggestion' => true,
     746                    'author'           => null,
     747                ),
     748                'expected'    => $expected,
     749            ),
     750            'is_wp_suggestion: false' => array(
     751                'body_params' => array(
     752                    'slug'             => 'page-hi',
     753                    'description'      => 'Just a description',
     754                    'title'            => 'My Template',
     755                    'content'          => 'Content',
     756                    'is_wp_suggestion' => false,
     757                    'author'           => null,
     758                ),
     759                'expected'    => array_merge(
     760                    $expected,
     761                    array(
     762                        'id'        => 'default//page-hi',
     763                        'slug'      => 'page-hi',
     764                        'is_custom' => true,
     765                    )
     766                ),
     767            ),
     768        );
     769    }
     770
     771    /**
     772     * @ticket 56467
     773     * @covers WP_REST_Templates_Controller::get_template_fallback
     774     */
     775    public function test_get_template_fallback() {
     776        wp_set_current_user( self::$admin_id );
     777        switch_theme( 'block-theme' );
     778        $request = new WP_REST_Request( 'GET', '/wp/v2/templates/lookup' );
     779        // Should fallback to `index.html`.
     780        $request->set_param( 'slug', 'tag-status' );
     781        $request->set_param( 'is_custom', false );
     782        $request->set_param( 'template_prefix', 'tag' );
     783        $response = rest_get_server()->dispatch( $request );
     784        $this->assertSame( 'index', $response->get_data()['slug'], 'Should fallback to `index.html`.' );
     785        // Should fallback to `page.html`.
     786        $request->set_param( 'slug', 'page-hello' );
     787        $request->set_param( 'is_custom', false );
     788        $request->set_param( 'template_prefix', 'page' );
     789        $response = rest_get_server()->dispatch( $request );
     790        $this->assertSame( 'page', $response->get_data()['slug'], 'Should fallback to `page.html`.' );
     791    }
    681792}
  • trunk/tests/qunit/fixtures/wp-api-generated.js

    r54123 r54269  
    51415141            }
    51425142        },
     5143        "/wp/v2/templates/lookup": {
     5144            "namespace": "wp/v2",
     5145            "methods": [
     5146                "GET"
     5147            ],
     5148            "endpoints": [
     5149                {
     5150                    "methods": [
     5151                        "GET"
     5152                    ],
     5153                    "args": {
     5154                        "slug": {
     5155                            "description": "The slug of the template to get the fallback for",
     5156                            "type": "string",
     5157                            "required": true
     5158                        },
     5159                        "is_custom": {
     5160                            "description": " Indicates if a template is custom or part of the template hierarchy",
     5161                            "type": "boolean",
     5162                            "required": false
     5163                        },
     5164                        "template_prefix": {
     5165                            "description": "The template prefix for the created template. This is used to extract the main template type, e.g. in `taxonomy-books` extracts the `taxonomy`",
     5166                            "type": "string",
     5167                            "required": false
     5168                        }
     5169                    }
     5170                }
     5171            ],
     5172            "_links": {
     5173                "self": [
     5174                    {
     5175                        "href": "http://example.org/index.php?rest_route=/wp/v2/templates/lookup"
     5176                    }
     5177                ]
     5178            }
     5179        },
    51435180        "/wp/v2/templates/(?P<id>([^\\/:<>\\*\\?\"\\|]+(?:\\/[^\\/:<>\\*\\?\"\\|]+)?)[\\/\\w-]+)": {
    51445181            "namespace": "wp/v2",
     
    57895826                    {
    57905827                        "href": "http://example.org/index.php?rest_route=/wp/v2/template-parts"
     5828                    }
     5829                ]
     5830            }
     5831        },
     5832        "/wp/v2/template-parts/lookup": {
     5833            "namespace": "wp/v2",
     5834            "methods": [
     5835                "GET"
     5836            ],
     5837            "endpoints": [
     5838                {
     5839                    "methods": [
     5840                        "GET"
     5841                    ],
     5842                    "args": {
     5843                        "slug": {
     5844                            "description": "The slug of the template to get the fallback for",
     5845                            "type": "string",
     5846                            "required": true
     5847                        },
     5848                        "is_custom": {
     5849                            "description": " Indicates if a template is custom or part of the template hierarchy",
     5850                            "type": "boolean",
     5851                            "required": false
     5852                        },
     5853                        "template_prefix": {
     5854                            "description": "The template prefix for the created template. This is used to extract the main template type, e.g. in `taxonomy-books` extracts the `taxonomy`",
     5855                            "type": "string",
     5856                            "required": false
     5857                        }
     5858                    }
     5859                }
     5860            ],
     5861            "_links": {
     5862                "self": [
     5863                    {
     5864                        "href": "http://example.org/index.php?rest_route=/wp/v2/template-parts/lookup"
    57915865                    }
    57925866                ]
     
    1159211666        "name": "Posts",
    1159311667        "slug": "post",
     11668        "icon": "dashicons-admin-post",
    1159411669        "taxonomies": [
    1159511670            "category",
     
    1162311698        "name": "Pages",
    1162411699        "slug": "page",
     11700        "icon": "dashicons-admin-page",
    1162511701        "taxonomies": [],
    1162611702        "rest_base": "pages",
     
    1165111727        "name": "Media",
    1165211728        "slug": "attachment",
     11729        "icon": "dashicons-admin-media",
    1165311730        "taxonomies": [],
    1165411731        "rest_base": "media",
     
    1167911756        "name": "Navigation Menu Items",
    1168011757        "slug": "nav_menu_item",
     11758        "icon": null,
    1168111759        "taxonomies": [
    1168211760            "nav_menu"
     
    1170911787        "name": "Reusable blocks",
    1171011788        "slug": "wp_block",
     11789        "icon": null,
    1171111790        "taxonomies": [],
    1171211791        "rest_base": "blocks",
     
    1173711816        "name": "Templates",
    1173811817        "slug": "wp_template",
     11818        "icon": null,
    1173911819        "taxonomies": [],
    1174011820        "rest_base": "templates",
     
    1176511845        "name": "Template Parts",
    1176611846        "slug": "wp_template_part",
     11847        "icon": null,
    1176711848        "taxonomies": [],
    1176811849        "rest_base": "template-parts",
     
    1179311874        "name": "Navigation Menus",
    1179411875        "slug": "wp_navigation",
     11876        "icon": null,
    1179511877        "taxonomies": [],
    1179611878        "rest_base": "navigation",
     
    1182311905    "name": "Posts",
    1182411906    "slug": "post",
     11907    "icon": "dashicons-admin-post",
    1182511908    "taxonomies": [
    1182611909        "category",
Note: See TracChangeset for help on using the changeset viewer.