Make WordPress Core

Changeset 55132


Ignore:
Timestamp:
01/24/2023 04:52:42 PM (13 months ago)
Author:
hellofromTonya
Message:

Editor: Adds pagination and ordering support to WP_REST_Pattern_Directory_Controller.

Adds pagination and ordering support to WP_REST_Pattern_Directory_Controller by allow listing 'per_page', 'page', 'offset', 'order', and 'orderby' query parameters. This change enables pagination and ordering features in the pattern directory explorer by using the same sort as wordpress.org/patterns.

Reference:

Follow-up to [55098], [51206], [51021].

Props ntsekouras, ryelle, arrasel403, hellofromTonya, ironprogrammer, mukesh27, robinwpdeveloper.
Fixes #57501.

Location:
trunk
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-includes/rest-api/endpoints/class-wp-rest-pattern-directory-controller.php

    r53665 r55132  
    8282     * @since 5.8.0
    8383     * @since 6.0.0 Added 'slug' to request.
     84     * @since 6.2.0 Added 'per_page', 'page', 'offset', 'order', and 'orderby' to request.
    8485     *
    8586     * @param WP_REST_Request $request Full details about the request.
     
    9495        require ABSPATH . WPINC . '/version.php';
    9596
    96         $query_args = array(
    97             'locale'     => get_user_locale(),
    98             'wp-version' => $wp_version,
    99         );
    100 
    101         $category_id = $request['category'];
    102         $keyword_id  = $request['keyword'];
    103         $search_term = $request['search'];
    104         $slug        = $request['slug'];
    105 
    106         if ( $category_id ) {
    107             $query_args['pattern-categories'] = $category_id;
    108         }
    109 
    110         if ( $keyword_id ) {
    111             $query_args['pattern-keywords'] = $keyword_id;
    112         }
    113 
    114         if ( $search_term ) {
    115             $query_args['search'] = $search_term;
    116         }
    117 
    118         if ( $slug ) {
    119             $query_args['slug'] = $slug;
    120         }
     97        $valid_query_args = array(
     98            'offset'   => true,
     99            'order'    => true,
     100            'orderby'  => true,
     101            'page'     => true,
     102            'per_page' => true,
     103            'search'   => true,
     104            'slug'     => true,
     105        );
     106        $query_args = array_intersect_key( $request->get_params(), $valid_query_args );
     107
     108        $query_args['locale']             = get_user_locale();
     109        $query_args['wp-version']         = $wp_version; // phpcs:ignore VariableAnalysis.CodeAnalysis.VariableAnalysis.UndefinedVariable -- it's defined in `version.php` above.
     110        $query_args['pattern-categories'] = isset( $request['category'] ) ? $request['category'] : false;
     111        $query_args['pattern-keywords']   = isset( $request['keyword'] ) ? $request['keyword'] : false;
     112
     113        $query_args = array_filter( $query_args );
    121114
    122115        $transient_key = $this->get_transient_key( $query_args );
     
    304297     *
    305298     * @since 5.8.0
     299     * @since 6.2.0 Added 'per_page', 'page', 'offset', 'order', and 'orderby' to request.
    306300     *
    307301     * @return array Collection parameters.
     
    310304        $query_params = parent::get_collection_params();
    311305
    312         // Pagination is not supported.
    313         unset( $query_params['page'] );
    314         unset( $query_params['per_page'] );
    315 
     306        $query_params['per_page']['default'] = 100;
    316307        $query_params['search']['minLength'] = 1;
    317308        $query_params['context']['default']  = 'view';
     
    332323            'description' => __( 'Limit results to those matching a pattern (slug).' ),
    333324            'type'        => 'array',
     325        );
     326
     327        $query_params['offset'] = array(
     328            'description' => __( 'Offset the result set by a specific number of items.' ),
     329            'type'        => 'integer',
     330        );
     331
     332        $query_params['order'] = array(
     333            'description' => __( 'Order sort attribute ascending or descending.' ),
     334            'type'        => 'string',
     335            'default'     => 'desc',
     336            'enum'        => array( 'asc', 'desc' ),
     337        );
     338
     339        $query_params['orderby'] = array(
     340            'description' => __( 'Sort collection by post attribute.' ),
     341            'type'        => 'string',
     342            'default'     => 'date',
     343            'enum'        => array(
     344                'author',
     345                'date',
     346                'id',
     347                'include',
     348                'modified',
     349                'parent',
     350                'relevance',
     351                'slug',
     352                'include_slugs',
     353                'title',
     354                'favorite_count',
     355            ),
    334356        );
    335357
  • trunk/tests/phpunit/tests/rest-api/rest-pattern-directory-controller.php

    r55029 r55132  
    3232
    3333    /**
     34     * List of URLs captured.
     35     *
     36     * @since 6.2.0
     37     *
     38     * @var string[]
     39     */
     40    protected static $http_request_urls;
     41
     42    /**
    3443     * Set up class test fixtures.
    3544     *
     
    4554        );
    4655
     56        self::$http_request_urls = array();
     57
    4758        static::$controller = new WP_REST_Pattern_Directory_Controller();
     59    }
     60
     61    /**
     62     * Tear down after class.
     63     *
     64     * @since 6.2.0
     65     */
     66    public static function wpTearDownAfterClass() {
     67        self::delete_user( self::$contributor_id );
     68    }
     69
     70    /**
     71     * Clear the captured request URLs after each test.
     72     *
     73     * @since 6.2.0
     74     */
     75    public function tear_down() {
     76        self::$http_request_urls = array();
     77        parent::tear_down();
    4878    }
    4979
     
    309339
    310340        $this->assertSame( 'modified the cache', $patterns[0] );
     341    }
     342
     343    /**
     344     * Tests if the provided query args are passed through to the wp.org API.
     345     *
     346     * @since 6.2.0
     347     *
     348     * @ticket 57501
     349     *
     350     * @covers WP_REST_Pattern_Directory_Controller::get_items
     351     *
     352     * @dataProvider data_get_items_query_args
     353     *
     354     * @param string $param    Query parameter name (ex, page).
     355     * @param mixed  $value    Query value to test.
     356     * @param bool   $is_error Whether this value should error or not.
     357     * @param mixed  $expected Expected value (or expected error code).
     358     */
     359    public function test_get_items_query_args( $param, $value, $is_error, $expected ) {
     360        wp_set_current_user( self::$contributor_id );
     361        add_filter( 'pre_http_request', array( $this, 'mock_request_to_apiwporg_url' ), 10, 3 );
     362
     363        $request = new WP_REST_Request( 'GET', '/wp/v2/pattern-directory/patterns' );
     364        if ( $value ) {
     365            $request->set_query_params( array( $param => $value ) );
     366        }
     367
     368        $response = rest_do_request( $request );
     369        $data     = $response->get_data();
     370        if ( $is_error ) {
     371            $this->assertSame( $expected, $data['code'], 'Response error code does not match' );
     372            $this->assertStringContainsString( $param, $data['message'], 'Response error message does not match' );
     373        } else {
     374            $this->assertCount( 1, self::$http_request_urls, 'The number of HTTP Request URLs is not 1' );
     375            $this->assertStringContainsString( $param . '=' . $expected, self::$http_request_urls[0], 'The param and/or value do not match' );
     376        }
     377    }
     378
     379    /**
     380     * Data provider.
     381     *
     382     * return array[]
     383     */
     384    public function data_get_items_query_args() {
     385        return array(
     386            'per_page default'   => array(
     387                'param'    => 'per_page',
     388                'value'    => false,
     389                'is_error' => false,
     390                'expected' => 100,
     391            ),
     392            'per_page custom-1'  => array(
     393                'param'    => 'per_page',
     394                'value'    => 5,
     395                'is_error' => false,
     396                'expected' => 5,
     397            ),
     398            'per_page custom-2'  => array(
     399                'param'    => 'per_page',
     400                'value'    => 50,
     401                'is_error' => false,
     402                'expected' => 50,
     403            ),
     404            'per_page invalid-1' => array(
     405                'param'    => 'per_page',
     406                'value'    => 200,
     407                'is_error' => true,
     408                'expected' => 'rest_invalid_param',
     409            ),
     410            'per_page invalid-2' => array(
     411                'param'    => 'per_page',
     412                'value'    => 'abc',
     413                'is_error' => true,
     414                'expected' => 'rest_invalid_param',
     415            ),
     416
     417            'page default'       => array(
     418                'param'    => 'page',
     419                'value'    => false,
     420                'is_error' => false,
     421                'expected' => 1,
     422            ),
     423            'page custom'        => array(
     424                'param'    => 'page',
     425                'value'    => 5,
     426                'is_error' => false,
     427                'expected' => 5,
     428            ),
     429            'page invalid'       => array(
     430                'param'    => 'page',
     431                'value'    => 'abc',
     432                'is_error' => true,
     433                'expected' => 'rest_invalid_param',
     434            ),
     435
     436            'offset custom'      => array(
     437                'param'    => 'offset',
     438                'value'    => 5,
     439                'is_error' => false,
     440                'expected' => 5,
     441            ),
     442            'offset invalid-1'   => array(
     443                'param'    => 'offset',
     444                'value'    => 'abc',
     445                'is_error' => true,
     446                'expected' => 'rest_invalid_param',
     447            ),
     448
     449            'order default'      => array(
     450                'param'    => 'order',
     451                'value'    => false,
     452                'is_error' => false,
     453                'expected' => 'desc',
     454            ),
     455            'order custom'       => array(
     456                'param'    => 'order',
     457                'value'    => 'asc',
     458                'is_error' => false,
     459                'expected' => 'asc',
     460            ),
     461            'order invalid-1'    => array(
     462                'param'    => 'order',
     463                'value'    => 10,
     464                'is_error' => true,
     465                'expected' => 'rest_invalid_param',
     466            ),
     467            'order invalid-2'    => array(
     468                'param'    => 'order',
     469                'value'    => 'fake',
     470                'is_error' => true,
     471                'expected' => 'rest_invalid_param',
     472            ),
     473
     474            'orderby default'    => array(
     475                'param'    => 'orderby',
     476                'value'    => false,
     477                'is_error' => false,
     478                'expected' => 'date',
     479            ),
     480            'orderby custom-1'   => array(
     481                'param'    => 'orderby',
     482                'value'    => 'title',
     483                'is_error' => false,
     484                'expected' => 'title',
     485            ),
     486            'orderby custom-2'   => array(
     487                'param'    => 'orderby',
     488                'value'    => 'date',
     489                'is_error' => false,
     490                'expected' => 'date',
     491            ),
     492            'orderby custom-3'   => array(
     493                'param'    => 'orderby',
     494                'value'    => 'favorite_count',
     495                'is_error' => false,
     496                'expected' => 'favorite_count',
     497            ),
     498            'orderby invalid-1'  => array(
     499                'param'    => 'orderby',
     500                'value'    => 10,
     501                'is_error' => true,
     502                'expected' => 'rest_invalid_param',
     503            ),
     504            'orderby invalid-2'  => array(
     505                'param'    => 'orderby',
     506                'value'    => 'fake',
     507                'is_error' => true,
     508                'expected' => 'rest_invalid_param',
     509            ),
     510        );
    311511    }
    312512
     
    574774        );
    575775    }
     776
     777    /**
     778     * Mock the request to wp.org URL to capture the URLs.
     779     *
     780     * @since 6.2.0
     781     *
     782     * @return array faux/mocked response.
     783     */
     784    public function mock_request_to_apiwporg_url( $response, $args, $url ) {
     785        if ( 'api.wordpress.org' !== wp_parse_url( $url, PHP_URL_HOST ) ) {
     786            return $response;
     787        }
     788
     789        self::$http_request_urls[] = $url;
     790
     791        // Return a response to prevent external API request.
     792        $response = array(
     793            'headers'  => array(),
     794            'response' => array(
     795                'code'    => 200,
     796                'message' => 'OK',
     797            ),
     798            'body'     => '[]',
     799            'cookies'  => array(),
     800            'filename' => null,
     801        );
     802
     803        return $response;
     804    }
    576805}
  • trunk/tests/qunit/fixtures/wp-api-generated.js

    r54356 r55132  
    1047610476                            "required": false
    1047710477                        },
     10478                        "page": {
     10479                            "description": "Current page of the collection.",
     10480                            "type": "integer",
     10481                            "default": 1,
     10482                            "minimum": 1,
     10483                            "required": false
     10484                        },
     10485                        "per_page": {
     10486                            "description": "Maximum number of items to be returned in result set.",
     10487                            "type": "integer",
     10488                            "default": 100,
     10489                            "minimum": 1,
     10490                            "maximum": 100,
     10491                            "required": false
     10492                        },
    1047810493                        "search": {
    1047910494                            "description": "Limit results to those matching a string.",
     
    1049710512                            "description": "Limit results to those matching a pattern (slug).",
    1049810513                            "type": "array",
     10514                            "required": false
     10515                        },
     10516                        "offset": {
     10517                            "description": "Offset the result set by a specific number of items.",
     10518                            "type": "integer",
     10519                            "required": false
     10520                        },
     10521                        "order": {
     10522                            "description": "Order sort attribute ascending or descending.",
     10523                            "type": "string",
     10524                            "default": "desc",
     10525                            "enum": [
     10526                                "asc",
     10527                                "desc"
     10528                            ],
     10529                            "required": false
     10530                        },
     10531                        "orderby": {
     10532                            "description": "Sort collection by post attribute.",
     10533                            "type": "string",
     10534                            "default": "date",
     10535                            "enum": [
     10536                                "author",
     10537                                "date",
     10538                                "id",
     10539                                "include",
     10540                                "modified",
     10541                                "parent",
     10542                                "relevance",
     10543                                "slug",
     10544                                "include_slugs",
     10545                                "title",
     10546                                "favorite_count"
     10547                            ],
    1049910548                            "required": false
    1050010549                        }
Note: See TracChangeset for help on using the changeset viewer.