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 9 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
127 changes: 127 additions & 0 deletions lib/experimental/class-wp-rest-post-archive-search-handler.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
<?php
/**
* REST API: WP_REST_Post_Archive_Search_Handler class
*
* @package WordPress
* @subpackage REST_API
* @since 6.6.0
*/

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

Check failure on line 17 in lib/experimental/class-wp-rest-post-archive-search-handler.php

View workflow job for this annotation

GitHub Actions / PHP coding standards

The "WP_REST_Post_Archive_Search_Handler" class should be guarded against redeclaration.

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

/**
* Searches post-type archives for a given search request.
*
* @since 5.6.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.
* }
*/
public function search_items( WP_REST_Request $request ) {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Need to check possible $request params for the search handler endpoints and ensure we're handling those correctly.

For example, offset and pagination...etc.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Here are the Search endpoint docs.

We're handling pagination based on this example from post-formats.


$search_term = $request['search'];

$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, 'objects' );
$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->name, $search_term ) !== false ) {
$found_ids[] = $post_type->name;
}
}
}

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

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 5.6.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.
* @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 ] = $post_type->name;
}

return $data;
}

/**
* Prepares links for the search result of a given ID.
*
* @since 5.6.0
*
* @param int $id Item ID.
* @return array[] Array of link arrays for the given item.
*/
public function prepare_item_links( $id ) {

Check warning on line 120 in lib/experimental/class-wp-rest-post-archive-search-handler.php

View workflow job for this annotation

GitHub Actions / PHP coding standards

Unused function parameter $id.
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Is it worth linking to the collection for each post archive returned? I have no use case for this so might be unnecessary at this stage,


$links = array();

return $links;
}
}

Check failure on line 126 in lib/experimental/class-wp-rest-post-archive-search-handler.php

View workflow job for this annotation

GitHub Actions / PHP coding standards

Expected 1 blank line at end of file; 2 found

13 changes: 13 additions & 0 deletions lib/experimental/rest-api.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@
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 Expand Up @@ -92,3 +95,13 @@
return $permalink;
}
add_filter( 'get_sample_permalink', 'gutenberg_auto_draft_get_sample_permalink', 10, 5 );



function register_post_archive_rest_search_handler( $handlers ) {

Check failure on line 101 in lib/experimental/rest-api.php

View workflow job for this annotation

GitHub Actions / PHP coding standards

The "register_post_archive_rest_search_handler()" function should be guarded against redeclaration.
$handlers[] = new WP_REST_Post_Archive_Search_Handler();

Check failure on line 103 in lib/experimental/rest-api.php

View workflow job for this annotation

GitHub Actions / PHP coding standards

Functions must not contain multiple empty lines in a row; found 2 empty lines

return $handlers;
}
add_filter( 'wp_rest_search_handlers', 'register_post_archive_rest_search_handler' );

Check failure on line 107 in lib/experimental/rest-api.php

View workflow job for this annotation

GitHub Actions / PHP coding standards

Expected 1 newline at end of file; 0 found
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_once __DIR__ . '/experimental/class-wp-rest-post-archive-search-handler.php';
getdave marked this conversation as resolved.
Show resolved Hide resolved

// Plugin specific code.
require_once __DIR__ . '/class-wp-rest-global-styles-controller-gutenberg.php';
Expand Down
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
27 changes: 27 additions & 0 deletions packages/block-library/src/navigation-link/index.php
Original file line number Diff line number Diff line change
Expand Up @@ -371,9 +371,13 @@
* @return array
*/
function block_core_navigation_link_build_variations() {

Check failure on line 374 in packages/block-library/src/navigation-link/index.php

View workflow job for this annotation

GitHub Actions / PHP coding standards

Functions must not contain multiple empty lines in a row; found 2 empty lines

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

Check failure on line 378 in packages/block-library/src/navigation-link/index.php

View workflow job for this annotation

GitHub Actions / PHP coding standards

Functions must not contain multiple empty lines in a row; found 3 empty lines


/*
* Use two separate arrays as a way to order the variations in the UI.
* Known variations (like Post Link and Page Link) are added to the
Expand All @@ -392,6 +396,29 @@
$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 ) {

Check failure on line 403 in packages/block-library/src/navigation-link/index.php

View workflow job for this annotation

GitHub Actions / PHP coding standards

Expected 1 space after FUNCTION keyword; 0 found
return $post_type->has_archive;
}
);
if ( $has_archive ) {
$variation = array(

Check warning on line 408 in packages/block-library/src/navigation-link/index.php

View workflow job for this annotation

GitHub Actions / PHP coding standards

Equals sign not aligned with surrounding assignments; expected 4 spaces but found 1 space
'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;
}

Check failure on line 418 in packages/block-library/src/navigation-link/index.php

View workflow job for this annotation

GitHub Actions / PHP coding standards

Blank line found after control structure

Check failure on line 419 in packages/block-library/src/navigation-link/index.php

View workflow job for this annotation

GitHub Actions / PHP coding standards

Functions must not contain multiple empty lines in a row; found 3 empty lines


}
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 } archive`,
kind: 'post-type-archive',
};
} );
} )
.catch( () => [] ) // Fail by returning no results.
);
}

const responses = await Promise.all( queries );

let results = responses.flat();
Expand Down
Loading