Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
98.89% covered (success)
98.89%
89 / 90
100.00% covered (success)
100.00%
1 / 1
CRAP
100.00% covered (success)
100.00%
1 / 1
Knowledge_Post_Type
100.00% covered (success)
100.00%
88 / 88
100.00% covered (success)
100.00%
1 / 1
2
100.00% covered (success)
100.00%
1 / 1
 register
100.00% covered (success)
100.00%
88 / 88
100.00% covered (success)
100.00%
1 / 1
2
1<?php
2/**
3 * Knowledge Post Type registration.
4 *
5 * @package automattic/jetpack-knowledge
6 */
7
8namespace Automattic\Jetpack\Knowledge;
9
10if ( ! defined( 'ABSPATH' ) ) {
11    exit;
12}
13
14/**
15 * Handles registration of the Knowledge custom post type.
16 */
17class Knowledge_Post_Type {
18
19    /**
20     * The post type name.
21     *
22     * @var string
23     */
24    const POST_TYPE = 'wp_knowledge';
25
26    /**
27     * The taxonomy name for knowledge types.
28     *
29     * @var string
30     */
31    const TAXONOMY = 'wp_knowledge_type';
32
33    /**
34     * Taxonomy term slug for the `guideline` knowledge type.
35     *
36     * @var string
37     */
38    const TERM_GUIDELINE = 'guideline';
39
40    /**
41     * Register the custom post type.
42     */
43    public static function register(): void {
44        if ( post_type_exists( self::POST_TYPE ) ) {
45            return;
46        }
47
48        register_post_type(
49            self::POST_TYPE,
50            array(
51                'labels'                => array(
52                    'name'                     => _x( 'Guidelines', 'post type general name', 'jetpack-knowledge' ),
53                    'singular_name'            => _x( 'Guideline', 'post type singular name', 'jetpack-knowledge' ),
54                    'add_new'                  => __( 'Add Guideline', 'jetpack-knowledge' ),
55                    'add_new_item'             => __( 'Add Guideline', 'jetpack-knowledge' ),
56                    'all_items'                => __( 'All Guidelines', 'jetpack-knowledge' ),
57                    'edit_item'                => __( 'Edit Guideline', 'jetpack-knowledge' ),
58                    'filter_items_list'        => __( 'Filter guidelines list', 'jetpack-knowledge' ),
59                    'item_published'           => __( 'Guideline published.', 'jetpack-knowledge' ),
60                    'item_published_privately' => __( 'Guideline published privately.', 'jetpack-knowledge' ),
61                    'item_reverted_to_draft'   => __( 'Guideline reverted to draft.', 'jetpack-knowledge' ),
62                    'item_scheduled'           => __( 'Guideline scheduled.', 'jetpack-knowledge' ),
63                    'item_updated'             => __( 'Guideline updated.', 'jetpack-knowledge' ),
64                    'items_list'               => __( 'Guidelines list', 'jetpack-knowledge' ),
65                    'items_list_navigation'    => __( 'Guidelines list navigation', 'jetpack-knowledge' ),
66                    'new_item'                 => __( 'New Guideline', 'jetpack-knowledge' ),
67                    'not_found'                => __( 'No guidelines found.', 'jetpack-knowledge' ),
68                    'not_found_in_trash'       => __( 'No guidelines found in Trash.', 'jetpack-knowledge' ),
69                    'search_items'             => __( 'Search Guidelines', 'jetpack-knowledge' ),
70                    'view_item'                => __( 'View Guideline', 'jetpack-knowledge' ),
71                    'view_items'               => __( 'View Guidelines', 'jetpack-knowledge' ),
72                ),
73                'public'                => false,
74                // Knowledge rows are managed through the REST API without post-type screens.
75                'show_ui'               => false,
76                'show_in_rest'          => true,
77                'rest_base'             => 'knowledge',
78
79                'rest_controller_class' => Knowledge_REST_Controller::class,
80
81                // Primitive capabilities stay plural and meta capabilities singular to avoid collisions.
82                'capability_type'       => array( 'knowledge_item', 'knowledge_items' ),
83                'map_meta_cap'          => true,
84                // `read` is remapped so Subscribers (who hold the base `read`
85                // cap) are blocked at the post-type door. Every other primitive
86                // defaults to a knowledge_items-suffixed cap synthesized by
87                // `wp_maybe_grant_knowledge_caps()`.
88                'capabilities'          => array(
89                    'read' => 'read_knowledge_items',
90                ),
91                'supports'              => array( 'title', 'editor', 'excerpt', 'author', 'revisions' ),
92                'hierarchical'          => false,
93                'has_archive'           => false,
94                'rewrite'               => false,
95                'query_var'             => false,
96                'can_export'            => true,
97            )
98        );
99
100        /*
101         * Disable autosave endpoints for knowledge. 'editor' support implies 'autosave', but knowledge is
102         * headless storage with no editor session, so the autosave REST routes have no consumer.
103         */
104        remove_post_type_support( self::POST_TYPE, 'autosave' );
105
106        register_taxonomy(
107            self::TAXONOMY,
108            self::POST_TYPE,
109            array(
110                'public'             => false,
111                'publicly_queryable' => false,
112                'hierarchical'       => true,
113                'labels'             => array(
114                    'name'                  => _x( 'Guideline Types', 'taxonomy general name', 'jetpack-knowledge' ),
115                    'singular_name'         => _x( 'Guideline Type', 'taxonomy singular name', 'jetpack-knowledge' ),
116                    'add_new_item'          => __( 'Add Guideline Type', 'jetpack-knowledge' ),
117                    'add_or_remove_items'   => __( 'Add or remove guideline types', 'jetpack-knowledge' ),
118                    'back_to_items'         => __( '&larr; Go to Guideline Types', 'jetpack-knowledge' ),
119                    'edit_item'             => __( 'Edit Guideline Type', 'jetpack-knowledge' ),
120                    'item_link'             => __( 'Guideline Type Link', 'jetpack-knowledge' ),
121                    'item_link_description' => __( 'A link to a guideline type.', 'jetpack-knowledge' ),
122                    'items_list'            => __( 'Guideline Types list', 'jetpack-knowledge' ),
123                    'items_list_navigation' => __( 'Guideline Types list navigation', 'jetpack-knowledge' ),
124                    'new_item_name'         => __( 'New Guideline Type Name', 'jetpack-knowledge' ),
125                    'no_terms'              => __( 'No guideline types', 'jetpack-knowledge' ),
126                    'not_found'             => __( 'No guideline types found.', 'jetpack-knowledge' ),
127                    'search_items'          => __( 'Search Guideline Types', 'jetpack-knowledge' ),
128                    'update_item'           => __( 'Update Guideline Type', 'jetpack-knowledge' ),
129                    'view_item'             => __( 'View Guideline Type', 'jetpack-knowledge' ),
130                ),
131
132                /*
133                 * Editing and assigning terms reuse the `wp_knowledge` primitive `edit_knowledge_items` so that anyone
134                 * who can edit a knowledge row can also lazily create and assign its type.
135                 */
136                'capabilities'       => array(
137                    'manage_terms' => 'manage_options',
138                    'edit_terms'   => 'edit_knowledge_items',
139                    'delete_terms' => 'manage_options',
140                    'assign_terms' => 'edit_knowledge_items',
141                ),
142                'query_var'          => false,
143                'rewrite'            => false,
144                // Headless, like the post type: knowledge type terms are managed
145                // through the REST API, not a wp-admin taxonomy screen.
146                'show_ui'            => false,
147                'show_in_nav_menus'  => false,
148                'show_in_rest'       => true,
149            )
150        );
151
152        add_filter( 'user_has_cap', 'wp_maybe_grant_knowledge_caps', 1, 4 );
153        add_action( 'save_post_' . self::POST_TYPE, 'wp_knowledge_ensure_default_type_term' );
154        add_filter( 'wp_insert_term_data', 'wp_knowledge_maybe_map_term_label', 10, 2 );
155
156        // Sanitize guideline content and re-stamp registry scope titles on the
157        // REST insert path. Slug uniqueness is left to WordPress: the published
158        // row keeps its exact slug and duplicates are suffixed (see knowledge.php).
159        add_filter( 'rest_pre_insert_' . self::POST_TYPE, 'wp_knowledge_guard_guideline_row', 10, 2 );
160    }
161}