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 / Repositories / CampaignRepository.php

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

409 lines 13.4 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\Repositories;
4
5 use Exception;
6 use Give\Campaigns\Models\Campaign;
7 use Give\Campaigns\ValueObjects\CampaignType;
8 use Give\Donations\ValueObjects\DonationMetaKeys;
9 use Give\Framework\Database\DB;
10 use Give\Framework\Exceptions\Primitives\InvalidArgumentException;
11 use Give\Framework\Models\ModelQueryBuilder;
12 use Give\Framework\Support\Facades\DateTime\Temporal;
13 use Give\Helpers\Hooks;
14 use Give\Log\Log;
15
16 /**
17 * @since 4.0.0
18 */
19 class CampaignRepository
20 {
21 /**
22 * @since 4.0.0
23 *
24 * @var string[]
25 */
26 private $requiredProperties = [
27 'title',
28 'status',
29 ];
30
31 /**
32 * @since 4.0.0
33 *
34 * Get Campaign by ID
35 *
36 * @since 4.0.0
37 */
38 public function getById(int $id)
39 {
40 return $this->queryById($id)->get();
41 }
42
43 /**
44 * @since 4.0.0
45 *
46 * Query Campaign by ID
47 *
48 * @since 4.0.0
49 */
50 public function queryById(int $id): ModelQueryBuilder
51 {
52 return $this->prepareQuery()
53 ->where('id', $id);
54 }
55
56 /**
57 * @since 4.0.0
58 *
59 * Get Campaign by Form ID using a lookup table
60 */
61 public function getByFormId(int $formId)
62 {
63 return $this->queryByFormId($formId)->get();
64 }
65
66 /**
67 * @since 4.0.0
68 *
69 * @param int $formId
70 *
71 * @return ModelQueryBuilder<Campaign>
72 */
73 public function queryByFormId(int $formId): ModelQueryBuilder
74 {
75 return $this->prepareQuery()
76 ->leftJoin('give_campaign_forms', 'campaigns.id', 'forms.campaign_id', 'forms')
77 ->where('forms.form_id', $formId);
78 }
79
80 /**
81 * @since 4.18.0 Keep the original error as the previous exception when the write fails.
82 * @since 4.0.0
83 *
84 * @throws Exception|InvalidArgumentException
85 */
86 public function insert(Campaign $campaign): void
87 {
88 $this->validateProperties($campaign);
89
90 Hooks::doAction('givewp_campaign_creating', $campaign);
91
92 $currentDate = Temporal::getCurrentDateTime();
93
94 $dateCreated = Temporal::withoutMicroseconds($campaign->createdAt ?: $currentDate);
95 $dateCreatedFormatted = Temporal::getFormattedDateTime($dateCreated);
96
97 $startDate = Temporal::withoutMicroseconds($campaign->startDate ?: $currentDate);
98 $startDateFormatted = Temporal::getFormattedDateTime($startDate);
99
100 $endDateFormatted = $campaign->endDate ? Temporal::getFormattedDateTime($campaign->endDate) : $campaign->endDate;
101
102 DB::query('START TRANSACTION');
103
104 try {
105 DB::table('give_campaigns')
106 ->insert([
107 'campaign_type' => $campaign->type->getValue(),
108 'campaign_title' => wp_strip_all_tags($campaign->title, true),
109 'short_desc' => wp_strip_all_tags($campaign->shortDescription),
110 'long_desc' => wp_strip_all_tags($campaign->longDescription),
111 'campaign_logo' => $campaign->logo,
112 'campaign_image' => $campaign->image,
113 'primary_color' => $campaign->primaryColor,
114 'secondary_color' => $campaign->secondaryColor,
115 'campaign_goal' => $campaign->goal,
116 'goal_type' => $campaign->goalType->getValue(),
117 'status' => $campaign->status->getValue(),
118 'start_date' => $startDateFormatted,
119 'end_date' => $endDateFormatted,
120 'date_created' => $dateCreatedFormatted,
121 ]);
122
123 $campaignId = DB::last_insert_id();
124
125 } catch (Exception $exception) {
126 DB::query('ROLLBACK');
127
128 Log::error('Failed creating a campaign', compact('campaign'));
129
130 throw new Exception('Failed creating a campaign', 0, $exception);
131 }
132
133 DB::query('COMMIT');
134
135 $campaign->id = $campaignId;
136 $campaign->createdAt = $dateCreated;
137 $campaign->startDate = $startDate;
138
139 Hooks::doAction('givewp_campaign_created', $campaign);
140 }
141
142 /**
143 * @since 4.18.0 Keep the original error as the previous exception when the write fails.
144 * @since 4.0.0
145 *
146 * @throws Exception|InvalidArgumentException
147 */
148 public function update(Campaign $campaign): void
149 {
150 $this->validateProperties($campaign);
151
152 $startDateFormatted = Temporal::getFormattedDateTime($campaign->startDate);
153 $endDateFormatted = $campaign->endDate ? Temporal::getFormattedDateTime($campaign->endDate) : $campaign->endDate;
154
155 Hooks::doAction('givewp_campaign_updating', $campaign);
156
157 DB::query('START TRANSACTION');
158
159 try {
160 DB::table('give_campaigns')
161 ->where('id', $campaign->id)
162 ->update([
163 'campaign_type' => $campaign->type->getValue(),
164 'campaign_page_id' => $campaign->pageId,
165 'campaign_title' => wp_strip_all_tags($campaign->title, true),
166 'short_desc' => wp_strip_all_tags($campaign->shortDescription),
167 'long_desc' => wp_strip_all_tags($campaign->longDescription),
168 'campaign_logo' => $campaign->logo,
169 'campaign_image' => $campaign->image,
170 'primary_color' => $campaign->primaryColor,
171 'secondary_color' => $campaign->secondaryColor,
172 'campaign_goal' => $campaign->goal,
173 'goal_type' => $campaign->goalType->getValue(),
174 'status' => $campaign->status->getValue(),
175 'start_date' => $startDateFormatted,
176 'end_date' => $endDateFormatted,
177 ]);
178 } catch (Exception $exception) {
179 DB::query('ROLLBACK');
180
181 Log::error('Failed updating a campaign', compact('campaign'));
182
183 throw new Exception('Failed updating a campaign', 0, $exception);
184 }
185
186 DB::query('COMMIT');
187
188 Hooks::doAction('givewp_campaign_updated', $campaign);
189 }
190
191 /**
192 * @since 4.18.0 Keep the original error as the previous exception when the write fails.
193 * @since 4.0.0
194 *
195 * @throws Exception
196 */
197 public function addCampaignForm(Campaign $campaign, int $donationFormId, bool $isDefault = false)
198 {
199 Hooks::doAction('givewp_campaign_form_relationship_creating', $campaign, $donationFormId, $isDefault);
200
201 DB::query('START TRANSACTION');
202
203 try {
204 if ($isDefault) {
205 DB::table('give_campaigns')
206 ->where('id', $campaign->id)
207 ->update([
208 'form_id' => $donationFormId,
209 ]);
210
211 $campaign->defaultFormId = $donationFormId;
212 }
213
214 DB::table('give_campaign_forms')
215 ->insert([
216 'form_id' => $donationFormId,
217 'campaign_id' => $campaign->id,
218 ]);
219 } catch (Exception $exception) {
220 DB::query('ROLLBACK');
221
222 Log::error('Failed creating a campaign form relationship', compact('campaign'));
223
224 throw new Exception('Failed creating a campaign form relationship', 0, $exception);
225 }
226
227 DB::query('COMMIT');
228
229 Hooks::doAction('givewp_campaign_form_relationship_created', $campaign, $donationFormId, $isDefault);
230 }
231
232 /**
233 * @since 4.18.0 Keep the original error as the previous exception when the write fails.
234 * @since 4.0.0
235 *
236 * @throws Exception
237 */
238 public function updateDefaultCampaignForm(Campaign $campaign, int $donationFormId)
239 {
240 Hooks::doAction('givewp_campaign_default_form_updating', $campaign, $donationFormId);
241
242 DB::query('START TRANSACTION');
243
244 try {
245 DB::table('give_campaigns')
246 ->where('id', $campaign->id)
247 ->update([
248 'form_id' => $donationFormId
249 ]);
250
251 $campaign->defaultFormId = $donationFormId;
252 } catch (Exception $exception) {
253 DB::query('ROLLBACK');
254
255 Log::error('Failed updating the campaign default form', compact('campaign'));
256
257 throw new Exception('Failed updating the campaign default form', 0, $exception);
258 }
259
260 DB::query('COMMIT');
261
262 Hooks::doAction('givewp_campaign_default_form_updated', $campaign, $donationFormId);
263 }
264
265 /**
266 * @since 4.18.0 Keep the original error as the previous exception when the write fails.
267 * @since 4.0.0
268 *
269 * @throws Exception
270 */
271 public function delete(Campaign $campaign): bool
272 {
273 DB::query('START TRANSACTION');
274
275 Hooks::doAction('givewp_campaign_deleting', $campaign);
276
277 try {
278 DB::table('give_campaigns')
279 ->where('id', $campaign->id)
280 ->delete();
281
282 } catch (Exception $exception) {
283 DB::query('ROLLBACK');
284
285 Log::error('Failed deleting a campaign', compact('campaign'));
286
287 throw new Exception('Failed deleting a campaign', 0, $exception);
288 }
289
290 DB::query('COMMIT');
291
292 Hooks::doAction('givewp_campaign_deleted', $campaign);
293
294 return true;
295 }
296
297 /**
298 * @since 4.18.0 Keep the original error as the previous exception when the write fails.
299 * @since 4.0.0
300 *
301 * @throws Exception
302 */
303 public function mergeCampaigns(Campaign $destinationCampaign, Campaign ...$campaignsToMerge): bool
304 {
305 // Make sure the destination campaign ID will not be included into $campaignsToMergeIds
306 $campaignsToMergeIds = array_column($campaignsToMerge, 'id');
307 if ($key = array_search($destinationCampaign->id, $campaignsToMergeIds, true)) {
308 unset($campaignsToMergeIds[$key]);
309 }
310
311 Hooks::doAction('givewp_campaigns_merging', $destinationCampaign, $campaignsToMergeIds);
312
313 DB::query('START TRANSACTION');
314
315 try {
316 // Convert $campaignsToMergeIds to string to use it in the queries
317 $campaignsToMergeIdsString = implode(', ', $campaignsToMergeIds);
318
319 // Migrate revenue entries from campaigns to merge to the destination campaign
320 DB::query(
321 DB::prepare("UPDATE " . DB::prefix('give_revenue') . " SET campaign_id = %d WHERE campaign_id IN ($campaignsToMergeIdsString)",
322 [
323 $destinationCampaign->id,
324 ])
325 );
326
327 // Migrate forms from campaigns to merge to the destination campaign
328 DB::query(
329 DB::prepare("UPDATE " . DB::prefix('give_campaign_forms') . " SET campaign_id = %d WHERE campaign_id IN ($campaignsToMergeIdsString)",
330 [
331 $destinationCampaign->id,
332 ])
333 );
334
335 // Update donations campaign id meta value
336 DB::query(
337 DB::prepare("UPDATE " . DB::prefix('give_donationmeta') . " SET meta_value = %d WHERE meta_key = %s AND meta_value IN ($campaignsToMergeIdsString)",
338 [
339 $destinationCampaign->id,
340 DonationMetaKeys::CAMPAIGN_ID
341 ])
342 );
343
344 // Delete campaigns to merge now that we already migrated the necessary data to the destination campaign
345 DB::query("DELETE FROM " . DB::prefix('give_campaigns') . " WHERE id IN ($campaignsToMergeIdsString)");
346 } catch (Exception $exception) {
347 DB::query('ROLLBACK');
348
349 Log::error('Failed merging campaigns into destination campaign', [
350 'campaignsToMergeIds' => $campaignsToMergeIds,
351 'destinationCampaign' => compact('destinationCampaign'),
352 ]);
353
354 throw new Exception('Failed merging campaigns into destination campaign', 0, $exception);
355 }
356
357 DB::query('COMMIT');
358
359 Hooks::doAction('givewp_campaigns_merged', $destinationCampaign, $campaignsToMergeIds);
360
361 return true;
362 }
363
364 /**
365 * @since 4.0.0
366 */
367 private function validateProperties(Campaign $campaign): void
368 {
369 foreach ($this->requiredProperties as $key) {
370 if ( ! isset($campaign->$key)) {
371 throw new InvalidArgumentException("'$key' is required.");
372 }
373 }
374 }
375
376 /**
377 * @since 4.0.0
378 *
379 * @return ModelQueryBuilder<Campaign>
380 */
381 public function prepareQuery(): ModelQueryBuilder
382 {
383 $builder = new ModelQueryBuilder(Campaign::class);
384
385 return $builder->from('give_campaigns', 'campaigns')
386 ->select(
387 ['campaigns.id', 'id'],
388 ['campaigns.form_id', 'defaultFormId'], // Prefix the `form_id` column to avoid conflicts with the `give_campaign_forms` table.
389 ['campaign_type', 'type'],
390 ['campaign_page_id', 'pageId'],
391 ['campaign_title', 'title'],
392 ['short_desc', 'shortDescription'],
393 ['long_desc', 'longDescription'],
394 ['campaign_logo', 'logo'],
395 ['campaign_image', 'image'],
396 ['primary_color', 'primaryColor'],
397 ['secondary_color', 'secondaryColor'],
398 ['campaign_goal', 'goal'],
399 ['goal_type', 'goalType'],
400 'status',
401 ['start_date', 'startDate'],
402 ['end_date', 'endDate'],
403 ['date_created', 'createdAt']
404 )
405 // Select only core campaign
406 ->where('campaigns.campaign_type', CampaignType::CORE);
407 }
408 }
409