← All changes
|
src/Subscriptions/Repositories/SubscriptionRepository.php
+180
-14
2.30.0
→
4.16.9
View file →
| @@ -2,9 +2,13 @@ | ||
| 2 | 2 | |
| 3 | 3 | namespace Give\Subscriptions\Repositories; |
| 4 | 4 | |
| 5 | 5 | use Exception; |
| 6 | +use Give\Donations\Models\Donation; | |
| 6 | 7 | use Give\Donations\ValueObjects\DonationMetaKeys; |
| 8 | +use Give\Donations\ValueObjects\DonationMode; | |
| 9 | +use Give\Donations\ValueObjects\DonationStatus; | |
| 10 | +use Give\Donations\ValueObjects\DonationType; | |
| 7 | 11 | use Give\Framework\Database\DB; |
| 8 | 12 | use Give\Framework\Exceptions\Primitives\InvalidArgumentException; |
| 9 | 13 | use Give\Framework\Models\ModelQueryBuilder; |
| 10 | 14 | use Give\Framework\Support\Facades\DateTime\Temporal; |
| @@ -11,15 +15,22 @@ | ||
| 11 | 15 | use Give\Helpers\Hooks; |
| 12 | 16 | use Give\Log\Log; |
| 13 | 17 | use Give\Subscriptions\Models\Subscription; |
| 14 | 18 | use Give\Subscriptions\ValueObjects\SubscriptionMode; |
| 19 | +use Give\Subscriptions\ValueObjects\SubscriptionStatus; | |
| 15 | 20 | |
| 16 | 21 | /** |
| 22 | + * @since 4.8.0 Add notes repository | |
| 17 | 23 | * @since 2.19.6 |
| 18 | 24 | */ |
| 19 | 25 | class SubscriptionRepository |
| 20 | 26 | { |
| 21 | 27 | /** |
| 28 | + * @var SubscriptionNotesRepository | |
| 29 | + */ | |
| 30 | + public $notes; | |
| 31 | + | |
| 32 | + /** | |
| 22 | 33 | * @var string[] |
| 23 | 34 | */ |
| 24 | 35 | private $requiredSubscriptionProperties = [ |
| 25 | 36 | 'donorId', |
| @@ -30,8 +41,16 @@ | ||
| 30 | 41 | 'donationFormId', |
| 31 | 42 | ]; |
| 32 | 43 | |
| 33 | 44 | /** |
| 45 | + * @since 4.8.0 | |
| 46 | + */ | |
| 47 | + public function __construct() | |
| 48 | + { | |
| 49 | + $this->notes = give(SubscriptionNotesRepository::class); | |
| 50 | + } | |
| 51 | + | |
| 52 | + /** | |
| 34 | 53 | * @since 2.19.6 |
| 35 | 54 | * |
| 36 | 55 | * @return Subscription|null |
| 37 | 56 | */ |
| @@ -66,16 +85,14 @@ | ||
| 66 | 85 | |
| 67 | 86 | /** |
| 68 | 87 | * @since 2.21.0 |
| 69 | 88 | * |
| 70 | - * @param string $gatewayTransactionId | |
| 71 | - * | |
| 72 | 89 | * @return ModelQueryBuilder<Subscription> |
| 73 | 90 | */ |
| 74 | - public function queryByGatewaySubscriptionId(string $gatewayTransactionId): ModelQueryBuilder | |
| 91 | + public function queryByGatewaySubscriptionId(string $gatewaySubscriptionId): ModelQueryBuilder | |
| 75 | 92 | { |
| 76 | 93 | return $this->prepareQuery() |
| 77 | - ->where('profile_id', $gatewayTransactionId); | |
| 94 | + ->where('profile_id', $gatewaySubscriptionId); | |
| 78 | 95 | } |
| 79 | 96 | |
| 80 | 97 | /** |
| 81 | 98 | * @since 2.19.6 |
| @@ -103,8 +120,22 @@ | ||
| 103 | 120 | ->where('customer_id', $donorId); |
| 104 | 121 | } |
| 105 | 122 | |
| 106 | 123 | /** |
| 124 | + * @since 4.11.0 | |
| 125 | + * | |
| 126 | + * @param int $campaignId | |
| 127 | + * | |
| 128 | + * @return ModelQueryBuilder<Subscription> | |
| 129 | + */ | |
| 130 | + public function queryByCampaignId(int $campaignId): ModelQueryBuilder | |
| 131 | + { | |
| 132 | + return $this->prepareQuery() | |
| 133 | + ->where('campaign_id', $campaignId); | |
| 134 | + } | |
| 135 | + | |
| 136 | + /** | |
| 137 | + * @deprecated Use give()->subscriptions->notes()->queryBySubscriptionId()->getAll() instead. | |
| 107 | 138 | * @since 2.19.6 |
| 108 | 139 | * |
| 109 | 140 | * @return object[] |
| 110 | 141 | */ |
| @@ -109,18 +140,20 @@ | ||
| 109 | 140 | * @return object[] |
| 110 | 141 | */ |
| 111 | 142 | public function getNotesBySubscriptionId(int $id): array |
| 112 | 143 | { |
| 113 | - $notes = DB::table('comments') | |
| 114 | - ->select( | |
| 115 | - ['comment_content', 'note'], | |
| 116 | - ['comment_date', 'date'] | |
| 117 | - ) | |
| 118 | - ->where('comment_post_ID', $id) | |
| 119 | - ->where('comment_type', 'give_sub_note') | |
| 120 | - ->orderBy('comment_date', 'DESC') | |
| 121 | - ->getAll(); | |
| 144 | + _give_deprecated_function(__METHOD__, '4.6.0', 'give()->subscriptions->notes()->queryBySubscriptionId()->getAll()'); | |
| 122 | 145 | |
| 146 | + $notes = array_map( | |
| 147 | + static function ($note) { | |
| 148 | + return array_merge($note->toArray(), [ | |
| 149 | + 'note' => $note->comment_content, | |
| 150 | + 'date' => $note->comment_date, | |
| 151 | + ]); | |
| 152 | + }, | |
| 153 | + $this->notes->queryBySubscriptionId($id)->getAll() | |
| 154 | + ); | |
| 155 | + | |
| 123 | 156 | if (!$notes) { |
| 124 | 157 | return []; |
| 125 | 158 | } |
| 126 | 159 | |
| @@ -127,8 +160,9 @@ | ||
| 127 | 160 | return $notes; |
| 128 | 161 | } |
| 129 | 162 | |
| 130 | 163 | /** |
| 164 | + * @since 4.11.0 add campaign_id column to insert | |
| 131 | 165 | * @since 2.24.0 add payment_mode column to insert |
| 132 | 166 | * @since 2.21.0 replace actions with givewp_subscription_creating and givewp_subscription_created |
| 133 | 167 | * @since 2.19.6 |
| 134 | 168 | * |
| @@ -142,8 +176,14 @@ | ||
| 142 | 176 | if ($subscription->renewsAt === null) { |
| 143 | 177 | $subscription->bumpRenewalDate(); |
| 144 | 178 | } |
| 145 | 179 | |
| 180 | + // If the subscription is not associated with a campaign, try to find the campaign ID by the form ID | |
| 181 | + if (!$subscription->campaignId) { | |
| 182 | + $campaign = give()->campaigns->getByFormId($subscription->donationFormId); | |
| 183 | + $subscription->campaignId = $campaign ? $campaign->id : null; | |
| 184 | + } | |
| 185 | + | |
| 146 | 186 | Hooks::doAction('givewp_subscription_creating', $subscription); |
| 147 | 187 | |
| 148 | 188 | $dateCreated = Temporal::withoutMicroseconds($subscription->createdAt ?: Temporal::getCurrentDateTime()); |
| 149 | 189 | |
| @@ -164,8 +204,9 @@ | ||
| 164 | 204 | ) : 0, |
| 165 | 205 | 'bill_times' => $subscription->installments, |
| 166 | 206 | 'transaction_id' => $subscription->transactionId ?? '', |
| 167 | 207 | 'product_id' => $subscription->donationFormId, |
| 208 | + 'campaign_id' => $subscription->campaignId, | |
| 168 | 209 | 'payment_mode' => $subscription->mode->getValue(), |
| 169 | 210 | ]); |
| 170 | 211 | } catch (Exception $exception) { |
| 171 | 212 | DB::query('ROLLBACK'); |
| @@ -185,8 +226,10 @@ | ||
| 185 | 226 | Hooks::doAction('givewp_subscription_created', $subscription); |
| 186 | 227 | } |
| 187 | 228 | |
| 188 | 229 | /** |
| 230 | + * @since 4.11.0 add campaign_id column to update | |
| 231 | + * @since 3.17.0 add expiration column to update | |
| 189 | 232 | * @since 2.24.0 add payment_mode column to update |
| 190 | 233 | * @since 2.21.0 replace actions with givewp_subscription_updating and givewp_subscription_updated |
| 191 | 234 | * @since 2.19.6 |
| 192 | 235 | * |
| @@ -208,8 +251,9 @@ | ||
| 208 | 251 | try { |
| 209 | 252 | DB::table('give_subscriptions') |
| 210 | 253 | ->where('id', $subscription->id) |
| 211 | 254 | ->update([ |
| 255 | + 'expiration' => Temporal::getFormattedDateTime($subscription->renewsAt), | |
| 212 | 256 | 'status' => $subscription->status->getValue(), |
| 213 | 257 | 'profile_id' => $subscription->gatewaySubscriptionId, |
| 214 | 258 | 'customer_id' => $subscription->donorId, |
| 215 | 259 | 'period' => $subscription->period->getValue(), |
| @@ -220,8 +264,9 @@ | ||
| 220 | 264 | ) : 0, |
| 221 | 265 | 'bill_times' => $subscription->installments, |
| 222 | 266 | 'transaction_id' => $subscription->transactionId ?? '', |
| 223 | 267 | 'product_id' => $subscription->donationFormId, |
| 268 | + 'campaign_id' => $subscription->campaignId, | |
| 224 | 269 | 'payment_mode' => $subscription->mode->getValue(), |
| 225 | 270 | ]); |
| 226 | 271 | } catch (Exception $exception) { |
| 227 | 272 | DB::query('ROLLBACK'); |
| @@ -272,8 +317,82 @@ | ||
| 272 | 317 | return true; |
| 273 | 318 | } |
| 274 | 319 | |
| 275 | 320 | /** |
| 321 | + * @since 4.8.0 | |
| 322 | + * | |
| 323 | + * @throws Exception | |
| 324 | + */ | |
| 325 | + public function trash(Subscription $subscription): bool | |
| 326 | + { | |
| 327 | + DB::query('START TRANSACTION'); | |
| 328 | + | |
| 329 | + Hooks::doAction('givewp_subscription_trashing', $subscription); | |
| 330 | + | |
| 331 | + try { | |
| 332 | + $previousStatus = DB::table('give_subscriptions') | |
| 333 | + ->where('id', $subscription->id) | |
| 334 | + ->value('status'); | |
| 335 | + | |
| 336 | + give()->subscription_meta->update_meta($subscription->id, '_wp_trash_meta_status', $previousStatus); | |
| 337 | + give()->subscription_meta->update_meta($subscription->id, '_wp_trash_meta_time', time()); | |
| 338 | + | |
| 339 | + DB::table('give_subscriptions') | |
| 340 | + ->where('id', $subscription->id) | |
| 341 | + ->update(['status' => SubscriptionStatus::TRASHED()->getValue()]); | |
| 342 | + } catch (Exception $exception) { | |
| 343 | + DB::query('ROLLBACK'); | |
| 344 | + | |
| 345 | + Log::error('Failed trashing a subscription', compact('subscription')); | |
| 346 | + | |
| 347 | + throw new $exception('Failed trashing a subscription'); | |
| 348 | + } | |
| 349 | + | |
| 350 | + DB::query('COMMIT'); | |
| 351 | + | |
| 352 | + Hooks::doAction('givewp_subscription_trashed', $subscription); | |
| 353 | + | |
| 354 | + return true; | |
| 355 | + } | |
| 356 | + | |
| 357 | + /** | |
| 358 | + * @since 4.12.0 | |
| 359 | + * | |
| 360 | + * @throws Exception | |
| 361 | + */ | |
| 362 | + public function unTrash(Subscription $subscription): bool | |
| 363 | + { | |
| 364 | + DB::query('START TRANSACTION'); | |
| 365 | + | |
| 366 | + Hooks::doAction('givewp_subscription_untrashing', $subscription); | |
| 367 | + | |
| 368 | + try { | |
| 369 | + $previousStatus = give()->subscription_meta->get_meta($subscription->id, '_wp_trash_meta_status', true); | |
| 370 | + | |
| 371 | + // If no previous status was saved, default to 'active' | |
| 372 | + if (empty($previousStatus)) { | |
| 373 | + $previousStatus = SubscriptionStatus::ACTIVE; | |
| 374 | + } | |
| 375 | + | |
| 376 | + DB::table('give_subscriptions') | |
| 377 | + ->where('id', $subscription->id) | |
| 378 | + ->update(['status' => $previousStatus]); | |
| 379 | + } catch (Exception $exception) { | |
| 380 | + DB::query('ROLLBACK'); | |
| 381 | + | |
| 382 | + Log::error('Failed untrashing a subscription', compact('subscription')); | |
| 383 | + | |
| 384 | + throw new $exception('Failed untrashing a subscription'); | |
| 385 | + } | |
| 386 | + | |
| 387 | + DB::query('COMMIT'); | |
| 388 | + | |
| 389 | + Hooks::doAction('givewp_subscription_untrashed', $subscription); | |
| 390 | + | |
| 391 | + return true; | |
| 392 | + } | |
| 393 | + | |
| 394 | + /** | |
| 276 | 395 | * Up to this point the donation is created first and then the subscription, and the donation is stored as the |
| 277 | 396 | * parent_payment_id of the subscription. This is backwards and should not be the case. But legacy code depends on |
| 278 | 397 | * this value, so we still need to store it for now. |
| 279 | 398 | * |
| @@ -373,8 +492,53 @@ | ||
| 373 | 492 | return (int)$query->ID; |
| 374 | 493 | } |
| 375 | 494 | |
| 376 | 495 | /** |
| 496 | + * @since 4.11.0 add campaignId to renewal | |
| 497 | + * @since 4.8.1 Remove campaignId from the attributes array since it is auto-generated based on the subscription's form. | |
| 498 | + * @since 4.8.0 Add campaignId support. | |
| 499 | + * @since 3.20.0 | |
| 500 | + * @throws Exception | |
| 501 | + */ | |
| 502 | + public function createRenewal(Subscription $subscription, array $attributes = []): Donation | |
| 503 | + { | |
| 504 | + $initialDonation = $subscription->initialDonation(); | |
| 505 | + | |
| 506 | + $donation = Donation::create( | |
| 507 | + array_merge([ | |
| 508 | + 'subscriptionId' => $subscription->id, | |
| 509 | + 'gatewayId' => $subscription->gatewayId, | |
| 510 | + 'amount' => $subscription->amount, | |
| 511 | + 'status' => DonationStatus::COMPLETE(), | |
| 512 | + 'type' => DonationType::RENEWAL(), | |
| 513 | + 'donorId' => $subscription->donorId, | |
| 514 | + 'formId' => $subscription->donationFormId, | |
| 515 | + 'honorific' => $initialDonation->honorific, | |
| 516 | + 'firstName' => $initialDonation->firstName, | |
| 517 | + 'lastName' => $initialDonation->lastName, | |
| 518 | + 'email' => $initialDonation->email, | |
| 519 | + 'phone' => $initialDonation->phone, | |
| 520 | + 'anonymous' => $initialDonation->anonymous, | |
| 521 | + 'levelId' => $initialDonation->levelId, | |
| 522 | + 'company' => $initialDonation->company, | |
| 523 | + 'comment' => $initialDonation->comment, | |
| 524 | + 'billingAddress' => $initialDonation->billingAddress, | |
| 525 | + 'feeAmountRecovered' => $subscription->feeAmountRecovered, | |
| 526 | + 'exchangeRate' => $initialDonation->exchangeRate, | |
| 527 | + 'formTitle' => $initialDonation->formTitle, | |
| 528 | + 'mode' => $subscription->mode->isLive() ? DonationMode::LIVE() : DonationMode::TEST(), | |
| 529 | + 'donorIp' => $initialDonation->donorIp, | |
| 530 | + 'campaignId' => $subscription->campaignId, | |
| 531 | + ], $attributes) | |
| 532 | + ); | |
| 533 | + | |
| 534 | + $subscription->bumpRenewalDate(); | |
| 535 | + $subscription->save(); | |
| 536 | + | |
| 537 | + return $donation; | |
| 538 | + } | |
| 539 | + | |
| 540 | + /** | |
| 377 | 541 | * @since 2.19.6 |
| 378 | 542 | * |
| 379 | 543 | * @return void |
| 380 | 544 | */ |
| @@ -391,8 +555,9 @@ | ||
| 391 | 555 | } |
| 392 | 556 | } |
| 393 | 557 | |
| 394 | 558 | /** |
| 559 | + * @since 4.11.0 add campaign_id column to select | |
| 395 | 560 | * @since 2.19.6 |
| 396 | 561 | * |
| 397 | 562 | * @return ModelQueryBuilder<Subscription> |
| 398 | 563 | */ |
| @@ -414,9 +579,10 @@ | ||
| 414 | 579 | ['recurring_amount', 'amount'], |
| 415 | 580 | ['recurring_fee_amount', 'feeAmount'], |
| 416 | 581 | 'status', |
| 417 | 582 | ['profile_id', 'gatewaySubscriptionId'], |
| 418 | - ['product_id', 'donationFormId'] | |
| 583 | + ['product_id', 'donationFormId'], | |
| 584 | + ['campaign_id', 'campaignId'] | |
| 419 | 585 | ) |
| 420 | 586 | ->attachMeta( |
| 421 | 587 | 'give_donationmeta', |
| 422 | 588 | 'parent_payment_id', |