balmet.com

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs

class-wp-post-type.php (20820B)


      1 <?php
      2 /**
      3  * Post API: WP_Post_Type class
      4  *
      5  * @package WordPress
      6  * @subpackage Post
      7  * @since 4.6.0
      8  */
      9 
     10 /**
     11  * Core class used for interacting with post types.
     12  *
     13  * @since 4.6.0
     14  *
     15  * @see register_post_type()
     16  */
     17 final class WP_Post_Type {
     18 	/**
     19 	 * Post type key.
     20 	 *
     21 	 * @since 4.6.0
     22 	 * @var string $name
     23 	 */
     24 	public $name;
     25 
     26 	/**
     27 	 * Name of the post type shown in the menu. Usually plural.
     28 	 *
     29 	 * @since 4.6.0
     30 	 * @var string $label
     31 	 */
     32 	public $label;
     33 
     34 	/**
     35 	 * Labels object for this post type.
     36 	 *
     37 	 * If not set, post labels are inherited for non-hierarchical types
     38 	 * and page labels for hierarchical ones.
     39 	 *
     40 	 * @see get_post_type_labels()
     41 	 *
     42 	 * @since 4.6.0
     43 	 * @var stdClass $labels
     44 	 */
     45 	public $labels;
     46 
     47 	/**
     48 	 * A short descriptive summary of what the post type is.
     49 	 *
     50 	 * Default empty.
     51 	 *
     52 	 * @since 4.6.0
     53 	 * @var string $description
     54 	 */
     55 	public $description = '';
     56 
     57 	/**
     58 	 * Whether a post type is intended for use publicly either via the admin interface or by front-end users.
     59 	 *
     60 	 * While the default settings of $exclude_from_search, $publicly_queryable, $show_ui, and $show_in_nav_menus
     61 	 * are inherited from public, each does not rely on this relationship and controls a very specific intention.
     62 	 *
     63 	 * Default false.
     64 	 *
     65 	 * @since 4.6.0
     66 	 * @var bool $public
     67 	 */
     68 	public $public = false;
     69 
     70 	/**
     71 	 * Whether the post type is hierarchical (e.g. page).
     72 	 *
     73 	 * Default false.
     74 	 *
     75 	 * @since 4.6.0
     76 	 * @var bool $hierarchical
     77 	 */
     78 	public $hierarchical = false;
     79 
     80 	/**
     81 	 * Whether to exclude posts with this post type from front end search
     82 	 * results.
     83 	 *
     84 	 * Default is the opposite value of $public.
     85 	 *
     86 	 * @since 4.6.0
     87 	 * @var bool $exclude_from_search
     88 	 */
     89 	public $exclude_from_search = null;
     90 
     91 	/**
     92 	 * Whether queries can be performed on the front end for the post type as part of `parse_request()`.
     93 	 *
     94 	 * Endpoints would include:
     95 	 * - `?post_type={post_type_key}`
     96 	 * - `?{post_type_key}={single_post_slug}`
     97 	 * - `?{post_type_query_var}={single_post_slug}`
     98 	 *
     99 	 * Default is the value of $public.
    100 	 *
    101 	 * @since 4.6.0
    102 	 * @var bool $publicly_queryable
    103 	 */
    104 	public $publicly_queryable = null;
    105 
    106 	/**
    107 	 * Whether to generate and allow a UI for managing this post type in the admin.
    108 	 *
    109 	 * Default is the value of $public.
    110 	 *
    111 	 * @since 4.6.0
    112 	 * @var bool $show_ui
    113 	 */
    114 	public $show_ui = null;
    115 
    116 	/**
    117 	 * Where to show the post type in the admin menu.
    118 	 *
    119 	 * To work, $show_ui must be true. If true, the post type is shown in its own top level menu. If false, no menu is
    120 	 * shown. If a string of an existing top level menu (eg. 'tools.php' or 'edit.php?post_type=page'), the post type
    121 	 * will be placed as a sub-menu of that.
    122 	 *
    123 	 * Default is the value of $show_ui.
    124 	 *
    125 	 * @since 4.6.0
    126 	 * @var bool|string $show_in_menu
    127 	 */
    128 	public $show_in_menu = null;
    129 
    130 	/**
    131 	 * Makes this post type available for selection in navigation menus.
    132 	 *
    133 	 * Default is the value $public.
    134 	 *
    135 	 * @since 4.6.0
    136 	 * @var bool $show_in_nav_menus
    137 	 */
    138 	public $show_in_nav_menus = null;
    139 
    140 	/**
    141 	 * Makes this post type available via the admin bar.
    142 	 *
    143 	 * Default is the value of $show_in_menu.
    144 	 *
    145 	 * @since 4.6.0
    146 	 * @var bool $show_in_admin_bar
    147 	 */
    148 	public $show_in_admin_bar = null;
    149 
    150 	/**
    151 	 * The position in the menu order the post type should appear.
    152 	 *
    153 	 * To work, $show_in_menu must be true. Default null (at the bottom).
    154 	 *
    155 	 * @since 4.6.0
    156 	 * @var int $menu_position
    157 	 */
    158 	public $menu_position = null;
    159 
    160 	/**
    161 	 * The URL or reference to the icon to be used for this menu.
    162 	 *
    163 	 * Pass a base64-encoded SVG using a data URI, which will be colored to match the color scheme.
    164 	 * This should begin with 'data:image/svg+xml;base64,'. Pass the name of a Dashicons helper class
    165 	 * to use a font icon, e.g. 'dashicons-chart-pie'. Pass 'none' to leave div.wp-menu-image empty
    166 	 * so an icon can be added via CSS.
    167 	 *
    168 	 * Defaults to use the posts icon.
    169 	 *
    170 	 * @since 4.6.0
    171 	 * @var string $menu_icon
    172 	 */
    173 	public $menu_icon = null;
    174 
    175 	/**
    176 	 * The string to use to build the read, edit, and delete capabilities.
    177 	 *
    178 	 * May be passed as an array to allow for alternative plurals when using
    179 	 * this argument as a base to construct the capabilities, e.g.
    180 	 * array( 'story', 'stories' ). Default 'post'.
    181 	 *
    182 	 * @since 4.6.0
    183 	 * @var string $capability_type
    184 	 */
    185 	public $capability_type = 'post';
    186 
    187 	/**
    188 	 * Whether to use the internal default meta capability handling.
    189 	 *
    190 	 * Default false.
    191 	 *
    192 	 * @since 4.6.0
    193 	 * @var bool $map_meta_cap
    194 	 */
    195 	public $map_meta_cap = false;
    196 
    197 	/**
    198 	 * Provide a callback function that sets up the meta boxes for the edit form.
    199 	 *
    200 	 * Do `remove_meta_box()` and `add_meta_box()` calls in the callback. Default null.
    201 	 *
    202 	 * @since 4.6.0
    203 	 * @var callable $register_meta_box_cb
    204 	 */
    205 	public $register_meta_box_cb = null;
    206 
    207 	/**
    208 	 * An array of taxonomy identifiers that will be registered for the post type.
    209 	 *
    210 	 * Taxonomies can be registered later with `register_taxonomy()` or `register_taxonomy_for_object_type()`.
    211 	 *
    212 	 * Default empty array.
    213 	 *
    214 	 * @since 4.6.0
    215 	 * @var array $taxonomies
    216 	 */
    217 	public $taxonomies = array();
    218 
    219 	/**
    220 	 * Whether there should be post type archives, or if a string, the archive slug to use.
    221 	 *
    222 	 * Will generate the proper rewrite rules if $rewrite is enabled. Default false.
    223 	 *
    224 	 * @since 4.6.0
    225 	 * @var bool|string $has_archive
    226 	 */
    227 	public $has_archive = false;
    228 
    229 	/**
    230 	 * Sets the query_var key for this post type.
    231 	 *
    232 	 * Defaults to $post_type key. If false, a post type cannot be loaded at `?{query_var}={post_slug}`.
    233 	 * If specified as a string, the query `?{query_var_string}={post_slug}` will be valid.
    234 	 *
    235 	 * @since 4.6.0
    236 	 * @var string|bool $query_var
    237 	 */
    238 	public $query_var;
    239 
    240 	/**
    241 	 * Whether to allow this post type to be exported.
    242 	 *
    243 	 * Default true.
    244 	 *
    245 	 * @since 4.6.0
    246 	 * @var bool $can_export
    247 	 */
    248 	public $can_export = true;
    249 
    250 	/**
    251 	 * Whether to delete posts of this type when deleting a user.
    252 	 *
    253 	 * - If true, posts of this type belonging to the user will be moved to Trash when the user is deleted.
    254 	 * - If false, posts of this type belonging to the user will *not* be trashed or deleted.
    255 	 * - If not set (the default), posts are trashed if post type supports the 'author' feature.
    256 	 *   Otherwise posts are not trashed or deleted.
    257 	 *
    258 	 * Default null.
    259 	 *
    260 	 * @since 4.6.0
    261 	 * @var bool $delete_with_user
    262 	 */
    263 	public $delete_with_user = null;
    264 
    265 	/**
    266 	 * Array of blocks to use as the default initial state for an editor session.
    267 	 *
    268 	 * Each item should be an array containing block name and optional attributes.
    269 	 *
    270 	 * Default empty array.
    271 	 *
    272 	 * @link https://developer.wordpress.org/block-editor/developers/block-api/block-templates/
    273 	 *
    274 	 * @since 5.0.0
    275 	 * @var array $template
    276 	 */
    277 	public $template = array();
    278 
    279 	/**
    280 	 * Whether the block template should be locked if $template is set.
    281 	 *
    282 	 * - If set to 'all', the user is unable to insert new blocks, move existing blocks
    283 	 *   and delete blocks.
    284 	 * - If set to 'insert', the user is able to move existing blocks but is unable to insert
    285 	 *   new blocks and delete blocks.
    286 	 *
    287 	 * Default false.
    288 	 *
    289 	 * @link https://developer.wordpress.org/block-editor/developers/block-api/block-templates/
    290 	 *
    291 	 * @since 5.0.0
    292 	 * @var string|false $template_lock
    293 	 */
    294 	public $template_lock = false;
    295 
    296 	/**
    297 	 * Whether this post type is a native or "built-in" post_type.
    298 	 *
    299 	 * Default false.
    300 	 *
    301 	 * @since 4.6.0
    302 	 * @var bool $_builtin
    303 	 */
    304 	public $_builtin = false;
    305 
    306 	/**
    307 	 * URL segment to use for edit link of this post type.
    308 	 *
    309 	 * Default 'post.php?post=%d'.
    310 	 *
    311 	 * @since 4.6.0
    312 	 * @var string $_edit_link
    313 	 */
    314 	public $_edit_link = 'post.php?post=%d';
    315 
    316 	/**
    317 	 * Post type capabilities.
    318 	 *
    319 	 * @since 4.6.0
    320 	 * @var stdClass $cap
    321 	 */
    322 	public $cap;
    323 
    324 	/**
    325 	 * Triggers the handling of rewrites for this post type.
    326 	 *
    327 	 * Defaults to true, using $post_type as slug.
    328 	 *
    329 	 * @since 4.6.0
    330 	 * @var array|false $rewrite
    331 	 */
    332 	public $rewrite;
    333 
    334 	/**
    335 	 * The features supported by the post type.
    336 	 *
    337 	 * @since 4.6.0
    338 	 * @var array|bool $supports
    339 	 */
    340 	public $supports;
    341 
    342 	/**
    343 	 * Whether this post type should appear in the REST API.
    344 	 *
    345 	 * Default false. If true, standard endpoints will be registered with
    346 	 * respect to $rest_base and $rest_controller_class.
    347 	 *
    348 	 * @since 4.7.4
    349 	 * @var bool $show_in_rest
    350 	 */
    351 	public $show_in_rest;
    352 
    353 	/**
    354 	 * The base path for this post type's REST API endpoints.
    355 	 *
    356 	 * @since 4.7.4
    357 	 * @var string|bool $rest_base
    358 	 */
    359 	public $rest_base;
    360 
    361 	/**
    362 	 * The controller for this post type's REST API endpoints.
    363 	 *
    364 	 * Custom controllers must extend WP_REST_Controller.
    365 	 *
    366 	 * @since 4.7.4
    367 	 * @var string|bool $rest_controller_class
    368 	 */
    369 	public $rest_controller_class;
    370 
    371 	/**
    372 	 * The controller instance for this post type's REST API endpoints.
    373 	 *
    374 	 * Lazily computed. Should be accessed using {@see WP_Post_Type::get_rest_controller()}.
    375 	 *
    376 	 * @since 5.3.0
    377 	 * @var WP_REST_Controller $rest_controller
    378 	 */
    379 	public $rest_controller;
    380 
    381 	/**
    382 	 * Constructor.
    383 	 *
    384 	 * See the register_post_type() function for accepted arguments for `$args`.
    385 	 *
    386 	 * Will populate object properties from the provided arguments and assign other
    387 	 * default properties based on that information.
    388 	 *
    389 	 * @since 4.6.0
    390 	 *
    391 	 * @see register_post_type()
    392 	 *
    393 	 * @param string       $post_type Post type key.
    394 	 * @param array|string $args      Optional. Array or string of arguments for registering a post type.
    395 	 *                                Default empty array.
    396 	 */
    397 	public function __construct( $post_type, $args = array() ) {
    398 		$this->name = $post_type;
    399 
    400 		$this->set_props( $args );
    401 	}
    402 
    403 	/**
    404 	 * Sets post type properties.
    405 	 *
    406 	 * See the register_post_type() function for accepted arguments for `$args`.
    407 	 *
    408 	 * @since 4.6.0
    409 	 *
    410 	 * @param array|string $args Array or string of arguments for registering a post type.
    411 	 */
    412 	public function set_props( $args ) {
    413 		$args = wp_parse_args( $args );
    414 
    415 		/**
    416 		 * Filters the arguments for registering a post type.
    417 		 *
    418 		 * @since 4.4.0
    419 		 *
    420 		 * @param array  $args      Array of arguments for registering a post type.
    421 		 *                          See the register_post_type() function for accepted arguments.
    422 		 * @param string $post_type Post type key.
    423 		 */
    424 		$args = apply_filters( 'register_post_type_args', $args, $this->name );
    425 
    426 		$has_edit_link = ! empty( $args['_edit_link'] );
    427 
    428 		// Args prefixed with an underscore are reserved for internal use.
    429 		$defaults = array(
    430 			'labels'                => array(),
    431 			'description'           => '',
    432 			'public'                => false,
    433 			'hierarchical'          => false,
    434 			'exclude_from_search'   => null,
    435 			'publicly_queryable'    => null,
    436 			'show_ui'               => null,
    437 			'show_in_menu'          => null,
    438 			'show_in_nav_menus'     => null,
    439 			'show_in_admin_bar'     => null,
    440 			'menu_position'         => null,
    441 			'menu_icon'             => null,
    442 			'capability_type'       => 'post',
    443 			'capabilities'          => array(),
    444 			'map_meta_cap'          => null,
    445 			'supports'              => array(),
    446 			'register_meta_box_cb'  => null,
    447 			'taxonomies'            => array(),
    448 			'has_archive'           => false,
    449 			'rewrite'               => true,
    450 			'query_var'             => true,
    451 			'can_export'            => true,
    452 			'delete_with_user'      => null,
    453 			'show_in_rest'          => false,
    454 			'rest_base'             => false,
    455 			'rest_controller_class' => false,
    456 			'template'              => array(),
    457 			'template_lock'         => false,
    458 			'_builtin'              => false,
    459 			'_edit_link'            => 'post.php?post=%d',
    460 		);
    461 
    462 		$args = array_merge( $defaults, $args );
    463 
    464 		$args['name'] = $this->name;
    465 
    466 		// If not set, default to the setting for 'public'.
    467 		if ( null === $args['publicly_queryable'] ) {
    468 			$args['publicly_queryable'] = $args['public'];
    469 		}
    470 
    471 		// If not set, default to the setting for 'public'.
    472 		if ( null === $args['show_ui'] ) {
    473 			$args['show_ui'] = $args['public'];
    474 		}
    475 
    476 		// If not set, default to the setting for 'show_ui'.
    477 		if ( null === $args['show_in_menu'] || ! $args['show_ui'] ) {
    478 			$args['show_in_menu'] = $args['show_ui'];
    479 		}
    480 
    481 		// If not set, default to the setting for 'show_in_menu'.
    482 		if ( null === $args['show_in_admin_bar'] ) {
    483 			$args['show_in_admin_bar'] = (bool) $args['show_in_menu'];
    484 		}
    485 
    486 		// If not set, default to the setting for 'public'.
    487 		if ( null === $args['show_in_nav_menus'] ) {
    488 			$args['show_in_nav_menus'] = $args['public'];
    489 		}
    490 
    491 		// If not set, default to true if not public, false if public.
    492 		if ( null === $args['exclude_from_search'] ) {
    493 			$args['exclude_from_search'] = ! $args['public'];
    494 		}
    495 
    496 		// Back compat with quirky handling in version 3.0. #14122.
    497 		if ( empty( $args['capabilities'] )
    498 			&& null === $args['map_meta_cap'] && in_array( $args['capability_type'], array( 'post', 'page' ), true )
    499 		) {
    500 			$args['map_meta_cap'] = true;
    501 		}
    502 
    503 		// If not set, default to false.
    504 		if ( null === $args['map_meta_cap'] ) {
    505 			$args['map_meta_cap'] = false;
    506 		}
    507 
    508 		// If there's no specified edit link and no UI, remove the edit link.
    509 		if ( ! $args['show_ui'] && ! $has_edit_link ) {
    510 			$args['_edit_link'] = '';
    511 		}
    512 
    513 		$this->cap = get_post_type_capabilities( (object) $args );
    514 		unset( $args['capabilities'] );
    515 
    516 		if ( is_array( $args['capability_type'] ) ) {
    517 			$args['capability_type'] = $args['capability_type'][0];
    518 		}
    519 
    520 		if ( false !== $args['query_var'] ) {
    521 			if ( true === $args['query_var'] ) {
    522 				$args['query_var'] = $this->name;
    523 			} else {
    524 				$args['query_var'] = sanitize_title_with_dashes( $args['query_var'] );
    525 			}
    526 		}
    527 
    528 		if ( false !== $args['rewrite'] && ( is_admin() || get_option( 'permalink_structure' ) ) ) {
    529 			if ( ! is_array( $args['rewrite'] ) ) {
    530 				$args['rewrite'] = array();
    531 			}
    532 			if ( empty( $args['rewrite']['slug'] ) ) {
    533 				$args['rewrite']['slug'] = $this->name;
    534 			}
    535 			if ( ! isset( $args['rewrite']['with_front'] ) ) {
    536 				$args['rewrite']['with_front'] = true;
    537 			}
    538 			if ( ! isset( $args['rewrite']['pages'] ) ) {
    539 				$args['rewrite']['pages'] = true;
    540 			}
    541 			if ( ! isset( $args['rewrite']['feeds'] ) || ! $args['has_archive'] ) {
    542 				$args['rewrite']['feeds'] = (bool) $args['has_archive'];
    543 			}
    544 			if ( ! isset( $args['rewrite']['ep_mask'] ) ) {
    545 				if ( isset( $args['permalink_epmask'] ) ) {
    546 					$args['rewrite']['ep_mask'] = $args['permalink_epmask'];
    547 				} else {
    548 					$args['rewrite']['ep_mask'] = EP_PERMALINK;
    549 				}
    550 			}
    551 		}
    552 
    553 		foreach ( $args as $property_name => $property_value ) {
    554 			$this->$property_name = $property_value;
    555 		}
    556 
    557 		$this->labels = get_post_type_labels( $this );
    558 		$this->label  = $this->labels->name;
    559 	}
    560 
    561 	/**
    562 	 * Sets the features support for the post type.
    563 	 *
    564 	 * @since 4.6.0
    565 	 */
    566 	public function add_supports() {
    567 		if ( ! empty( $this->supports ) ) {
    568 			foreach ( $this->supports as $feature => $args ) {
    569 				if ( is_array( $args ) ) {
    570 					add_post_type_support( $this->name, $feature, $args );
    571 				} else {
    572 					add_post_type_support( $this->name, $args );
    573 				}
    574 			}
    575 			unset( $this->supports );
    576 		} elseif ( false !== $this->supports ) {
    577 			// Add default features.
    578 			add_post_type_support( $this->name, array( 'title', 'editor' ) );
    579 		}
    580 	}
    581 
    582 	/**
    583 	 * Adds the necessary rewrite rules for the post type.
    584 	 *
    585 	 * @since 4.6.0
    586 	 *
    587 	 * @global WP_Rewrite $wp_rewrite WordPress rewrite component.
    588 	 * @global WP         $wp         Current WordPress environment instance.
    589 	 */
    590 	public function add_rewrite_rules() {
    591 		global $wp_rewrite, $wp;
    592 
    593 		if ( false !== $this->query_var && $wp && is_post_type_viewable( $this ) ) {
    594 			$wp->add_query_var( $this->query_var );
    595 		}
    596 
    597 		if ( false !== $this->rewrite && ( is_admin() || get_option( 'permalink_structure' ) ) ) {
    598 			if ( $this->hierarchical ) {
    599 				add_rewrite_tag( "%$this->name%", '(.+?)', $this->query_var ? "{$this->query_var}=" : "post_type=$this->name&pagename=" );
    600 			} else {
    601 				add_rewrite_tag( "%$this->name%", '([^/]+)', $this->query_var ? "{$this->query_var}=" : "post_type=$this->name&name=" );
    602 			}
    603 
    604 			if ( $this->has_archive ) {
    605 				$archive_slug = true === $this->has_archive ? $this->rewrite['slug'] : $this->has_archive;
    606 				if ( $this->rewrite['with_front'] ) {
    607 					$archive_slug = substr( $wp_rewrite->front, 1 ) . $archive_slug;
    608 				} else {
    609 					$archive_slug = $wp_rewrite->root . $archive_slug;
    610 				}
    611 
    612 				add_rewrite_rule( "{$archive_slug}/?$", "index.php?post_type=$this->name", 'top' );
    613 				if ( $this->rewrite['feeds'] && $wp_rewrite->feeds ) {
    614 					$feeds = '(' . trim( implode( '|', $wp_rewrite->feeds ) ) . ')';
    615 					add_rewrite_rule( "{$archive_slug}/feed/$feeds/?$", "index.php?post_type=$this->name" . '&feed=$matches[1]', 'top' );
    616 					add_rewrite_rule( "{$archive_slug}/$feeds/?$", "index.php?post_type=$this->name" . '&feed=$matches[1]', 'top' );
    617 				}
    618 				if ( $this->rewrite['pages'] ) {
    619 					add_rewrite_rule( "{$archive_slug}/{$wp_rewrite->pagination_base}/([0-9]{1,})/?$", "index.php?post_type=$this->name" . '&paged=$matches[1]', 'top' );
    620 				}
    621 			}
    622 
    623 			$permastruct_args         = $this->rewrite;
    624 			$permastruct_args['feed'] = $permastruct_args['feeds'];
    625 			add_permastruct( $this->name, "{$this->rewrite['slug']}/%$this->name%", $permastruct_args );
    626 		}
    627 	}
    628 
    629 	/**
    630 	 * Registers the post type meta box if a custom callback was specified.
    631 	 *
    632 	 * @since 4.6.0
    633 	 */
    634 	public function register_meta_boxes() {
    635 		if ( $this->register_meta_box_cb ) {
    636 			add_action( 'add_meta_boxes_' . $this->name, $this->register_meta_box_cb, 10, 1 );
    637 		}
    638 	}
    639 
    640 	/**
    641 	 * Adds the future post hook action for the post type.
    642 	 *
    643 	 * @since 4.6.0
    644 	 */
    645 	public function add_hooks() {
    646 		add_action( 'future_' . $this->name, '_future_post_hook', 5, 2 );
    647 	}
    648 
    649 	/**
    650 	 * Registers the taxonomies for the post type.
    651 	 *
    652 	 * @since 4.6.0
    653 	 */
    654 	public function register_taxonomies() {
    655 		foreach ( $this->taxonomies as $taxonomy ) {
    656 			register_taxonomy_for_object_type( $taxonomy, $this->name );
    657 		}
    658 	}
    659 
    660 	/**
    661 	 * Removes the features support for the post type.
    662 	 *
    663 	 * @since 4.6.0
    664 	 *
    665 	 * @global array $_wp_post_type_features Post type features.
    666 	 */
    667 	public function remove_supports() {
    668 		global $_wp_post_type_features;
    669 
    670 		unset( $_wp_post_type_features[ $this->name ] );
    671 	}
    672 
    673 	/**
    674 	 * Removes any rewrite rules, permastructs, and rules for the post type.
    675 	 *
    676 	 * @since 4.6.0
    677 	 *
    678 	 * @global WP_Rewrite $wp_rewrite          WordPress rewrite component.
    679 	 * @global WP         $wp                  Current WordPress environment instance.
    680 	 * @global array      $post_type_meta_caps Used to remove meta capabilities.
    681 	 */
    682 	public function remove_rewrite_rules() {
    683 		global $wp, $wp_rewrite, $post_type_meta_caps;
    684 
    685 		// Remove query var.
    686 		if ( false !== $this->query_var ) {
    687 			$wp->remove_query_var( $this->query_var );
    688 		}
    689 
    690 		// Remove any rewrite rules, permastructs, and rules.
    691 		if ( false !== $this->rewrite ) {
    692 			remove_rewrite_tag( "%$this->name%" );
    693 			remove_permastruct( $this->name );
    694 			foreach ( $wp_rewrite->extra_rules_top as $regex => $query ) {
    695 				if ( false !== strpos( $query, "index.php?post_type=$this->name" ) ) {
    696 					unset( $wp_rewrite->extra_rules_top[ $regex ] );
    697 				}
    698 			}
    699 		}
    700 
    701 		// Remove registered custom meta capabilities.
    702 		foreach ( $this->cap as $cap ) {
    703 			unset( $post_type_meta_caps[ $cap ] );
    704 		}
    705 	}
    706 
    707 	/**
    708 	 * Unregisters the post type meta box if a custom callback was specified.
    709 	 *
    710 	 * @since 4.6.0
    711 	 */
    712 	public function unregister_meta_boxes() {
    713 		if ( $this->register_meta_box_cb ) {
    714 			remove_action( 'add_meta_boxes_' . $this->name, $this->register_meta_box_cb, 10 );
    715 		}
    716 	}
    717 
    718 	/**
    719 	 * Removes the post type from all taxonomies.
    720 	 *
    721 	 * @since 4.6.0
    722 	 */
    723 	public function unregister_taxonomies() {
    724 		foreach ( get_object_taxonomies( $this->name ) as $taxonomy ) {
    725 			unregister_taxonomy_for_object_type( $taxonomy, $this->name );
    726 		}
    727 	}
    728 
    729 	/**
    730 	 * Removes the future post hook action for the post type.
    731 	 *
    732 	 * @since 4.6.0
    733 	 */
    734 	public function remove_hooks() {
    735 		remove_action( 'future_' . $this->name, '_future_post_hook', 5 );
    736 	}
    737 
    738 	/**
    739 	 * Gets the REST API controller for this post type.
    740 	 *
    741 	 * Will only instantiate the controller class once per request.
    742 	 *
    743 	 * @since 5.3.0
    744 	 *
    745 	 * @return WP_REST_Controller|null The controller instance, or null if the post type
    746 	 *                                 is set not to show in rest.
    747 	 */
    748 	public function get_rest_controller() {
    749 		if ( ! $this->show_in_rest ) {
    750 			return null;
    751 		}
    752 
    753 		$class = $this->rest_controller_class ? $this->rest_controller_class : WP_REST_Posts_Controller::class;
    754 
    755 		if ( ! class_exists( $class ) ) {
    756 			return null;
    757 		}
    758 
    759 		if ( ! is_subclass_of( $class, WP_REST_Controller::class ) ) {
    760 			return null;
    761 		}
    762 
    763 		if ( ! $this->rest_controller ) {
    764 			$this->rest_controller = new $class( $this->name );
    765 		}
    766 
    767 		if ( ! ( $this->rest_controller instanceof $class ) ) {
    768 			return null;
    769 		}
    770 
    771 		return $this->rest_controller;
    772 	}
    773 }