Skip to content

Commit

Permalink
Pattern CPT: Add validation for the pattern metadata (#41)
Browse files Browse the repository at this point in the history
* Add schema to the post meta, for validation

* Add validation to check the pattern title existence

* Check for a real `prepared_post` before using it

* Add test cases for title validation
  • Loading branch information
ryelle authored Feb 17, 2021
1 parent b6a4d64 commit 6fc5d1b
Show file tree
Hide file tree
Showing 3 changed files with 160 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,12 @@ function register_post_type_data() {
'default' => '',
'sanitize_callback' => 'sanitize_text_field',
'auth_callback' => __NAMESPACE__ . '\can_edit_this_pattern',
'show_in_rest' => true,
'show_in_rest' => array(
'schema' => array(
'maxLength' => 360,
'required' => true,
),
),
)
);

Expand All @@ -119,10 +124,15 @@ function register_post_type_data() {
'type' => 'number',
'description' => 'The width of the pattern in the block inserter.',
'single' => true,
'default' => 0,
'default' => 1200,
'sanitize_callback' => 'absint',
'auth_callback' => __NAMESPACE__ . '\can_edit_this_pattern',
'show_in_rest' => true,
'show_in_rest' => array(
'schema' => array(
'minimum' => 400,
'maximum' => 2000,
),
),
)
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,16 @@
use const WordPressdotorg\Pattern_Directory\Pattern_Post_Type\POST_TYPE;

add_filter( 'rest_pre_insert_' . POST_TYPE, __NAMESPACE__ . '\validate_content', 10, 2 );
add_filter( 'rest_pre_insert_' . POST_TYPE, __NAMESPACE__ . '\validate_title', 11, 2 );

/**
* Validate the pattern content.
*/
function validate_content( $prepared_post, $request ) {
if ( is_wp_error( $prepared_post ) ) {
return $prepared_post;
}

$content = $prepared_post->post_content;
if ( ! $content ) {
return new \WP_Error(
Expand Down Expand Up @@ -71,3 +76,39 @@ function validate_content( $prepared_post, $request ) {

return $prepared_post;
}

/**
* Validate the pattern title.
*/
function validate_title( $prepared_post, $request ) {
if ( is_wp_error( $prepared_post ) ) {
return $prepared_post;
}

$status = isset( $request['status'] ) ? $request['status'] : get_post_status( $prepared_post->ID );
// Bypass this validation for drafts.
if ( 'draft' === $status || 'auto-draft' === $status ) {
return $prepared_post;
}

// A title exists, but is empty -- invalid.
if ( isset( $request['title'] ) && empty( trim( $request['title'] ) ) ) {
return new \WP_Error(
'rest_pattern_empty_title',
__( 'A pattern title is required.', 'wporg-patterns' ),
array( 'status' => 400 )
);
}

// The existing pattern doesn't have a title, and none is set -- invalid.
$post_title = get_the_title( $prepared_post->ID );
if ( empty( $post_title ) && ! isset( $request['title'] ) ) {
return new \WP_Error(
'rest_pattern_empty_title',
__( 'A pattern title is required.', 'wporg-patterns' ),
array( 'status' => 400 )
);
}

return $prepared_post;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
<?php
/**
* Test Block Pattern validation.
*/

use const WordPressdotorg\Pattern_Directory\Pattern_Post_Type\POST_TYPE;

/**
* Test pattern validation.
*/
class Pattern_Title_Validation_Test extends WP_UnitTestCase {
protected static $pattern_id;
protected static $user;

/**
* Setup fixtures that are shared across all tests.
*/
public static function wpSetUpBeforeClass( $factory ) {
self::$pattern_id = $factory->post->create(
array( 'post_type' => POST_TYPE )
);
self::$user = $factory->user->create(
array(
'role' => 'administrator',
)
);
}

/**
* Helper function to handle REST requests to save the pattern.
*/
protected function save_block( $args = array() ) {
$request = new WP_REST_Request( 'POST', '/wp/v2/wporg-pattern/' . self::$pattern_id );
$request->set_header( 'content-type', 'application/json' );
$request_args = wp_parse_args( $args, array(
'status' => 'publish',
'content' => "<!-- wp:paragraph -->\n<p>This is a block.</p>\n<!-- /wp:paragraph -->",
) );
$request->set_body( json_encode( $request_args ) );
return rest_do_request( $request );
}

/**
* Test valid pattern title: Add a new title.
*/
public function test_valid_create_title() {
wp_set_current_user( self::$user );
$response = $this->save_block( array( 'title' => 'Default Paragraph' ) );
$this->assertFalse( $response->is_error() );
}

/**
* Test valid pattern title: empty title for a draft pattern.
*/
public function test_valid_empty_title_draft() {
wp_set_current_user( self::$user );
$response = $this->save_block( array(
'title' => '',
'status' => 'draft',
) );
$this->assertFalse( $response->is_error() );
}

/**
* Test valid pattern title: the existing pattern already has a title.
*/
public function test_valid_title_already_set() {
wp_set_current_user( self::$user );
wp_update_post( array(
'ID' => self::$pattern_id,
'post_title' => 'Test Title',
) );
$response = $this->save_block();
$this->assertFalse( $response->is_error() );
}

/**
* Test invalid pattern title: Published pattern, setting empty title.
*/
public function test_invalid_empty_new_title() {
wp_set_current_user( self::$user );
$response = $this->save_block( array(
'status' => 'publish',
'title' => '',
) );
$this->assertTrue( $response->is_error() );
$data = $response->get_data();
$this->assertSame( 'rest_pattern_empty_title', $data['code'] );
}

/**
* Test invalid pattern title: Published pattern, has empty title with no new title.
*/
public function test_invalid_empty_existing_title() {
wp_set_current_user( self::$user );
wp_update_post( array(
'ID' => self::$pattern_id,
'post_title' => '',
) );
$response = $this->save_block();
$this->assertTrue( $response->is_error() );
$data = $response->get_data();
$this->assertSame( 'rest_pattern_empty_title', $data['code'] );
}
}

0 comments on commit 6fc5d1b

Please sign in to comment.