X-Git-Url: https://vcs.fsf.org/?a=blobdiff_plain;f=CRM%2FContact%2FImport%2FParser%2FContact.php;h=c46a60338f9afacace83de426b8b31ea46db0b94;hb=d60cd664d3c04e2dffa6df5e2cd16ce1e5564d18;hp=59dafa45603802f3487f536cfe0ffb44a70f776d;hpb=64b64daaac52ec6253438134ed69eaef32b3f0fd;p=civicrm-core.git diff --git a/CRM/Contact/Import/Parser/Contact.php b/CRM/Contact/Import/Parser/Contact.php index 59dafa4560..c46a60338f 100644 --- a/CRM/Contact/Import/Parser/Contact.php +++ b/CRM/Contact/Import/Parser/Contact.php @@ -877,7 +877,6 @@ class CRM_Contact_Import_Parser_Contact extends CRM_Contact_Import_Parser { //if more than one duplicate contact //found, create relationship with first contact // now create the relationship record - $relationParams = []; $relationParams = [ 'relationship_type_id' => $key, 'contact_check' => [ @@ -893,7 +892,7 @@ class CRM_Contact_Import_Parser_Contact extends CRM_Contact_Import_Parser { 'contact' => $primaryContactId, ]; - [$valid, $invalid, $duplicate, $saved, $relationshipIds] = CRM_Contact_BAO_Relationship::legacyCreateMultiple($relationParams, $relationIds); + [$valid, $duplicate] = self::legacyCreateMultiple($relationParams, $relationIds); if ($valid || $duplicate) { $relationIds['contactTarget'] = $relContactId; @@ -957,6 +956,296 @@ class CRM_Contact_Import_Parser_Contact extends CRM_Contact_Import_Parser { return $this->processMessage($values, $statusFieldName, CRM_Import_Parser::VALID); } + /** + * Only called from import now... plus one place outside of core & tests. + * + * @todo - deprecate more aggressively - will involve copying to the import + * class, adding a deprecation notice here & removing from tests. + * + * Takes an associative array and creates a relationship object. + * + * @deprecated For single creates use the api instead (it's tested). + * For multiple a new variant of this function needs to be written and migrated to as this is a bit + * nasty + * + * @param array $params + * (reference ) an assoc array of name/value pairs. + * @param array $ids + * The array that holds all the db ids. + * per http://wiki.civicrm.org/confluence/display/CRM/Database+layer + * "we are moving away from the $ids param " + * + * @return array + * @throws \CRM_Core_Exception + */ + private static function legacyCreateMultiple($params, $ids = []) { + // clarify that the only key ever pass in the ids array is 'contact' + // There is legacy handling for other keys but a universe search on + // calls to this function (not supported to be called from outside core) + // only returns 2 calls - one in CRM_Contact_Import_Parser_Contact + // and the other in jma grant applications (CRM_Grant_Form_Grant_Confirm) + // both only pass in contact as a key here. + $contactID = $ids['contact']; + unset($ids); + // There is only ever one value passed in from the 2 places above that call + // this - by clarifying here like this we can cleanup within this + // function without having to do more universe searches. + $relatedContactID = key($params['contact_check']); + + // check if the relationship is valid between contacts. + // step 1: check if the relationship is valid if not valid skip and keep the count + // step 2: check the if two contacts already have a relationship if yes skip and keep the count + // step 3: if valid relationship then add the relation and keep the count + + // step 1 + [$contactFields['relationship_type_id'], $firstLetter, $secondLetter] = explode('_', $params['relationship_type_id']); + $contactFields['contact_id_' . $firstLetter] = $contactID; + $contactFields['contact_id_' . $secondLetter] = $relatedContactID; + if (!CRM_Contact_BAO_Relationship::checkRelationshipType($contactFields['contact_id_a'], $contactFields['contact_id_b'], + $contactFields['relationship_type_id'])) { + return [0, 0]; + } + + if ( + CRM_Contact_BAO_Relationship::checkDuplicateRelationship( + $contactFields, + $contactID, + // step 2 + $relatedContactID + ) + ) { + return [0, 1]; + } + + $singleInstanceParams = array_merge($params, $contactFields); + CRM_Contact_BAO_Relationship::add($singleInstanceParams); + return [1, 0]; + } + + /** + * Format common params data to proper format to store. + * + * @param array $params + * Contain record values. + * @param array $formatted + * Array of formatted data. + * @param array $contactFields + * Contact DAO fields. + */ + private function formatCommonData($params, &$formatted, $contactFields) { + $csType = [ + CRM_Utils_Array::value('contact_type', $formatted), + ]; + + //CRM-5125 + //add custom fields for contact sub type + if (!empty($this->_contactSubType)) { + $csType = $this->_contactSubType; + } + + if ($relCsType = CRM_Utils_Array::value('contact_sub_type', $formatted)) { + $csType = $relCsType; + } + + $customFields = CRM_Core_BAO_CustomField::getFields($formatted['contact_type'], FALSE, FALSE, $csType); + + $addressCustomFields = CRM_Core_BAO_CustomField::getFields('Address'); + $customFields = $customFields + $addressCustomFields; + + //if a Custom Email Greeting, Custom Postal Greeting or Custom Addressee is mapped, and no "Greeting / Addressee Type ID" is provided, then automatically set the type = Customized, CRM-4575 + $elements = [ + 'email_greeting_custom' => 'email_greeting', + 'postal_greeting_custom' => 'postal_greeting', + 'addressee_custom' => 'addressee', + ]; + foreach ($elements as $k => $v) { + if (array_key_exists($k, $params) && !(array_key_exists($v, $params))) { + $label = key(CRM_Core_OptionGroup::values($v, TRUE, NULL, NULL, 'AND v.name = "Customized"')); + $params[$v] = $label; + } + } + + //format date first + $session = CRM_Core_Session::singleton(); + $dateType = $session->get("dateTypes"); + foreach ($params as $key => $val) { + $customFieldID = CRM_Core_BAO_CustomField::getKeyID($key); + if ($customFieldID && + !array_key_exists($customFieldID, $addressCustomFields) + ) { + //we should not update Date to null, CRM-4062 + if ($val && ($customFields[$customFieldID]['data_type'] == 'Date')) { + //CRM-21267 + CRM_Contact_Import_Parser_Contact::formatCustomDate($params, $formatted, $dateType, $key); + } + elseif ($customFields[$customFieldID]['data_type'] == 'Boolean') { + if (empty($val) && !is_numeric($val) && $this->_onDuplicate == CRM_Import_Parser::DUPLICATE_FILL) { + //retain earlier value when Import mode is `Fill` + unset($params[$key]); + } + else { + $params[$key] = CRM_Utils_String::strtoboolstr($val); + } + } + } + + if ($key == 'birth_date' && $val) { + CRM_Utils_Date::convertToDefaultDate($params, $dateType, $key); + } + elseif ($key == 'deceased_date' && $val) { + CRM_Utils_Date::convertToDefaultDate($params, $dateType, $key); + $params['is_deceased'] = 1; + } + elseif ($key == 'is_deceased' && $val) { + $params[$key] = CRM_Utils_String::strtoboolstr($val); + } + } + + //now format custom data. + foreach ($params as $key => $field) { + if (is_array($field)) { + $isAddressCustomField = FALSE; + foreach ($field as $value) { + $break = FALSE; + if (is_array($value)) { + foreach ($value as $name => $testForEmpty) { + if ($addressCustomFieldID = CRM_Core_BAO_CustomField::getKeyID($name)) { + $isAddressCustomField = TRUE; + break; + } + // check if $value does not contain IM provider or phoneType + if (($name !== 'phone_type_id' || $name !== 'provider_id') && ($testForEmpty === '' || $testForEmpty == NULL)) { + $break = TRUE; + break; + } + } + } + else { + $break = TRUE; + } + + if (!$break) { + if (!empty($value['location_type_id'])) { + $this->formatLocationBlock($value, $formatted); + } + else { + // @todo - this is still reachable - e.g. import with related contact info like firstname,lastname,spouse-first-name,spouse-last-name,spouse-home-phone + CRM_Core_Error::deprecatedFunctionWarning('this is not expected to be reachable now'); + $this->formatContactParameters($value, $formatted); + } + } + } + if (!$isAddressCustomField) { + continue; + } + } + + $formatValues = [ + $key => $field, + ]; + + if (($key !== 'preferred_communication_method') && (array_key_exists($key, $contactFields))) { + // due to merging of individual table and + // contact table, we need to avoid + // preferred_communication_method forcefully + $formatValues['contact_type'] = $formatted['contact_type']; + } + + if ($key == 'id' && isset($field)) { + $formatted[$key] = $field; + } + $this->formatContactParameters($formatValues, $formatted); + + //Handling Custom Data + // note: Address custom fields will be handled separately inside formatContactParameters + if (($customFieldID = CRM_Core_BAO_CustomField::getKeyID($key)) && + array_key_exists($customFieldID, $customFields) && + !array_key_exists($customFieldID, $addressCustomFields) + ) { + + $extends = $customFields[$customFieldID]['extends'] ?? NULL; + $htmlType = $customFields[$customFieldID]['html_type'] ?? NULL; + $dataType = $customFields[$customFieldID]['data_type'] ?? NULL; + $serialized = CRM_Core_BAO_CustomField::isSerialized($customFields[$customFieldID]); + + if (!$serialized && in_array($htmlType, ['Select', 'Radio', 'Autocomplete-Select']) && in_array($dataType, ['String', 'Int'])) { + $customOption = CRM_Core_BAO_CustomOption::getCustomOption($customFieldID, TRUE); + foreach ($customOption as $customValue) { + $val = $customValue['value'] ?? NULL; + $label = strtolower($customValue['label'] ?? ''); + $value = strtolower(trim($formatted[$key])); + if (($value == $label) || ($value == strtolower($val))) { + $params[$key] = $formatted[$key] = $val; + } + } + } + elseif ($serialized && !empty($formatted[$key]) && !empty($params[$key])) { + $mulValues = explode(',', $formatted[$key]); + $customOption = CRM_Core_BAO_CustomOption::getCustomOption($customFieldID, TRUE); + $formatted[$key] = []; + $params[$key] = []; + foreach ($mulValues as $v1) { + foreach ($customOption as $v2) { + if ((strtolower($v2['label']) == strtolower(trim($v1))) || + (strtolower($v2['value']) == strtolower(trim($v1))) + ) { + if ($htmlType == 'CheckBox') { + $params[$key][$v2['value']] = $formatted[$key][$v2['value']] = 1; + } + else { + $params[$key][] = $formatted[$key][] = $v2['value']; + } + } + } + } + } + } + } + + if (!empty($key) && ($customFieldID = CRM_Core_BAO_CustomField::getKeyID($key)) && array_key_exists($customFieldID, $customFields) && + !array_key_exists($customFieldID, $addressCustomFields) + ) { + // @todo calling api functions directly is not supported + _civicrm_api3_custom_format_params($params, $formatted, $extends); + } + + // to check if not update mode and unset the fields with empty value. + if (!$this->_updateWithId && array_key_exists('custom', $formatted)) { + foreach ($formatted['custom'] as $customKey => $customvalue) { + if (empty($formatted['custom'][$customKey][-1]['is_required'])) { + $formatted['custom'][$customKey][-1]['is_required'] = $customFields[$customKey]['is_required']; + } + $emptyValue = $customvalue[-1]['value'] ?? NULL; + if (!isset($emptyValue)) { + unset($formatted['custom'][$customKey]); + } + } + } + + // parse street address, CRM-5450 + if ($this->_parseStreetAddress) { + if (array_key_exists('address', $formatted) && is_array($formatted['address'])) { + foreach ($formatted['address'] as $instance => & $address) { + $streetAddress = $address['street_address'] ?? NULL; + if (empty($streetAddress)) { + continue; + } + // parse address field. + $parsedFields = CRM_Core_BAO_Address::parseStreetAddress($streetAddress); + + //street address consider to be parsed properly, + //If we get street_name and street_number. + if (empty($parsedFields['street_name']) || empty($parsedFields['street_number'])) { + $parsedFields = array_fill_keys(array_keys($parsedFields), ''); + } + + // merge parse address w/ main address block. + $address = array_merge($address, $parsedFields); + } + } + } + } + /** * Get the array of successfully imported contact id's * @@ -1003,7 +1292,7 @@ class CRM_Contact_Import_Parser_Contact extends CRM_Contact_Import_Parser { } // get array of subtypes - CRM-18708 - if (in_array($csType, ['Individual', 'Organization', 'Household'])) { + if (in_array($csType, CRM_Contact_BAO_ContactType::basicTypes(TRUE), TRUE)) { $csType = self::getSubtypes($params['contact_type']); } @@ -2115,9 +2404,6 @@ class CRM_Contact_Import_Parser_Contact extends CRM_Contact_Import_Parser { $requiredCheck = FALSE; } if ($requiredCheck) { - if (isset($params['id'])) { - $required = ['Individual', 'Household', 'Organization']; - } $required = [ 'Individual' => [ ['first_name', 'last_name'],