PluginProbe
GiveWP – Donation Plugin and Fundraising Platform / 4.18.0
GiveWP – Donation Plugin and Fundraising Platform v4.18.0
4.18.0 4.17.0 4.16.9 4.16.8.1 4.16.8 4.16.7.2 4.16.7.1 4.16.7 4.16.6.1 4.16.6 4.16.5.1 4.16.5 4.16.4 4.16.3 4.16.2 4.16.1 4.16.0 4.15.5 4.15.4 4.15.3 4.15.2 4.15.1 4.15.0 2.3.0 2.3.1 All 257 releases
give / src / Campaigns / Actions / CacheCampaignData.php

CacheCampaignData.php in GiveWP – Donation Plugin and Fundraising Platform 4.18.0, at src/Campaigns/Actions/CacheCampaignData.php

210 lines 6.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace Give\Campaigns\Actions;
4
5 use Give\Campaigns\CampaignsDataQuery;
6 use Give\Campaigns\Models\Campaign;
7 use Give\Donations\Models\Donation;
8
9 /**
10 * @since 4.8.0
11 *
12 * @uses give_insert_payment hook
13 * @uses give_update_payment_status hook
14 * @uses give_recurring_add_subscription_payment hook
15 * @uses givewp_campaigns_merged hook
16 *
17 * Action used to update campaign's stats data
18 *
19 */
20 class CacheCampaignData
21 {
22 /**
23 * @since 4.13.1 added dispatch method
24 * @since 4.8.0
25 */
26 public function __invoke(int $donationId): void
27 {
28 $donation = Donation::find($donationId);
29
30 if (!$donation) {
31 return;
32 }
33
34 if ($donation->status->isComplete() || $donation->status->isRenewal()) {
35 $this->dispatch($donation->campaignId);
36 }
37 }
38
39 /**
40 * Dispatch the cache campaign data action
41 * @since 4.13.1
42 */
43 public function dispatch(int $campaignId): void
44 {
45 as_enqueue_async_action('givewp_cache_campaign_data', [$campaignId], 'givewp_campaigns_cache');
46 }
47
48 /**
49 * Handle campaign cache
50 *
51 * @since 4.18.0 Read the subscriptions cache from the option it is written to; always compute live stats, keep zero rows when a campaign has no donations.
52 * @since 4.8.0
53 */
54 public function handleCache(int $campaignId): void
55 {
56 // The cache holds live stats only. The queries follow the site's payment mode, so force
57 // live for the duration of the job in case test mode was switched on before it ran.
58 add_filter('give_is_test_mode', '__return_false', PHP_INT_MAX);
59
60 try {
61 $this->refresh($campaignId);
62 } finally {
63 remove_filter('give_is_test_mode', '__return_false', PHP_INT_MAX);
64 }
65 }
66
67 /**
68 * @since 4.18.0
69 */
70 private function refresh(int $campaignId): void
71 {
72 $campaign = Campaign::find($campaignId);
73
74 if (!$campaign) {
75 return;
76 }
77
78 $campaignsData = get_option('give_campaigns_data', []);
79 $campaignsSubscriptionData = get_option('give_campaigns_subscriptions_data', []);
80
81 // Prefill cache structure to ensure keys exist
82 $campaignsData = array_merge([
83 'amounts' => [],
84 'donationsCount' => [],
85 'donorsCount' => []
86 ], $campaignsData);
87
88 $campaignsSubscriptionData = array_merge([
89 'amounts' => [],
90 'donationsCount' => [],
91 'donorsCount' => []
92 ], $campaignsSubscriptionData);
93
94 $donations = CampaignsDataQuery::donations([$campaign->id]);
95
96 $isCached = $isSubscriptionCached = false;
97
98 // Update cache only if it exists for this campaign
99 foreach ($campaignsData['amounts'] as $i => $data) {
100 if ($data['campaign_id'] == $campaign->id) {
101 $isCached = true;
102
103 $campaignsData['amounts'][$i] = $this->row($donations->collectIntendedAmounts(), $campaign->id, 'sum');
104 break;
105 }
106 }
107
108 foreach ($campaignsData['donationsCount'] as $i => $data) {
109 if ($data['campaign_id'] == $campaign->id) {
110 $campaignsData['donationsCount'][$i] = $this->row($donations->collectDonations(), $campaign->id, 'count');
111 break;
112 }
113 }
114
115 foreach ($campaignsData['donorsCount'] as $i => $data) {
116 if ($data['campaign_id'] == $campaign->id) {
117 $campaignsData['donorsCount'][$i] = $this->row($donations->collectDonors(), $campaign->id, 'count');
118 break;
119 }
120 }
121
122
123 // Update campaign subscriptions data
124 if (defined('GIVE_RECURRING_VERSION')) {
125
126 $subscriptions = CampaignsDataQuery::subscriptions([$campaign->id]);
127
128 foreach ($campaignsSubscriptionData['amounts'] as $i => $data) {
129 if ($data['campaign_id'] == $campaign->id) {
130 $isSubscriptionCached = true;
131
132 $campaignsSubscriptionData['amounts'][$i] = $this->row($subscriptions->collectInitialAmounts(), $campaign->id, 'sum');
133 break;
134 }
135 }
136
137 foreach ($campaignsSubscriptionData['donationsCount'] as $i => $data) {
138 if ($data['campaign_id'] == $campaign->id) {
139 $campaignsSubscriptionData['donationsCount'][$i] = $this->row($subscriptions->collectDonations(), $campaign->id, 'count');
140 break;
141 }
142 }
143
144 foreach ($campaignsSubscriptionData['donorsCount'] as $i => $data) {
145 if ($data['campaign_id'] == $campaign->id) {
146 $campaignsSubscriptionData['donorsCount'][$i] = $this->row($subscriptions->collectDonors(), $campaign->id, 'count');
147 break;
148 }
149 }
150 }
151
152
153 // Save updated cache
154 if ($isCached) {
155 update_option('give_campaigns_data', $campaignsData);
156 }
157
158 if ($isSubscriptionCached) {
159 update_option('give_campaigns_subscriptions_data', $campaignsSubscriptionData);
160 }
161
162 if ($isCached || $isSubscriptionCached) {
163 return;
164 }
165
166 update_option('give_campaigns_data', [
167 'amounts' => array_merge(
168 $campaignsData['amounts'] ?? [],
169 $donations->collectIntendedAmounts()
170 ),
171 'donationsCount' => array_merge(
172 $campaignsData['donationsCount'] ?? [],
173 $donations->collectDonations()
174 ),
175 'donorsCount' => array_merge(
176 $campaignsData['donorsCount'] ?? [],
177 $donations->collectDonors()
178 ),
179 ]);
180
181 if (defined('GIVE_RECURRING_VERSION')) {
182 update_option('give_campaigns_subscriptions_data', [
183 'amounts' => array_merge(
184 $campaignsSubscriptionData['amounts'] ?? [],
185 $subscriptions->collectInitialAmounts()
186 ),
187 'donationsCount' => array_merge(
188 $campaignsSubscriptionData['donationsCount'] ?? [],
189 $subscriptions->collectDonations()
190 ),
191 'donorsCount' => array_merge(
192 $campaignsSubscriptionData['donorsCount'] ?? [],
193 $subscriptions->collectDonors()
194 ),
195 ]);
196 }
197 }
198
199 /**
200 * The aggregate queries return no row for a campaign with no donations. Keep a zero row so the
201 * campaign stays cached instead of turning into a null row and a PHP warning.
202 *
203 * @since 4.18.0
204 */
205 private function row($rows, int $campaignId, string $column): array
206 {
207 return $rows[0] ?? ['campaign_id' => (string)$campaignId, $column => 0];
208 }
209 }
210