wp/wp-includes/class-wp-post-type.php
changeset 21 48c4eec2b7e6
parent 19 3d72ae0968f4
child 22 8c2e4d02f4ef
--- a/wp/wp-includes/class-wp-post-type.php	Thu Sep 29 08:06:27 2022 +0200
+++ b/wp/wp-includes/class-wp-post-type.php	Fri Sep 05 18:40:08 2025 +0200
@@ -14,6 +14,7 @@
  *
  * @see register_post_type()
  */
+#[AllowDynamicProperties]
 final class WP_Post_Type {
 	/**
 	 * Post type key.
@@ -221,7 +222,7 @@
 	 * Default empty array.
 	 *
 	 * @since 4.6.0
-	 * @var array $taxonomies
+	 * @var string[] $taxonomies
 	 */
 	public $taxonomies = array();
 
@@ -281,7 +282,7 @@
 	 * @link https://developer.wordpress.org/block-editor/developers/block-api/block-templates/
 	 *
 	 * @since 5.0.0
-	 * @var array $template
+	 * @var array[] $template
 	 */
 	public $template = array();
 
@@ -396,6 +397,54 @@
 	public $rest_controller;
 
 	/**
+	 * The controller for this post type's revisions REST API endpoints.
+	 *
+	 * Custom controllers must extend WP_REST_Controller.
+	 *
+	 * @since 6.4.0
+	 * @var string|bool $revisions_rest_controller_class
+	 */
+	public $revisions_rest_controller_class;
+
+	/**
+	 * The controller instance for this post type's revisions REST API endpoints.
+	 *
+	 * Lazily computed. Should be accessed using {@see WP_Post_Type::get_revisions_rest_controller()}.
+	 *
+	 * @since 6.4.0
+	 * @var WP_REST_Controller $revisions_rest_controller
+	 */
+	public $revisions_rest_controller;
+
+	/**
+	 * The controller for this post type's autosave REST API endpoints.
+	 *
+	 * Custom controllers must extend WP_REST_Controller.
+	 *
+	 * @since 6.4.0
+	 * @var string|bool $autosave_rest_controller_class
+	 */
+	public $autosave_rest_controller_class;
+
+	/**
+	 * The controller instance for this post type's autosave REST API endpoints.
+	 *
+	 * Lazily computed. Should be accessed using {@see WP_Post_Type::get_autosave_rest_controller()}.
+	 *
+	 * @since 6.4.0
+	 * @var WP_REST_Controller $autosave_rest_controller
+	 */
+	public $autosave_rest_controller;
+
+	/**
+	 * A flag to register the post type REST API controller after its associated autosave / revisions controllers, instead of before. Registration order affects route matching priority.
+	 *
+	 * @since 6.4.0
+	 * @var bool $late_route_registration
+	 */
+	public $late_route_registration;
+
+	/**
 	 * Constructor.
 	 *
 	 * See the register_post_type() function for accepted arguments for `$args`.
@@ -409,6 +458,7 @@
 	 *
 	 * @param string       $post_type Post type key.
 	 * @param array|string $args      Optional. Array or string of arguments for registering a post type.
+	 *                                See register_post_type() for information on accepted arguments.
 	 *                                Default empty array.
 	 */
 	public function __construct( $post_type, $args = array() ) {
@@ -453,6 +503,7 @@
 		 *  - `register_page_post_type_args`
 		 *
 		 * @since 6.0.0
+		 * @since 6.4.0 Added `late_route_registration`, `autosave_rest_controller_class` and `revisions_rest_controller_class` arguments.
 		 *
 		 * @param array  $args      Array of arguments for registering a post type.
 		 *                          See the register_post_type() function for accepted arguments.
@@ -464,37 +515,40 @@
 
 		// Args prefixed with an underscore are reserved for internal use.
 		$defaults = array(
-			'labels'                => array(),
-			'description'           => '',
-			'public'                => false,
-			'hierarchical'          => false,
-			'exclude_from_search'   => null,
-			'publicly_queryable'    => null,
-			'show_ui'               => null,
-			'show_in_menu'          => null,
-			'show_in_nav_menus'     => null,
-			'show_in_admin_bar'     => null,
-			'menu_position'         => null,
-			'menu_icon'             => null,
-			'capability_type'       => 'post',
-			'capabilities'          => array(),
-			'map_meta_cap'          => null,
-			'supports'              => array(),
-			'register_meta_box_cb'  => null,
-			'taxonomies'            => array(),
-			'has_archive'           => false,
-			'rewrite'               => true,
-			'query_var'             => true,
-			'can_export'            => true,
-			'delete_with_user'      => null,
-			'show_in_rest'          => false,
-			'rest_base'             => false,
-			'rest_namespace'        => false,
-			'rest_controller_class' => false,
-			'template'              => array(),
-			'template_lock'         => false,
-			'_builtin'              => false,
-			'_edit_link'            => 'post.php?post=%d',
+			'labels'                          => array(),
+			'description'                     => '',
+			'public'                          => false,
+			'hierarchical'                    => false,
+			'exclude_from_search'             => null,
+			'publicly_queryable'              => null,
+			'show_ui'                         => null,
+			'show_in_menu'                    => null,
+			'show_in_nav_menus'               => null,
+			'show_in_admin_bar'               => null,
+			'menu_position'                   => null,
+			'menu_icon'                       => null,
+			'capability_type'                 => 'post',
+			'capabilities'                    => array(),
+			'map_meta_cap'                    => null,
+			'supports'                        => array(),
+			'register_meta_box_cb'            => null,
+			'taxonomies'                      => array(),
+			'has_archive'                     => false,
+			'rewrite'                         => true,
+			'query_var'                       => true,
+			'can_export'                      => true,
+			'delete_with_user'                => null,
+			'show_in_rest'                    => false,
+			'rest_base'                       => false,
+			'rest_namespace'                  => false,
+			'rest_controller_class'           => false,
+			'autosave_rest_controller_class'  => false,
+			'revisions_rest_controller_class' => false,
+			'late_route_registration'         => false,
+			'template'                        => array(),
+			'template_lock'                   => false,
+			'_builtin'                        => false,
+			'_edit_link'                      => 'post.php?post=%d',
 		);
 
 		$args = array_merge( $defaults, $args );
@@ -616,9 +670,20 @@
 				}
 			}
 			unset( $this->supports );
+
+			/*
+			 * 'editor' support implies 'autosave' support for backward compatibility.
+			 * 'autosave' support needs to be explicitly removed if not desired.
+			 */
+			if (
+				post_type_supports( $this->name, 'editor' ) &&
+				! post_type_supports( $this->name, 'autosave' )
+			) {
+				add_post_type_support( $this->name, 'autosave' );
+			}
 		} elseif ( false !== $this->supports ) {
 			// Add default features.
-			add_post_type_support( $this->name, array( 'title', 'editor' ) );
+			add_post_type_support( $this->name, array( 'title', 'editor', 'autosave' ) );
 		}
 	}
 
@@ -735,7 +800,7 @@
 			remove_rewrite_tag( "%$this->name%" );
 			remove_permastruct( $this->name );
 			foreach ( $wp_rewrite->extra_rules_top as $regex => $query ) {
-				if ( false !== strpos( $query, "index.php?post_type=$this->name" ) ) {
+				if ( str_contains( $query, "index.php?post_type=$this->name" ) ) {
 					unset( $wp_rewrite->extra_rules_top[ $regex ] );
 				}
 			}
@@ -815,6 +880,85 @@
 	}
 
 	/**
+	 * Gets the REST API revisions controller for this post type.
+	 *
+	 * Will only instantiate the controller class once per request.
+	 *
+	 * @since 6.4.0
+	 *
+	 * @return WP_REST_Controller|null The controller instance, or null if the post type
+	 *                                 is set not to show in rest.
+	 */
+	public function get_revisions_rest_controller() {
+		if ( ! $this->show_in_rest ) {
+			return null;
+		}
+
+		if ( ! post_type_supports( $this->name, 'revisions' ) ) {
+			return null;
+		}
+
+		$class = $this->revisions_rest_controller_class ? $this->revisions_rest_controller_class : WP_REST_Revisions_Controller::class;
+		if ( ! class_exists( $class ) ) {
+			return null;
+		}
+
+		if ( ! is_subclass_of( $class, WP_REST_Controller::class ) ) {
+			return null;
+		}
+
+		if ( ! $this->revisions_rest_controller ) {
+			$this->revisions_rest_controller = new $class( $this->name );
+		}
+
+		if ( ! ( $this->revisions_rest_controller instanceof $class ) ) {
+			return null;
+		}
+
+		return $this->revisions_rest_controller;
+	}
+
+	/**
+	 * Gets the REST API autosave controller for this post type.
+	 *
+	 * Will only instantiate the controller class once per request.
+	 *
+	 * @since 6.4.0
+	 *
+	 * @return WP_REST_Controller|null The controller instance, or null if the post type
+	 *                                 is set not to show in rest.
+	 */
+	public function get_autosave_rest_controller() {
+		if ( ! $this->show_in_rest ) {
+			return null;
+		}
+
+		if ( ! post_type_supports( $this->name, 'autosave' ) ) {
+			return null;
+		}
+
+		$class = $this->autosave_rest_controller_class ? $this->autosave_rest_controller_class : WP_REST_Autosaves_Controller::class;
+
+		if ( ! class_exists( $class ) ) {
+			return null;
+		}
+
+		if ( ! is_subclass_of( $class, WP_REST_Controller::class ) ) {
+			return null;
+		}
+
+		if ( ! $this->autosave_rest_controller ) {
+			$this->autosave_rest_controller = new $class( $this->name );
+		}
+
+		if ( ! ( $this->autosave_rest_controller instanceof $class ) ) {
+			return null;
+		}
+
+		return $this->autosave_rest_controller;
+	}
+
+	/**
 	 * Returns the default labels for post types.
 	 *
 	 * @since 6.0.0
@@ -829,7 +973,7 @@
 		self::$default_labels = array(
 			'name'                     => array( _x( 'Posts', 'post type general name' ), _x( 'Pages', 'post type general name' ) ),
 			'singular_name'            => array( _x( 'Post', 'post type singular name' ), _x( 'Page', 'post type singular name' ) ),
-			'add_new'                  => array( _x( 'Add New', 'post' ), _x( 'Add New', 'page' ) ),
+			'add_new'                  => array( __( 'Add New Post' ), __( 'Add New Page' ) ),
 			'add_new_item'             => array( __( 'Add New Post' ), __( 'Add New Page' ) ),
 			'edit_item'                => array( __( 'Edit Post' ), __( 'Edit Page' ) ),
 			'new_item'                 => array( __( 'New Post' ), __( 'New Page' ) ),
@@ -855,6 +999,7 @@
 			'item_published'           => array( __( 'Post published.' ), __( 'Page published.' ) ),
 			'item_published_privately' => array( __( 'Post published privately.' ), __( 'Page published privately.' ) ),
 			'item_reverted_to_draft'   => array( __( 'Post reverted to draft.' ), __( 'Page reverted to draft.' ) ),
+			'item_trashed'             => array( __( 'Post trashed.' ), __( 'Page trashed.' ) ),
 			'item_scheduled'           => array( __( 'Post scheduled.' ), __( 'Page scheduled.' ) ),
 			'item_updated'             => array( __( 'Post updated.' ), __( 'Page updated.' ) ),
 			'item_link'                => array(