PluginProbe
Discount Rules for WooCommerce – Disco | Dynamic Pricing, Conditions, Bulk, Bundle, BOGO / 1.4.14
Discount Rules for WooCommerce – Disco | Dynamic Pricing, Conditions, Bulk, Bundle, BOGO v1.4.14
1.4.14 1.4.13 1.4.12 1.4.11 1.4.10 1.4.9 1.4.8 1.4.7 1.4.6 1.4.5 1.4.4 1.4.3 1.4.2 1.4.1 1.4.0 1.3.54 1.3.53 1.3.52 1.3.51 1.3.50 1.3.49 1.3.48 1.3.47 1.3.46 1.3.45 All 177 releases
disco / app / Analytics / Services / CampaignService.php

CampaignService.php in Discount Rules for WooCommerce – Disco | Dynamic Pricing, Conditions, Bulk, Bundle, BOGO 1.4.14, at app/Analytics/Services/CampaignService.php

146 lines 4.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php //phpcs:ignore
2
3 /**
4 * CampaignService — composes campaign queries into service-level results.
5 *
6 * @package Disco
7 * @subpackage Disco\App\Analytics\Services
8 * @since 1.3.37
9 */
10
11 namespace Disco\App\Analytics\Services;
12
13 use Disco\App\Analytics\Queries\CampaignQuery;
14
15 /**
16 * Provides campaign analytics at the service layer.
17 *
18 * Provides campaign analytics for the campaigns list and single-campaign endpoints.
19 * No SQL lives here — all DB work is delegated to CampaignQuery.
20 */
21 class CampaignService extends BaseService {
22
23 /**
24 * Returns a paginated list of campaigns with aggregate order metrics.
25 *
26 * @param array $args search, date_from, date_to, sort_by, order, page, per_page.
27 * @return array { current_period, compare_period, pagination, data }
28 */
29 public static function get_campaigns( array $args ): array {
30 $result = ( new CampaignQuery )->get_campaign_list( $args );
31 $date_to = $args['date_to'] ?? '';
32 $date_from = $args['date_from'] ?? '';
33 $per_page = (int) ( $args['per_page'] ?? 10 );
34 $page = (int) ( $args['page'] ?? 1 );
35
36 $data = array();
37
38 foreach ( $result['rows'] as $row ) {
39 $data[] = array(
40 'campaign_id' => (int) $row->campaign_id,
41 'campaign_name' => $row->campaign_name,
42 'intent' => $row->intent,
43 'valid_date' => self::resolve_valid_date( $row->campaign_data ),
44 'orders' => (int) $row->total_orders,
45 'customers' => (int) $row->total_customers,
46 'revenue' => round( (float) $row->total_revenue, 2 ),
47 'status' => $row->status,
48 );
49 }
50
51 return array(
52 'current_period' => array( 'from' => $date_from, 'to' => $date_to ),
53 'compare_period' => self::resolve_compare_period( $date_from, $date_to ),
54 'pagination' => array(
55 'total' => $result['total'],
56 'per_page' => $per_page,
57 'current_page' => $page,
58 'total_pages' => $result['pages'],
59 ),
60 'data' => $data,
61 );
62 }
63
64 /**
65 * Returns KPIs for a single campaign including top products and time-series chart.
66 *
67 * @param int $campaign_id Campaign ID.
68 * @param array $args date_from, date_to.
69 * @return array|\WP_Error
70 */
71 public static function get_campaign( int $campaign_id, array $args ) {
72 $period = array(
73 'from' => $args['date_from'] ?? '',
74 'to' => $args['date_to'] ?? '',
75 );
76
77 $query = new CampaignQuery;
78 $row = $query->get_campaign( $campaign_id, $period );
79 /** @var object{campaign_data: string, orders_count: int, revenue: string, campaign_id: int, intent: string, status: string, is_deleted: int, customers_count: int} $row */
80
81 if ( ! $row ) {
82 return new \WP_Error(
83 'disco_not_found',
84 __( 'No order data found for this campaign ID.', 'disco' ),
85 array( 'status' => 404 )
86 );
87 }
88
89 $campaign_data = null;
90
91 if ( $row->campaign_data ) {
92 $campaign_data = json_decode( $row->campaign_data, true );
93 }
94
95 $campaign_name = 'Unknown';
96
97 if ( is_array( $campaign_data ) ) {
98 $campaign_name = $campaign_data['name'] ?? 'Unknown';
99 }
100
101 $orders_count = (int) $row->orders_count;
102 $revenue = round( (float) $row->revenue, 2 );
103
104 return array(
105 'current_period' => array( 'from' => $period['from'], 'to' => $period['to'] ),
106 'compare_period' => self::resolve_compare_period( $period['from'], $period['to'] ),
107 'campaign_id' => (int) $row->campaign_id,
108 'campaign_name' => $campaign_name,
109 'intent' => $row->intent,
110 'status' => $row->status,
111 'is_deleted' => (bool) $row->is_deleted,
112 'valid_date' => array(
113 'from' => is_array( $campaign_data ) ? ( $campaign_data['discount_valid_from'] ?? '' ) : '',
114 'to' => is_array( $campaign_data ) ? ( $campaign_data['discount_valid_to'] ?? '' ) : '',
115 ),
116 'total_orders' => $orders_count,
117 'total_customers' => (int) $row->customers_count,
118 'revenue' => $revenue,
119 'average_order_value' => $orders_count > 0 ? round( $revenue / $orders_count, 2 ) : 0.0,
120 );
121 }
122
123 /**
124 * Resolves the validity date range from raw campaign JSON data.
125 *
126 * Returns "Unknown" for deleted campaigns (null data), or an object
127 * { from, to } with the campaign's discount validity dates.
128 *
129 * @param string|null $raw_data JSON string from the campaigns.data column.
130 * @return array|string
131 */
132 private static function resolve_valid_date( ?string $raw_data ) {
133 if ( null === $raw_data ) {
134 return 'Unknown';
135 }
136
137 $data = json_decode( $raw_data, true );
138
139 return array(
140 'from' => is_array( $data ) ? ( $data['discount_valid_from'] ?? '' ) : '',
141 'to' => is_array( $data ) ? ( $data['discount_valid_to'] ?? '' ) : '',
142 );
143 }
144
145 }
146