woocommerce/plugins/woocommerce-admin/includes/api/class-wc-admin-rest-reports...

288 lines
8.5 KiB
PHP

<?php
/**
* REST API Performance indicators controller
*
* Handles requests to the /reports/store-performance endpoint.
*
* @package WooCommerce Admin/API
*/
defined( 'ABSPATH' ) || exit;
/**
* REST API Reports Performance indicators controller class.
*
* @package WooCommerce/API
* @extends WC_REST_Reports_Controller
*/
class WC_Admin_REST_Reports_Performance_Indicators_Controller extends WC_REST_Reports_Controller {
/**
* Endpoint namespace.
*
* @var string
*/
protected $namespace = 'wc/v3';
/**
* Route base.
*
* @var string
*/
protected $rest_base = 'reports/performance-indicators';
/**
* Maps query arguments from the REST request.
*
* @param array $request Request array.
* @return array
*/
protected function prepare_reports_query( $request ) {
$args = array();
$args['before'] = $request['before'];
$args['after'] = $request['after'];
$args['stats'] = $request['stats'];
return $args;
}
/**
* Get all allowed stats that can be returned from this endpoint.
*
* @return array
*/
public function get_allowed_stats() {
global $wp_rest_server;
$request = new WP_REST_Request( 'GET', '/wc/v3/reports' );
$response = rest_do_request( $request );
$endpoints = $response->get_data();
$allowed_stats = array();
if ( 200 !== $response->get_status() ) {
return new WP_Error( 'woocommerce_reports_performance_indicators_result_failed', __( 'Sorry, fetching performance indicators failed.', 'wc-admin' ) );
}
foreach ( $endpoints as $endpoint ) {
if ( '/stats' === substr( $endpoint['slug'], -6 ) ) {
$request = new WP_REST_Request( 'OPTIONS', '/wc/v3/reports/' . $endpoint['slug'] );
$response = rest_do_request( $request );
$data = $response->get_data();
$prefix = substr( $endpoint['slug'], 0, -6 );
if ( empty( $data['schema']['properties']['totals']['properties'] ) ) {
continue;
}
foreach ( $data['schema']['properties']['totals']['properties'] as $property_key => $schema_info ) {
$allowed_stats[] = $prefix . '/' . $property_key;
}
}
}
/**
* Filter the list of allowed stats that can be returned via the performance indiciator endpoint.
*
* @param array $allowed_stats The list of allowed stats.
*/
return apply_filters( 'woocommerce_admin_performance_indicators_allowed_stats', $allowed_stats );
}
/**
* Get all reports.
*
* @param WP_REST_Request $request Request data.
* @return array|WP_Error
*/
public function get_items( $request ) {
$allowed_stats = $this->get_allowed_stats();
if ( is_wp_error( $allowed_stats ) ) {
return $allowed_stats;
}
$query_args = $this->prepare_reports_query( $request );
if ( empty( $query_args['stats'] ) ) {
return new WP_Error( 'woocommerce_reports_performance_indicators_empty_query', __( 'A list of stats to query must be provided.', 'wc-admin' ), 400 );
}
$stats = array();
foreach ( $query_args['stats'] as $stat_request ) {
$is_error = false;
$pieces = explode( '/', $stat_request );
$endpoint = $pieces[0];
$stat = $pieces[1];
if ( ! in_array( $stat_request, $allowed_stats ) ) {
continue;
}
/**
* Filter the list of allowed endpoints, so that data can be loaded from extensions rather than core.
* These should be in the format of slug => path. Example: `bookings` => `/wc-bookings/v1/reports/bookings/stats`.
*
* @param array $endpoints The list of allowed endpoints.
*/
$stats_endpoints = apply_filters( 'woocommerce_admin_performance_indicators_stats_endpoints', array() );
if ( ! empty( $stats_endpoints [ $endpoint ] ) ) {
$request_url = $stats_endpoints [ $endpoint ];
} else {
$request_url = '/wc/v3/reports/' . $endpoint . '/stats';
}
$request = new WP_REST_Request( 'GET', $request_url );
$request->set_param( 'before', $query_args['before'] );
$request->set_param( 'after', $query_args['after'] );
$response = rest_do_request( $request );
$data = $response->get_data();
if ( 200 !== $response->get_status() || empty( $data['totals'][ $stat ] ) ) {
$stats[] = (object) array(
'stat' => $stat_request,
'value' => null,
);
continue;
}
$stats[] = (object) array(
'stat' => $stat_request,
'value' => $data['totals'][ $stat ],
);
}
$objects = array();
foreach ( $stats as $stat ) {
$data = $this->prepare_item_for_response( $stat, $request );
$objects[] = $this->prepare_response_for_collection( $data );
}
$response = rest_ensure_response( $objects );
$response->header( 'X-WP-Total', count( $stats ) );
$response->header( 'X-WP-TotalPages', 1 );
$base = add_query_arg( $request->get_query_params(), rest_url( sprintf( '/%s/%s', $this->namespace, $this->rest_base ) ) );
return $response;
}
/**
* Prepare a report object for serialization.
*
* @param stdClass $stat_data Report data.
* @param WP_REST_Request $request Request object.
* @return WP_REST_Response
*/
public function prepare_item_for_response( $stat_data, $request ) {
$context = ! empty( $request['context'] ) ? $request['context'] : 'view';
$data = $this->add_additional_fields_to_object( $stat_data, $request );
$data = $this->filter_response_by_context( $data, $context );
// Wrap the data in a response object.
$response = rest_ensure_response( $data );
$response->add_links( $this->prepare_links( $data ) );
/**
* Filter a report returned from the API.
*
* Allows modification of the report data right before it is returned.
*
* @param WP_REST_Response $response The response object.
* @param object $report The original report object.
* @param WP_REST_Request $request Request used to generate the response.
*/
return apply_filters( 'woocommerce_rest_prepare_report_performance_indicators', $response, $stat_data, $request );
}
/**
* Prepare links for the request.
*
* @param WC_Admin_Reports_Query $object Object data.
* @return array
*/
protected function prepare_links( $object ) {
$pieces = explode( '/', $object->stat );
$endpoint = $pieces[0];
$stat = $pieces[1];
$links = array(
'report' => array(
'href' => rest_url( sprintf( '/%s/reports/%s/stats', $this->namespace, $endpoint ) ),
),
);
return $links;
}
/**
* Get the Report's schema, conforming to JSON Schema.
*
* @return array
*/
public function get_item_schema() {
$schema = array(
'$schema' => 'http://json-schema.org/draft-04/schema#',
'title' => 'report_performance_indicator',
'type' => 'object',
'properties' => array(
'stat' => array(
'description' => __( 'Unique identifier for the resource.', 'wc-admin' ),
'type' => 'string',
'context' => array( 'view', 'edit' ),
'readonly' => true,
),
'value' => array(
'description' => __( 'Value of the stat. Returns null if the stat does not exist or cannot be loaded.', 'wc-admin' ),
'type' => 'number',
'context' => array( 'view', 'edit' ),
'readonly' => true,
),
),
);
return $this->add_additional_fields_schema( $schema );
}
/**
* Get the query params for collections.
*
* @return array
*/
public function get_collection_params() {
$allowed_stats = $this->get_allowed_stats();
if ( is_wp_error( $allowed_stats ) ) {
$allowed_stats = __( 'There was an issue loading the report endpoints', 'wc-admin' );
} else {
$allowed_stats = implode( ', ', $allowed_stats );
}
$params = array();
$params['context'] = $this->get_context_param( array( 'default' => 'view' ) );
$params['stats'] = array(
'description' => sprintf(
/* translators: Allowed values is a list of stat endpoints. */
__( 'Limit response to specific report stats. Allowed values: %s.', 'wc-admin' ),
$allowed_stats
),
'type' => 'array',
'validate_callback' => 'rest_validate_request_arg',
'items' => array(
'type' => 'string',
),
);
$params['after'] = array(
'description' => __( 'Limit response to resources published after a given ISO8601 compliant date.', 'wc-admin' ),
'type' => 'string',
'format' => 'date-time',
'validate_callback' => 'rest_validate_request_arg',
);
$params['before'] = array(
'description' => __( 'Limit response to resources published before a given ISO8601 compliant date.', 'wc-admin' ),
'type' => 'string',
'format' => 'date-time',
'validate_callback' => 'rest_validate_request_arg',
);
return $params;
}
}