<?php namespace Give\API\REST\V3\Routes\Donors; use Exception; use Give\API\REST\V3\Routes\Donors\ValueObjects\DonorRoute; use Give\API\REST\V3\Support\CURIE; use Give\Campaigns\Models\Campaign; use Give\Donors\DonorStatisticsQuery; use Give\Donors\Models\Donor; use Give\Framework\Permissions\Facades\UserPermissions; use WP_Error; use WP_REST_Controller; use WP_REST_Request; use WP_REST_Response; use WP_REST_Server; /** * @since 4.4.0 */ class DonorStatisticsController extends WP_REST_Controller { /** * @since 4.4.0 */ public function __construct() { $this->namespace = DonorRoute::NAMESPACE; $this->rest_base = DonorRoute::BASE; } /** * @since 4.13.0 add schema * @since 4.4.0 */ public function register_routes() { register_rest_route($this->namespace, '/' . $this->rest_base . '/(?P<donorId>[\d]+)/statistics', [ [ 'methods' => WP_REST_Server::READABLE, 'callback' => [$this, 'get_item'], 'permission_callback' => [$this, 'get_item_permissions_check'], 'args' => [ 'donorId' => [ 'description' => __('The donor ID.', 'give'), 'type' => 'integer', 'required' => true, ], 'mode' => [ 'description' => __('The mode of donations to filter by "live" or "test".', 'give'), 'type' => 'string', 'default' => 'live', 'enum' => ['live', 'test'], ], 'campaignId' => [ 'description' => __('The ID of the campaign to filter donors by - zero or empty mean "all campaigns".', 'give'), 'type' => 'integer', 'default' => 0, ], ], ], 'schema' => [$this, 'get_item_schema'], ]); } /** * Get a single donor statistics. * * @since 4.4.0 * * @param WP_REST_Request $request Full data about the request. * * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. * * @throws Exception */ public function get_item($request) { $donor = Donor::find($request->get_param('donorId')); if (!$donor) { return new WP_Error('donor_not_found', __('Donor not found', 'give'), ['status' => 404]); } $query = new DonorStatisticsQuery($donor, $request->get_param('mode')); if ($campaign = Campaign::find($request->get_param('campaignId'))) { $query = $query->filterByCampaign($campaign); } $item = [ 'donations' => [ 'lifetimeAmount' => $query->getLifetimeDonationsAmount(), 'highestAmount' => $query->getHighestDonationAmount(), 'averageAmount' => $query->getAverageDonationAmount(), 'count' => $query->getDonationsCount(), 'first' => $query->getFirstDonation(), 'last' => $query->getLastDonation() ], 'donorType' => $query->getDonorType(), 'preferredPaymentMethod' => $query->preferredPaymentMethod(), ]; $response = $this->prepare_item_for_response($item, $request); return rest_ensure_response($response); } /** * @since 4.14.0 replace logic with UserPermissions facade * @since 4.4.0 * * @param WP_REST_Request $request * * @return bool */ public function get_item_permissions_check($request): bool { return UserPermissions::donors()->canView(); } /** * @since 4.14.0 Add donor link to the response * @since 4.4.0 */ public function prepare_item_for_response($item, $request): WP_REST_Response { $self_url = rest_url(sprintf( '%s/%s/%d/%s', $this->namespace, $this->rest_base, $request->get_param('donorId'), 'statistics' )); $self_url = add_query_arg([ 'mode' => $request->get_param('mode'), 'campaignId' => $request->get_param('campaignId'), ], $self_url); $donor_url = rest_url(sprintf( '%s/%s/%d', $this->namespace, $this->rest_base, $request->get_param('donorId') )); $donor_url = add_query_arg([ 'mode' => $request->get_param('mode'), 'campaignId' => $request->get_param('campaignId'), ], $donor_url); $links = [ 'self' => ['href' => $self_url], CURIE::relationUrl('donor') => [ 'href' => $donor_url, 'embeddable' => true, ], ]; $response = new WP_REST_Response($item); $response->add_links($links); return $response; } /** * @since 4.14.0 Moved from getSchema to get_item_schema and added response schema * @since 4.13.0 */ public function get_item_schema(): array { return [ '$schema' => 'http://json-schema.org/draft-04/schema#', 'title' => 'givewp/donor-statistics', 'description' => esc_html__('Provides statistics for a specific donor.', 'give'), 'type' => 'object', 'properties' => [ 'donations' => [ 'type' => 'object', 'description' => esc_html__('Donation statistics', 'give'), 'properties' => [ 'lifetimeAmount' => [ 'type' => ['integer', 'number'], 'description' => esc_html__('Total lifetime donation amount', 'give'), ], 'highestAmount' => [ 'type' => ['integer', 'number'], 'description' => esc_html__('Highest single donation amount', 'give'), ], 'averageAmount' => [ 'type' => ['integer', 'number'], 'description' => esc_html__('Average donation amount', 'give'), ], 'count' => [ 'type' => 'integer', 'description' => esc_html__('Total number of donations', 'give'), ], 'first' => [ 'type' => ['object', 'null'], 'description' => esc_html__('First donation details', 'give'), ], 'last' => [ 'type' => ['object', 'null'], 'description' => esc_html__('Last donation details', 'give'), ], ], ], 'donorType' => [ 'type' => 'string', 'description' => esc_html__('Type of donor', 'give'), ], 'preferredPaymentMethod' => [ 'type' => ['string', 'null'], 'description' => esc_html__('Preferred payment method', 'give'), ], ], ]; } }