Merge pull request #18794 from eileenmcnaughton/need_less
[civicrm-core.git] / ext / contributioncancelactions / contributioncancelactions.php
1 <?php
2
3 require_once 'contributioncancelactions.civix.php';
4 // phpcs:disable
5 use CRM_Contributioncancelactions_ExtensionUtil as E;
6 // phpcs:enable
7 use Civi\Api4\LineItem;
8 use Civi\Api4\Participant;
9
10 /**
11 * Implements hook_civicrm_preProcess().
12 *
13 * This enacts the following
14 * - find and cancel any related pending memberships
15 * - (not yet implemented) find and cancel any related pending participant
16 * records
17 * - (not yet implemented) find any related pledge payment records. Remove the
18 * contribution id.
19 *
20 * @link https://docs.civicrm.org/dev/en/latest/hooks/hook_civicrm_post
21 *
22 * @throws \CiviCRM_API3_Exception
23 * @throws \API_Exception
24 */
25 function contributioncancelactions_civicrm_post($op, $objectName, $objectId, $objectRef) {
26 if ($op === 'edit' && $objectName === 'Contribution') {
27 if (in_array(CRM_Core_PseudoConstant::getName('CRM_Contribute_BAO_Contribution', 'contribution_status_id', $objectRef->contribution_status_id),
28 ['Cancelled', 'Failed']
29 )) {
30 contributioncancelactions_cancel_related_pending_memberships((int) $objectId);
31 contributioncancelactions_cancel_related_pending_participant_records((int) $objectId);
32 contributioncancelactions_update_related_pledge((int) $objectId, (int) $objectRef->contribution_status_id);
33 }
34 }
35 }
36
37 /**
38 * Update any related pledge when a contribution is cancelled.
39 *
40 * This updates the status of the pledge and amount paid.
41 *
42 * The functionality should probably be give more thought in that it currently
43 * does not un-assign the contribution id from the pledge payment. However,
44 * at time of writing the goal is to move rather than fix functionality.
45 *
46 * @param int $contributionID
47 * @param int $contributionStatusID
48 *
49 * @throws CiviCRM_API3_Exception
50 */
51 function contributioncancelactions_update_related_pledge(int $contributionID, int $contributionStatusID) {
52 $pledgePayments = civicrm_api3('PledgePayment', 'get', ['contribution_id' => $contributionID])['values'];
53 if (!empty($pledgePayments)) {
54 $pledgePaymentIDS = array_keys($pledgePayments);
55 $pledgePayment = reset($pledgePayments);
56 CRM_Pledge_BAO_PledgePayment::updatePledgePaymentStatus($pledgePayment['pledge_id'], $pledgePaymentIDS, $contributionStatusID);
57 }
58 }
59
60 /**
61 * Find and cancel any pending participant records.
62 *
63 * @param int $contributionID
64 * @throws CiviCRM_API3_Exception
65 */
66 function contributioncancelactions_cancel_related_pending_participant_records($contributionID): void {
67 $pendingStatuses = CRM_Event_PseudoConstant::participantStatus(NULL, "class = 'Pending'");
68 $waitingStatuses = CRM_Event_PseudoConstant::participantStatus(NULL, "class = 'Waiting'");
69 $cancellableParticipantRecords = civicrm_api3('ParticipantPayment', 'get', [
70 'contribution_id' => $contributionID,
71 'participant_id.status_id' => ['IN' => array_merge(array_keys($pendingStatuses), array_keys($waitingStatuses))],
72 ])['values'];
73 if (empty($cancellableParticipantRecords)) {
74 return;
75 }
76 Participant::update(FALSE)
77 ->addWhere('id', 'IN', array_keys($cancellableParticipantRecords))
78 ->setValues(['status_id:name' => 'Cancelled'])
79 ->execute();
80 }
81
82 /**
83 * Find and cancel any pending memberships.
84 *
85 * @param int $contributionID
86 * @throws API_Exception
87 * @throws CiviCRM_API3_Exception
88 */
89 function contributioncancelactions_cancel_related_pending_memberships($contributionID): void {
90 $connectedMemberships = (array) LineItem::get(FALSE)->setWhere([
91 ['contribution_id', '=', $contributionID],
92 ['entity_table', '=', 'civicrm_membership'],
93 ])->execute()->indexBy('entity_id');
94
95 if (empty($connectedMemberships)) {
96 return;
97 }
98 // @todo we don't have v4 membership api yet so v3 for now.
99 $connectedMemberships = array_keys(civicrm_api3('Membership', 'get', [
100 'status_id' => 'Pending',
101 'id' => ['IN' => array_keys($connectedMemberships)],
102 ])['values']);
103 if (empty($connectedMemberships)) {
104 return;
105 }
106 foreach ($connectedMemberships as $membershipID) {
107 civicrm_api3('Membership', 'create', ['status_id' => 'Cancelled', 'id' => $membershipID, 'is_override' => 1, 'status_override_end_date' => 'null']);
108 }
109 }