Refactor notes controller and add ordering params (https://github.com/woocommerce/woocommerce-admin/pull/1878)

* Separate notes controller request args and add collection params

* Fix page param var

* Fix collection params sanitization

* Allow array of note types to be queried

* Add order and orderby collection params to notes controller

* Allow sorting by order and orderby params in notes data store

* Make sure notes are ordered by date and unread matches inbox note types

* Allow status or type params to use an array of items

* Add tests for notes ordering

* Remove unnecessary query arg assignment in the notes data store

* Update get_notes_count to use array for status and type
This commit is contained in:
Joshua T Flowers 2019-04-01 10:53:34 +08:00 committed by GitHub
parent 5324f223b6
commit 9c3faea12f
7 changed files with 149 additions and 57 deletions

View File

@ -113,6 +113,8 @@ export default compose(
page: 1,
per_page: QUERY_DEFAULTS.pageSize,
type: 'info,warning',
orderby: 'date',
order: 'desc',
};
const notes = getNotes( inboxQuery );

View File

@ -11,6 +11,9 @@ export function getUnreadNotes( select ) {
const notesQuery = {
page: 1,
per_page: 1,
type: 'info,warning',
orderby: 'date',
order: 'desc',
};
const latestNote = getNotes( notesQuery );

View File

@ -43,6 +43,7 @@ class WC_Admin_REST_Admin_Notes_Controller extends WC_REST_CRUD_Controller {
'methods' => WP_REST_Server::READABLE,
'callback' => array( $this, 'get_items' ),
'permission_callback' => array( $this, 'get_items_permissions_check' ),
'args' => $this->get_collection_params(),
),
'schema' => array( $this, 'get_public_item_schema' ),
)
@ -108,34 +109,9 @@ class WC_Admin_REST_Admin_Notes_Controller extends WC_REST_CRUD_Controller {
* @return WP_REST_Response
*/
public function get_items( $request ) {
$per_page = isset( $request['per_page'] ) ? intval( $request['per_page'] ) : 10;
if ( $per_page <= 0 ) {
$per_page = 10;
}
$query_args = $this->prepare_objects_query( $request );
$page = isset( $request['page'] ) ? intval( $request['page'] ) : 1;
if ( $page <= 0 ) {
$page = 1;
}
$args = array(
'per_page' => $per_page,
'page' => $page,
);
$type = isset( $request['type'] ) ? $request['type'] : '';
$type = sanitize_text_field( $type );
if ( ! empty( $type ) ) {
$args['type'] = $type;
}
$status = isset( $request['status'] ) ? $request['status'] : '';
$status = sanitize_text_field( $status );
if ( ! empty( $status ) ) {
$args['status'] = $status;
}
$notes = WC_Admin_Notes::get_notes( 'edit', $args );
$notes = WC_Admin_Notes::get_notes( 'edit', $query_args );
$data = array();
foreach ( (array) $notes as $note_obj ) {
@ -145,11 +121,44 @@ class WC_Admin_REST_Admin_Notes_Controller extends WC_REST_CRUD_Controller {
}
$response = rest_ensure_response( $data );
$response->header( 'X-WP-Total', WC_Admin_Notes::get_notes_count( $type, $status ) );
$response->header( 'X-WP-Total', WC_Admin_Notes::get_notes_count( $query_args['type'], $query_args['status'] ) );
return $response;
}
/**
* Prepare objects query.
*
* @param WP_REST_Request $request Full details about the request.
* @return array
*/
protected function prepare_objects_query( $request ) {
$args = array();
$args['order'] = $request['order'];
$args['orderby'] = $request['orderby'];
$args['per_page'] = $request['per_page'];
$args['page'] = $request['page'];
$args['type'] = isset( $request['type'] ) ? $request['type'] : array();
$args['status'] = isset( $request['status'] ) ? $request['status'] : array();
if ( 'date' === $args['orderby'] ) {
$args['orderby'] = 'date_created';
}
/**
* Filter the query arguments for a request.
*
* Enables adding extra arguments or setting defaults for a post
* collection request.
*
* @param array $args Key value array of query var to query value.
* @param WP_REST_Request $request The request used.
*/
$args = apply_filters( 'woocommerce_rest_admin_notes_object_query', $args, $request );
return $args;
}
/**
* Check whether a given request has permission to read a single note.
*
@ -300,20 +309,65 @@ class WC_Admin_REST_Admin_Notes_Controller extends WC_REST_CRUD_Controller {
* @return array
*/
public function get_collection_params() {
$params = array();
$params['context'] = $this->get_context_param( array( 'default' => 'view' ) );
$params['type'] = array(
'description' => __( 'Type of note.', 'woocommerce-admin' ),
$params = array();
$params['context'] = $this->get_context_param( array( 'default' => 'view' ) );
$params['order'] = array(
'description' => __( 'Order sort attribute ascending or descending.', 'woocommerce-admin' ),
'type' => 'string',
'enum' => WC_Admin_Note::get_allowed_types(),
'default' => 'desc',
'enum' => array( 'asc', 'desc' ),
'validate_callback' => 'rest_validate_request_arg',
);
$params['status'] = array(
'description' => __( 'Status of note.', 'woocommerce-admin' ),
$params['orderby'] = array(
'description' => __( 'Sort collection by object attribute.', 'woocommerce-admin' ),
'type' => 'string',
'enum' => WC_Admin_Note::get_allowed_statuses(),
'default' => 'date',
'enum' => array(
'note_id',
'date',
'type',
'title',
'status',
),
'validate_callback' => 'rest_validate_request_arg',
);
$params['page'] = array(
'description' => __( 'Current page of the collection.', 'woocommerce-admin' ),
'type' => 'integer',
'default' => 1,
'sanitize_callback' => 'absint',
'validate_callback' => 'rest_validate_request_arg',
'minimum' => 1,
);
$params['per_page'] = array(
'description' => __( 'Maximum number of items to be returned in result set.', 'woocommerce-admin' ),
'type' => 'integer',
'default' => 10,
'minimum' => 1,
'maximum' => 100,
'sanitize_callback' => 'absint',
'validate_callback' => 'rest_validate_request_arg',
);
$params['type'] = array(
'description' => __( 'Type of note.', 'woocommerce-admin' ),
'type' => 'array',
'sanitize_callback' => 'wp_parse_slug_list',
'validate_callback' => 'rest_validate_request_arg',
'items' => array(
'enum' => WC_Admin_Note::get_allowed_types(),
'type' => 'string',
),
);
$params['status'] = array(
'description' => __( 'Status of note.', 'woocommerce-admin' ),
'type' => 'array',
'sanitize_callback' => 'wp_parse_slug_list',
'validate_callback' => 'rest_validate_request_arg',
'items' => array(
'enum' => WC_Admin_Note::get_allowed_statuses(),
'type' => 'string',
),
);
return $params;
}

View File

@ -250,24 +250,21 @@ class WC_Admin_Notes_Data_Store extends WC_Data_Store_WP implements WC_Object_Da
public function get_notes( $args = array() ) {
global $wpdb;
$per_page = isset( $args['per_page'] ) ? intval( $args['per_page'] ) : 10;
if ( $per_page <= 0 ) {
$per_page = 10;
}
$page = isset( $args['page'] ) ? intval( $args['page'] ) : 1;
if ( $page <= 0 ) {
$page = 1;
}
$offset = $per_page * ( $page - 1 );
$defaults = array(
'per_page' => get_option( 'posts_per_page' ),
'page' => 1,
'order' => 'DESC',
'orderby' => 'date_created',
);
$args = wp_parse_args( $args, $defaults );
$offset = $args['per_page'] * ( $args['page'] - 1 );
$where_clauses = $this->get_notes_where_clauses( $args );
$query = $wpdb->prepare(
"SELECT note_id, title, content FROM {$wpdb->prefix}wc_admin_notes WHERE 1=1{$where_clauses} ORDER BY note_id DESC LIMIT %d, %d",
"SELECT note_id, title, content FROM {$wpdb->prefix}wc_admin_notes WHERE 1=1{$where_clauses} ORDER BY {$args['orderby']} {$args['order']} LIMIT %d, %d",
$offset,
$per_page
$args['per_page']
); // WPCS: unprepared SQL ok.
return $wpdb->get_results( $query ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
@ -280,7 +277,7 @@ class WC_Admin_Notes_Data_Store extends WC_Data_Store_WP implements WC_Object_Da
* @param string $status Comma separated list of statuses.
* @return array An array of objects containing a note id.
*/
public function get_notes_count( $type = '', $status = '' ) {
public function get_notes_count( $type = array(), $status = array() ) {
global $wpdb;
$where_clauses = $this->get_notes_where_clauses(
@ -308,8 +305,7 @@ class WC_Admin_Notes_Data_Store extends WC_Data_Store_WP implements WC_Object_Da
$allowed_types = WC_Admin_Note::get_allowed_types();
$where_type_array = array();
if ( isset( $args['type'] ) ) {
$args_types = explode( ',', $args['type'] );
foreach ( (array) $args_types as $args_type ) {
foreach ( $args['type'] as $args_type ) {
$args_type = trim( $args_type );
if ( in_array( $args_type, $allowed_types, true ) ) {
$where_type_array[] = "'" . esc_sql( $args_type ) . "'";
@ -320,8 +316,7 @@ class WC_Admin_Notes_Data_Store extends WC_Data_Store_WP implements WC_Object_Da
$allowed_statuses = WC_Admin_Note::get_allowed_statuses();
$where_status_array = array();
if ( isset( $args['status'] ) ) {
$args_statuses = explode( ',', $args['status'] );
foreach ( (array) $args_statuses as $args_status ) {
foreach ( $args['status'] as $args_status ) {
$args_status = trim( $args_status );
if ( in_array( $args_status, $allowed_statuses, true ) ) {
$where_status_array[] = "'" . esc_sql( $args_status ) . "'";

View File

@ -86,7 +86,7 @@ class WC_Admin_Notes {
* @param string $status Comma separated list of statuses.
* @return int
*/
public static function get_notes_count( $type = '', $status = '' ) {
public static function get_notes_count( $type = array(), $status = array() ) {
$data_store = WC_Data_Store::load( 'admin-note' );
return $data_store->get_notes_count( $type, $status );
}
@ -112,7 +112,7 @@ class WC_Admin_Notes {
$data_store = WC_Data_Store::load( 'admin-note' );
$raw_notes = $data_store->get_notes(
array(
'status' => WC_Admin_Note::E_WC_ADMIN_NOTE_SNOOZED,
'status' => array( WC_Admin_Note::E_WC_ADMIN_NOTE_SNOOZED ),
)
);
$now = new DateTime();

View File

@ -194,7 +194,7 @@ function wc_admin_print_script_settings() {
'weekdaysShort' => array_values( $wp_locale->weekday_abbrev ),
),
'currentUserData' => $current_user_data,
'alertCount' => WC_Admin_Notes::get_notes_count( 'error,update', 'unactioned' ),
'alertCount' => WC_Admin_Notes::get_notes_count( array( 'error', 'update' ), array( 'unactioned' ) ),
'reviewsEnabled' => get_option( 'woocommerce_enable_reviews' ),
'manageStock' => get_option( 'woocommerce_manage_stock' ),
'commentModeration' => get_option( 'comment_moderation' ),

View File

@ -228,6 +228,44 @@ class WC_Tests_API_Admin_Notes extends WC_REST_Unit_Test_Case {
$this->assertEmpty( $notes );
}
/**
* Test ordering of notes.
*/
public function test_order_notes() {
wp_set_current_user( $this->user );
$request = new WP_REST_Request( 'GET', $this->endpoint );
$request->set_query_params(
array(
'orderby' => 'title',
'order' => 'asc',
)
);
$response = $this->server->dispatch( $request );
$notes = $response->get_data();
$this->assertEquals( 200, $response->get_status() );
$this->assertEquals( 3, count( $notes ) );
$this->assertEquals( $notes[0]['title'], 'PHPUNIT_TEST_NOTE_1_TITLE' );
$this->assertEquals( $notes[1]['title'], 'PHPUNIT_TEST_NOTE_2_TITLE' );
$this->assertEquals( $notes[2]['title'], 'PHPUNIT_TEST_NOTE_3_TITLE' );
$request = new WP_REST_Request( 'GET', $this->endpoint );
$request->set_query_params(
array(
'orderby' => 'status',
'order' => 'desc',
)
);
$response = $this->server->dispatch( $request );
$notes = $response->get_data();
$this->assertEquals( 3, count( $notes ) );
$this->assertEquals( $notes[0]['status'], WC_Admin_Note::E_WC_ADMIN_NOTE_UNACTIONED );
$this->assertEquals( $notes[1]['status'], WC_Admin_Note::E_WC_ADMIN_NOTE_SNOOZED );
$this->assertEquals( $notes[2]['status'], WC_Admin_Note::E_WC_ADMIN_NOTE_ACTIONED );
}
/**
* Test getting lots of notes without permission. It should fail.
*