Swap CRM_Utils_Array::value for empty() or isset() in conditionals
[civicrm-core.git] / CRM / Contribute / BAO / Contribution.php
index a45652a17ae2d6a2da3edc595080eed969ded736..ebc06b6e47f08a349f547e878b8cb02809fee4c6 100644 (file)
@@ -110,7 +110,7 @@ class CRM_Contribute_BAO_Contribution extends CRM_Contribute_DAO_Contribution {
     $contributionID = CRM_Utils_Array::value('contribution', $ids, CRM_Utils_Array::value('id', $params));
     $duplicates = [];
     if (self::checkDuplicate($params, $duplicates, $contributionID)) {
-      $message = ts("Duplicate error - existing contribution record(s) have a matching Transaction ID or Invoice ID. Contribution record ID(s) are: " . implode(', ', $duplicates));
+      $message = ts("Duplicate error - existing contribution record(s) have a matching Transaction ID or Invoice ID. Contribution record ID(s) are: %1", [1 => implode(', ', $duplicates)]);
       throw new CRM_Core_Exception($message);
     }
 
@@ -992,7 +992,7 @@ class CRM_Contribute_BAO_Contribution extends CRM_Contribute_DAO_Contribution {
     // as they would then me membership.contact_id, membership.is_test etc
     return civicrm_api3('Membership', 'get', [
       'id' => ['IN' => $membershipIDs],
-      'return' => ['id', 'contact_id', 'membership_type_id', 'is_test'],
+      'return' => ['id', 'contact_id', 'membership_type_id', 'is_test', 'status_id', 'end_date'],
     ])['values'];
   }
 
@@ -2913,6 +2913,7 @@ INNER JOIN civicrm_activity ON civicrm_activity_contact.activity_id = civicrm_ac
    *   The set of ids related to the input.
    *
    * @return array
+   * @throws \CRM_Core_Exception
    */
   public function _gatherMessageValues($input, &$values, $ids = []) {
     // set display address of contributor
@@ -2961,7 +2962,7 @@ INNER JOIN civicrm_activity ON civicrm_activity_contact.activity_id = civicrm_ac
         if (!empty($lineItems)) {
           $firstLineItem = reset($lineItems);
           $priceSet = [];
-          if (CRM_Utils_Array::value('price_set_id', $firstLineItem)) {
+          if (!empty($firstLineItem['price_set_id'])) {
             $priceSet = civicrm_api3('PriceSet', 'getsingle', [
               'id' => $firstLineItem['price_set_id'],
               'return' => 'is_quick_config, id',
@@ -2994,92 +2995,7 @@ INNER JOIN civicrm_activity ON civicrm_activity_contact.activity_id = civicrm_ac
       }
     }
     else {
-      // event
-      $eventParams = [
-        'id' => $this->_relatedObjects['event']->id,
-      ];
-      $values['event'] = [];
-
-      CRM_Event_BAO_Event::retrieve($eventParams, $values['event']);
-      // add custom fields for event
-      $eventGroupTree = CRM_Core_BAO_CustomGroup::getTree('Event', NULL, $this->_relatedObjects['event']->id);
-
-      $eventCustomGroup = [];
-      foreach ($eventGroupTree as $key => $group) {
-        if ($key === 'info') {
-          continue;
-        }
-
-        foreach ($group['fields'] as $k => $customField) {
-          $groupLabel = $group['title'];
-          if (!empty($customField['customValue'])) {
-            foreach ($customField['customValue'] as $customFieldValues) {
-              $eventCustomGroup[$groupLabel][$customField['label']] = CRM_Utils_Array::value('data', $customFieldValues);
-            }
-          }
-        }
-      }
-      $values['event']['customGroup'] = $eventCustomGroup;
-
-      //get participant details
-      $participantParams = [
-        'id' => $this->_relatedObjects['participant']->id,
-      ];
-
-      $values['participant'] = [];
-
-      CRM_Event_BAO_Participant::getValues($participantParams, $values['participant'], $participantIds);
-      // add custom fields for event
-      $participantGroupTree = CRM_Core_BAO_CustomGroup::getTree('Participant', NULL, $this->_relatedObjects['participant']->id);
-      $participantCustomGroup = [];
-      foreach ($participantGroupTree as $key => $group) {
-        if ($key === 'info') {
-          continue;
-        }
-
-        foreach ($group['fields'] as $k => $customField) {
-          $groupLabel = $group['title'];
-          if (!empty($customField['customValue'])) {
-            foreach ($customField['customValue'] as $customFieldValues) {
-              $participantCustomGroup[$groupLabel][$customField['label']] = CRM_Utils_Array::value('data', $customFieldValues);
-            }
-          }
-        }
-      }
-      $values['participant']['customGroup'] = $participantCustomGroup;
-
-      //get location details
-      $locationParams = [
-        'entity_id' => $this->_relatedObjects['event']->id,
-        'entity_table' => 'civicrm_event',
-      ];
-      $values['location'] = CRM_Core_BAO_Location::getValues($locationParams);
-
-      $ufJoinParams = [
-        'entity_table' => 'civicrm_event',
-        'entity_id' => $ids['event'],
-        'module' => 'CiviEvent',
-      ];
-
-      list($custom_pre_id,
-        $custom_post_ids
-        ) = CRM_Core_BAO_UFJoin::getUFGroupIds($ufJoinParams);
-
-      $values['custom_pre_id'] = $custom_pre_id;
-      $values['custom_post_id'] = $custom_post_ids;
-
-      // set lineItem for event contribution
-      if ($this->id) {
-        $participantIds = CRM_Event_BAO_Participant::getParticipantIds($this->id);
-        if (!empty($participantIds)) {
-          foreach ($participantIds as $pIDs) {
-            $lineItem = CRM_Price_BAO_LineItem::getLineItems($pIDs);
-            if (!CRM_Utils_System::isNull($lineItem)) {
-              $values['lineItem'][] = $lineItem;
-            }
-          }
-        }
-      }
+      $values = array_merge($values, $this->loadEventMessageTemplateParams((int) $ids['event'], (int) $this->_relatedObjects['participant']->id, $this->id));
     }
 
     $groupTree = CRM_Core_BAO_CustomGroup::getTree('Contribution', NULL, $this->id);
@@ -3891,6 +3807,7 @@ INNER JOIN civicrm_activity ON civicrm_activity_contact.activity_id = civicrm_ac
       'In Progress' => ['Cancelled', 'Completed', 'Failed'],
       'Refunded' => ['Cancelled', 'Completed'],
       'Partially paid' => ['Completed'],
+      'Pending refund' => ['Completed', 'Refunded'],
     ];
 
     if (!in_array($contributionStatuses[$fields['contribution_status_id']],
@@ -4013,6 +3930,7 @@ INNER JOIN civicrm_activity ON civicrm_activity_contact.activity_id = civicrm_ac
     elseif ($paymentType == 'refund') {
       $trxnsData['total_amount'] = -$trxnsData['total_amount'];
       $trxnsData['participant_id'] = $participantId;
+      $trxnsData['contribution_id'] = $contributionId;
       return civicrm_api3('Payment', 'create', $trxnsData)['id'];
     }
   }
@@ -4095,7 +4013,7 @@ INNER JOIN civicrm_activity ON civicrm_activity_contact.activity_id = civicrm_ac
       $baseTrxnId = CRM_Core_BAO_FinancialTrxn::getFinancialTrxnId($contributionId);
       $baseTrxnId = $baseTrxnId['financialTrxnId'];
     }
-    if (!CRM_Utils_Array::value('total_amount', $total) || $usingLineTotal) {
+    if (empty($total['total_amount']) || $usingLineTotal) {
       $total = CRM_Price_BAO_LineItem::getLineTotal($contributionId);
     }
     else {
@@ -4620,7 +4538,7 @@ INNER JOIN civicrm_activity ON civicrm_activity_contact.activity_id = civicrm_ac
     $contributionResult = civicrm_api3('Contribution', 'create', $contributionParams);
 
     // Add new soft credit against current $contribution.
-    if (CRM_Utils_Array::value('contributionRecur', $objects) && $objects['contributionRecur']->id) {
+    if (!empty($objects['contributionRecur']) && $objects['contributionRecur']->id) {
       CRM_Contribute_BAO_ContributionRecur::addrecurSoftCredit($objects['contributionRecur']->id, $contribution->id);
     }
 
@@ -5128,7 +5046,7 @@ INNER JOIN civicrm_activity ON civicrm_activity_contact.activity_id = civicrm_ac
   public static function checkContributeSettings($name = NULL, $checkInvoicing = FALSE) {
     $contributeSettings = Civi::settings()->get('contribution_invoice_settings');
 
-    if ($checkInvoicing && !CRM_Utils_Array::value('invoicing', $contributeSettings)) {
+    if ($checkInvoicing && empty($contributeSettings['invoicing'])) {
       return NULL;
     }
 
@@ -5410,11 +5328,16 @@ LIMIT 1;";
           $membershipParams['membership_type_id'] = $dao->membership_type_id;
         }
       }
-
-      $membershipParams['num_terms'] = $contribution->getNumTermsByContributionAndMembershipType(
-        $membershipParams['membership_type_id'],
-        $primaryContributionID
-      );
+      if (empty($membership['end_date']) || (int) $membership['status_id'] !== CRM_Core_PseudoConstant::getKey('CRM_Member_BAO_Membership', 'status_id', 'Pending')) {
+        // Passing num_terms to the api triggers date calculations, but for pending memberships these may be already calculated.
+        // sigh - they should  be  consistent but removing the end date check causes test failures & maybe UI too?
+        // The api assumes num_terms is a special sauce for 'is_renewal' so we need to not pass it when updating a pending to completed.
+        // @todo once apiv4 ships with core switch to that & find sanity.
+        $membershipParams['num_terms'] = $contribution->getNumTermsByContributionAndMembershipType(
+          $membershipParams['membership_type_id'],
+          $primaryContributionID
+        );
+      }
       // @todo remove all this stuff in favour of letting the api call further down handle in
       // (it is a duplication of what the api does).
       $dates = array_fill_keys([
@@ -5905,7 +5828,7 @@ LIMIT 1;";
     }
     $contributionDetails = [];
     foreach ($contributionIds as $id) {
-      $result = civicrm_api3('Contribution', 'get', ['id' => $id]);
+      $result = self::getContributionTokenValues($id, $messageToken);
       $contributionDetails[$result['values'][$result['id']]['contact_id']]['subject'] = CRM_Utils_Token::replaceContributionTokens($subject, $result, FALSE, $subjectToken, FALSE, $escapeSmarty);
       $contributionDetails[$result['values'][$result['id']]['contact_id']]['text'] = CRM_Utils_Token::replaceContributionTokens($text, $result, FALSE, $messageToken, FALSE, $escapeSmarty);
       $contributionDetails[$result['values'][$result['id']]['contact_id']]['html'] = CRM_Utils_Token::replaceContributionTokens($html, $result, FALSE, $messageToken, FALSE, $escapeSmarty);
@@ -5913,6 +5836,30 @@ LIMIT 1;";
     return $contributionDetails;
   }
 
+  /**
+   * Get the contribution fields for $id and display labels where
+   * appropriate (if the token is present).
+   *
+   * @param int $id
+   * @param array $messageToken
+   * @return array
+   */
+  public static function getContributionTokenValues($id, $messageToken) {
+    if (empty($id)) {
+      return [];
+    }
+    $result = civicrm_api3('Contribution', 'get', ['id' => $id]);
+    // lab.c.o mail#46 - show labels, not values, for custom fields with option values.
+    if (!empty($messageToken)) {
+      foreach ($result['values'][$id] as $fieldName => $fieldValue) {
+        if (strpos($fieldName, 'custom_') === 0 && array_search($fieldName, $messageToken['contribution']) !== FALSE) {
+          $result['values'][$id][$fieldName] = CRM_Core_BAO_CustomField::displayValue($result['values'][$id][$fieldName], $fieldName);
+        }
+      }
+    }
+    return $result;
+  }
+
   /**
    * Get invoice_number for contribution.
    *
@@ -5928,4 +5875,104 @@ LIMIT 1;";
     return NULL;
   }
 
+  /**
+   * Load the values needed for the event message.
+   *
+   * @param int $eventID
+   * @param int $participantID
+   * @param int|null $contributionID
+   *
+   * @return array
+   * @throws \CRM_Core_Exception
+   */
+  protected function loadEventMessageTemplateParams(int $eventID, int $participantID, $contributionID): array {
+
+    $eventParams = [
+      'id' => $eventID,
+    ];
+    $values = ['event' => []];
+
+    CRM_Event_BAO_Event::retrieve($eventParams, $values['event']);
+    // add custom fields for event
+    $eventGroupTree = CRM_Core_BAO_CustomGroup::getTree('Event', NULL, $eventID);
+
+    $eventCustomGroup = [];
+    foreach ($eventGroupTree as $key => $group) {
+      if ($key === 'info') {
+        continue;
+      }
+
+      foreach ($group['fields'] as $k => $customField) {
+        $groupLabel = $group['title'];
+        if (!empty($customField['customValue'])) {
+          foreach ($customField['customValue'] as $customFieldValues) {
+            $eventCustomGroup[$groupLabel][$customField['label']] = CRM_Utils_Array::value('data', $customFieldValues);
+          }
+        }
+      }
+    }
+    $values['event']['customGroup'] = $eventCustomGroup;
+
+    //get participant details
+    $participantParams = [
+      'id' => $participantID,
+    ];
+
+    $values['participant'] = [];
+
+    CRM_Event_BAO_Participant::getValues($participantParams, $values['participant'], $participantIds);
+    // add custom fields for event
+    $participantGroupTree = CRM_Core_BAO_CustomGroup::getTree('Participant', NULL, $participantID);
+    $participantCustomGroup = [];
+    foreach ($participantGroupTree as $key => $group) {
+      if ($key === 'info') {
+        continue;
+      }
+
+      foreach ($group['fields'] as $k => $customField) {
+        $groupLabel = $group['title'];
+        if (!empty($customField['customValue'])) {
+          foreach ($customField['customValue'] as $customFieldValues) {
+            $participantCustomGroup[$groupLabel][$customField['label']] = CRM_Utils_Array::value('data', $customFieldValues);
+          }
+        }
+      }
+    }
+    $values['participant']['customGroup'] = $participantCustomGroup;
+
+    //get location details
+    $locationParams = [
+      'entity_id' => $eventID,
+      'entity_table' => 'civicrm_event',
+    ];
+    $values['location'] = CRM_Core_BAO_Location::getValues($locationParams);
+
+    $ufJoinParams = [
+      'entity_table' => 'civicrm_event',
+      'entity_id' => $eventID,
+      'module' => 'CiviEvent',
+    ];
+
+    list($custom_pre_id,
+      $custom_post_ids
+      ) = CRM_Core_BAO_UFJoin::getUFGroupIds($ufJoinParams);
+
+    $values['custom_pre_id'] = $custom_pre_id;
+    $values['custom_post_id'] = $custom_post_ids;
+
+    // set lineItem for event contribution
+    if ($contributionID) {
+      $participantIds = CRM_Event_BAO_Participant::getParticipantIds($contributionID);
+      if (!empty($participantIds)) {
+        foreach ($participantIds as $pIDs) {
+          $lineItem = CRM_Price_BAO_LineItem::getLineItems($pIDs);
+          if (!CRM_Utils_System::isNull($lineItem)) {
+            $values['lineItem'][] = $lineItem;
+          }
+        }
+      }
+    }
+    return $values;
+  }
+
 }