Skip to content

Commit 208f44d

Browse files
matiasbenedettomikachancreativecoder
authored
Font Library: Improve font collection rest controller (#58222)
* make WP_Font_Collection object properties public * remove class method no longer used * simplify the acces to the font collection properties * add schema, args, fields and pagination to font collections rest controller * add one test case for params * request a subset of font collection fields * lint * remove not needed default change * update version since * use placeholder for translation * update comment Co-authored-by: Sarah Norris <[email protected]> * update translation domain Co-authored-by: Grant Kinney <[email protected]> * update wording * set context to edit only * use 'view', 'edit' and 'embed' on the context of all the schema properties * prepare_item_for_response * default context param * args for item endpoint * format php --------- Co-authored-by: Sarah Norris <[email protected]> Co-authored-by: Grant Kinney <[email protected]>
1 parent 9704888 commit 208f44d

File tree

7 files changed

+255
-124
lines changed

7 files changed

+255
-124
lines changed

lib/experimental/fonts/font-library/class-wp-font-collection.php

+16-28
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ class WP_Font_Collection {
2727
*
2828
* @var string
2929
*/
30-
private $slug;
30+
public $slug;
3131

3232
/**
3333
* The name of the font collection.
@@ -36,7 +36,7 @@ class WP_Font_Collection {
3636
*
3737
* @var string
3838
*/
39-
private $name;
39+
public $name;
4040

4141
/**
4242
* Description of the font collection.
@@ -45,7 +45,7 @@ class WP_Font_Collection {
4545
*
4646
* @var string
4747
*/
48-
private $description;
48+
public $description;
4949

5050
/**
5151
* Source of the font collection.
@@ -54,7 +54,7 @@ class WP_Font_Collection {
5454
*
5555
* @var string
5656
*/
57-
private $src;
57+
public $src;
5858

5959
/**
6060
* Array of font families in the collection.
@@ -63,7 +63,7 @@ class WP_Font_Collection {
6363
*
6464
* @var array
6565
*/
66-
private $font_families;
66+
public $font_families;
6767

6868
/**
6969
* Categories associated with the font collection.
@@ -72,7 +72,7 @@ class WP_Font_Collection {
7272
*
7373
* @var array
7474
*/
75-
private $categories;
75+
public $categories;
7676

7777

7878
/**
@@ -138,34 +138,22 @@ public static function is_config_valid( $config ) {
138138
( empty( $config['src'] ) && empty( $config['font_families'] ) ) ||
139139
( ! empty( $config['src'] ) && ! empty( $config['font_families'] ) )
140140
) {
141-
_doing_it_wrong( __METHOD__, __( 'Font Collection config "src" option OR "font_families" option are required.', 'gutenberg' ), '6.5.0' );
141+
_doing_it_wrong(
142+
__METHOD__,
143+
sprintf(
144+
/* translators: %1$s: src, %2$s: font_families */
145+
__( 'Font Collection config "%1$s" option OR "%2$s" option is required.', 'gutenberg' ),
146+
'src',
147+
'font_families'
148+
),
149+
'6.5.0'
150+
);
142151
return false;
143152
}
144153

145154
return true;
146155
}
147156

148-
/**
149-
* Gets the font collection config.
150-
*
151-
* @since 6.5.0
152-
*
153-
* @return array {
154-
* An array of font collection config.
155-
*
156-
* @type string $slug The font collection's unique slug.
157-
* @type string $name The font collection's name.
158-
* @type string $description The font collection's description.
159-
* }
160-
*/
161-
public function get_config() {
162-
return array(
163-
'slug' => $this->slug,
164-
'name' => $this->name,
165-
'description' => $this->description,
166-
);
167-
}
168-
169157
/**
170158
* Gets the font collection content.
171159
*

lib/experimental/fonts/font-library/class-wp-font-library.php

+2-2
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ public static function register_font_collection( $config ) {
6969

7070
$new_collection = new WP_Font_Collection( $config );
7171

72-
if ( self::is_collection_registered( $new_collection->get_config()['slug'] ) ) {
72+
if ( self::is_collection_registered( $new_collection->slug ) ) {
7373
$error_message = sprintf(
7474
/* translators: %s: Font collection slug. */
7575
__( 'Font collection with slug: "%s" is already registered.', 'gutenberg' ),
@@ -82,7 +82,7 @@ public static function register_font_collection( $config ) {
8282
);
8383
return new WP_Error( 'font_collection_registration_error', $error_message );
8484
}
85-
self::$collections[ $new_collection->get_config()['slug'] ] = $new_collection;
85+
self::$collections[ $new_collection->slug ] = $new_collection;
8686
return $new_collection;
8787
}
8888

lib/experimental/fonts/font-library/class-wp-rest-font-collections-controller.php

+221-13
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,10 @@ public function register_routes() {
4444
'methods' => WP_REST_Server::READABLE,
4545
'callback' => array( $this, 'get_items' ),
4646
'permission_callback' => array( $this, 'get_items_permissions_check' ),
47+
'args' => $this->get_collection_params(),
48+
4749
),
50+
'schema' => array( $this, 'get_public_item_schema' ),
4851
)
4952
);
5053

@@ -56,7 +59,11 @@ public function register_routes() {
5659
'methods' => WP_REST_Server::READABLE,
5760
'callback' => array( $this, 'get_item' ),
5861
'permission_callback' => array( $this, 'get_items_permissions_check' ),
62+
'args' => array(
63+
'context' => $this->get_context_param( array( 'default' => 'view' ) ),
64+
),
5965
),
66+
'schema' => array( $this, 'get_public_item_schema' ),
6067
)
6168
);
6269
}
@@ -68,13 +75,61 @@ public function register_routes() {
6875
*
6976
* @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure.
7077
*/
71-
public function get_items( $request ) { // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
72-
$collections = array();
73-
foreach ( WP_Font_Library::get_font_collections() as $collection ) {
74-
$collections[] = $collection->get_config();
78+
public function get_items( $request ) {
79+
$collections_all = WP_Font_Library::get_font_collections();
80+
81+
$page = $request['page'];
82+
$per_page = $request['per_page'];
83+
$total_items = count( $collections_all );
84+
$max_pages = ceil( $total_items / $per_page );
85+
86+
if ( $page > $max_pages && $total_items > 0 ) {
87+
return new WP_Error(
88+
'rest_post_invalid_page_number',
89+
__( 'The page number requested is larger than the number of pages available.', 'default' ),
90+
array( 'status' => 400 )
91+
);
92+
}
93+
94+
$collections_page = array_slice( $collections_all, ( $page - 1 ) * $per_page, $per_page );
95+
96+
$items = array();
97+
foreach ( $collections_page as $collection ) {
98+
$item = $this->prepare_item_for_response( $collection, $request );
99+
if ( is_wp_error( $item ) ) {
100+
return $item;
101+
}
102+
$item = $this->prepare_response_for_collection( $item );
103+
$items[] = $item;
104+
}
105+
106+
$response = rest_ensure_response( $items );
107+
108+
$response->header( 'X-WP-Total', (int) $total_items );
109+
$response->header( 'X-WP-TotalPages', (int) $max_pages );
110+
111+
$request_params = $request->get_query_params();
112+
$collection_url = rest_url( $this->namespace . '/' . $this->rest_base );
113+
$base = add_query_arg( urlencode_deep( $request_params ), $collection_url );
114+
115+
if ( $page > 1 ) {
116+
$prev_page = $page - 1;
117+
118+
if ( $prev_page > $max_pages ) {
119+
$prev_page = $max_pages;
120+
}
121+
122+
$prev_link = add_query_arg( 'page', $prev_page, $base );
123+
$response->link_header( 'prev', $prev_link );
124+
}
125+
if ( $max_pages > $page ) {
126+
$next_page = $page + 1;
127+
$next_link = add_query_arg( 'page', $next_page, $base );
128+
129+
$response->link_header( 'next', $next_link );
75130
}
76131

77-
return rest_ensure_response( $collections, 200 );
132+
return $response;
78133
}
79134

80135
/**
@@ -95,17 +150,170 @@ public function get_item( $request ) {
95150
return $collection;
96151
}
97152

98-
$config = $collection->get_config();
99-
$contents = $collection->get_content();
153+
$item = $this->prepare_item_for_response( $collection, $request );
100154

101-
// If there was an error getting the collection data, return the error.
102-
if ( is_wp_error( $contents ) ) {
103-
$contents->add_data( array( 'status' => 500 ) );
104-
return $contents;
155+
if ( is_wp_error( $item ) ) {
156+
return $item;
105157
}
106158

107-
$collection_data = array_merge( $config, $contents );
108-
return rest_ensure_response( $collection_data );
159+
return $item;
160+
}
161+
162+
/*
163+
* Prepare a single collection output for response.
164+
*
165+
* @since 6.5.0
166+
*
167+
* @param WP_Font_Collection $collection Collection object.
168+
* @param WP_REST_Request $request Request object.
169+
* @return array|WP_Error
170+
*/
171+
public function prepare_item_for_response( $collection, $request ) {
172+
$fields = $this->get_fields_for_response( $request );
173+
$item = array();
174+
175+
$config_fields = array( 'slug', 'name', 'description' );
176+
foreach ( $config_fields as $field ) {
177+
if ( in_array( $field, $fields, true ) ) {
178+
$item[ $field ] = $collection->$field;
179+
}
180+
}
181+
182+
$data_fields = array( 'font_families', 'categories' );
183+
if ( in_array( 'font_families', $fields, true ) || in_array( 'categories', $fields, true ) ) {
184+
$content = $collection->get_content();
185+
186+
// If there was an error getting the collection data, return the error.
187+
if ( is_wp_error( $content ) ) {
188+
$content->add_data( array( 'status' => 500 ) );
189+
return $content;
190+
}
191+
192+
foreach ( $data_fields as $field ) {
193+
if ( in_array( $field, $fields, true ) ) {
194+
$item[ $field ] = $content[ $field ];
195+
}
196+
}
197+
}
198+
199+
$response = rest_ensure_response( $item );
200+
201+
if ( rest_is_field_included( '_links', $fields ) ) {
202+
$links = $this->prepare_links( $collection );
203+
$response->add_links( $links );
204+
}
205+
206+
$context = ! empty( $request['context'] ) ? $request['context'] : 'view';
207+
$response->data = $this->add_additional_fields_to_object( $response->data, $request );
208+
$response->data = $this->filter_response_by_context( $response->data, $context );
209+
210+
/**
211+
* Filters a font collection returned from the REST API.
212+
*
213+
* Allows modification of the font collection right before it is returned.
214+
*
215+
* @since 6.5.0
216+
*
217+
* @param WP_REST_Response $response The response object.
218+
* @param WP_Font_Collection $collection The Font Collection object.
219+
* @param WP_REST_Request $request Request used to generate the response.
220+
*/
221+
return apply_filters( 'rest_prepare_font_collection', $response, $collection, $request );
222+
}
223+
224+
/**
225+
* Retrieves the font collection's schema, conforming to JSON Schema.
226+
*
227+
* @since 6.5.0
228+
*
229+
* @return array Item schema data.
230+
*/
231+
public function get_item_schema() {
232+
if ( $this->schema ) {
233+
return $this->add_additional_fields_schema( $this->schema );
234+
}
235+
236+
$schema = array(
237+
'$schema' => 'http://json-schema.org/draft-04/schema#',
238+
'title' => 'font-collection',
239+
'type' => 'object',
240+
'properties' => array(
241+
'slug' => array(
242+
'description' => __( 'Unique identifier for the font collection.', 'gutenberg' ),
243+
'type' => 'string',
244+
'context' => array( 'view', 'edit', 'embed' ),
245+
'readonly' => true,
246+
),
247+
'name' => array(
248+
'description' => __( 'The name for the font collection.', 'gutenberg' ),
249+
'type' => 'string',
250+
'context' => array( 'view', 'edit', 'embed' ),
251+
),
252+
'description' => array(
253+
'description' => __( 'The description for the font collection.', 'gutenberg' ),
254+
'type' => 'string',
255+
'context' => array( 'view', 'edit', 'embed' ),
256+
),
257+
'font_families' => array(
258+
'description' => __( 'The font families for the font collection.', 'gutenberg' ),
259+
'type' => 'array',
260+
'context' => array( 'view', 'edit', 'embed' ),
261+
),
262+
'categories' => array(
263+
'description' => __( 'The categories for the font collection.', 'gutenberg' ),
264+
'type' => 'array',
265+
'context' => array( 'view', 'edit', 'embed' ),
266+
),
267+
),
268+
);
269+
270+
$this->schema = $schema;
271+
272+
return $this->add_additional_fields_schema( $this->schema );
273+
}
274+
275+
/**
276+
* Prepares links for the request.
277+
*
278+
* @since 6.5.0
279+
*
280+
* @param WP_Font_Collection $collection Font collection data
281+
* @return array Links for the given font collection.
282+
*/
283+
protected function prepare_links( $collection ) {
284+
$links = array(
285+
'self' => array(
286+
'href' => rest_url( sprintf( '%s/%s/%s', $this->namespace, $this->rest_base, $collection->slug ) ),
287+
),
288+
'collection' => array(
289+
'href' => rest_url( sprintf( '%s/%s', $this->namespace, $this->rest_base ) ),
290+
),
291+
);
292+
return $links;
293+
}
294+
295+
/**
296+
* Retrieves the search params for the font collections.
297+
*
298+
* @since 6.5.0
299+
*
300+
* @return array Collection parameters.
301+
*/
302+
public function get_collection_params() {
303+
$query_params = parent::get_collection_params();
304+
305+
$query_params['context'] = $this->get_context_param( array( 'default' => 'view' ) );
306+
307+
unset( $query_params['search'] );
308+
309+
/**
310+
* Filters REST API collection parameters for the font collections controller.
311+
*
312+
* @since 6.5.0
313+
*
314+
* @param array $query_params JSON Schema-formatted collection parameters.
315+
*/
316+
return apply_filters( 'rest_font_collections_collection_params', $query_params );
109317
}
110318

111319
/**

packages/edit-site/src/components/global-styles/font-library-modal/resolvers.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ export async function fetchUninstallFontFamily( fontFamilyId ) {
6363

6464
export async function fetchFontCollections() {
6565
const config = {
66-
path: FONT_COLLECTIONS_URL,
66+
path: `${ FONT_COLLECTIONS_URL }?_fields=slug,name,description`,
6767
method: 'GET',
6868
};
6969
return await apiFetch( config );

0 commit comments

Comments
 (0)