Merge pull request #22832 from jmcclelland/ufexport
[civicrm-core.git] / ext / contributioncancelactions / contributioncancelactions.php
index 2ec3aae284fa85aef5c403b27c3158e63d7d898d..26fea163413380231987cd1cf8c4600a328025e1 100644 (file)
@@ -5,39 +5,81 @@ require_once 'contributioncancelactions.civix.php';
 use CRM_Contributioncancelactions_ExtensionUtil as E;
 // phpcs:enable
 use Civi\Api4\LineItem;
+use Civi\Api4\Participant;
 
 /**
  * Implements hook_civicrm_preProcess().
  *
  * This enacts the following
  * - find and cancel any related pending memberships
- * - (not yet implemented) find and cancel any related pending participant records
- * - (not yet implemented) find any related pledge payment records. Remove the contribution id.
+ * - (not yet implemented) find and cancel any related pending participant
+ * records
+ * - (not yet implemented) find any related pledge payment records. Remove the
+ * contribution id.
  *
  * @link https://docs.civicrm.org/dev/en/latest/hooks/hook_civicrm_post
+ *
+ * @throws \CiviCRM_API3_Exception
+ * @throws \API_Exception
  */
 function contributioncancelactions_civicrm_post($op, $objectName, $objectId, $objectRef) {
   if ($op === 'edit' && $objectName === 'Contribution') {
-    if ('Cancelled' === CRM_Core_PseudoConstant::getName('CRM_Contribute_BAO_Contribution', 'contribution_status_id', $objectRef->contribution_status_id)) {
-      // Find and cancel any pending memberships.
-      $connectedMemberships = (array) LineItem::get(FALSE)->setWhere([
-        ['contribution_id', '=', $objectId],
-        ['entity_table', '=', 'civicrm_membership'],
-      ])->execute()->indexBy('entity_id');
-      if (empty($connectedMemberships)) {
-        return;
-      }
-      // @todo we don't have v4 membership api yet so v3 for now.
-      $connectedMemberships = array_keys(civicrm_api3('Membership', 'get', [
-        'status_id' => 'Pending',
-        'id' => ['IN' => array_keys($connectedMemberships)],
-      ])['values']);
-      if (empty($connectedMemberships)) {
-        return;
-      }
-      foreach ($connectedMemberships as $membershipID) {
-        civicrm_api3('Membership', 'create', ['status_id' => 'Cancelled', 'id' => $membershipID, 'is_override' => 1]);
-      }
+    if (in_array(CRM_Core_PseudoConstant::getName('CRM_Contribute_BAO_Contribution', 'contribution_status_id', $objectRef->contribution_status_id),
+      ['Cancelled', 'Failed']
+    )) {
+      contributioncancelactions_cancel_related_pending_memberships((int) $objectId);
+      contributioncancelactions_cancel_related_pending_participant_records((int) $objectId);
     }
   }
 }
+
+/**
+ * Find and cancel any pending participant records.
+ *
+ * @param int $contributionID
+ * @throws CiviCRM_API3_Exception
+ */
+function contributioncancelactions_cancel_related_pending_participant_records($contributionID): void {
+  $pendingStatuses = CRM_Event_PseudoConstant::participantStatus(NULL, "class = 'Pending'");
+  $waitingStatuses = CRM_Event_PseudoConstant::participantStatus(NULL, "class = 'Waiting'");
+  $cancellableParticipantRecords = civicrm_api3('ParticipantPayment', 'get', [
+    'contribution_id' => $contributionID,
+    'participant_id.status_id' => ['IN' => array_merge(array_keys($pendingStatuses), array_keys($waitingStatuses))],
+  ])['values'];
+  if (empty($cancellableParticipantRecords)) {
+    return;
+  }
+  Participant::update(FALSE)
+    ->addWhere('id', 'IN', array_keys($cancellableParticipantRecords))
+    ->setValues(['status_id:name' => 'Cancelled'])
+    ->execute();
+}
+
+/**
+ * Find and cancel any pending memberships.
+ *
+ * @param int $contributionID
+ * @throws API_Exception
+ * @throws CiviCRM_API3_Exception
+ */
+function contributioncancelactions_cancel_related_pending_memberships($contributionID): void {
+  $connectedMemberships = (array) LineItem::get(FALSE)->setWhere([
+    ['contribution_id', '=', $contributionID],
+    ['entity_table', '=', 'civicrm_membership'],
+  ])->execute()->indexBy('entity_id');
+
+  if (empty($connectedMemberships)) {
+    return;
+  }
+  // @todo we don't have v4 membership api yet so v3 for now.
+  $connectedMemberships = array_keys(civicrm_api3('Membership', 'get', [
+    'status_id' => 'Pending',
+    'id' => ['IN' => array_keys($connectedMemberships)],
+  ])['values']);
+  if (empty($connectedMemberships)) {
+    return;
+  }
+  foreach ($connectedMemberships as $membershipID) {
+    civicrm_api3('Membership', 'create', ['status_id' => 'Cancelled', 'id' => $membershipID, 'is_override' => 1, 'status_override_end_date' => 'null']);
+  }
+}