From 817ca2a96fbb902ed9612c083e80201c9be51eb0 Mon Sep 17 00:00:00 2001 From: Nima Date: Wed, 28 Dec 2022 13:27:10 +0000 Subject: [PATCH] Add `marketing/campaigns` API --- plugins/woocommerce/src/Admin/API/Init.php | 1 + .../src/Admin/API/MarketingCampaigns.php | 237 ++++++++++++++++++ 2 files changed, 238 insertions(+) create mode 100644 plugins/woocommerce/src/Admin/API/MarketingCampaigns.php diff --git a/plugins/woocommerce/src/Admin/API/Init.php b/plugins/woocommerce/src/Admin/API/Init.php index bf2232185ca..8fff86a1ee1 100644 --- a/plugins/woocommerce/src/Admin/API/Init.php +++ b/plugins/woocommerce/src/Admin/API/Init.php @@ -66,6 +66,7 @@ class Init { 'Automattic\WooCommerce\Admin\API\MarketingOverview', 'Automattic\WooCommerce\Admin\API\MarketingRecommendations', 'Automattic\WooCommerce\Admin\API\MarketingChannels', + 'Automattic\WooCommerce\Admin\API\MarketingCampaigns', 'Automattic\WooCommerce\Admin\API\Options', 'Automattic\WooCommerce\Admin\API\Orders', 'Automattic\WooCommerce\Admin\API\PaymentGatewaySuggestions', diff --git a/plugins/woocommerce/src/Admin/API/MarketingCampaigns.php b/plugins/woocommerce/src/Admin/API/MarketingCampaigns.php new file mode 100644 index 00000000000..9c479d5e705 --- /dev/null +++ b/plugins/woocommerce/src/Admin/API/MarketingCampaigns.php @@ -0,0 +1,237 @@ +namespace, + '/' . $this->rest_base, + array( + array( + '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' ), + ) + ); + } + + /** + * Check whether a given request has permission to view marketing campaigns. + * + * @param WP_REST_Request $request Full details about the request. + * + * @return WP_Error|boolean + */ + public function get_items_permissions_check( $request ) { + if ( ! current_user_can( 'install_plugins' ) ) { + return new WP_Error( 'woocommerce_rest_cannot_view', __( 'Sorry, you cannot view marketing campaigns.', 'woocommerce' ), array( 'status' => 400 ) ); + } + + return true; + } + + + /** + * Returns an aggregated array of marketing campaigns for all active marketing channels. + * + * @param WP_REST_Request $request Request data. + * + * @return WP_Error|WP_REST_Response + */ + public function get_items( $request ) { + /** + * MarketingChannels class. + * + * @var MarketingChannelsService $marketing_channels_service + */ + $marketing_channels_service = wc_get_container()->get( MarketingChannelsService::class ); + + // Aggregate the campaigns from all registered marketing channels. + $responses = []; + foreach ( $marketing_channels_service->get_registered_channels() as $channel ) { + foreach ( $channel->get_campaigns() as $campaign ) { + $response = $this->prepare_item_for_response( $campaign, $request ); + $responses[] = $this->prepare_response_for_collection( $response ); + } + } + + // Pagination. + $page = $request['page']; + $items_per_page = $request['per_page']; + $offset = ( $page - 1 ) * $items_per_page; + $paginated_results = array_slice( $responses, $offset, $items_per_page ); + + $response = rest_ensure_response( $paginated_results ); + + $total_campaigns = count( $responses ); + $max_pages = ceil( $total_campaigns / $items_per_page ); + $response->header( 'X-WP-Total', $total_campaigns ); + $response->header( 'X-WP-TotalPages', (int) $max_pages ); + + // Add previous and next page links to response header. + $request_params = $request->get_query_params(); + $base = add_query_arg( urlencode_deep( $request_params ), rest_url( sprintf( '%s/%s', $this->namespace, $this->rest_base ) ) ); + if ( $page > 1 ) { + $prev_page = $page - 1; + if ( $prev_page > $max_pages ) { + $prev_page = $max_pages; + } + $prev_link = add_query_arg( 'page', $prev_page, $base ); + $response->link_header( 'prev', $prev_link ); + } + if ( $max_pages > $page ) { + $next_page = $page + 1; + $next_link = add_query_arg( 'page', $next_page, $base ); + $response->link_header( 'next', $next_link ); + } + + return $response; + } + + /** + * Prepares the item for the REST response. + * + * @param MarketingCampaign $item WordPress representation of the item. + * @param WP_REST_Request $request Request object. + * + * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure. + */ + public function prepare_item_for_response( $item, $request ) { + $data = [ + 'id' => $item->get_id(), + 'channel' => $item->get_channel()->get_slug(), + 'title' => $item->get_title(), + 'manage_url' => $item->get_manage_url(), + ]; + + if ( $item->get_cost() instanceof Price ) { + $data['cost'] = [ + 'value' => wc_format_decimal( $item->get_cost()->get_value() ), + 'currency' => $item->get_cost()->get_currency(), + ]; + } + + $context = $request['context'] ?? 'view'; + $data = $this->add_additional_fields_to_object( $data, $request ); + $data = $this->filter_response_by_context( $data, $context ); + + return rest_ensure_response( $data ); + } + + /** + * Retrieves the item's schema, conforming to JSON Schema. + * + * @return array Item schema data. + */ + public function get_item_schema() { + $schema = [ + '$schema' => 'http://json-schema.org/draft-04/schema#', + 'title' => 'marketing_campaign', + 'type' => 'object', + 'properties' => [ + 'id' => [ + 'description' => __( 'The unique identifier for the marketing campaign.', 'woocommerce' ), + 'type' => 'string', + 'context' => [ 'view' ], + 'readonly' => true, + ], + 'channel' => [ + 'description' => __( 'The unique identifier for the marketing channel that this campaign belongs to.', 'woocommerce' ), + 'type' => 'string', + 'context' => [ 'view' ], + 'readonly' => true, + ], + 'title' => [ + 'description' => __( 'Title of the marketing campaign.', 'woocommerce' ), + 'type' => 'string', + 'context' => [ 'view' ], + 'readonly' => true, + ], + 'manage_url' => [ + 'description' => __( 'URL to the campaign management page', 'woocommerce' ), + 'type' => 'string', + 'context' => [ 'view' ], + 'readonly' => true, + ], + 'cost' => [ + 'description' => __( 'Cost of the marketing campaign.', 'woocommerce' ), + 'context' => [ 'view' ], + 'readonly' => true, + 'type' => 'object', + 'properties' => [ + 'value' => [ + 'type' => 'string', + 'context' => [ 'view' ], + 'readonly' => true, + ], + 'currency' => [ + 'type' => 'string', + 'context' => [ 'view' ], + 'readonly' => true, + ], + ], + ], + ], + ]; + + return $this->add_additional_fields_schema( $schema ); + } + + /** + * Retrieves the query params for the collections. + * + * @return array Query parameters for the collection. + */ + public function get_collection_params() { + $params = parent::get_collection_params(); + unset( $params['search'] ); + + return $params; + } + + +}