diff --git a/CRM/Contact/Import/Parser/Contact.php b/CRM/Contact/Import/Parser/Contact.php index cf7c765d590d..fc4737e2b6d0 100644 --- a/CRM/Contact/Import/Parser/Contact.php +++ b/CRM/Contact/Import/Parser/Contact.php @@ -1710,17 +1710,7 @@ protected function lookupContactID(array $params, bool $isMainContact): ?int { throw new CRM_Core_Exception(ts('External ID already exists in Database.'), CRM_Import_Parser::DUPLICATE); } if ($contactID) { - $existingContact = Contact::get(FALSE) - ->addWhere('id', '=', $contactID) - // Don't auto-filter deleted - people use import to undelete. - ->addWhere('is_deleted', 'IN', [0, 1]) - ->addSelect('contact_type')->execute()->first(); - if (empty($existingContact['id'])) { - throw new CRM_Core_Exception('No contact found for this contact ID:' . $params['id'], CRM_Import_Parser::NO_MATCH); - } - if ($existingContact['contact_type'] !== $params['contact_type']) { - throw new CRM_Core_Exception('Mismatched contact Types', CRM_Import_Parser::NO_MATCH); - } + $this->validateContactID($contactID, $params['contact_type']); return $contactID; } // Time to see if we can find an existing contact ID to make this an update diff --git a/CRM/Contribute/Import/Parser/Contribution.php b/CRM/Contribute/Import/Parser/Contribution.php index 3e781ed0499a..7847f3112082 100644 --- a/CRM/Contribute/Import/Parser/Contribution.php +++ b/CRM/Contribute/Import/Parser/Contribution.php @@ -206,7 +206,7 @@ public function init() { /** * Set field metadata. */ - protected function setFieldMetadata() { + protected function setFieldMetadata(): void { if (empty($this->importableFieldsMetadata)) { $fields = $this->importableFields($this->getContactType()); @@ -311,6 +311,9 @@ public function import($values): void { $rowNumber = (int) ($values[array_key_last($values)]); try { $params = $this->getMappedRow($values); + if (!empty($params['contact_id'])) { + $this->validateContactID($params['contact_id'], $this->getContactType()); + } $formatted = array_merge(['version' => 3, 'skipRecentView' => TRUE, 'skipCleanMoney' => TRUE, 'contribution_id' => $params['id'] ?? NULL], $params); //CRM-10994 if (isset($params['total_amount']) && $params['total_amount'] == 0) { @@ -340,17 +343,7 @@ public function import($values): void { $paramValues['contact_type'] = $this->getContactType(); } - $formatError = $this->deprecatedFormatParams($paramValues, $formatted); - - if ($formatError) { - if (CRM_Utils_Array::value('error_data', $formatError) == 'soft_credit') { - throw new CRM_Core_Exception('', self::SOFT_CREDIT_ERROR); - } - if (CRM_Utils_Array::value('error_data', $formatError) == 'pledge_payment') { - throw new CRM_Core_Exception('', self::PLEDGE_PAYMENT_ERROR); - } - throw new CRM_Core_Exception('', CRM_Import_Parser::ERROR); - } + $this->deprecatedFormatParams($paramValues, $formatted); if ($this->isUpdateExisting()) { //fix for CRM-2219 - Update Contribution @@ -611,10 +604,9 @@ public function &getImportedContributions() { * The reformatted properties that we can use internally. * @param bool $create * - * @return array|CRM_Error * @throws \CRM_Core_Exception */ - private function deprecatedFormatParams($params, &$values, $create = FALSE) { + private function deprecatedFormatParams($params, &$values, $create = FALSE): void { // copy all the contribution fields as is require_once 'api/v3/utils.php'; @@ -625,23 +617,6 @@ private function deprecatedFormatParams($params, &$values, $create = FALSE) { } switch ($key) { - case 'contact_id': - if (!CRM_Utils_Rule::integer($value)) { - return civicrm_api3_create_error("contact_id not valid: $value"); - } - $dao = new CRM_Core_DAO(); - $qParams = []; - $svq = $dao->singleValueQuery("SELECT is_deleted FROM civicrm_contact WHERE id = $value", - $qParams - ); - if (!isset($svq)) { - return civicrm_api3_create_error("Invalid Contact ID: There is no contact record with contact_id = $value."); - } - elseif ($svq == 1) { - return civicrm_api3_create_error("Invalid Contact ID: contact_id $value is a soft-deleted contact."); - } - $values['contact_id'] = $value; - break; case 'contact_type': // import contribution record according to select contact type @@ -656,13 +631,13 @@ private function deprecatedFormatParams($params, &$values, $create = FALSE) { $contactType->external_identifier = $externalId; if ($contactType->find(TRUE)) { if ($params['contact_type'] != $contactType->contact_type) { - return civicrm_api3_create_error("Contact Type is wrong: $contactType->contact_type"); + throw new CRM_Core_Exception("Contact Type is wrong: $contactType->contact_type", CRM_Import_Parser::ERROR); } } } elseif ($email) { if (!CRM_Utils_Rule::email($email)) { - return civicrm_api3_create_error("Invalid email address $email provided. Row was skipped"); + throw new CRM_Core_Exception("Invalid email address $email provided. Row was skipped", CRM_Import_Parser::ERROR); } // get the contact id from duplicate contact rule, if more than one contact is returned @@ -687,11 +662,11 @@ private function deprecatedFormatParams($params, &$values, $create = FALSE) { $checkDedupe = ['is_error' => 0]; } if (!$checkDedupe['is_error']) { - return civicrm_api3_create_error("Invalid email address(doesn't exist) $email. Row was skipped"); + throw new CRM_Core_Exception("Invalid email address(doesn't exist) $email. Row was skipped", CRM_Import_Parser::ERROR); } $matchingContactIds = explode(',', $checkDedupe['error_message']['params'][0]); if (count($matchingContactIds) > 1) { - return civicrm_api3_create_error("Invalid email address(duplicate) $email. Row was skipped"); + throw new CRM_Core_Exception("Invalid email address(duplicate) $email. Row was skipped", CRM_Import_Parser::ERROR); } if (count($matchingContactIds) == 1) { $params['contribution_contact_id'] = $matchingContactIds[0]; @@ -714,14 +689,14 @@ private function deprecatedFormatParams($params, &$values, $create = FALSE) { $contactType->id = $contactId->contact_id; if ($contactType->find(TRUE)) { if ($params['contact_type'] != $contactType->contact_type) { - return civicrm_api3_create_error("Contact Type is wrong: $contactType->contact_type"); + throw new CRM_Core_Exception("Contact Type is wrong: $contactType->contact_type", CRM_Import_Parser::ERROR); } } } } else { if ($this->isUpdateExisting()) { - return civicrm_api3_create_error("Empty Contribution and Invoice and Transaction ID. Row was skipped."); + throw new CRM_Core_Exception('Empty Contribution and Invoice and Transaction ID. Row was skipped.', CRM_Import_Parser::ERROR); } } break; @@ -765,7 +740,7 @@ private function deprecatedFormatParams($params, &$values, $create = FALSE) { } } else { - throw new CRM_Core_Exception('No match found for specified contact in pledge payment data. Row was skipped.'); + throw new CRM_Core_Exception('No match found for specified contact in pledge payment data. Row was skipped.', CRM_Import_Parser::ERROR); } } else { @@ -781,7 +756,7 @@ private function deprecatedFormatParams($params, &$values, $create = FALSE) { $contributionContactID = $params['contribution_contact_id'] = $values['contribution_contact_id'] = $contact->id; } else { - return civicrm_api3_create_error('No match found for specified contact in pledge payment data. Row was skipped.'); + throw new CRM_Core_Exception('No match found for specified contact in pledge payment data. Row was skipped.'); } } else { @@ -793,19 +768,19 @@ private function deprecatedFormatParams($params, &$values, $create = FALSE) { // check if only one contact is found if (count($matchedIDs) > 1) { - return civicrm_api3_create_error($error['error_message']['message']); + throw new CRM_Core_Exception($error['error_message']['message'], CRM_Import_Parser::ERROR); } $contributionContactID = $params['contribution_contact_id'] = $values['contribution_contact_id'] = $matchedIDs[0]; } else { - return civicrm_api3_create_error('No match found for specified contact in contribution data. Row was skipped.'); + throw new CRM_Core_Exception('No match found for specified contact in contribution data. Row was skipped.', CRM_Import_Parser::ERROR); } } } if (!empty($params['pledge_id'])) { if (CRM_Core_DAO::getFieldValue('CRM_Pledge_DAO_Pledge', $params['pledge_id'], 'contact_id') != $contributionContactID) { - return civicrm_api3_create_error('Invalid Pledge ID provided. Contribution row was skipped.'); + throw new CRM_Core_Exception('Invalid Pledge ID provided. Contribution row was skipped.', CRM_Import_Parser::ERROR); } $values['pledge_id'] = $params['pledge_id']; } @@ -815,10 +790,10 @@ private function deprecatedFormatParams($params, &$values, $create = FALSE) { $pledgeDetails = CRM_Pledge_BAO_Pledge::getContactPledges($contributionContactID); if (empty($pledgeDetails)) { - return civicrm_api3_create_error('No open pledges found for this contact. Contribution row was skipped.'); + throw new CRM_Core_Exception('No open pledges found for this contact. Contribution row was skipped.', CRM_Import_Parser::ERROR); } if (count($pledgeDetails) > 1) { - return civicrm_api3_create_error('This contact has more than one open pledge. Unable to determine which pledge to apply the contribution to. Contribution row was skipped.'); + throw new CRM_Core_Exception('This contact has more than one open pledge. Unable to determine which pledge to apply the contribution to. Contribution row was skipped.', CRM_Import_Parser::ERROR); } // this mean we have only one pending / in progress pledge @@ -833,15 +808,8 @@ private function deprecatedFormatParams($params, &$values, $create = FALSE) { $values['pledge_payment_id'] = $pledgePaymentDetails['id']; } else { - return civicrm_api3_create_error('Contribution and Pledge Payment amount mismatch for this record. Contribution row was skipped.'); - } - break; - - case 'contribution_campaign_id': - if (empty(CRM_Core_DAO::getFieldValue('CRM_Campaign_DAO_Campaign', $params['contribution_campaign_id']))) { - return civicrm_api3_create_error('Invalid Campaign ID provided. Contribution row was skipped.'); + throw new CRM_Core_Exception('Contribution and Pledge Payment amount mismatch for this record. Contribution row was skipped.', CRM_Import_Parser::ERROR); } - $values['contribution_campaign_id'] = $params['contribution_campaign_id']; break; } @@ -863,8 +831,6 @@ private function deprecatedFormatParams($params, &$values, $create = FALSE) { } } } - - return NULL; } /** @@ -879,7 +845,6 @@ private function deprecatedFormatParams($params, &$values, $create = FALSE) { * @param int $columnNumber * * @return array - * @throws \API_Exception */ public function getMappingFieldFromMapperInput(array $fieldMapping, int $mappingID, int $columnNumber): array { return [ @@ -954,7 +919,6 @@ private function lookupMatchingContact(array $params): int { * or as returned from getMappingFieldFromMapperInput * * @return string - * @throws \API_Exception */ public function getMappedFieldLabel(array $mappedField): string { if (empty($this->importableFieldsMetadata)) { diff --git a/CRM/Import/Parser.php b/CRM/Import/Parser.php index 0c867dc80440..2a0e5773dd8d 100644 --- a/CRM/Import/Parser.php +++ b/CRM/Import/Parser.php @@ -10,6 +10,7 @@ */ use Civi\Api4\Campaign; +use Civi\Api4\Contact; use Civi\Api4\CustomField; use Civi\Api4\Event; use Civi\Api4\UserJob; @@ -730,6 +731,28 @@ public static function errorFileName($type) { return $fileName; } + /** + * Validate that a passed in contact ID is for an existing, not-deleted contact. + * + * @param int $contactID + * @param string|null $contactType + * + * @throws \CRM_Core_Exception + */ + protected function validateContactID(int $contactID, ?string $contactType): void { + $existingContact = Contact::get(FALSE) + ->addWhere('id', '=', $contactID) + // Don't auto-filter deleted - people use import to undelete. + ->addWhere('is_deleted', 'IN', [0, 1]) + ->addSelect('contact_type')->execute()->first(); + if (empty($existingContact['id'])) { + throw new CRM_Core_Exception('No contact found for this contact ID:' . $contactID, CRM_Import_Parser::NO_MATCH); + } + if ($contactType && $existingContact['contact_type'] !== $contactType) { + throw new CRM_Core_Exception('Mismatched contact Types', CRM_Import_Parser::NO_MATCH); + } + } + /** * Determines the file name based on error code. *