PluginProbe
FireBox – WooCommerce Popup Builder, Exit Intent Popup, Email Optin & Cart Abandonment / 3.1.9
FireBox – WooCommerce Popup Builder, Exit Intent Popup, Email Optin & Cart Abandonment v3.1.9
3.1.13 3.1.12 3.1.11 3.1.10 3.1.9 3.1.8 3.1.7 trunk 1.0.0 1.0.1 1.0.10 1.0.11 1.0.12 1.0.13 1.0.14 1.0.2 1.0.3 1.0.4 1.0.5 1.0.6 1.0.7 1.0.8 1.0.9 1.1.0 1.1.1 All 122 releases
firebox / Inc / Core / FB / CampaignsQuery.php

CampaignsQuery.php in FireBox – WooCommerce Popup Builder, Exit Intent Popup, Email Optin & Cart Abandonment 3.1.9, at Inc/Core/FB/CampaignsQuery.php

243 lines 5.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * @package FireBox
4 * @version 3.1.9 Free
5 *
6 * @author FirePlugins <info@fireplugins.com>
7 * @link https://www.fireplugins.com
8 * @copyright Copyright © 2026 FirePlugins All Rights Reserved
9 * @license GNU GPLv3 <http://www.gnu.org/licenses/gpl.html> or later
10 */
11
12 namespace FireBox\Core\FB;
13
14 if (!defined('ABSPATH'))
15 {
16 exit; // Exit if accessed directly.
17 }
18
19 /**
20 * Shared data layer for the Campaigns list, consumed by both the classic
21 * WP_List_Table (CampaignsList) and the DataViews REST endpoint, so both
22 * UIs query/sort/paginate campaigns identically.
23 */
24 class CampaignsQuery
25 {
26 const ALLOWED_ANALYTICS_ORDERBY = ['views', 'conversions', 'conversionrate'];
27
28 /**
29 * Fetches campaigns (+ analytics) for the given args.
30 *
31 * @param array $args {
32 * @type string $status all|mine|publish|draft|trash
33 * @type string $search title search term
34 * @type string $orderby id|title|date|views|conversions|conversionrate
35 * @type string $order asc|desc
36 * @type int $page 1-based page number
37 * @type int $per_page
38 * }
39 *
40 * @return array ['items' => array[], 'found_posts' => int]
41 */
42 public function getItems(array $args = [])
43 {
44 $args = wp_parse_args($args, [
45 'status' => 'all',
46 'search' => '',
47 'orderby' => 'id',
48 'order' => 'desc',
49 'page' => 1,
50 'per_page' => 30,
51 ]);
52
53 $query_args = [
54 'post_type' => 'firebox',
55 'posts_per_page' => $args['per_page'],
56 'paged' => $args['page'],
57 ];
58
59 if ($args['search'] !== '')
60 {
61 $query_args['s'] = $args['search'];
62 }
63
64 switch ($args['status'])
65 {
66 case 'mine':
67 $query_args['author'] = get_current_user_id();
68 break;
69 case 'publish':
70 $query_args['post_status'] = 'publish';
71 break;
72 case 'draft':
73 $query_args['post_status'] = 'draft';
74 break;
75 case 'trash':
76 $query_args['post_status'] = 'trash';
77 break;
78 default:
79 // "all" mirrors the legacy get_views() definition of "All": published + drafts, not trash.
80 $query_args['post_status'] = ['publish', 'draft'];
81 break;
82 }
83
84 $this->applyInitialSorting($query_args, $args['orderby'], $args['order']);
85
86 $query = new \WP_Query($query_args);
87
88 $items = [];
89
90 if ($query->have_posts())
91 {
92 foreach ($query->posts as $post)
93 {
94 $items[] = [
95 'ID' => $post->ID,
96 'label' => $post->post_title,
97 'post_type' => $post->post_type,
98 'post_status' => $post->post_status,
99 'date' => $post->post_modified_gmt,
100 'analytics' => $this->getCampaignAnalytics($post->ID),
101 ];
102 }
103
104 $this->applySecondarySorting($items, $args['orderby'], $args['order']);
105 }
106
107 return [
108 'items' => $items,
109 'found_posts' => (int) $query->found_posts,
110 ];
111 }
112
113 /**
114 * Returns campaign counts per status, mirroring the legacy get_views() counts.
115 *
116 * @return array ['all' => int, 'mine' => int, 'publish' => int, 'draft' => int, 'trash' => int]
117 */
118 public function getStatusCounts()
119 {
120 $counts = (array) wp_count_posts('firebox', 'readable');
121
122 $publish = (int) ($counts['publish'] ?? 0);
123 $draft = (int) ($counts['draft'] ?? 0);
124 $trash = (int) ($counts['trash'] ?? 0);
125
126 return [
127 'all' => $publish + $draft,
128 'mine' => $this->getMineCount(),
129 'publish' => $publish,
130 'draft' => $draft,
131 'trash' => $trash,
132 ];
133 }
134
135 /**
136 * Counts campaigns authored by the current user (any readable status).
137 *
138 * @return int
139 */
140 public function getMineCount()
141 {
142 $query = new \WP_Query([
143 'post_type' => 'firebox',
144 'author' => get_current_user_id(),
145 ]);
146
147 return (int) $query->found_posts;
148 }
149
150 /**
151 * Fetches analytics metrics (views/conversions/conversionrate) for a campaign.
152 *
153 * @param int $campaign_id
154 *
155 * @return array
156 */
157 public function getCampaignAnalytics($campaign_id)
158 {
159 if (!$campaign_id)
160 {
161 return [];
162 }
163
164 $data = new \FireBox\Core\Analytics\Data();
165
166 $metrics = self::ALLOWED_ANALYTICS_ORDERBY;
167
168 $filters = [
169 'campaign' => [
170 'value' => [$campaign_id]
171 ]
172 ];
173
174 $data->metrics($metrics)->filters($filters);
175
176 return $data->getData('count');
177 }
178
179 /**
180 * Applies DB-level sorting (id/title/date) to the WP_Query args.
181 * Analytics-based sorting cannot happen at the DB level and is handled
182 * by applySecondarySorting() once the analytics values are attached.
183 *
184 * @param array $query_args
185 * @param string $orderby
186 * @param string $order
187 *
188 * @return void
189 */
190 private function applyInitialSorting(&$query_args, $orderby, $order)
191 {
192 switch ($orderby)
193 {
194 case 'id':
195 $query_args['orderby'] = 'ID';
196 $query_args['order'] = $order;
197 break;
198 case 'title':
199 $query_args['orderby'] = 'title';
200 $query_args['order'] = $order;
201 break;
202 case 'date':
203 $query_args['orderby'] = 'modified';
204 $query_args['order'] = $order;
205 break;
206 }
207 }
208
209 /**
210 * Sorts the fetched page's items by an analytics metric in PHP, since
211 * views/conversions/conversionrate don't live on the `firebox` post row.
212 * This preserves the pre-existing behavior of sorting only within the
213 * fetched/paginated set, not across the full result set.
214 *
215 * @param array $items
216 * @param string $orderby
217 * @param string $order
218 *
219 * @return void
220 */
221 private function applySecondarySorting(&$items, $orderby, $order)
222 {
223 if (!in_array($orderby, self::ALLOWED_ANALYTICS_ORDERBY, true))
224 {
225 return;
226 }
227
228 usort($items, function ($a, $b) use ($order, $orderby) {
229 $value_a = (float) ($a['analytics'][$orderby] ?? 0);
230 $value_b = (float) ($b['analytics'][$orderby] ?? 0);
231
232 if ($order === 'asc')
233 {
234 return $value_a > $value_b ? 1 : -1;
235 }
236 else
237 {
238 return $value_a < $value_b ? 1 : -1;
239 }
240 });
241 }
242 }
243