Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 61
0.00% covered (danger)
0.00%
0 / 2
CRAP
0.00% covered (danger)
0.00%
0 / 1
WPCOM_JSON_API_List_Post_Types_Endpoint
0.00% covered (danger)
0.00%
0 / 38
0.00% covered (danger)
0.00%
0 / 2
342
0.00% covered (danger)
0.00%
0 / 1
 callback
0.00% covered (danger)
0.00%
0 / 30
0.00% covered (danger)
0.00%
0 / 1
156
 post_type_supports_tags
0.00% covered (danger)
0.00%
0 / 8
0.00% covered (danger)
0.00%
0 / 1
42
1<?php // phpcs:ignore WordPress.Files.FileName.InvalidClassFileName
2
3if ( ! defined( 'ABSPATH' ) ) {
4    exit( 0 );
5}
6
7/**
8 * List post types endpoint.
9 */
10new WPCOM_JSON_API_List_Post_Types_Endpoint(
11    array(
12        'description'                          => 'Get a list of post types available for a site.',
13        'group'                                => 'sites',
14        'stat'                                 => 'sites:X:post-types',
15
16        'method'                               => 'GET',
17        'path'                                 => '/sites/%s/post-types',
18        'path_labels'                          => array(
19            '$site' => '(int|string) Site ID or domain',
20        ),
21
22        'allow_fallback_to_jetpack_blog_token' => true,
23
24        'query_parameters'                     => array(
25            'api_queryable' => '(bool) If true, only queryable post types are returned',
26        ),
27
28        'response_format'                      => array(
29            'found'      => '(int) The number of post types found',
30            'post_types' => '(array) A list of available post types',
31        ),
32        'example_request'                      => 'https://public-api.wordpress.com/rest/v1.1/sites/33534099/post-types',
33    )
34);
35
36/**
37 * List Post types endpoint class.
38 *
39 * /sites/%s/post-types -> $blog_id
40 *
41 * @phan-constructor-used-for-side-effects
42 */
43class WPCOM_JSON_API_List_Post_Types_Endpoint extends WPCOM_JSON_API_Endpoint {
44
45    /**
46     * Post type keys to include.
47     *
48     * @var array
49     */
50    public static $post_type_keys_to_include = array(
51        'name'               => 'name',
52        'label'              => 'label',
53        'labels'             => 'labels',
54        'description'        => 'description',
55        'map_meta_cap'       => 'map_meta_cap',
56        'cap'                => 'capabilities',
57        'hierarchical'       => 'hierarchical',
58        'public'             => 'public',
59        'show_ui'            => 'show_ui',
60        'publicly_queryable' => 'publicly_queryable',
61    );
62
63    /**
64     * API callback.
65     *
66     * @param string $path - the path.
67     * @param string $blog_id - the blog ID.
68     */
69    public function callback( $path = '', $blog_id = 0 ) {
70        $blog_id = $this->api->switch_to_blog_and_validate_user( $this->api->get_blog_id( $blog_id ) );
71        if ( is_wp_error( $blog_id ) ) {
72            return $blog_id;
73        }
74
75        if ( defined( 'IS_WPCOM' ) && IS_WPCOM ) {
76            $this->load_theme_functions();
77
78            /**
79             * Whether API responses should be returned in a custom locale.  False
80             * for Jetpack; may be true for WP.com requests.
81             *
82             * @since 3.9.2
83             */
84            if ( apply_filters( 'rest_api_localize_response', false ) ) {
85                // API localization occurs after the initial post types have been
86                // registered, so let's get the post type labels translated.
87                if ( 'en' !== get_locale() ) {
88                    global $wp_post_types;
89                    foreach ( $wp_post_types as $post_type_object ) {
90                        foreach ( array_keys( (array) $post_type_object->labels ) as $label_key ) {
91                            // Direct use of translate call because this doesn't need to be extracted.
92                            // phpcs:ignore WordPress.WP.I18n
93                            $post_type_object->labels->$label_key = translate( $post_type_object->labels->$label_key, 'default' );
94                        }
95                    }
96                }
97            }
98        }
99
100        // Get a list of available post types.
101        $post_types                  = get_post_types();
102        $formatted_post_type_objects = array();
103
104        // Retrieve post type object for each post type.
105        foreach ( $post_types as $post_type ) {
106            // Skip non-queryable if filtering on queryable only.
107            $is_queryable = $this->is_post_type_allowed( $post_type );
108            if ( ! $is_queryable ) {
109                continue;
110            }
111
112            $post_type_object           = get_post_type_object( $post_type );
113            $formatted_post_type_object = array();
114
115            // Include only the desired keys in the response.
116            foreach ( self::$post_type_keys_to_include as $key => $value ) {
117                $formatted_post_type_object[ $value ] = $post_type_object->{ $key };
118            }
119            $formatted_post_type_object['api_queryable'] = $is_queryable;
120            $formatted_post_type_object['supports']      = get_all_post_type_supports( $post_type );
121            if ( $this->post_type_supports_tags( $post_type ) ) {
122                $formatted_post_type_object['supports']['tags'] = true;
123            }
124
125            $formatted_post_type_objects[] = $formatted_post_type_object;
126        }
127
128        return array(
129            'found'      => count( $formatted_post_type_objects ),
130            'post_types' => $formatted_post_type_objects,
131        );
132    }
133
134    /**
135     * See if post type supports tags.
136     *
137     * @param string $post_type - the post type.
138     */
139    public function post_type_supports_tags( $post_type ) {
140        if ( in_array( 'post_tag', get_object_taxonomies( $post_type ), true ) ) {
141            return true;
142        }
143
144        // the featured content module adds post_tag support
145        // to the post types that are registered for it
146        // however it does so in a way that isn't available
147        // to get_object_taxonomies.
148        $featured_content = get_theme_support( 'featured-content' );
149        if ( ! $featured_content || empty( $featured_content[0] ) || empty( $featured_content[0]['post_types'] ) ) {
150            return false;
151        }
152
153        if ( is_array( $featured_content[0]['post_types'] ) ) {
154            return in_array( $post_type, $featured_content[0]['post_types'], true );
155        }
156        return $post_type === $featured_content[0]['post_types'];
157    }
158}