* @param WP_REST_Request $request Full data about the request.
public function update_items_permissions_check( $request ) {
if ( ! wc_rest_check_manager_permissions( 'settings', 'edit' ) ) {
return new \WP_Error( 'woocommerce_rest_cannot_edit', __( 'Sorry, you cannot edit this resource.', 'woocommerce' ), array( 'status' => rest_authorization_required_code() ) );
* Prepare a path or query for serialization to the client.
* @param string $query The query, path, or URL to transform.
* @return string A fully formed URL.
public function prepare_query_for_response( $query ) {
if ( 'https://' === substr( $query, 0, 8 ) ) {
if ( 'http://' === substr( $query, 0, 7 ) ) {
if ( '?' === substr( $query, 0, 1 ) ) {
return admin_url( 'admin.php' . $query );
return admin_url( $query );
* Maybe add a nonce to a URL.
* @link https://codex.wordpress.org/WordPress_Nonces
* @param string $url The URL needing a nonce.
* @param string $action The nonce action.
* @param string $name The nonce name.
* @return string A fully formed URL.
private function maybe_add_nonce_to_url( string $url, string $action = '', string $name = '' ) : string {
if ( empty( $action ) ) {
// Default parameter name.
return add_query_arg( $name, wp_create_nonce( $action ), $url );
* Prepare a note object for serialization.
* @param array $data Note data.
* @param WP_REST_Request $request Request object.
* @return WP_REST_Response $response Response data.
public function prepare_item_for_response( $data, $request ) {
$context = ! empty( $request['context'] ) ? $request['context'] : 'view';
$data = $this->add_additional_fields_to_object( $data, $request );
$data['date_created_gmt'] = wc_rest_prepare_date_response( $data['date_created'] );
$data['date_created'] = wc_rest_prepare_date_response( $data['date_created'], false );
$data['date_reminder_gmt'] = wc_rest_prepare_date_response( $data['date_reminder'] );
$data['date_reminder'] = wc_rest_prepare_date_response( $data['date_reminder'], false );
$data['title'] = stripslashes( $data['title'] );
$data['content'] = stripslashes( $data['content'] );
$data['is_snoozable'] = (bool) $data['is_snoozable'];
$data['is_deleted'] = (bool) $data['is_deleted'];
$data['is_read'] = (bool) $data['is_read'];
foreach ( (array) $data['actions'] as $key => $value ) {
$data['actions'][ $key ]->label = stripslashes( $data['actions'][ $key ]->label );
$data['actions'][ $key ]->url = $this->maybe_add_nonce_to_url(
$this->prepare_query_for_response( $data['actions'][ $key ]->query ),
(string) $data['actions'][ $key ]->nonce_action,
(string) $data['actions'][ $key ]->nonce_name
$data['actions'][ $key ]->status = stripslashes( $data['actions'][ $key ]->status );
$data = $this->filter_response_by_context( $data, $context );
// Wrap the data in a response object.
$response = rest_ensure_response( $data );
'href' => rest_url( sprintf( '/%s/%s/%d', $this->namespace, $this->rest_base, $data['id'] ) ),
'href' => rest_url( sprintf( '%s/%s', $this->namespace, $this->rest_base ) ),
* Filter a note returned from the API.
* Allows modification of the note data right before it is returned.
* @param WP_REST_Response $response The response object.
* @param array $data The original note.
* @param WP_REST_Request $request Request used to generate the response.
return apply_filters( 'woocommerce_rest_prepare_note', $response, $data, $request );
* @param WP_REST_Request $request Request object.
public function track_opened_email( $request ) {
$note = NotesRepository::get_note( $request->get_param( 'note_id' ) );
NotesRepository::record_tracks_event_with_user( $request->get_param( 'user_id' ), 'email_note_opened', array( 'note_name' => $note->get_name() ) );
* Get the query params for collections.
public function get_collection_params() {
$params['context'] = $this->get_context_param( array( 'default' => 'view' ) );
$params['order'] = array(
'description' => __( 'Order sort attribute ascending or descending.', 'woocommerce' ),
'enum' => array( 'asc', 'desc' ),
'validate_callback' => 'rest_validate_request_arg',
$params['orderby'] = array(
'description' => __( 'Sort collection by object attribute.', 'woocommerce' ),
'validate_callback' => 'rest_validate_request_arg',
'description' => __( 'Current page of the collection.', 'woocommerce' ),
'sanitize_callback' => 'absint',
'validate_callback' => 'rest_validate_request_arg',
$params['per_page'] = array(
'description' => __( 'Maximum number of items to be returned in result set.', 'woocommerce' ),
'sanitize_callback' => 'absint',
'validate_callback' => 'rest_validate_request_arg',
'description' => __( 'Type of note.', 'woocommerce' ),
'sanitize_callback' => 'wp_parse_slug_list',
'validate_callback' => 'rest_validate_request_arg',
'enum' => Note::get_allowed_types(),
$params['status'] = array(
'description' => __( 'Status of note.', 'woocommerce' ),
'sanitize_callback' => 'wp_parse_slug_list',
'validate_callback' => 'rest_validate_request_arg',
'enum' => Note::get_allowed_statuses(),
$params['source'] = array(
'description' => __( 'Source of note.', 'woocommerce' ),
'sanitize_callback' => 'wp_parse_list',
'validate_callback' => 'rest_validate_request_arg',
* Get the note's schema, conforming to JSON Schema.
public function get_item_schema() {
'$schema' => 'http://json-schema.org/draft-04/schema#',
'description' => __( 'ID of the note record.', 'woocommerce' ),
'context' => array( 'view' ),
'description' => __( 'Name of the note.', 'woocommerce' ),
'context' => array( 'view', 'edit' ),
'description' => __( 'The type of the note (e.g. error, warning, etc.).', 'woocommerce' ),
'context' => array( 'view', 'edit' ),
'description' => __( 'Locale used for the note title and content.', 'woocommerce' ),
'context' => array( 'view', 'edit' ),
'description' => __( 'Title of the note.', 'woocommerce' ),
'context' => array( 'view', 'edit' ),
'description' => __( 'Content of the note.', 'woocommerce' ),
'context' => array( 'view', 'edit' ),
'description' => __( 'Content data for the note. JSON string. Available for re-localization.', 'woocommerce' ),
'context' => array( 'view', 'edit' ),
'description' => __( 'The status of the note (e.g. unactioned, actioned).', 'woocommerce' ),
'context' => array( 'view', 'edit' ),
'description' => __( 'Source of the note.', 'woocommerce' ),
'context' => array( 'view', 'edit' ),
'description' => __( 'Date the note was created.', 'woocommerce' ),
'context' => array( 'view', 'edit' ),
'date_created_gmt' => array(
'description' => __( 'Date the note was created (GMT).', 'woocommerce' ),
'context' => array( 'view', 'edit' ),
'date_reminder' => array(
'description' => __( 'Date after which the user should be reminded of the note, if any.', 'woocommerce' ),
'context' => array( 'view', 'edit' ),
'readonly' => true, // @todo Allow date_reminder to be updated.
'date_reminder_gmt' => array(
'description' => __( 'Date after which the user should be reminded of the note, if any (GMT).', 'woocommerce' ),
'context' => array( 'view', 'edit' ),
'description' => __( 'Whether or not a user can request to be reminded about the note.', 'woocommerce' ),
'context' => array( 'view', 'edit' ),
'description' => __( 'An array of actions, if any, for the note.', 'woocommerce' ),
'context' => array( 'view', 'edit' ),
'description' => __( 'The layout of the note (e.g. banner, thumbnail, plain).', 'woocommerce' ),
'context' => array( 'view', 'edit' ),
'description' => __( 'The image of the note, if any.', 'woocommerce' ),
'context' => array( 'view', 'edit' ),
'description' => __( 'Registers whether the note is deleted or not', 'woocommerce' ),
'context' => array( 'view', 'edit' ),
'description' => __( 'Registers whether the note is read or not', 'woocommerce' ),
'context' => array( 'view', 'edit' ),
return $this->add_additional_fields_schema( $schema );