Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Try add Post Type Archive in Link UI and Navigation Link #66821

Open
wants to merge 21 commits into
base: trunk
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 20 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
<?php
/**
* REST API: WP_REST_Post_Archive_Search_Handler class
*
* @package WordPress
* @subpackage REST_API
* @since 6.8.0
*/

/**
* Core class representing a search handler for Post Archives in the REST API.
*
* @since 6.8.0
*
* @see WP_REST_Search_Handler
*/
class Gutenberg_REST_Post_Archive_Search_Handler extends WP_REST_Search_Handler {

/**
* Constructor.
*
* @since 6.8.0
*/
public function __construct() {
$this->type = 'post-type-archive';
}

/**
* Searches post-type archives for a given search request.
*
* @since 6.8.0
*
* @param WP_REST_Request $request Full REST request.
* @return array {
* Associative array containing found IDs and total count for the matching search results.
*
* @type int[] $ids Found post archive IDs.
* @type string|int|WP_Error $total Numeric string containing the number of post-type archives found, or WP_Error object.
getdave marked this conversation as resolved.
Show resolved Hide resolved
* }
*/
public function search_items( WP_REST_Request $request ) {

$search_term = $request['search'];
$page = (int) $request['page'];
$per_page = (int) $request['per_page'];

$args = array(
'public' => true,
'has_archive' => true, // ensure only posts with archive are considered.
'show_in_rest' => true,
'_builtin' => false,
);

$post_types = get_post_types( $args );
$found_ids = array();

if ( ! empty( $post_types ) ) {
foreach ( $post_types as $post_type ) {
// Check if the search term matches the post type name.
if ( empty( $search_term ) || stripos( $post_type, $search_term ) !== false ) {
$found_ids[] = $post_type;
}
}
}

return array(
self::RESULT_IDS => array_slice( $found_ids, ( $page - 1 ) * $per_page, $per_page ),
self::RESULT_TOTAL => count( $found_ids ),
);
}

/**
* Prepares the search result for a given post archive ID.
*
* @since 6.8.0
*
* @param int $id Term ID.
* @param array $fields Fields to include for the post archive.
* @return array {
* Associative array containing fields for the post-archive based on the `$fields` parameter.
*
* @type string $id Optional. Post Archive Slug.
getdave marked this conversation as resolved.
Show resolved Hide resolved
* @type string $title Optional. Post Archive name.
* @type string $url Optional. Post Archive permalink URL.
* }
*/
public function prepare_item( $id, array $fields ) {

$post_type = get_post_type_object( $id );

$data = array();

if ( in_array( WP_REST_Search_Controller::PROP_ID, $fields, true ) ) {
$data[ WP_REST_Search_Controller::PROP_ID ] = $id;
}
if ( in_array( WP_REST_Search_Controller::PROP_TITLE, $fields, true ) ) {
$data[ WP_REST_Search_Controller::PROP_TITLE ] = $post_type->labels->archives;
}
if ( in_array( WP_REST_Search_Controller::PROP_URL, $fields, true ) ) {
$data[ WP_REST_Search_Controller::PROP_URL ] = get_post_type_archive_link( $id );
}

if ( in_array( WP_REST_Search_Controller::PROP_TYPE, $fields, true ) ) {
$data[ WP_REST_Search_Controller::PROP_TYPE ] = sprintf( '%s-%s', $post_type->name, __( 'archive' ) );
}

return $data;
}

/**
* Prepares links for the search result of a given ID.
*
* @since 6.8.0
*
* @param int $id Item ID.
* @return array[] Array of link arrays for the given item.
*/
public function prepare_item_links( $id ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
return array();
}
}
3 changes: 3 additions & 0 deletions lib/experimental/rest-api.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ function gutenberg_register_block_editor_settings() {
add_action( 'rest_api_init', 'gutenberg_register_block_editor_settings' );



Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nitpick: Are these empty lines needed for some reason?



/**
* Shim for get_sample_permalink() to add support for auto-draft status.
*
Expand Down
1 change: 1 addition & 0 deletions lib/load.php
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ function gutenberg_is_experiment_enabled( $name ) {
// WordPress 6.8 compat.
require __DIR__ . '/compat/wordpress-6.8/block-comments.php';
require __DIR__ . '/compat/wordpress-6.8/class-gutenberg-rest-comment-controller-6-8.php';
require __DIR__ . '/compat/wordpress-6.8/class-gutenberg-rest-post-archive-search-handler.php';

// Plugin specific code.
require_once __DIR__ . '/class-wp-rest-global-styles-controller-gutenberg.php';
Expand Down
10 changes: 10 additions & 0 deletions lib/rest-api.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,13 @@ function gutenberg_register_edit_site_export_controller_endpoints() {
$edit_site_export_controller->register_routes();
}
add_action( 'rest_api_init', 'gutenberg_register_edit_site_export_controller_endpoints' );


/**
* Registers REST search handler for Post Type Archives.
*/
function gutenberg_register_post_archive_rest_search_handler( $handlers ) {
$handlers[] = new Gutenberg_REST_Post_Archive_Search_Handler();
return $handlers;
}
add_filter( 'wp_rest_search_handlers', 'gutenberg_register_post_archive_rest_search_handler' );
23 changes: 13 additions & 10 deletions packages/block-editor/src/components/link-control/search-item.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
file,
home,
verse,
customPostType,
} from '@wordpress/icons';
import { __unstableStripHTML as stripHTML } from '@wordpress/dom';
import { safeDecodeURI, filterURLForDisplay, getPath } from '@wordpress/url';
Expand Down Expand Up @@ -41,18 +42,16 @@ function SearchItemIcon( { isURL, suggestion } ) {
icon = verse;
}
}
} else {
icon = customPostType;
}

if ( icon ) {
return (
<Icon
className="block-editor-link-control__search-item-icon"
icon={ icon }
/>
);
}

return null;
return (
<Icon
className="block-editor-link-control__search-item-icon"
icon={ icon }
/>
);
}

/**
Expand Down Expand Up @@ -155,6 +154,10 @@ function getVisualTypeName( suggestion ) {
return 'blog home';
}

if ( suggestion.kind === 'post-type-archive' ) {
return 'archive';
}

// Rename 'post_tag' to 'tag'. Ideally, the API would return the localised CPT or taxonomy label.
return suggestion.type === 'post_tag' ? 'tag' : suggestion.type;
}
Expand Down
22 changes: 22 additions & 0 deletions packages/block-library/src/navigation-link/index.php
Original file line number Diff line number Diff line change
Expand Up @@ -371,6 +371,7 @@ function block_core_navigation_link_filter_variations( $variations, $block_type
* @return array
*/
function block_core_navigation_link_build_variations() {

$post_types = get_post_types( array( 'show_in_nav_menus' => true ), 'objects' );
$taxonomies = get_taxonomies( array( 'show_in_nav_menus' => true ), 'objects' );

Expand All @@ -392,6 +393,27 @@ function block_core_navigation_link_build_variations() {
$variations[] = $variation;
}
}

// If any of the post types have `has_archive` set to true then add a post-type-archive variation.
$has_archive = array_filter(
$post_types,
function ( $post_type ) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This closure can be declared as static (might improve performance).

Suggested change
function ( $post_type ) {
static function ( $post_type ) {

return $post_type->has_archive;
}
);

if ( $has_archive ) {
$variation = array(
'name' => 'post-type-archive',
'title' => __( 'Post Type Archive Link' ),
'description' => __( 'A link to a post type archive' ),
'attributes' => array(
'type' => 'all',
'kind' => 'post-type-archive',
),
);
$variations[] = $variation;
}
}
if ( $taxonomies ) {
foreach ( $taxonomies as $taxonomy ) {
Expand Down
3 changes: 3 additions & 0 deletions packages/block-library/src/navigation-link/link-ui.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,9 @@ export function getSuggestionsQuery( type, kind ) {
if ( kind === 'taxonomy' ) {
return { type: 'term', subtype: type };
}
if ( kind === 'post-type-archive' ) {
return { type: 'post-type-archive' };
}
if ( kind === 'post-type' ) {
return { type: 'post', subtype: type };
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export type SearchOptions = {
/**
* Filters by search type.
*/
type?: 'attachment' | 'post' | 'term' | 'post-format';
type?: 'attachment' | 'post' | 'term' | 'post-format' | 'post-type-archive';
/**
* Slug of the post-type or taxonomy.
*/
Expand Down Expand Up @@ -240,6 +240,33 @@ export default async function fetchLinkSuggestions(
);
}

if ( ! type || type === 'post-type-archive' ) {
queries.push(
apiFetch< SearchAPIResult[] >( {
path: addQueryArgs( '/wp/v2/search', {
search,
page,
per_page: perPage,
type: 'post-type-archive',
} ),
} )
.then( ( results ) => {
return results.map( ( result ) => {
return {
id: result.id,
url: result.url,
title:
decodeEntities( result.title || '' ) ||
__( '(no title)' ),
type: `${ result.type }`,
kind: 'post-type-archive',
};
} );
} )
.catch( () => [] ) // Fail by returning no results.
);
}

const responses = await Promise.all( queries );

let results = responses.flat();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,16 @@ jest.mock( '@wordpress/api-fetch', () =>
'http://localhost:8888/wp-content/uploads/2022/03/test-pdf.pdf',
},
] );
case '/wp/v2/search?search=&per_page=20&type=post-type-archive':
return Promise.resolve( [
{
id: 'books',
title: 'All Books',
url: 'http://wordpress.local/books/',
type: 'books-archive',
kind: 'post-type-archive',
},
] );
default:
return Promise.resolve( [
{
Expand Down Expand Up @@ -187,7 +197,7 @@ describe( 'fetchLinkSuggestions', () => {
);
} );

it( 'returns suggestions from post, term, post-format and media', () => {
it( 'returns suggestions from post, term, post-format, media and post-type-archive', () => {
return fetchLinkSuggestions( '', {} ).then( ( suggestions ) =>
expect( suggestions ).toEqual( [
{
Expand Down Expand Up @@ -232,6 +242,13 @@ describe( 'fetchLinkSuggestions', () => {
type: 'attachment',
kind: 'media',
},
{
id: 'books',
title: 'All Books',
url: 'http://wordpress.local/books/',
type: 'books-archive',
kind: 'post-type-archive',
},
] )
);
} );
Expand Down
Loading