Нет описания

class-wp-post-type.php 25KB

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