diff --git a/gutenberg.php b/gutenberg.php index ca61f52f1afe47..5adc8d03a33323 100644 --- a/gutenberg.php +++ b/gutenberg.php @@ -3,7 +3,7 @@ * Plugin Name: Gutenberg * Plugin URI: https://github.com/WordPress/gutenberg * Description: Printing since 1440. This is the development plugin for the block editor, site editor, and other future WordPress core functionality. - * Requires at least: 6.2 + * Requires at least: 6.3 * Requires PHP: 7.0 * Version: 17.1.2 * Author: Gutenberg Team diff --git a/lib/compat/wordpress-6.3/block-editor-settings.php b/lib/compat/wordpress-6.3/block-editor-settings.php deleted file mode 100644 index b478d022c16dd9..00000000000000 --- a/lib/compat/wordpress-6.3/block-editor-settings.php +++ /dev/null @@ -1,89 +0,0 @@ -slug ) { - $page_slug = 'page'; - } - if ( 'single' === $template_type->slug ) { - $post_slug = 'single'; - } - } - - $what_post_type = get_post_type( $post_ID ); - switch ( $what_post_type ) { - case 'page': - $template_slug = $page_slug; - break; - default: - $template_slug = $post_slug; - break; - } - } - - $current_template = get_block_templates( array( 'slug__in' => array( $template_slug ) ) ); - - if ( ! empty( $current_template ) ) { - $template_blocks = parse_blocks( $current_template[0]->content ); - $post_content_block = gutenberg_find_first_block( 'core/post-content', $template_blocks ); - - if ( isset( $post_content_block['attrs'] ) ) { - $settings['postContentAttributes'] = $post_content_block['attrs']; - } - } - - return $settings; -} - -add_filter( 'block_editor_settings_all', 'gutenberg_get_block_editor_settings_experimental', PHP_INT_MAX ); diff --git a/lib/compat/wordpress-6.3/block-patterns.php b/lib/compat/wordpress-6.3/block-patterns.php deleted file mode 100644 index bf7ef632846c2d..00000000000000 --- a/lib/compat/wordpress-6.3/block-patterns.php +++ /dev/null @@ -1,165 +0,0 @@ -is_block_editor ) { - return; - } - } - - $supports_core_patterns = get_theme_support( 'core-block-patterns' ); - - /** - * Filter to disable remote block patterns. - * - * @since 5.8.0 - * - * @param bool $should_load_remote - */ - $should_load_remote = apply_filters( 'should_load_remote_block_patterns', true ); - - if ( $supports_core_patterns && $should_load_remote ) { - $request = new WP_REST_Request( 'GET', '/wp/v2/pattern-directory/patterns' ); - $core_keyword_id = 11; // 11 is the ID for "core". - $request->set_param( 'keyword', $core_keyword_id ); - $response = rest_do_request( $request ); - if ( $response->is_error() ) { - return; - } - $patterns = $response->get_data(); - - foreach ( $patterns as $pattern ) { - $pattern['source'] = 'pattern-directory/core'; // Added in 6.3.0. - $normalized_pattern = wp_normalize_remote_block_pattern( $pattern ); - $pattern_name = 'core/' . sanitize_title( $normalized_pattern['title'] ); - register_block_pattern( $pattern_name, (array) $normalized_pattern ); - } - } -} - -/** - * Register `Featured` (category) patterns from wordpress.org/patterns. - * - * @since 5.9.0 - * @since 6.2.0 Normalize the pattern from the API (snake_case) to the format expected by `register_block_pattern` (camelCase). - * @since 6.3.0 Add 'pattern-directory/featured' to the pattern's 'source'. - */ -function gutenberg_load_remote_featured_patterns() { - $supports_core_patterns = get_theme_support( 'core-block-patterns' ); - - /** This filter is documented in wp-includes/block-patterns.php */ - $should_load_remote = apply_filters( 'should_load_remote_block_patterns', true ); - - if ( ! $should_load_remote || ! $supports_core_patterns ) { - return; - } - - $request = new WP_REST_Request( 'GET', '/wp/v2/pattern-directory/patterns' ); - $featured_cat_id = 26; // This is the `Featured` category id from pattern directory. - $request->set_param( 'category', $featured_cat_id ); - $response = rest_do_request( $request ); - if ( $response->is_error() ) { - return; - } - $patterns = $response->get_data(); - $registry = WP_Block_Patterns_Registry::get_instance(); - foreach ( $patterns as $pattern ) { - $pattern['source'] = 'pattern-directory/featured'; // Added in 6.3.0. - $normalized_pattern = wp_normalize_remote_block_pattern( $pattern ); - $pattern_name = sanitize_title( $normalized_pattern['title'] ); - // Some patterns might be already registered as core patterns with the `core` prefix. - $is_registered = $registry->is_registered( $pattern_name ) || $registry->is_registered( "core/$pattern_name" ); - if ( ! $is_registered ) { - register_block_pattern( $pattern_name, (array) $normalized_pattern ); - } - } -} - -/** - * Registers patterns from Pattern Directory provided by a theme's - * `theme.json` file. - * - * @since 6.0.0 - * @since 6.2.0 Normalize the pattern from the API (snake_case) to the format expected by `register_block_pattern` (camelCase). - * @since 6.3.0 Add 'pattern-directory/theme' to the pattern's 'source'. - * @access private - */ -function gutenberg_register_remote_theme_patterns() { - /** This filter is documented in wp-includes/block-patterns.php */ - if ( ! apply_filters( 'should_load_remote_block_patterns', true ) ) { - return; - } - - if ( ! wp_theme_has_theme_json() ) { - return; - } - - $pattern_settings = gutenberg_get_theme_directory_pattern_slugs(); - if ( empty( $pattern_settings ) ) { - return; - } - - $request = new WP_REST_Request( 'GET', '/wp/v2/pattern-directory/patterns' ); - $request['slug'] = $pattern_settings; - $response = rest_do_request( $request ); - if ( $response->is_error() ) { - return; - } - $patterns = $response->get_data(); - $patterns_registry = WP_Block_Patterns_Registry::get_instance(); - foreach ( $patterns as $pattern ) { - $pattern['source'] = 'pattern-directory/theme'; // Added in 6.3.0. - $normalized_pattern = wp_normalize_remote_block_pattern( $pattern ); - $pattern_name = sanitize_title( $normalized_pattern['title'] ); - // Some patterns might be already registered as core patterns with the `core` prefix. - $is_registered = $patterns_registry->is_registered( $pattern_name ) || $patterns_registry->is_registered( "core/$pattern_name" ); - if ( ! $is_registered ) { - register_block_pattern( $pattern_name, (array) $normalized_pattern ); - } - } -} diff --git a/lib/compat/wordpress-6.3/block-template-utils.php b/lib/compat/wordpress-6.3/block-template-utils.php deleted file mode 100644 index d5f69593e473f5..00000000000000 --- a/lib/compat/wordpress-6.3/block-template-utils.php +++ /dev/null @@ -1,150 +0,0 @@ - _x( 'Index', 'Template name', 'gutenberg' ), - 'description' => __( - 'Used as a fallback template for all pages when a more specific template is not defined.', - 'gutenberg' - ), - ); - } - if ( isset( $default_template_types['home'] ) ) { - $default_template_types['home'] = array( - 'title' => _x( 'Blog Home', 'Template name', 'gutenberg' ), - 'description' => __( - 'Displays the latest posts as either the site homepage or as the "Posts page" as defined under reading settings. If it exists, the Front Page template overrides this template when posts are shown on the homepage.', - 'gutenberg' - ), - ); - } - if ( isset( $default_template_types['front-page'] ) ) { - $default_template_types['front-page'] = array( - 'title' => _x( 'Front Page', 'Template name', 'gutenberg' ), - 'description' => __( - "Displays your site's homepage, whether it is set to display latest posts or a static page. The Front Page template takes precedence over all templates.", - 'gutenberg' - ), - ); - } - if ( isset( $default_template_types['singular'] ) ) { - $default_template_types['singular'] = array( - 'title' => _x( 'Single Entries', 'Template name', 'gutenberg' ), - 'description' => __( - 'Displays any single entry, such as a post or a page. This template will serve as a fallback when a more specific template (e.g. Single Post, Page, or Attachment) cannot be found.', - 'gutenberg' - ), - ); - } - if ( isset( $default_template_types['single'] ) ) { - $default_template_types['single'] = array( - 'title' => _x( 'Single Posts', 'Template name', 'gutenberg' ), - 'description' => __( 'Displays single posts on your website unless a custom template has been applied to that post or a dedicated template exists.', 'gutenberg' ), - ); - } - if ( isset( $default_template_types['page'] ) ) { - $default_template_types['page'] = array( - 'title' => _x( 'Pages', 'Template name', 'gutenberg' ), - 'description' => __( 'Display all static pages unless a custom template has been applied or a dedicated template exists.', 'gutenberg' ), - ); - } - if ( isset( $default_template_types['archive'] ) ) { - $default_template_types['archive'] = array( - 'title' => _x( 'All Archives', 'Template name', 'gutenberg' ), - 'description' => __( - 'Displays any archive, including posts by a single author, category, tag, taxonomy, custom post type, and date. This template will serve as a fallback when more specific templates (e.g. Category or Tag) cannot be found.', - 'gutenberg' - ), - ); - } - if ( isset( $default_template_types['author'] ) ) { - $default_template_types['author'] = array( - 'title' => _x( 'Author Archives', 'Template name', 'gutenberg' ), - 'description' => __( - "Displays a single author's post archive. This template will serve as a fallback when a more a specific template (e.g. Author: Admin) cannot be found.", - 'gutenberg' - ), - ); - } - if ( isset( $default_template_types['category'] ) ) { - $default_template_types['category'] = array( - 'title' => _x( 'Category Archives', 'Template name', 'gutenberg' ), - 'description' => __( - 'Displays a post category archive. This template will serve as a fallback when more specific template (e.g. Category: Recipes) cannot be found.', - 'gutenberg' - ), - ); - } - if ( isset( $default_template_types['taxonomy'] ) ) { - $default_template_types['taxonomy'] = array( - 'title' => _x( 'Taxonomy', 'Template name', 'gutenberg' ), - 'description' => __( - 'Displays a custom taxonomy archive. Like categories and tags, taxonomies have terms which you use to classify things. For example: a taxonomy named "Art" can have multiple terms, such as "Modern" and "18th Century." This template will serve as a fallback when a more specific template (e.g. Taxonomy: Art) cannot be found.', - 'gutenberg' - ), - ); - } - if ( isset( $default_template_types['date'] ) ) { - $default_template_types['date'] = array( - 'title' => _x( 'Date Archives', 'Template name', 'gutenberg' ), - 'description' => __( 'Displays a post archive when a specific date is visited (e.g. example.com/2023/).', 'gutenberg' ), - ); - } - if ( isset( $default_template_types['tag'] ) ) { - $default_template_types['tag'] = array( - 'title' => _x( 'Tag Archives', 'Template name', 'gutenberg' ), - 'description' => __( - 'Displays a post tag archive. This template will serve as a fallback when more specific template (e.g. Tag: Pizza) cannot be found.', - 'gutenberg' - ), - ); - } - if ( isset( $default_template_types['attachment'] ) ) { - $default_template_types['attachment'] = array( - 'title' => _x( 'Attachment Pages', 'Template name', 'gutenberg' ), - 'description' => __( 'Displays when a visitor views the dedicated page that exists for any media attachment.', 'gutenberg' ), - ); - } - if ( isset( $default_template_types['search'] ) ) { - $default_template_types['search'] = array( - 'title' => _x( 'Search Results', 'Template name', 'gutenberg' ), - 'description' => __( 'Displays when a visitor performs a search on your website.', 'gutenberg' ), - ); - } - if ( isset( $default_template_types['privacy-policy'] ) ) { - $default_template_types['privacy-policy'] = array( - 'title' => _x( 'Privacy Policy', 'Template name', 'gutenberg' ), - 'description' => __( - "Displays your site's Privacy Policy page.", - 'gutenberg' - ), - ); - } - if ( isset( $default_template_types['404'] ) ) { - $default_template_types['404'] = array( - 'title' => _x( 'Page: 404', 'Template name', 'gutenberg' ), - 'description' => __( 'Displays when a visitor views a non-existent page, such as a dead link or a mistyped URL.', 'gutenberg' ), - ); - } - - return $default_template_types; -} -add_filter( 'default_template_types', 'gutenberg_get_default_block_template_types', 10 ); diff --git a/lib/compat/wordpress-6.3/blocks.php b/lib/compat/wordpress-6.3/blocks.php deleted file mode 100644 index 001416b42566f7..00000000000000 --- a/lib/compat/wordpress-6.3/blocks.php +++ /dev/null @@ -1,122 +0,0 @@ -= 6.3. - * - * @see https://github.com/WordPress/gutenberg/pull/46496 - * - * @param array $settings Current block type settings. - * @param array $metadata Block metadata as read in via block.json. - * - * @return array Filtered block type settings. - */ -function gutenberg_add_selectors_property_to_block_type_settings( $settings, $metadata ) { - if ( ! isset( $settings['selectors'] ) && isset( $metadata['selectors'] ) ) { - $settings['selectors'] = $metadata['selectors']; - } - - return $settings; -} -add_filter( 'block_type_metadata_settings', 'gutenberg_add_selectors_property_to_block_type_settings', 10, 2 ); - -/** - * Renames Reusable block CPT to Pattern. - * - * Note: This should be removed when the minimum required WP version is >= 6.3. - * - * @see https://github.com/WordPress/gutenberg/pull/51144 - * - * @param array $args Register post type args. - * @param string $post_type The post type string. - * - * @return array Register post type args. - */ -function gutenberg_rename_reusable_block_cpt_to_pattern( $args, $post_type ) { - if ( 'wp_block' === $post_type ) { - $args['labels']['name'] = _x( 'Patterns', 'post type general name' ); - $args['labels']['singular_name'] = _x( 'Pattern', 'post type singular name' ); - $args['labels']['add_new_item'] = __( 'Add new Pattern' ); - $args['labels']['new_item'] = __( 'New Pattern' ); - $args['labels']['edit_item'] = __( 'Edit Block Pattern' ); - $args['labels']['view_item'] = __( 'View Pattern' ); - $args['labels']['view_items'] = __( 'View Patterns' ); - $args['labels']['all_items'] = __( 'All Patterns' ); - $args['labels']['search_items'] = __( 'Search Patterns' ); - $args['labels']['not_found'] = __( 'No Patterns found.' ); - $args['labels']['not_found_in_trash'] = __( 'No Patterns found in Trash.' ); - $args['labels']['filter_items_list'] = __( 'Filter Patterns list' ); - $args['labels']['items_list_navigation'] = __( 'Patterns list navigation' ); - $args['labels']['items_list'] = __( 'Patterns list' ); - $args['labels']['item_published'] = __( 'Pattern published.' ); - $args['labels']['item_published_privately'] = __( 'Pattern published privately.' ); - $args['labels']['item_reverted_to_draft'] = __( 'Pattern reverted to draft.' ); - $args['labels']['item_scheduled'] = __( 'Pattern scheduled.' ); - $args['labels']['item_updated'] = __( 'Pattern updated.' ); - $args['rest_controller_class'] = 'Gutenberg_REST_Blocks_Controller'; - } - - return $args; -} - -add_filter( 'register_post_type_args', 'gutenberg_rename_reusable_block_cpt_to_pattern', 10, 2 ); - -/** - * Adds custom fields support to the wp_block post type so an unsynced option can be added. - * - * Note: This should be removed when the minimum required WP version is >= 6.3. - * - * @see https://github.com/WordPress/gutenberg/pull/51144 - * - * @param array $args Register post type args. - * @param string $post_type The post type string. - * - * @return array Register post type args. - */ -function gutenberg_add_custom_fields_to_wp_block( $args, $post_type ) { - if ( 'wp_block' === $post_type ) { - array_push( $args['supports'], 'custom-fields' ); - } - - return $args; -} -add_filter( 'register_post_type_args', 'gutenberg_add_custom_fields_to_wp_block', 10, 2 ); - -/** - * Adds wp_pattern_sync_status meta fields to the wp_block post type so an unsynced option can be added. - * - * Note: This should be removed when the minimum required WP version is >= 6.3. - * - * @see https://github.com/WordPress/gutenberg/pull/51144 - * - * @return void - */ -function gutenberg_wp_block_register_post_meta() { - $post_type = 'wp_block'; - register_post_meta( - $post_type, - 'wp_pattern_sync_status', - array( - 'auth_callback' => function () { - return current_user_can( 'edit_posts' ); - }, - 'sanitize_callback' => 'sanitize_text_field', - 'single' => true, - 'type' => 'string', - 'show_in_rest' => array( - 'schema' => array( - 'type' => 'string', - 'enum' => array( 'partial', 'unsynced' ), - ), - ), - ) - ); -} -add_action( 'init', 'gutenberg_wp_block_register_post_meta' ); diff --git a/lib/compat/wordpress-6.3/class-gutenberg-classic-to-block-menu-converter.php b/lib/compat/wordpress-6.3/class-gutenberg-classic-to-block-menu-converter.php deleted file mode 100644 index 8677f9abaee170..00000000000000 --- a/lib/compat/wordpress-6.3/class-gutenberg-classic-to-block-menu-converter.php +++ /dev/null @@ -1,123 +0,0 @@ -term_id, array( 'update_post_term_cache' => false ) ); - - if ( empty( $menu_items ) ) { - return array(); - } - - // Set up the $menu_item variables. - // Adds the class property classes for the current context, if applicable. - _wp_menu_item_classes_by_context( $menu_items ); - - $menu_items_by_parent_id = static::group_by_parent_id( $menu_items ); - - $first_menu_item = isset( $menu_items_by_parent_id[0] ) - ? $menu_items_by_parent_id[0] - : array(); - - $inner_blocks = static::to_blocks( - $first_menu_item, - $menu_items_by_parent_id - ); - - return serialize_blocks( $inner_blocks ); - } - - /** - * Returns an array of menu items grouped by the id of the parent menu item. - * - * @param array $menu_items An array of menu items. - * @return array - */ - private static function group_by_parent_id( $menu_items ) { - $menu_items_by_parent_id = array(); - - foreach ( $menu_items as $menu_item ) { - $menu_items_by_parent_id[ $menu_item->menu_item_parent ][] = $menu_item; - } - - return $menu_items_by_parent_id; - } - - /** - * Turns menu item data into a nested array of parsed blocks - * - * @param array $menu_items An array of menu items that represent - * an individual level of a menu. - * @param array $menu_items_by_parent_id An array keyed by the id of the - * parent menu where each element is an - * array of menu items that belong to - * that parent. - * @return array An array of parsed block data. - */ - private static function to_blocks( $menu_items, $menu_items_by_parent_id ) { - - if ( empty( $menu_items ) ) { - return array(); - } - - $blocks = array(); - - foreach ( $menu_items as $menu_item ) { - $class_name = ! empty( $menu_item->classes ) ? implode( ' ', (array) $menu_item->classes ) : null; - $id = ( null !== $menu_item->object_id && 'custom' !== $menu_item->object ) ? $menu_item->object_id : null; - $opens_in_new_tab = null !== $menu_item->target && '_blank' === $menu_item->target; - $rel = ( null !== $menu_item->xfn && '' !== $menu_item->xfn ) ? $menu_item->xfn : null; - $kind = null !== $menu_item->type ? str_replace( '_', '-', $menu_item->type ) : 'custom'; - - $block = array( - 'blockName' => isset( $menu_items_by_parent_id[ $menu_item->ID ] ) ? 'core/navigation-submenu' : 'core/navigation-link', - 'attrs' => array( - 'className' => $class_name, - 'description' => $menu_item->description, - 'id' => $id, - 'kind' => $kind, - 'label' => $menu_item->title, - 'opensInNewTab' => $opens_in_new_tab, - 'rel' => $rel, - 'title' => $menu_item->attr_title, - 'type' => $menu_item->object, - 'url' => $menu_item->url, - ), - ); - - $block['innerBlocks'] = isset( $menu_items_by_parent_id[ $menu_item->ID ] ) - ? static::to_blocks( $menu_items_by_parent_id[ $menu_item->ID ], $menu_items_by_parent_id ) - : array(); - $block['innerContent'] = array_map( 'serialize_block', $block['innerBlocks'] ); - - $blocks[] = $block; - } - - return $blocks; - } -} diff --git a/lib/compat/wordpress-6.3/class-gutenberg-navigation-fallback.php b/lib/compat/wordpress-6.3/class-gutenberg-navigation-fallback.php deleted file mode 100644 index fcd70da61f57ed..00000000000000 --- a/lib/compat/wordpress-6.3/class-gutenberg-navigation-fallback.php +++ /dev/null @@ -1,237 +0,0 @@ - 'wp_navigation', - 'no_found_rows' => true, - 'update_post_meta_cache' => false, - 'update_post_term_cache' => false, - 'order' => 'DESC', - 'orderby' => 'date', - 'post_status' => 'publish', - 'posts_per_page' => 1, - ); - - $navigation_post = new WP_Query( $parsed_args ); - - if ( count( $navigation_post->posts ) > 0 ) { - return $navigation_post->posts[0]; - } - - return null; - } - - /** - * Creates a Navigation Menu post from a Classic Menu. - * - * @return int|WP_Error The post ID of the default fallback menu or a WP_Error object. - */ - private static function create_classic_menu_fallback() { - // See if we have a classic menu. - $classic_nav_menu = static::get_fallback_classic_menu(); - - if ( ! $classic_nav_menu ) { - return new WP_Error( 'no_classic_menus', __( 'No Classic Menus found.', 'gutenberg' ) ); - } - - // If there is a classic menu then convert it to blocks. - $classic_nav_menu_blocks = Gutenberg_Classic_To_Block_Menu_Converter::convert( $classic_nav_menu ); - - if ( empty( $classic_nav_menu_blocks ) ) { - return new WP_Error( 'cannot_convert_classic_menu', __( 'Unable to convert Classic Menu to blocks.', 'gutenberg' ) ); - } - - // Create a new navigation menu from the classic menu. - $classic_menu_fallback = wp_insert_post( - array( - 'post_content' => $classic_nav_menu_blocks, - 'post_title' => $classic_nav_menu->name, - 'post_name' => $classic_nav_menu->slug, - 'post_status' => 'publish', - 'post_type' => 'wp_navigation', - ), - true // So that we can check whether the result is an error. - ); - - return $classic_menu_fallback; - } - - /** - * Determine the most appropriate classic navigation menu to use as a fallback. - * - * @return WP_Term|null The most appropriate classic navigation menu to use as a fallback. - */ - private static function get_fallback_classic_menu() { - $classic_nav_menus = wp_get_nav_menus(); - - if ( ! $classic_nav_menus || is_wp_error( $classic_nav_menus ) ) { - return null; - } - - $nav_menu = static::get_nav_menu_at_primary_location(); - - if ( $nav_menu ) { - return $nav_menu; - } - - $nav_menu = static::get_nav_menu_with_primary_slug( $classic_nav_menus ); - - if ( $nav_menu ) { - return $nav_menu; - } - - return static::get_most_recently_created_nav_menu( $classic_nav_menus ); - } - - - /** - * Sorts the classic menus and returns the most recently created one. - * - * @param WP_Term[] $classic_nav_menus Array of classic nav menu term objects. - * @return WP_Term The most recently created classic nav menu. - */ - private static function get_most_recently_created_nav_menu( $classic_nav_menus ) { - usort( - $classic_nav_menus, - static function ( $a, $b ) { - return $b->term_id - $a->term_id; - } - ); - - return $classic_nav_menus[0]; - } - - /** - * Returns the classic menu with the slug `primary` if it exists. - * - * @param WP_Term[] $classic_nav_menus Array of classic nav menu term objects. - * @return WP_Term|null The classic nav menu with the slug `primary` or null. - */ - private static function get_nav_menu_with_primary_slug( $classic_nav_menus ) { - foreach ( $classic_nav_menus as $classic_nav_menu ) { - if ( 'primary' === $classic_nav_menu->slug ) { - return $classic_nav_menu; - } - } - - return null; - } - - - /** - * Gets the classic menu assigned to the `primary` navigation menu location - * if it exists. - * - * @return WP_Term|null The classic nav menu assigned to the `primary` location or null. - */ - private static function get_nav_menu_at_primary_location() { - $locations = get_nav_menu_locations(); - - if ( isset( $locations['primary'] ) ) { - $primary_menu = wp_get_nav_menu_object( $locations['primary'] ); - - if ( $primary_menu ) { - return $primary_menu; - } - } - - return null; - } - - /** - * Creates a default Navigation Block Menu fallback. - * - * @return int|WP_Error The post ID of the default fallback menu or a WP_Error object. - */ - private static function create_default_fallback() { - - $default_blocks = static::get_default_fallback_blocks(); - - // Create a new navigation menu from the fallback blocks. - $default_fallback = wp_insert_post( - array( - 'post_content' => $default_blocks, - 'post_title' => _x( 'Navigation', 'Title of a Navigation menu', 'gutenberg' ), - 'post_name' => 'navigation', - 'post_status' => 'publish', - 'post_type' => 'wp_navigation', - ), - true // So that we can check whether the result is an error. - ); - - return $default_fallback; - } - - /** - * Gets the rendered markup for the default fallback blocks. - * - * @return string default blocks markup to use a the fallback. - */ - private static function get_default_fallback_blocks() { - $registry = WP_Block_Type_Registry::get_instance(); - - // If `core/page-list` is not registered then use empty blocks. - return $registry->is_registered( 'core/page-list' ) ? '' : ''; - } -} diff --git a/lib/compat/wordpress-6.3/class-gutenberg-rest-block-patterns-controller-6-3.php b/lib/compat/wordpress-6.3/class-gutenberg-rest-block-patterns-controller-6-3.php deleted file mode 100644 index 0a5b026cded3b9..00000000000000 --- a/lib/compat/wordpress-6.3/class-gutenberg-rest-block-patterns-controller-6-3.php +++ /dev/null @@ -1,198 +0,0 @@ -get_fields_for_response( $request ); - $keys = array( - 'name' => 'name', - 'title' => 'title', - 'description' => 'description', - 'viewportWidth' => 'viewport_width', - 'blockTypes' => 'block_types', - 'postTypes' => 'post_types', - 'categories' => 'categories', - 'keywords' => 'keywords', - 'content' => 'content', - 'inserter' => 'inserter', - 'templateTypes' => 'template_types', - 'source' => 'source', - ); - $data = array(); - foreach ( $keys as $item_key => $rest_key ) { - if ( isset( $item[ $item_key ] ) && rest_is_field_included( $rest_key, $fields ) ) { - $data[ $rest_key ] = $item[ $item_key ]; - } - } - $context = ! empty( $request['context'] ) ? $request['context'] : 'view'; - $data = $this->add_additional_fields_to_object( $data, $request ); - $data = $this->filter_response_by_context( $data, $context ); - return rest_ensure_response( $data ); - } - - /** - * Retrieves the block pattern schema, conforming to JSON Schema. - * - * @since 6.0.0 - * @since 6.1.0 Added `post_types` property. - * @since 6.3.0 Added `source` property. - * - * @return array Item schema data. - */ - public function get_item_schema() { - if ( $this->schema ) { - return $this->add_additional_fields_schema( $this->schema ); - } - - $schema = array( - '$schema' => 'http://json-schema.org/draft-04/schema#', - 'title' => 'block-pattern', - 'type' => 'object', - 'properties' => array( - 'name' => array( - 'description' => __( 'The pattern name.', 'gutenberg' ), - 'type' => 'string', - 'readonly' => true, - 'context' => array( 'view', 'edit', 'embed' ), - ), - 'title' => array( - 'description' => __( 'The pattern title, in human readable format.', 'gutenberg' ), - 'type' => 'string', - 'readonly' => true, - 'context' => array( 'view', 'edit', 'embed' ), - ), - 'description' => array( - 'description' => __( 'The pattern detailed description.', 'gutenberg' ), - 'type' => 'string', - 'readonly' => true, - 'context' => array( 'view', 'edit', 'embed' ), - ), - 'viewport_width' => array( - 'description' => __( 'The pattern viewport width for inserter preview.', 'gutenberg' ), - 'type' => 'number', - 'readonly' => true, - 'context' => array( 'view', 'edit', 'embed' ), - ), - 'block_types' => array( - 'description' => __( 'Block types that the pattern is intended to be used with.', 'gutenberg' ), - 'type' => 'array', - 'readonly' => true, - 'context' => array( 'view', 'edit', 'embed' ), - ), - 'post_types' => array( - 'description' => __( 'An array of post types that the pattern is restricted to be used with.', 'gutenberg' ), - 'type' => 'array', - 'readonly' => true, - 'context' => array( 'view', 'edit', 'embed' ), - ), - 'categories' => array( - 'description' => __( 'The pattern category slugs.', 'gutenberg' ), - 'type' => 'array', - 'readonly' => true, - 'context' => array( 'view', 'edit', 'embed' ), - ), - 'keywords' => array( - 'description' => __( 'The pattern keywords.', 'gutenberg' ), - 'type' => 'array', - 'readonly' => true, - 'context' => array( 'view', 'edit', 'embed' ), - ), - 'template_types' => array( - 'description' => __( 'An array of template types where the pattern fits.', 'gutenberg' ), - 'type' => 'array', - 'readonly' => true, - 'context' => array( 'view', 'edit', 'embed' ), - ), - 'content' => array( - 'description' => __( 'The pattern content.', 'gutenberg' ), - 'type' => 'string', - 'readonly' => true, - 'context' => array( 'view', 'edit', 'embed' ), - ), - 'inserter' => array( - 'description' => __( 'Determines whether the pattern is visible in inserter.', 'gutenberg' ), - 'type' => 'boolean', - 'readonly' => true, - 'context' => array( 'view', 'edit', 'embed' ), - ), - 'source' => array( - 'description' => __( 'Where the pattern comes from e.g. core', 'gutenberg' ), - 'type' => 'string', - 'readonly' => true, - 'context' => array( 'view', 'edit', 'embed' ), - 'enum' => array( - 'core', - 'plugin', - 'theme', - 'pattern-directory/core', - 'pattern-directory/theme', - 'pattern-directory/featured', - ), - ), - ), - ); - - $this->schema = $schema; - - return $this->add_additional_fields_schema( $this->schema ); - } - - /** - * Retrieves all block patterns. - * - * @since 6.0.0 - * @since 6.2.0 Added migration for old core pattern categories to the new ones. - * - * @param WP_REST_Request $request Full details about the request. - * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. - */ - public function get_items( $request ) { - if ( ! $this->remote_patterns_loaded ) { - // Load block patterns from w.org. - gutenberg_load_remote_block_patterns(); // Patterns with the `core` keyword. - gutenberg_load_remote_featured_patterns(); // Patterns in the `featured` category. - gutenberg_register_remote_theme_patterns(); // Patterns requested by current theme. - - $this->remote_patterns_loaded = true; - } - - $response = array(); - $patterns = WP_Block_Patterns_Registry::get_instance()->get_all_registered(); - foreach ( $patterns as $pattern ) { - $migrated_pattern = $this->migrate_pattern_categories( $pattern ); - $prepared_pattern = $this->prepare_item_for_response( $migrated_pattern, $request ); - $response[] = $this->prepare_response_for_collection( $prepared_pattern ); - } - return rest_ensure_response( $response ); - } -} diff --git a/lib/compat/wordpress-6.3/class-gutenberg-rest-blocks-controller.php b/lib/compat/wordpress-6.3/class-gutenberg-rest-blocks-controller.php deleted file mode 100644 index 5279a2c3a829ec..00000000000000 --- a/lib/compat/wordpress-6.3/class-gutenberg-rest-blocks-controller.php +++ /dev/null @@ -1,51 +0,0 @@ -parent_post_type = 'wp_global_styles'; - $this->rest_base = 'revisions'; - $this->parent_base = 'global-styles'; - $this->namespace = 'wp/v2'; - } - - /** - * Registers the controllers routes. - * - * @return void - */ - public function register_routes() { - register_rest_route( - $this->namespace, - '/' . $this->parent_base . '/(?P[\d]+)/' . $this->rest_base, - array( - 'args' => array( - 'parent' => array( - 'description' => __( 'The ID for the parent of the revision.', 'gutenberg' ), - 'type' => 'integer', - ), - ), - array( - 'methods' => WP_REST_Server::READABLE, - 'callback' => array( $this, 'get_items' ), - 'permission_callback' => array( $this, 'get_item_permissions_check' ), - 'args' => $this->get_collection_params(), - ), - 'schema' => array( $this, 'get_public_item_schema' ), - ) - ); - } - - /** - * Retrieves the query params for collections. - * - * Inherits from WP_REST_Controller::get_collection_params(), - * also reflects changes to return value WP_REST_Revisions_Controller::get_collection_params(). - * - * @since 6.3.0 - * - * @return array Collection parameters. - */ - public function get_collection_params() { - $collection_params = parent::get_collection_params(); - $collection_params['context']['default'] = 'view'; - $collection_params['offset'] = array( - 'description' => __( 'Offset the result set by a specific number of items.' ), - 'type' => 'integer', - ); - unset( $collection_params['search'] ); - unset( $collection_params['per_page']['default'] ); - - return $collection_params; - } - - /** - * Returns decoded JSON from post content string, - * or a 404 if not found. - * - * @since 6.3.0 - * - * @param string $raw_json Encoded JSON from global styles custom post content. - * @return Array|WP_Error - */ - protected function get_decoded_global_styles_json( $raw_json ) { - $decoded_json = json_decode( $raw_json, true ); - - if ( is_array( $decoded_json ) && isset( $decoded_json['isGlobalStylesUserThemeJSON'] ) && true === $decoded_json['isGlobalStylesUserThemeJSON'] ) { - return $decoded_json; - } - - return new WP_Error( - 'rest_global_styles_not_found', - __( 'Cannot find user global styles revisions.' ), - array( 'status' => 404 ) - ); - } - - /** - * Returns revisions of the given global styles config custom post type. - * - * @since 6.3.0 - * - * @param WP_REST_Request $request The request instance. - * - * @return WP_REST_Response|WP_Error - */ - public function get_items( $request ) { - $parent = $this->get_parent( $request['parent'] ); - - if ( is_wp_error( $parent ) ) { - return $parent; - } - - $global_styles_config = $this->get_decoded_global_styles_json( $parent->post_content ); - - if ( is_wp_error( $global_styles_config ) ) { - return $global_styles_config; - } - - if ( wp_revisions_enabled( $parent ) ) { - $registered = $this->get_collection_params(); - $query_args = array( - 'post_parent' => $parent->ID, - 'post_type' => 'revision', - 'post_status' => 'inherit', - 'posts_per_page' => -1, - 'orderby' => 'date ID', - 'order' => 'DESC', - ); - - $parameter_mappings = array( - 'offset' => 'offset', - 'page' => 'paged', - 'per_page' => 'posts_per_page', - ); - - foreach ( $parameter_mappings as $api_param => $wp_param ) { - if ( isset( $registered[ $api_param ], $request[ $api_param ] ) ) { - $query_args[ $wp_param ] = $request[ $api_param ]; - } - } - - $revisions_query = new WP_Query(); - $revisions = $revisions_query->query( $query_args ); - $offset = isset( $query_args['offset'] ) ? (int) $query_args['offset'] : 0; - $page = (int) $query_args['paged']; - $total_revisions = $revisions_query->found_posts; - - if ( $total_revisions < 1 ) { - // Out-of-bounds, run the query again without LIMIT for total count. - unset( $query_args['paged'], $query_args['offset'] ); - $count_query = new WP_Query(); - $count_query->query( $query_args ); - - $total_revisions = $count_query->found_posts; - } - - if ( $revisions_query->query_vars['posts_per_page'] > 0 ) { - $max_pages = ceil( $total_revisions / (int) $revisions_query->query_vars['posts_per_page'] ); - } else { - $max_pages = $total_revisions > 0 ? 1 : 0; - } - if ( $total_revisions > 0 ) { - if ( $offset >= $total_revisions ) { - return new WP_Error( - 'rest_revision_invalid_offset_number', - __( 'The offset number requested is larger than or equal to the number of available revisions.', 'gutenberg' ), - array( 'status' => 400 ) - ); - } elseif ( ! $offset && $page > $max_pages ) { - return new WP_Error( - 'rest_revision_invalid_page_number', - __( 'The page number requested is larger than the number of pages available.', 'gutenberg' ), - array( 'status' => 400 ) - ); - } - } - } else { - $revisions = array(); - $total_revisions = 0; - $max_pages = 0; - $page = (int) $request['page']; - } - - $response = array(); - - foreach ( $revisions as $revision ) { - $data = $this->prepare_item_for_response( $revision, $request ); - $response[] = $this->prepare_response_for_collection( $data ); - } - - $response = rest_ensure_response( $response ); - - $response->header( 'X-WP-Total', (int) $total_revisions ); - $response->header( 'X-WP-TotalPages', (int) $max_pages ); - - $request_params = $request->get_query_params(); - $base_path = rest_url( sprintf( '%s/%s/%d/%s', $this->namespace, $this->parent_base, $request['parent'], $this->rest_base ) ); - $base = add_query_arg( urlencode_deep( $request_params ), $base_path ); - - if ( $page > 1 ) { - $prev_page = $page - 1; - - if ( $prev_page > $max_pages ) { - $prev_page = $max_pages; - } - - $prev_link = add_query_arg( 'page', $prev_page, $base ); - $response->link_header( 'prev', $prev_link ); - } - if ( $max_pages > $page ) { - $next_page = $page + 1; - $next_link = add_query_arg( 'page', $next_page, $base ); - - $response->link_header( 'next', $next_link ); - } - - return $response; - } - - /** - * A direct copy of WP_REST_Revisions_Controller->prepare_date_response(). - * Checks the post_date_gmt or modified_gmt and prepare any post or - * modified date for single post output. - * - * @since 6.3.0 - * - * @param string $date_gmt GMT publication time. - * @param string|null $date Optional. Local publication time. Default null. - * @return string|null ISO8601/RFC3339 formatted datetime, otherwise null. - */ - protected function prepare_date_response( $date_gmt, $date = null ) { - if ( '0000-00-00 00:00:00' === $date_gmt ) { - return null; - } - - if ( isset( $date ) ) { - return mysql_to_rfc3339( $date ); - } - - return mysql_to_rfc3339( $date_gmt ); - } - - /** - * Prepares the revision for the REST response. - * - * @since 6.3.0 - * - * @param WP_Post $post Post revision object. - * @param WP_REST_Request $request Request object. - * @return WP_REST_Response|WP_Error Response object. - */ - public function prepare_item_for_response( $post, $request ) { - $parent = $this->get_parent( $request['parent'] ); - $global_styles_config = $this->get_decoded_global_styles_json( $post->post_content ); - - if ( is_wp_error( $global_styles_config ) ) { - return $global_styles_config; - } - - $fields = $this->get_fields_for_response( $request ); - $data = array(); - - if ( ! empty( $global_styles_config['styles'] ) || ! empty( $global_styles_config['settings'] ) ) { - $global_styles_config = ( new WP_Theme_JSON_Gutenberg( $global_styles_config, 'custom' ) )->get_raw_data(); - if ( rest_is_field_included( 'settings', $fields ) ) { - $data['settings'] = ! empty( $global_styles_config['settings'] ) ? $global_styles_config['settings'] : new stdClass(); - } - if ( rest_is_field_included( 'styles', $fields ) ) { - $data['styles'] = ! empty( $global_styles_config['styles'] ) ? $global_styles_config['styles'] : new stdClass(); - } - } - - if ( rest_is_field_included( 'author', $fields ) ) { - $data['author'] = (int) $post->post_author; - } - - if ( rest_is_field_included( 'date', $fields ) ) { - $data['date'] = $this->prepare_date_response( $post->post_date_gmt, $post->post_date ); - } - - if ( rest_is_field_included( 'date_gmt', $fields ) ) { - $data['date_gmt'] = $this->prepare_date_response( $post->post_date_gmt ); - } - - if ( rest_is_field_included( 'id', $fields ) ) { - $data['id'] = (int) $post->ID; - } - - if ( rest_is_field_included( 'modified', $fields ) ) { - $data['modified'] = $this->prepare_date_response( $post->post_modified_gmt, $post->post_modified ); - } - - if ( rest_is_field_included( 'modified_gmt', $fields ) ) { - $data['modified_gmt'] = $this->prepare_date_response( $post->post_modified_gmt ); - } - - if ( rest_is_field_included( 'parent', $fields ) ) { - $data['parent'] = (int) $parent->ID; - } - - $context = ! empty( $request['context'] ) ? $request['context'] : 'view'; - $data = $this->add_additional_fields_to_object( $data, $request ); - $data = $this->filter_response_by_context( $data, $context ); - - return rest_ensure_response( $data ); - } - - /** - * Retrieves the revision's schema, conforming to JSON Schema. - * - * @since 6.3.0 - * - * @return array Item schema data. - */ - public function get_item_schema() { - if ( $this->schema ) { - return $this->add_additional_fields_schema( $this->schema ); - } - - $schema = array( - '$schema' => 'http://json-schema.org/draft-04/schema#', - 'title' => "{$this->parent_post_type}-revision", - 'type' => 'object', - // Base properties for every Revision. - 'properties' => array( - - /* - * Adds settings and styles from the WP_REST_Revisions_Controller item fields. - * Leaves out GUID as global styles shouldn't be accessible via URL. - */ - 'author' => array( - 'description' => __( 'The ID for the author of the revision.', 'gutenberg' ), - 'type' => 'integer', - 'context' => array( 'view', 'edit', 'embed' ), - ), - 'date' => array( - 'description' => __( "The date the revision was published, in the site's timezone.", 'gutenberg' ), - 'type' => 'string', - 'format' => 'date-time', - 'context' => array( 'view', 'edit', 'embed' ), - ), - 'date_gmt' => array( - 'description' => __( 'The date the revision was published, as GMT.', 'gutenberg' ), - 'type' => 'string', - 'format' => 'date-time', - 'context' => array( 'view', 'edit' ), - ), - 'id' => array( - 'description' => __( 'Unique identifier for the revision.', 'gutenberg' ), - 'type' => 'integer', - 'context' => array( 'view', 'edit', 'embed' ), - ), - 'modified' => array( - 'description' => __( "The date the revision was last modified, in the site's timezone.", 'gutenberg' ), - 'type' => 'string', - 'format' => 'date-time', - 'context' => array( 'view', 'edit' ), - ), - 'modified_gmt' => array( - 'description' => __( 'The date the revision was last modified, as GMT.', 'gutenberg' ), - 'type' => 'string', - 'format' => 'date-time', - 'context' => array( 'view', 'edit' ), - ), - 'parent' => array( - 'description' => __( 'The ID for the parent of the revision.', 'gutenberg' ), - 'type' => 'integer', - 'context' => array( 'view', 'edit', 'embed' ), - ), - - // Adds settings and styles from the WP_REST_Global_Styles_Controller parent schema. - 'styles' => array( - 'description' => __( 'Global styles.', 'gutenberg' ), - 'type' => array( 'object' ), - 'context' => array( 'view', 'edit' ), - ), - 'settings' => array( - 'description' => __( 'Global settings.', 'gutenberg' ), - 'type' => array( 'object' ), - 'context' => array( 'view', 'edit' ), - ), - ), - ); - - $this->schema = $schema; - - return $this->add_additional_fields_schema( $this->schema ); - } - - /** - * Checks if a given request has access to read a single global style. - * - * @since 6.3.0 - * - * @param WP_REST_Request $request Full details about the request. - * @return true|WP_Error True if the request has read access, WP_Error object otherwise. - */ - public function get_item_permissions_check( $request ) { - $post = $this->get_parent( $request['parent'] ); - if ( is_wp_error( $post ) ) { - return $post; - } - - /* - * The same check as WP_REST_Global_Styles_Controller->get_item_permissions_check. - */ - if ( ! current_user_can( 'read_post', $post->ID ) ) { - return new WP_Error( - 'rest_cannot_view', - __( 'Sorry, you are not allowed to view revisions for this global style.', 'gutenberg' ), - array( 'status' => rest_authorization_required_code() ) - ); - } - - return true; - } - - /** - * Get the parent post, if the ID is valid. Copied from WP_REST_Revisions_Controller. - * - * @since 6.3.0 - * - * @param int $parent_post_id Supplied ID. - * @return WP_Post|WP_Error Post object if ID is valid, WP_Error otherwise. - */ - protected function get_parent( $parent_post_id ) { - $error = new WP_Error( - 'rest_post_invalid_parent', - __( 'Invalid post parent ID.', 'gutenberg' ), - array( 'status' => 404 ) - ); - - if ( (int) $parent_post_id <= 0 ) { - return $error; - } - - $parent_post = get_post( (int) $parent_post_id ); - - if ( empty( $parent_post ) || empty( $parent_post->ID ) - || $this->parent_post_type !== $parent_post->post_type - ) { - return $error; - } - - return $parent_post; - } -} diff --git a/lib/compat/wordpress-6.3/class-gutenberg-rest-navigation-fallback-controller.php b/lib/compat/wordpress-6.3/class-gutenberg-rest-navigation-fallback-controller.php deleted file mode 100644 index 2cac70f2ea1c34..00000000000000 --- a/lib/compat/wordpress-6.3/class-gutenberg-rest-navigation-fallback-controller.php +++ /dev/null @@ -1,178 +0,0 @@ -namespace = 'wp-block-editor/v1'; - $this->rest_base = 'navigation-fallback'; - $this->post_type = 'wp_navigation'; - } - - /** - * Registers the controllers routes. - * - * @return void - */ - public function register_routes() { - - // Lists a single nav item based on the given id or slug. - register_rest_route( - $this->namespace, - '/' . $this->rest_base, - array( - array( - 'methods' => WP_REST_Server::READABLE, - 'callback' => array( $this, 'get_item' ), - 'permission_callback' => array( $this, 'get_item_permissions_check' ), - 'args' => $this->get_endpoint_args_for_item_schema( WP_REST_Server::READABLE ), - ), - 'schema' => array( $this, 'get_item_schema' ), - ) - ); - } - - /** - * Checks if a given request has access to read fallbacks. - * - * @param WP_REST_Request $request Full details about the request. - * @return true|WP_Error True if the request has read access, WP_Error object otherwise. - */ - public function get_item_permissions_check( $request ) { - - $post_type = get_post_type_object( $this->post_type ); - - // Getting fallbacks requires creating and reading `wp_navigation` posts. - if ( ! current_user_can( $post_type->cap->create_posts ) || ! current_user_can( 'edit_theme_options' ) || ! current_user_can( 'edit_posts' ) ) { - return new WP_Error( - 'rest_cannot_create', - __( 'Sorry, you are not allowed to create Navigation Menus as this user.', 'gutenberg' ), - array( 'status' => rest_authorization_required_code() ) - ); - } - - if ( 'edit' === $request['context'] && ! current_user_can( $post_type->cap->edit_posts ) ) { - return new WP_Error( - 'rest_forbidden_context', - __( 'Sorry, you are not allowed to edit Navigation Menus as this user.', 'gutenberg' ), - array( 'status' => rest_authorization_required_code() ) - ); - } - - return true; - } - - /** - * Gets the most appropriate fallback Navigation Menu. - * - * @param WP_REST_Request $request Full details about the request. - * - * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. - */ - public function get_item( $request ) { - $post = Gutenberg_Navigation_Fallback::get_fallback(); - - if ( empty( $post ) ) { - return rest_ensure_response( new WP_Error( 'no_fallback_menu', __( 'No fallback menu found.', 'gutenberg' ), array( 'status' => 404 ) ) ); - } - - $response = $this->prepare_item_for_response( $post, $request ); - - return $response; - } - - /** - * Retrieves the fallbacks' schema, conforming to JSON Schema. - * - * @return array Item schema data. - */ - public function get_item_schema() { - if ( $this->schema ) { - return $this->add_additional_fields_schema( $this->schema ); - } - - $this->schema = array( - '$schema' => 'http://json-schema.org/draft-04/schema#', - 'title' => 'navigation-fallback', - 'type' => 'object', - 'properties' => array( - 'id' => array( - 'description' => __( 'The unique identifier for the Navigation Menu.', 'gutenberg' ), - 'type' => 'integer', - 'context' => array( 'view', 'edit', 'embed' ), - 'readonly' => true, - ), - ), - ); - - return $this->add_additional_fields_schema( $this->schema ); - } - - /** - * Matches the post data to the schema we want. - * - * @param WP_Post $item The wp_navigation Post object whose response is being prepared. - * @param WP_REST_Request $request Request object. - * @return WP_REST_Response $response The response data. - */ - public function prepare_item_for_response( $item, $request ) { - $data = array(); - - $fields = $this->get_fields_for_response( $request ); - - if ( rest_is_field_included( 'id', $fields ) ) { - $data['id'] = (int) $item->ID; - } - - $context = ! empty( $request['context'] ) ? $request['context'] : 'view'; - $data = $this->add_additional_fields_to_object( $data, $request ); - $data = $this->filter_response_by_context( $data, $context ); - - $response = rest_ensure_response( $data ); - - if ( rest_is_field_included( '_links', $fields ) || rest_is_field_included( '_embedded', $fields ) ) { - $links = $this->prepare_links( $item ); - $response->add_links( $links ); - } - - return $response; - } - - /** - * Prepares the links for the request. - * - * @param WP_Post $post the Navigation Menu post object. - * @return array Links for the given request. - */ - private function prepare_links( $post ) { - return array( - 'self' => array( - 'href' => rest_url( rest_get_route_for_post( $post->ID ) ), - 'embeddable' => true, - ), - ); - } -} diff --git a/lib/compat/wordpress-6.3/class-gutenberg-rest-templates-controller-6-3.php b/lib/compat/wordpress-6.3/class-gutenberg-rest-templates-controller-6-3.php deleted file mode 100644 index a92cbd1e2c1716..00000000000000 --- a/lib/compat/wordpress-6.3/class-gutenberg-rest-templates-controller-6-3.php +++ /dev/null @@ -1,68 +0,0 @@ -namespace, - '/' . $this->rest_base . '/lookup', - array( - array( - 'methods' => WP_REST_Server::READABLE, - 'callback' => array( $this, 'get_template_fallback' ), - 'permission_callback' => array( $this, 'get_item_permissions_check' ), - 'args' => array( - 'slug' => array( - 'description' => __( 'The slug of the template to get the fallback for', 'gutenberg' ), - 'type' => 'string', - 'required' => true, - ), - 'is_custom' => array( - 'description' => __( 'Indicates if a template is custom or part of the template hierarchy', 'gutenberg' ), - 'type' => 'boolean', - ), - 'template_prefix' => array( - 'description' => __( 'The template prefix for the created template. This is used to extract the main template type ex. in `taxonomy-books` we extract the `taxonomy`', 'gutenberg' ), - 'type' => 'string', - ), - ), - ), - ) - ); - parent::register_routes(); - // Get fallback template content. - } - - /** - * Returns the fallback template for a given slug. - * - * @param WP_REST_Request $request The request instance. - * - * @return WP_REST_Response|WP_Error - */ - public function get_template_fallback( $request ) { - $hierarchy = get_template_hierarchy( $request['slug'], $request['is_custom'], $request['template_prefix'] ); - $fallback_template = null; - do { - $fallback_template = resolve_block_template( $request['slug'], $hierarchy, '' ); - array_shift( $hierarchy ); - } while ( ! empty( $hierarchy ) && empty( $fallback_template->content ) ); - $response = $this->prepare_item_for_response( $fallback_template, $request ); - return rest_ensure_response( $response ); - } -} diff --git a/lib/compat/wordpress-6.3/footnotes.php b/lib/compat/wordpress-6.3/footnotes.php deleted file mode 100644 index 6225b280e1b6c2..00000000000000 --- a/lib/compat/wordpress-6.3/footnotes.php +++ /dev/null @@ -1,32 +0,0 @@ -\s*\d+\s*_', - '', - $content - ); -} - -add_filter( 'the_content', 'gutenberg_trim_footnotes' ); diff --git a/lib/compat/wordpress-6.3/get-global-styles-and-settings.php b/lib/compat/wordpress-6.3/get-global-styles-and-settings.php deleted file mode 100644 index 009fa6253f79d4..00000000000000 --- a/lib/compat/wordpress-6.3/get-global-styles-and-settings.php +++ /dev/null @@ -1,114 +0,0 @@ -selectors ); - - // Root Selector. - - // Calculated before returning as it can be used as fallback for - // feature selectors later on. - $root_selector = null; - - if ( $has_selectors && isset( $block_type->selectors['root'] ) ) { - // Use the selectors API if available. - $root_selector = $block_type->selectors['root']; - } elseif ( isset( $block_type->supports['__experimentalSelector'] ) && is_string( $block_type->supports['__experimentalSelector'] ) ) { - // Use the old experimental selector supports property if set. - $root_selector = $block_type->supports['__experimentalSelector']; - } else { - // If no root selector found, generate default block class selector. - $block_name = str_replace( '/', '-', str_replace( 'core/', '', $block_type->name ) ); - $root_selector = ".wp-block-{$block_name}"; - } - - // Return selector if it's the root target we are looking for. - if ( 'root' === $target ) { - return $root_selector; - } - - // If target is not `root` we have a feature or subfeature as the target. - // If the target is a string convert to an array. - if ( is_string( $target ) ) { - $target = explode( '.', $target ); - } - - // Feature Selectors ( May fallback to root selector ). - if ( 1 === count( $target ) ) { - $fallback_selector = $fallback ? $root_selector : null; - - // Prefer the selectors API if available. - if ( $has_selectors ) { - // Look for selector under `feature.root`. - $path = array_merge( $target, array( 'root' ) ); - $feature_selector = _wp_array_get( $block_type->selectors, $path, null ); - - if ( $feature_selector ) { - return $feature_selector; - } - - // Check if feature selector is set via shorthand. - $feature_selector = _wp_array_get( $block_type->selectors, $target, null ); - - return is_string( $feature_selector ) ? $feature_selector : $fallback_selector; - } - - // Try getting old experimental supports selector value. - $path = array_merge( $target, array( '__experimentalSelector' ) ); - $feature_selector = _wp_array_get( $block_type->supports, $path, null ); - - // Nothing to work with, provide fallback or null. - if ( null === $feature_selector ) { - return $fallback_selector; - } - - // Scope the feature selector by the block's root selector. - return WP_Theme_JSON_Gutenberg::scope_selector( $root_selector, $feature_selector ); - } - - // Subfeature selector - // This may fallback either to parent feature or root selector. - $subfeature_selector = null; - - // Use selectors API if available. - if ( $has_selectors ) { - $subfeature_selector = _wp_array_get( $block_type->selectors, $target, null ); - } - - // Only return if we have a subfeature selector. - if ( $subfeature_selector ) { - return $subfeature_selector; - } - - // To this point we don't have a subfeature selector. If a fallback - // has been requested, remove subfeature from target path and return - // results of a call for the parent feature's selector. - if ( $fallback ) { - return wp_get_block_css_selector( $block_type, $target[0], $fallback ); - } - - // We tried... - return null; - } -} diff --git a/lib/compat/wordpress-6.3/kses.php b/lib/compat/wordpress-6.3/kses.php deleted file mode 100644 index b0b7356d2dac1c..00000000000000 --- a/lib/compat/wordpress-6.3/kses.php +++ /dev/null @@ -1,29 +0,0 @@ -post_type || 'wp_template_part' === $post->post_type ) { - $post_type_object = get_post_type_object( $post->post_type ); - $slug = urlencode( get_stylesheet() . '//' . $post->post_name ); - $link = admin_url( sprintf( $post_type_object->_edit_link, $slug ) ); - } - - return $link; -} - -add_filter( 'get_edit_post_link', 'gutenberg_update_get_edit_post_link', 10, 2 ); - - - -/** - * Modifies the edit link for the `wp_navigation` custom post type. - * - * This has not been backported to Core. - * - * @param string $link The edit link. - * @param int $post_id Post ID. - * @return string|null The edit post link for the given post. Null if the post type does not exist - * or does not allow an editing UI. - */ -function gutenberg_update_navigation_get_edit_post_link( $link, $post_id ) { - $post = get_post( $post_id ); - - if ( 'wp_navigation' === $post->post_type ) { - $post_type_object = get_post_type_object( $post->post_type ); - $id = $post->ID; - $link = admin_url( sprintf( $post_type_object->_edit_link, $id ) ); - } - - return $link; -} -add_filter( 'get_edit_post_link', 'gutenberg_update_navigation_get_edit_post_link', 10, 2 ); diff --git a/lib/compat/wordpress-6.3/navigation-block-preloading.php b/lib/compat/wordpress-6.3/navigation-block-preloading.php deleted file mode 100644 index 22b4a97526793e..00000000000000 --- a/lib/compat/wordpress-6.3/navigation-block-preloading.php +++ /dev/null @@ -1,48 +0,0 @@ -name ) && 'core/edit-site' !== $context->name ) { - return $preload_paths; - } - - $navigation_rest_route = rest_get_route_for_post_type_items( - 'wp_navigation' - ); - - // Preload the OPTIONS request for all Navigation posts request. - $preload_paths[] = array( $navigation_rest_route, 'OPTIONS' ); - - // Preload request for all menus in Browse Mode sidebar "Navigation" section. - $preload_paths[] = array( - add_query_arg( - array( - 'context' => 'edit', - 'per_page' => 100, - 'order' => 'desc', - 'orderby' => 'date', - 'status[0]' => 'publish', - 'status[1]' => 'draft', - ), - $navigation_rest_route - ), - 'GET', - ); - - return $preload_paths; -} -add_filter( 'block_editor_rest_api_preload_paths', 'gutenberg_preload_navigation_posts', 10, 2 ); diff --git a/lib/compat/wordpress-6.3/navigation-fallback.php b/lib/compat/wordpress-6.3/navigation-fallback.php deleted file mode 100644 index 5cc84f4a1c848c..00000000000000 --- a/lib/compat/wordpress-6.3/navigation-fallback.php +++ /dev/null @@ -1,54 +0,0 @@ - $post_type, - 'postId' => '%s', - 'canvas' => 'edit', - ) - ); - $args['_edit_link'] = $template_edit_link; - } - - if ( in_array( $post_type, array( 'wp_global_styles' ), true ) ) { - $args['_edit_link'] = '/site-editor.php?canvas=edit'; - } - - if ( 'wp_navigation' === $post_type ) { - $navigation_edit_link = 'site-editor.php?' . build_query( - array( - 'postId' => '%s', - 'postType' => 'wp_navigation', - 'canvas' => 'edit', - ) - ); - $args['_edit_link'] = $navigation_edit_link; - } - - return $args; -} -add_filter( 'register_post_type_args', 'gutenberg_update_templates_template_parts_rest_controller', 10, 2 ); - -if ( ! function_exists( 'add_modified_wp_template_schema' ) ) { - /** - * Add the `modified` value to the `wp_template` schema. - * - * @since 6.3.0 Added 'modified' property and response value. - */ - function add_modified_wp_template_schema() { - register_rest_field( - array( 'wp_template', 'wp_template_part' ), - 'modified', - array( - 'schema' => array( - 'description' => __( "The date the template was last modified, in the site's timezone.", 'gutenberg' ), - 'type' => 'string', - 'format' => 'date-time', - 'context' => array( 'view', 'edit' ), - 'readonly' => true, - ), - 'get_callback' => function ( $template_object ) { - if ( ! empty( $template_object['wp_id'] ) ) { - $post = get_post( $template_object['wp_id'] ); - if ( $post && isset( $post->post_modified ) ) { - return mysql_to_rfc3339( $post->post_modified ); - } - } - return null; - }, - ) - ); - } -} -add_filter( 'rest_api_init', 'add_modified_wp_template_schema' ); - -/** - * Registers the Navigation Fallbacks REST API routes. - */ -function gutenberg_register_rest_navigation_fallbacks() { - $editor_settings = new Gutenberg_REST_Navigation_Fallback_Controller(); - $editor_settings->register_routes(); -} -add_action( 'rest_api_init', 'gutenberg_register_rest_navigation_fallbacks' ); - -/** - * Add extra collection params to themes requests. - * - * @param array $query_params JSON Schema-formatted collection parameters. - * @return array Updated parameters. - */ -function gutenberg_themes_collection_params_6_3( $query_params ) { - $query_params['is_block_theme'] = array( - 'description' => __( 'Whether the theme is a block-based theme.' ), - 'type' => 'boolean', - 'readonly' => true, - ); - return $query_params; -} -add_filter( 'rest_themes_collection_params', 'gutenberg_themes_collection_params_6_3' ); - -/** - * Updates REST API response for the themes and adds the `is_block_theme` flag. - * - * @param WP_REST_Response $response The response object. - * @param WP_Theme $theme Theme object used to create response. - * @return WP_REST_Response $response Updated response object. - */ -function gutenberg_modify_rest_themes_response( $response, $theme ) { - $response->data['is_block_theme'] = $theme->is_block_theme(); - return $response; -} -add_filter( 'rest_prepare_theme', 'gutenberg_modify_rest_themes_response', 10, 2 ); diff --git a/lib/compat/wordpress-6.3/script-loader.php b/lib/compat/wordpress-6.3/script-loader.php deleted file mode 100644 index c8de16efd06875..00000000000000 --- a/lib/compat/wordpress-6.3/script-loader.php +++ /dev/null @@ -1,14 +0,0 @@ -errors() ) ) { - if ( current_filter() === 'template' ) { - $theme_path = $wp_theme->get_template(); - } else { - $theme_path = $wp_theme->get_stylesheet(); - } - - return sanitize_text_field( $theme_path ); - } - - return $current_stylesheet; -} - -/** - * Adds a middleware to the REST API to set the theme for the preview. - */ -function gutenberg_attach_theme_preview_middleware() { - // Don't allow non-admins to preview themes. - if ( ! current_user_can( 'switch_themes' ) ) { - return; - } - - wp_add_inline_script( - 'wp-api-fetch', - sprintf( - 'wp.apiFetch.use( wp.apiFetch.createThemePreviewMiddleware( %s ) );', - wp_json_encode( sanitize_text_field( $_GET['wp_theme_preview'] ) ) - ), - 'after' - ); -} - -if ( ! function_exists( 'add_live_preview_button' ) ) { - /** - * Temporary function to add a live preview button to block themes. - * Remove when https://core.trac.wordpress.org/ticket/58190 lands. - */ - function add_live_preview_button() { - global $pagenow; - if ( 'themes.php' === $pagenow ) { - ?> - - - - assertTrue( class_exists( 'Gutenberg_Classic_To_Block_Menu_Converter' ) ); - } - - /** - * @covers WP_Classic_To_Block_Menu_Converter::convert - * @dataProvider provider_test_passing_non_menu_object_to_converter_returns_wp_error - */ - public function test_passing_non_menu_object_to_converter_returns_wp_error( $data ) { - - $result = Gutenberg_Classic_To_Block_Menu_Converter::convert( $data ); - - $this->assertTrue( is_wp_error( $result ), 'Should be a WP_Error instance' ); - - $this->assertEquals( 'invalid_menu', $result->get_error_code(), 'Error code should indicate invalidity of menu argument.' ); - - $this->assertEquals( 'The menu provided is not a valid menu.', $result->get_error_message(), 'Error message should communicate invalidity of menu argument.' ); - } - - /** - * @covers WP_Classic_To_Block_Menu_Converter::convert - */ - public function provider_test_passing_non_menu_object_to_converter_returns_wp_error() { - return array( - array( 1 ), - array( -1 ), - array( '1' ), - array( 'not a menu object' ), - array( true ), - array( false ), - array( array() ), - array( new stdClass() ), - ); - } - - /** - * @covers WP_Classic_To_Block_Menu_Converter::convert - */ - public function test_can_convert_classic_menu_to_blocks() { - - $menu_id = wp_create_nav_menu( 'Classic Menu' ); - - wp_update_nav_menu_item( - $menu_id, - 0, - array( - 'menu-item-title' => 'Classic Menu Item 1', - 'menu-item-url' => '/classic-menu-item-1', - 'menu-item-status' => 'publish', - ) - ); - - $second_menu_item_id = wp_update_nav_menu_item( - $menu_id, - 0, - array( - 'menu-item-title' => 'Classic Menu Item 2', - 'menu-item-url' => '/classic-menu-item-2', - 'menu-item-status' => 'publish', - ) - ); - - wp_update_nav_menu_item( - $menu_id, - 0, - array( - 'menu-item-title' => 'Nested Menu Item 1', - 'menu-item-url' => '/nested-menu-item-1', - 'menu-item-status' => 'publish', - 'menu-item-parent-id' => $second_menu_item_id, - ) - ); - - $classic_nav_menu = wp_get_nav_menu_object( $menu_id ); - - $blocks = Gutenberg_Classic_To_Block_Menu_Converter::convert( $classic_nav_menu ); - - $this->assertNotEmpty( $blocks ); - - $parsed_blocks = parse_blocks( $blocks ); - - $first_block = $parsed_blocks[0]; - $second_block = $parsed_blocks[1]; - $nested_block = $parsed_blocks[1]['innerBlocks'][0]; - - $this->assertEquals( 'core/navigation-link', $first_block['blockName'], 'First block name should be "core/navigation-link"' ); - - $this->assertEquals( 'Classic Menu Item 1', $first_block['attrs']['label'], 'First block label should match.' ); - - $this->assertEquals( '/classic-menu-item-1', $first_block['attrs']['url'], 'First block URL should match.' ); - - // Assert parent of nested menu item is a submenu block. - $this->assertEquals( 'core/navigation-submenu', $second_block['blockName'], 'Second block name should be "core/navigation-submenu"' ); - - $this->assertEquals( 'Classic Menu Item 2', $second_block['attrs']['label'], 'Second block label should match.' ); - - $this->assertEquals( '/classic-menu-item-2', $second_block['attrs']['url'], 'Second block URL should match.' ); - - $this->assertEquals( 'core/navigation-link', $nested_block['blockName'], 'Nested block name should be "core/navigation-link"' ); - - $this->assertEquals( 'Nested Menu Item 1', $nested_block['attrs']['label'], 'Nested block label should match.' ); - - $this->assertEquals( '/nested-menu-item-1', $nested_block['attrs']['url'], 'Nested block URL should match.' ); - - wp_delete_nav_menu( $menu_id ); - } - - /** - * @covers WP_Classic_To_Block_Menu_Converter::convert - */ - public function test_does_not_convert_menu_items_with_non_publish_status() { - - $menu_id = wp_create_nav_menu( 'Classic Menu' ); - - wp_update_nav_menu_item( - $menu_id, - 0, - array( - 'menu-item-title' => 'Classic Menu Item 1', - 'menu-item-url' => '/classic-menu-item-1', - 'menu-item-status' => 'publish', - ) - ); - - wp_update_nav_menu_item( - $menu_id, - 0, - array( - 'menu-item-status' => 'draft', - 'menu-item-title' => 'Draft Menu Item', - 'menu-item-url' => '/draft-menu-item', - ) - ); - - wp_update_nav_menu_item( - $menu_id, - 0, - array( - 'menu-item-status' => 'private', - 'menu-item-title' => 'Private Item', - 'menu-item-url' => '/private-menu-item', - ) - ); - - wp_update_nav_menu_item( - $menu_id, - 0, - array( - 'menu-item-status' => 'pending', - 'menu-item-title' => 'Pending Menu Item', - 'menu-item-url' => '/pending-menu-item', - ) - ); - - wp_update_nav_menu_item( - $menu_id, - 0, - array( - 'menu-item-status' => 'future', - 'menu-item-title' => 'Future Menu Item', - 'menu-item-url' => '/future-menu-item', - ) - ); - - $classic_nav_menu = wp_get_nav_menu_object( $menu_id ); - - $blocks = Gutenberg_Classic_To_Block_Menu_Converter::convert( $classic_nav_menu ); - - $this->assertNotEmpty( $blocks ); - - $parsed_blocks = parse_blocks( $blocks ); - - $this->assertCount( 1, $parsed_blocks, 'Should only be one block in the array.' ); - - $this->assertEquals( 'core/navigation-link', $parsed_blocks[0]['blockName'], 'First block name should be "core/navigation-link"' ); - - $this->assertEquals( 'Classic Menu Item 1', $parsed_blocks[0]['attrs']['label'], 'First block label should match.' ); - - $this->assertEquals( '/classic-menu-item-1', $parsed_blocks[0]['attrs']['url'], 'First block URL should match.' ); - - wp_delete_nav_menu( $menu_id ); - } - - /** - * @covers WP_Classic_To_Block_Menu_Converter::convert - */ - public function test_returns_empty_array_for_menus_with_no_items() { - $menu_id = wp_create_nav_menu( 'Empty Menu' ); - - $classic_nav_menu = wp_get_nav_menu_object( $menu_id ); - - $blocks = Gutenberg_Classic_To_Block_Menu_Converter::convert( $classic_nav_menu ); - - $this->assertEmpty( $blocks, 'Result should be empty.' ); - - $this->assertIsArray( $blocks, 'Result should be empty array.' ); - - wp_delete_nav_menu( $menu_id ); - } -} diff --git a/phpunit/class-gutenberg-navigation-fallback-gutenberg-test.php b/phpunit/class-gutenberg-navigation-fallback-gutenberg-test.php deleted file mode 100644 index 6ae05e0a5ffb7f..00000000000000 --- a/phpunit/class-gutenberg-navigation-fallback-gutenberg-test.php +++ /dev/null @@ -1,352 +0,0 @@ -user->create( array( 'role' => 'administrator' ) ); - - self::$editor_user = $factory->user->create( array( 'role' => 'editor' ) ); - } - - public function set_up() { - parent::set_up(); - - wp_set_current_user( self::$admin_user ); - } - - /** - * @covers WP_REST_Navigation_Fallback_Controller - */ - public function test_it_exists() { - $this->assertTrue( class_exists( 'Gutenberg_Navigation_Fallback' ), 'Gutenberg_Navigation_Fallback class should exist.' ); - } - - /** - * @covers WP_REST_Navigation_Fallback_Controller::get_fallback - */ - public function test_should_return_a_default_fallback_navigation_menu_in_absence_of_other_fallbacks() { - $data = Gutenberg_Navigation_Fallback::get_fallback(); - - $this->assertInstanceOf( 'WP_Post', $data, 'Response should be of the correct type.' ); - - $this->assertEquals( 'wp_navigation', $data->post_type, 'Fallback menu type should be `wp_navigation`' ); - - $this->assertEquals( 'Navigation', $data->post_title, 'Fallback menu title should be the default fallback title' ); - - $this->assertEquals( 'navigation', $data->post_name, 'Fallback menu slug (post_name) should be the default slug' ); - - $this->assertEquals( '', $data->post_content ); - - $navs_in_db = $this->get_navigations_in_database(); - - $this->assertCount( 1, $navs_in_db, 'The fallback Navigation post should be the only one in the database.' ); - } - - /** - * @covers WP_REST_Navigation_Fallback_Controller::get_fallback - */ - public function test_should_not_automatically_create_fallback_if_filter_is_falsey() { - - add_filter( 'gutenberg_navigation_should_create_fallback', '__return_false' ); - - $data = Gutenberg_Navigation_Fallback::get_fallback(); - - $this->assertEmpty( $data ); - - $navs_in_db = $this->get_navigations_in_database(); - - $this->assertCount( 0, $navs_in_db, 'The fallback Navigation post should not have been created.' ); - - remove_filter( 'gutenberg_navigation_should_create_fallback', '__return_false' ); - } - - /** - * @covers WP_REST_Navigation_Fallback_Controller::get_fallback - */ - public function test_should_return_a_default_fallback_navigation_menu_with_no_blocks_if_page_list_block_is_not_registered() { - - $original_page_list_block = WP_Block_Type_Registry::get_instance()->get_registered( 'core/page-list' ); - - unregister_block_type( 'core/page-list' ); - - $data = Gutenberg_Navigation_Fallback::get_fallback(); - - $this->assertInstanceOf( 'WP_Post', $data, 'Response should be of the correct type.' ); - - $this->assertNotEquals( '', $data->post_content, 'Navigation Menu should not contain a Page List block.' ); - - $this->assertEmpty( $data->post_content, 'Menu should be empty.' ); - - register_block_type( 'core/page-list', $original_page_list_block ); - } - - /** - * @covers WP_REST_Navigation_Fallback_Controller::get_fallback - */ - public function test_should_handle_consecutive_invocations() { - // Invoke the method multiple times to ensure that it doesn't create a new fallback menu on each invocation. - Gutenberg_Navigation_Fallback::get_fallback(); - Gutenberg_Navigation_Fallback::get_fallback(); - - // Assert on the final invocation. - $data = Gutenberg_Navigation_Fallback::get_fallback(); - - $this->assertInstanceOf( 'WP_Post', $data, 'Response should be of the correct type.' ); - - $this->assertEquals( 'Navigation', $data->post_title, 'Fallback menu title should be the default title' ); - - $navs_in_db = $this->get_navigations_in_database(); - - $this->assertCount( 1, $navs_in_db, 'The fallback Navigation post should be the only one in the database.' ); - } - - /** - * @covers WP_REST_Navigation_Fallback_Controller::get_fallback - */ - public function test_should_return_the_most_recently_created_navigation_menu() { - - self::factory()->post->create_and_get( - array( - 'post_type' => 'wp_navigation', - 'post_title' => 'Existing Navigation Menu 1', - 'post_content' => '', - ) - ); - - $most_recently_published_nav = self::factory()->post->create_and_get( - array( - 'post_type' => 'wp_navigation', - 'post_title' => 'Existing Navigation Menu 2', - 'post_content' => '', - ) - ); - - $data = Gutenberg_Navigation_Fallback::get_fallback(); - - $this->assertInstanceOf( 'WP_Post', $data, 'Response should be of the correct type.' ); - - $this->assertEquals( $most_recently_published_nav->post_title, $data->post_title, 'Fallback menu title should be the same as the most recently created menu.' ); - - $this->assertEquals( $most_recently_published_nav->post_name, $data->post_name, 'Post name should be the same as the most recently created menu.' ); - - $this->assertEquals( $most_recently_published_nav->post_content, $data->post_content, 'Post content should be the same as the most recently created menu.' ); - - // Check that no new Navigation menu was created. - $navs_in_db = $this->get_navigations_in_database(); - - $this->assertCount( 2, $navs_in_db, 'Only the existing Navigation menus should be present in the database.' ); - } - - /** - * @covers WP_REST_Navigation_Fallback_Controller::get_fallback - */ - public function test_should_return_fallback_navigation_from_existing_classic_menu_if_no_navigation_menus_exist() { - $menu_id = wp_create_nav_menu( 'Existing Classic Menu' ); - - wp_update_nav_menu_item( - $menu_id, - 0, - array( - 'menu-item-title' => 'Classic Menu Item 1', - 'menu-item-url' => '/classic-menu-item-1', - 'menu-item-status' => 'publish', - ) - ); - - $data = Gutenberg_Navigation_Fallback::get_fallback(); - - $this->assertInstanceOf( 'WP_Post', $data, 'Response should be of the correct type.' ); - - $this->assertEquals( 'Existing Classic Menu', $data->post_title, 'Fallback menu title should be the same as the classic menu.' ); - - // Assert that the fallback contains a navigation-link block. - $this->assertStringContainsString( '', - ) - ); - - $data = Gutenberg_Navigation_Fallback::get_fallback(); - - $this->assertInstanceOf( 'WP_Post', $data, 'Response should be of the correct type.' ); - - $this->assertEquals( $existing_navigation_menu->post_title, $data->post_title, 'Fallback menu title should be the same as the existing Navigation menu.' ); - - $this->assertNotEquals( 'Existing Classic Menu', $data->post_title, 'Fallback menu title should not be the same as the Classic Menu.' ); - - // Check that only a single Navigation fallback was created. - $navs_in_db = $this->get_navigations_in_database(); - - $this->assertCount( 1, $navs_in_db, 'Only the existing Navigation menus should be present in the database.' ); - } - - private function get_navigations_in_database() { - $navs_in_db = new WP_Query( - array( - 'post_type' => 'wp_navigation', - 'post_status' => 'publish', - 'posts_per_page' => -1, - 'orderby' => 'date', - 'order' => 'DESC', - ) - ); - - return $navs_in_db->posts ? $navs_in_db->posts : array(); - } -}