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']);
+ }
+}