PluginProbe
Product Labels, Quick View, Buy Now, Pre-Orders, Frequently Bought Together & More for WooCommerce – Merchant / 2.3.0
Product Labels, Quick View, Buy Now, Pre-Orders, Frequently Bought Together & More for WooCommerce – Merchant v2.3.0
2.3.2 2.3.1 2.3.0 2.2.8 2.2.7 trunk 1.10.0 1.10.1 1.10.2 1.10.3 1.10.4 1.10.5 1.11.0 1.11.1 1.11.2 1.6 1.7 1.8 1.8.1 1.8.2 1.8.3 1.9.0 1.9.1 1.9.10 1.9.11 All 60 releases
merchant / inc / abilities / handlers / class-merchant-get-analytics-handler.php

class-merchant-get-analytics-handler.php in Product Labels, Quick View, Buy Now, Pre-Orders, Frequently Bought Together & More for WooCommerce – Merchant 2.3.0, at inc/abilities/handlers/class-merchant-get-analytics-handler.php

171 lines 5.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Merchant Get Analytics Handler.
4 *
5 * @package Merchant
6 * @since 2.3.0
7 */
8
9 if ( ! defined( 'ABSPATH' ) ) {
10 exit;
11 }
12
13 /**
14 * Merchant_Get_Analytics_Handler
15 *
16 * Handles the merchant/get-analytics ability.
17 * Returns analytics data at global, module, or campaign scope.
18 *
19 * @since 2.3.0
20 */
21 class Merchant_Get_Analytics_Handler extends Merchant_Abstract_Handler {
22
23 /**
24 * Handle the get-analytics request.
25 *
26 * @param array<string, mixed> $params { scope, module_id?, campaign_id?, date_range?, metrics? }
27 *
28 * @return array<string, mixed>|WP_Error Response envelope or WP_Error on failure.
29 */
30 public function handle( $params ) {
31 $scope = isset( $params['scope'] ) ? $params['scope'] : 'global';
32 $module_id = isset( $params['module_id'] ) ? $params['module_id'] : '';
33
34 // Check analytics enabled.
35 $analytics_enabled = Merchant_Option::get( 'global-settings', 'analytics_toggle', true );
36
37 if ( ! $analytics_enabled ) {
38 return new WP_Error(
39 'analytics_disabled',
40 'Analytics is disabled in Merchant global settings.',
41 array( 'status' => 422 )
42 );
43 }
44
45 // Parse date range.
46 $date_range = isset( $params['date_range'] ) ? $params['date_range'] : array();
47 $start_date = isset( $date_range['start'] ) ? $date_range['start'] : '';
48 $end_date = isset( $date_range['end'] ) ? $date_range['end'] : '';
49
50 // Default: last 30 days.
51 if ( empty( $start_date ) || empty( $end_date ) ) {
52 $end_date = gmdate( 'm/d/y' );
53 $start_date = gmdate( 'm/d/y', strtotime( '-30 days' ) );
54 } else {
55 // Convert ISO 8601 to m/d/y if needed.
56 $start_date = $this->normalize_date( $start_date );
57 $end_date = $this->normalize_date( $end_date );
58 }
59
60 if ( false === $start_date || false === $end_date ) {
61 return new WP_Error(
62 'invalid_date_range',
63 'Invalid date format. Use Y-m-d (ISO 8601) or m/d/y.',
64 array( 'status' => 400 )
65 );
66 }
67
68 // Create data provider and set dates.
69 $provider = new Merchant_Analytics_Data_Provider();
70 $provider->set_start_date( $start_date );
71 $provider->set_end_date( $end_date );
72
73 $data = array( 'scope' => $scope );
74
75 // Pro gate for module-specific scopes.
76 if ( 'global' !== $scope && ! empty( $module_id ) ) {
77 if ( isset( Merchant_Admin_Modules::$modules_data[ $module_id ] ) ) {
78 $module_data = Merchant_Admin_Modules::$modules_data[ $module_id ];
79 if ( ! empty( $module_data['pro'] ) && ! defined( 'MERCHANT_PRO_VERSION' ) ) {
80 return new WP_Error(
81 'module_is_pro',
82 sprintf( "Module '%s' requires Merchant Pro.", $module_id ),
83 array( 'status' => 403 )
84 );
85 }
86 }
87 }
88
89 switch ( $scope ) {
90 case 'global':
91 $data['metrics'] = array(
92 'revenue' => $provider->get_revenue(),
93 'total_impressions' => $provider->get_total_impressions(),
94 'orders_count' => $provider->get_orders_count(),
95 'average_order_value' => $provider->get_average_order_value(),
96 'conversion_rate' => $provider->get_conversion_rate_percentage(),
97 );
98 break;
99
100 case 'module':
101 if ( empty( $module_id ) ) {
102 return new WP_Error(
103 'missing_module_id',
104 'module_id is required for module scope.',
105 array( 'status' => 400 )
106 );
107 }
108 $data['module_id'] = $module_id;
109 $data['metrics'] = array(
110 'impressions' => $provider->get_module_impressions( $module_id ),
111 'clicks' => $provider->get_module_clicks( $module_id ),
112 'orders_count' => $provider->get_module_orders_count( $module_id ),
113 'revenue' => $provider->get_module_revenue( $module_id ),
114 'average_order_value' => $provider->get_module_average_order_value( $module_id ),
115 'conversion_rate' => $provider->get_module_conversion_rate_percentage( $module_id ),
116 'ctr' => $provider->get_module_ctr_percentage( $module_id ),
117 );
118 break;
119
120 case 'campaign':
121 // FIX: was $params['campaign_identifier'], now matches schema.
122 $campaign_id = isset( $params['campaign_id'] ) ? $params['campaign_id'] : '';
123 if ( empty( $module_id ) || '' === $campaign_id ) {
124 return new WP_Error(
125 'missing_params',
126 'module_id and campaign_id are required for campaign scope.',
127 array( 'status' => 400 )
128 );
129 }
130 $data['module_id'] = $module_id;
131 $data['campaign_id'] = $campaign_id;
132 $data['metrics'] = array(
133 'impressions' => $provider->get_campaign_impressions( $campaign_id, $module_id ),
134 'clicks' => $provider->get_campaign_clicks( $campaign_id, $module_id ),
135 'orders_count' => $provider->get_campaign_orders_count( $campaign_id, $module_id ),
136 'revenue' => $provider->get_campaign_revenue( $campaign_id, $module_id ),
137 'average_order_value' => $provider->get_campaign_average_order_value( $campaign_id, $module_id ),
138 'ctr' => $provider->get_campaign_ctr_percentage( $campaign_id, $module_id ),
139 );
140 break;
141 }
142
143 return array(
144 'success' => true,
145 'data' => $data,
146 );
147 }
148
149 /**
150 * Normalize a date string to m/d/y format.
151 *
152 * @param string $date Date string (Y-m-d or m/d/y).
153 *
154 * @return string|false Normalized date or false on failure.
155 */
156 private function normalize_date( $date ) {
157 // ISO 8601: Y-m-d.
158 if ( preg_match( '/^\d{4}-\d{2}-\d{2}$/', $date ) ) {
159 $d = DateTime::createFromFormat( 'Y-m-d', $date );
160 return $d ? $d->format( 'm/d/y' ) : false;
161 }
162
163 // Legacy: m/d/y.
164 if ( preg_match( '#^\d{1,2}/\d{1,2}/\d{2,4}$#', $date ) ) {
165 return $date;
166 }
167
168 return false;
169 }
170 }
171