Skip to content

Commit

Permalink
Add title type (#397)
Browse files Browse the repository at this point in the history
* Add title type

Signed-off-by: brookewp <[email protected]>

* Fix loophole that allows invalid types in Validator

* Update inc/Sanitization/Sanitizer.php

Co-authored-by: Chris Zarate <[email protected]>

---------

Signed-off-by: brookewp <[email protected]>
Co-authored-by: chriszarate <[email protected]>
  • Loading branch information
brookewp and chriszarate authored Mar 6, 2025
1 parent 17e9130 commit 265b385
Show file tree
Hide file tree
Showing 12 changed files with 57 additions and 11 deletions.
1 change: 1 addition & 0 deletions docs/extending/query-output_schema.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ Unless your API returns a single value, `type` will be constructed of an associa
- `null`
- `number`
- `string`
- `title`
- `url`
- `uuid`

Expand Down
4 changes: 2 additions & 2 deletions example/rest-api/art-institute/art-institute.php
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ function register_aic_block(): void {
],
'title' => [
'name' => 'Title',
'type' => 'string',
'type' => 'title',
'path' => '$.title',
],
'image_id' => [
Expand Down Expand Up @@ -136,7 +136,7 @@ function register_aic_block(): void {
],
'title' => [
'name' => 'Title',
'type' => 'string',
'type' => 'title',
'path' => '$.title',
],
'image_url' => [
Expand Down
6 changes: 5 additions & 1 deletion inc/Editor/BlockPatterns/BlockPatterns.php
Original file line number Diff line number Diff line change
Expand Up @@ -112,12 +112,16 @@ public static function register_default_block_pattern( string $block_name, strin
$bindings['heading']['content'] = [ $field, $name ];
break;
}

$bindings['paragraphs'][] = [
'content' => [ $field, $name ],
];
break;

case 'title':
$bindings['heading']['content'] = [ $field, $name ];
break;

case 'image_alt':
$bindings['images']['alt'][] = [ $field, $name ];
break;
Expand Down
4 changes: 2 additions & 2 deletions inc/Integrations/SalesforceD2C/SalesforceD2CIntegration.php
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ private static function get_queries( SalesforceD2CDataSource $data_source ): arr
'name' => [
'name' => 'Name',
'path' => '$.name',
'type' => 'string',
'type' => 'title',
],
'sku' => [
'name' => 'SKU',
Expand Down Expand Up @@ -134,7 +134,7 @@ private static function get_queries( SalesforceD2CDataSource $data_source ): arr
'name' => [
'name' => 'Name',
'path' => '$.name',
'type' => 'string',
'type' => 'title',
],
'image_url' => [
'name' => 'Image URL',
Expand Down
4 changes: 2 additions & 2 deletions inc/Integrations/Shopify/ShopifyIntegration.php
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ public static function get_queries( ShopifyDataSource $data_source ): array {
'title' => [
'name' => 'Title',
'path' => '$.data.product.title',
'type' => 'string',
'type' => 'title',
],
'variant_id' => [
'name' => 'Variant ID',
Expand Down Expand Up @@ -109,7 +109,7 @@ public static function get_queries( ShopifyDataSource $data_source ): array {
'title' => [
'name' => 'Product title',
'path' => '$.node.title',
'type' => 'string',
'type' => 'title',
],
],
],
Expand Down
1 change: 1 addition & 0 deletions inc/Sanitization/Sanitizer.php
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ public static function sanitize_primitive_type( string $type_name, mixed $value
return null;

case 'string':
case 'title':
return sanitize_text_field( strval( $value ) );

case 'button_text':
Expand Down
1 change: 1 addition & 0 deletions inc/Validation/ConfigSchemas.php
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,7 @@ private static function generate_http_query_config_schema(): array {
'image_alt',
'image_url',
'markdown',
'title',
// 'json_path' is omitted since it likely has no user utility.
'url',
'uuid',
Expand Down
4 changes: 4 additions & 0 deletions inc/Validation/Types.php
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,10 @@ public static function url(): array {
return self::generate_primitive_type( 'url' );
}

public static function title(): array {
return self::generate_primitive_type( 'title' );
}

public static function uuid(): array {
return self::generate_primitive_type( 'uuid' );
}
Expand Down
13 changes: 10 additions & 3 deletions inc/Validation/Validator.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,16 @@ private function check_type( array $type, mixed $value = null ): bool|WP_Error {

if ( Types::is_primitive( $type ) ) {
$type_name = Types::get_type_name( $type );
if ( $this->check_primitive_type( $type_name, $value ) ) {
$result = $this->check_primitive_type( $type_name, $value );

if ( true === $result ) {
return true;
}

if ( is_wp_error( $result ) ) {
return $result;
}

return $this->create_error( sprintf( 'Value must be a %s', $type_name ), $value );
}

Expand Down Expand Up @@ -232,7 +238,7 @@ private function check_non_primitive_type( array $type, mixed $value ): bool|WP_
}
}

private function check_primitive_type( string $type_name, mixed $value ): bool {
private function check_primitive_type( string $type_name, mixed $value ): bool|WP_Error {
switch ( $type_name ) {
case 'any':
return true;
Expand All @@ -256,6 +262,7 @@ private function check_primitive_type( string $type_name, mixed $value ): bool {
case 'html':
case 'image_alt':
case 'markdown':
case 'title':
return is_string( $value );

case 'button_text':
Expand All @@ -274,7 +281,7 @@ private function check_primitive_type( string $type_name, mixed $value ): bool {
return wp_is_uuid( $value );

default:
return false;
return $this->create_error( 'Unknown type', $type_name );
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ export function ItemList( props: ItemListProps ) {

// Find title field from availableBindings by checking type
const titleField = Object.entries( availableBindings ).find(
( [ _, binding ] ) => binding.type === 'string' && binding.name.toLowerCase() === 'title'
( [ _, binding ] ) => binding.type === 'title'
)?.[ 0 ];

// Find media field from availableBindings by checking type
Expand Down
1 change: 1 addition & 0 deletions src/blocks/remote-data-container/config/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,5 @@ export const TEXT_FIELD_TYPES = [
'markdown',
'number',
'string',
'title',
];
27 changes: 27 additions & 0 deletions tests/inc/Validation/ValidatorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ public function testValidPrimitiveTypes(): void {
'image_url' => Types::image_url(),
'json_path' => Types::json_path(),
'markdown' => Types::markdown(),
'title' => Types::title(),
'url' => Types::url(),
'uuid' => Types::uuid(),
] );
Expand All @@ -52,6 +53,7 @@ public function testValidPrimitiveTypes(): void {
'image_url' => 'https://example.com/image.jpg',
'json_path' => '$.foo.bar',
'markdown' => '# Hello, world!',
'title' => 'A Title',
'url' => 'https://example.com/foo',
'uuid' => '123e4567-e89b-12d3-a456-426614174000',
] ) );
Expand Down Expand Up @@ -352,6 +354,31 @@ public function testInvalidIds( mixed $invalid_value ): void {
$this->assertStringStartsWith( 'Value must be a id:', $result->get_error_message() );
}

public function testInvalidNonPrimitiveType(): void {
$schema = [ '@type' => 'invented' ];

$validator = new Validator( $schema );

$result = $validator->validate( 'hello, world!' );

$this->assertInstanceOf( WP_Error::class, $result );
$this->assertSame( 'Unknown type: invented', $result->get_error_message() );
}

public function testInvalidPrimitiveType(): void {
$schema = [
'@primitive' => true,
'@type' => 'invented',
];

$validator = new Validator( $schema );

$result = $validator->validate( 'hello, world!' );

$this->assertInstanceOf( WP_Error::class, $result );
$this->assertSame( 'Unknown type: invented', $result->get_error_message() );
}

public function testCallable(): void {
$schema = Types::callable();

Expand Down

0 comments on commit 265b385

Please sign in to comment.