From 5dc4d424ff1b8ac7bedbdcde65a1aa48eb462f88 Mon Sep 17 00:00:00 2001 From: eileen Date: Fri, 29 Sep 2017 15:14:36 +1300 Subject: [PATCH] CRM-21230 fix fatal error on multi-data imports --- CRM/Contact/Import/Parser.php | 578 +++++++++++++++++++++++++ CRM/Contact/Import/Parser/Contact.php | 579 -------------------------- CRM/Custom/Import/Parser/Api.php | 2 +- 3 files changed, 579 insertions(+), 580 deletions(-) diff --git a/CRM/Contact/Import/Parser.php b/CRM/Contact/Import/Parser.php index 06dbb8978a..e5e93d857d 100644 --- a/CRM/Contact/Import/Parser.php +++ b/CRM/Contact/Import/Parser.php @@ -791,4 +791,582 @@ abstract class CRM_Contact_Import_Parser extends CRM_Import_Parser { } } + /** + * 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. + */ + public function formatCommonData($params, &$formatted, &$contactFields) { + $csType = array( + 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 = array( + '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')) { + self::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); + } + elseif ($key == 'gender') { + //CRM-4360 + $params[$key] = $this->checkGender($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) { + $this->formatContactParameters($value, $formatted); + } + } + if (!$isAddressCustomField) { + continue; + } + } + + $formatValues = array( + $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 = CRM_Utils_Array::value('extends', $customFields[$customFieldID]); + $htmlType = CRM_Utils_Array::value('html_type', $customFields[$customFieldID]); + switch ($htmlType) { + case 'Select': + case 'Radio': + case 'Autocomplete-Select': + if ($customFields[$customFieldID]['data_type'] == 'String' || $customFields[$customFieldID]['data_type'] == 'Int') { + $customOption = CRM_Core_BAO_CustomOption::getCustomOption($customFieldID, TRUE); + foreach ($customOption as $customValue) { + $val = CRM_Utils_Array::value('value', $customValue); + $label = CRM_Utils_Array::value('label', $customValue); + $label = strtolower($label); + $value = strtolower(trim($formatted[$key])); + if (($value == $label) || ($value == strtolower($val))) { + $params[$key] = $formatted[$key] = $val; + } + } + } + break; + + case 'CheckBox': + case 'AdvMulti-Select': + case 'Multi-Select': + + if (!empty($formatted[$key]) && !empty($params[$key])) { + $mulValues = explode(',', $formatted[$key]); + $customOption = CRM_Core_BAO_CustomOption::getCustomOption($customFieldID, TRUE); + $formatted[$key] = array(); + $params[$key] = array(); + 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']; + } + } + } + } + } + break; + } + } + } + + 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 = CRM_Utils_Array::value('value', $customvalue[-1]); + 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 = CRM_Utils_Array::value('street_address', $address); + 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); + } + } + } + } + + /** + * Format contact parameters. + * + * @todo this function needs re-writing & re-merging into the main function. + * + * Here be dragons. + * + * @param array $values + * @param array $params + * + * @return bool + */ + protected function formatContactParameters(&$values, &$params) { + // Crawl through the possible classes: + // Contact + // Individual + // Household + // Organization + // Location + // Address + // Email + // Phone + // IM + // Note + // Custom + + // Cache the various object fields + static $fields = array(); + + // first add core contact values since for other Civi modules they are not added + $contactFields = CRM_Contact_DAO_Contact::fields(); + _civicrm_api3_store_values($contactFields, $values, $params); + + if (isset($values['contact_type'])) { + // we're an individual/household/org property + + $fields[$values['contact_type']] = CRM_Contact_DAO_Contact::fields(); + + _civicrm_api3_store_values($fields[$values['contact_type']], $values, $params); + return TRUE; + } + + if (isset($values['individual_prefix'])) { + if (!empty($params['prefix_id'])) { + $prefixes = CRM_Core_PseudoConstant::get('CRM_Contact_DAO_Contact', 'prefix_id'); + $params['prefix'] = $prefixes[$params['prefix_id']]; + } + else { + $params['prefix'] = $values['individual_prefix']; + } + return TRUE; + } + + if (isset($values['individual_suffix'])) { + if (!empty($params['suffix_id'])) { + $suffixes = CRM_Core_PseudoConstant::get('CRM_Contact_DAO_Contact', 'suffix_id'); + $params['suffix'] = $suffixes[$params['suffix_id']]; + } + else { + $params['suffix'] = $values['individual_suffix']; + } + return TRUE; + } + + // CRM-4575 + if (isset($values['email_greeting'])) { + if (!empty($params['email_greeting_id'])) { + $emailGreetingFilter = array( + 'contact_type' => CRM_Utils_Array::value('contact_type', $params), + 'greeting_type' => 'email_greeting', + ); + $emailGreetings = CRM_Core_PseudoConstant::greeting($emailGreetingFilter); + $params['email_greeting'] = $emailGreetings[$params['email_greeting_id']]; + } + else { + $params['email_greeting'] = $values['email_greeting']; + } + + return TRUE; + } + + if (isset($values['postal_greeting'])) { + if (!empty($params['postal_greeting_id'])) { + $postalGreetingFilter = array( + 'contact_type' => CRM_Utils_Array::value('contact_type', $params), + 'greeting_type' => 'postal_greeting', + ); + $postalGreetings = CRM_Core_PseudoConstant::greeting($postalGreetingFilter); + $params['postal_greeting'] = $postalGreetings[$params['postal_greeting_id']]; + } + else { + $params['postal_greeting'] = $values['postal_greeting']; + } + return TRUE; + } + + if (isset($values['addressee'])) { + if (!empty($params['addressee_id'])) { + $addresseeFilter = array( + 'contact_type' => CRM_Utils_Array::value('contact_type', $params), + 'greeting_type' => 'addressee', + ); + $addressee = CRM_Core_PseudoConstant::addressee($addresseeFilter); + $params['addressee'] = $addressee[$params['addressee_id']]; + } + else { + $params['addressee'] = $values['addressee']; + } + return TRUE; + } + + if (isset($values['gender'])) { + if (!empty($params['gender_id'])) { + $genders = CRM_Core_PseudoConstant::get('CRM_Contact_DAO_Contact', 'gender_id'); + $params['gender'] = $genders[$params['gender_id']]; + } + else { + $params['gender'] = $values['gender']; + } + return TRUE; + } + + if (!empty($values['preferred_communication_method'])) { + $comm = array(); + $pcm = array_change_key_case(array_flip(CRM_Core_PseudoConstant::get('CRM_Contact_DAO_Contact', 'preferred_communication_method')), CASE_LOWER); + + $preffComm = explode(',', $values['preferred_communication_method']); + foreach ($preffComm as $v) { + $v = strtolower(trim($v)); + if (array_key_exists($v, $pcm)) { + $comm[$pcm[$v]] = 1; + } + } + + $params['preferred_communication_method'] = $comm; + return TRUE; + } + + // format the website params. + if (!empty($values['url'])) { + static $websiteFields; + if (!is_array($websiteFields)) { + $websiteFields = CRM_Core_DAO_Website::fields(); + } + if (!array_key_exists('website', $params) || + !is_array($params['website']) + ) { + $params['website'] = array(); + } + + $websiteCount = count($params['website']); + _civicrm_api3_store_values($websiteFields, $values, + $params['website'][++$websiteCount] + ); + + return TRUE; + } + + // get the formatted location blocks into params - w/ 3.0 format, CRM-4605 + if (!empty($values['location_type_id'])) { + $blockTypes = array( + 'phone' => 'Phone', + 'email' => 'Email', + 'im' => 'IM', + 'openid' => 'OpenID', + 'phone_ext' => 'Phone', + ); + foreach ($blockTypes as $blockFieldName => $block) { + if (!array_key_exists($blockFieldName, $values)) { + continue; + } + + // block present in value array. + if (!array_key_exists($blockFieldName, $params) || !is_array($params[$blockFieldName])) { + $params[$blockFieldName] = array(); + } + + if (!array_key_exists($block, $fields)) { + $className = "CRM_Core_DAO_$block"; + $fields[$block] = $className::fields(); + } + + $blockCnt = count($params[$blockFieldName]); + + // copy value to dao field name. + if ($blockFieldName == 'im') { + $values['name'] = $values[$blockFieldName]; + } + + _civicrm_api3_store_values($fields[$block], $values, + $params[$blockFieldName][++$blockCnt] + ); + + if ($values['location_type_id'] === 'Primary') { + if (!empty($params['id'])) { + $primary = civicrm_api3($block, 'get', array('return' => 'location_type_id', 'contact_id' => $params['id'], 'is_primary' => 1, 'sequential' => 1)); + } + $defaultLocationType = CRM_Core_BAO_LocationType::getDefault(); + $values['location_type_id'] = (isset($primary) && $primary['count']) ? $primary['values'][0]['location_type_id'] : $defaultLocationType->id; + $values['is_primary'] = 1; + } + + if (empty($params['id']) && ($blockCnt == 1)) { + $params[$blockFieldName][$blockCnt]['is_primary'] = TRUE; + } + + // we only process single block at a time. + return TRUE; + } + + // handle address fields. + if (!array_key_exists('address', $params) || !is_array($params['address'])) { + $params['address'] = array(); + } + + if (!array_key_exists('Address', $fields)) { + $fields['Address'] = CRM_Core_DAO_Address::fields(); + } + + // Note: we doing multiple value formatting here for address custom fields, plus putting into right format. + // The actual formatting (like date, country ..etc) for address custom fields is taken care of while saving + // the address in CRM_Core_BAO_Address::create method + if (!empty($values['location_type_id'])) { + static $customFields = array(); + if (empty($customFields)) { + $customFields = CRM_Core_BAO_CustomField::getFields('Address'); + } + // make a copy of values, as we going to make changes + $newValues = $values; + foreach ($values as $key => $val) { + $customFieldID = CRM_Core_BAO_CustomField::getKeyID($key); + if ($customFieldID && array_key_exists($customFieldID, $customFields)) { + // mark an entry in fields array since we want the value of custom field to be copied + $fields['Address'][$key] = NULL; + + $htmlType = CRM_Utils_Array::value('html_type', $customFields[$customFieldID]); + switch ($htmlType) { + case 'CheckBox': + case 'AdvMulti-Select': + case 'Multi-Select': + if ($val) { + $mulValues = explode(',', $val); + $customOption = CRM_Core_BAO_CustomOption::getCustomOption($customFieldID, TRUE); + $newValues[$key] = array(); + foreach ($mulValues as $v1) { + foreach ($customOption as $v2) { + if ((strtolower($v2['label']) == strtolower(trim($v1))) || + (strtolower($v2['value']) == strtolower(trim($v1))) + ) { + if ($htmlType == 'CheckBox') { + $newValues[$key][$v2['value']] = 1; + } + else { + $newValues[$key][] = $v2['value']; + } + } + } + } + } + break; + } + } + } + // consider new values + $values = $newValues; + } + + _civicrm_api3_store_values($fields['Address'], $values, $params['address'][$values['location_type_id']]); + + $addressFields = array( + 'county', + 'country', + 'state_province', + 'supplemental_address_1', + 'supplemental_address_2', + 'supplemental_address_3', + 'StateProvince.name', + ); + + foreach ($addressFields as $field) { + if (array_key_exists($field, $values)) { + if (!array_key_exists('address', $params)) { + $params['address'] = array(); + } + $params['address'][$values['location_type_id']][$field] = $values[$field]; + } + } + + if ($values['location_type_id'] === 'Primary') { + if (!empty($params['id'])) { + $primary = civicrm_api3('Address', 'get', array('return' => 'location_type_id', 'contact_id' => $params['id'], 'is_primary' => 1, 'sequential' => 1)); + } + $defaultLocationType = CRM_Core_BAO_LocationType::getDefault(); + $params['address'][$values['location_type_id']]['location_type_id'] = (isset($primary) && $primary['count']) ? $primary['values'][0]['location_type_id'] : $defaultLocationType->id; + $params['address'][$values['location_type_id']]['is_primary'] = 1; + + } + return TRUE; + } + + if (isset($values['note'])) { + // add a note field + if (!isset($params['note'])) { + $params['note'] = array(); + } + $noteBlock = count($params['note']) + 1; + + $params['note'][$noteBlock] = array(); + if (!isset($fields['Note'])) { + $fields['Note'] = CRM_Core_DAO_Note::fields(); + } + + // get the current logged in civicrm user + $session = CRM_Core_Session::singleton(); + $userID = $session->get('userID'); + + if ($userID) { + $values['contact_id'] = $userID; + } + + _civicrm_api3_store_values($fields['Note'], $values, $params['note'][$noteBlock]); + + return TRUE; + } + + // Check for custom field values + + if (empty($fields['custom'])) { + $fields['custom'] = &CRM_Core_BAO_CustomField::getFields(CRM_Utils_Array::value('contact_type', $values), + FALSE, FALSE, NULL, NULL, FALSE, FALSE, FALSE + ); + } + + foreach ($values as $key => $value) { + if ($customFieldID = CRM_Core_BAO_CustomField::getKeyID($key)) { + // check if it's a valid custom field id + + if (!array_key_exists($customFieldID, $fields['custom'])) { + return civicrm_api3_create_error('Invalid custom field ID'); + } + else { + $params[$key] = $value; + } + } + } + return TRUE; + } + } diff --git a/CRM/Contact/Import/Parser/Contact.php b/CRM/Contact/Import/Parser/Contact.php index a70ab571eb..ecff4e15f5 100644 --- a/CRM/Contact/Import/Parser/Contact.php +++ b/CRM/Contact/Import/Parser/Contact.php @@ -1872,236 +1872,6 @@ class CRM_Contact_Import_Parser_Contact extends CRM_Contact_Import_Parser { $formatted[$dateParam] = CRM_Utils_Date::processDate($params[$dateParam]); } - /** - * 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. - */ - public function formatCommonData($params, &$formatted, &$contactFields) { - $csType = array( - 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 = array( - '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')) { - self::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); - } - elseif ($key == 'gender') { - //CRM-4360 - $params[$key] = $this->checkGender($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) { - $this->formatContactParameters($value, $formatted); - } - } - if (!$isAddressCustomField) { - continue; - } - } - - $formatValues = array( - $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 = CRM_Utils_Array::value('extends', $customFields[$customFieldID]); - $htmlType = CRM_Utils_Array::value('html_type', $customFields[$customFieldID]); - switch ($htmlType) { - case 'Select': - case 'Radio': - case 'Autocomplete-Select': - if ($customFields[$customFieldID]['data_type'] == 'String' || $customFields[$customFieldID]['data_type'] == 'Int') { - $customOption = CRM_Core_BAO_CustomOption::getCustomOption($customFieldID, TRUE); - foreach ($customOption as $customValue) { - $val = CRM_Utils_Array::value('value', $customValue); - $label = CRM_Utils_Array::value('label', $customValue); - $label = strtolower($label); - $value = strtolower(trim($formatted[$key])); - if (($value == $label) || ($value == strtolower($val))) { - $params[$key] = $formatted[$key] = $val; - } - } - } - break; - - case 'CheckBox': - case 'AdvMulti-Select': - case 'Multi-Select': - - if (!empty($formatted[$key]) && !empty($params[$key])) { - $mulValues = explode(',', $formatted[$key]); - $customOption = CRM_Core_BAO_CustomOption::getCustomOption($customFieldID, TRUE); - $formatted[$key] = array(); - $params[$key] = array(); - 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']; - } - } - } - } - } - break; - } - } - } - - 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 = CRM_Utils_Array::value('value', $customvalue[-1]); - 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 = CRM_Utils_Array::value('street_address', $address); - 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); - } - } - } - } - /** * Generate status and error message for unparsed street address records. * @@ -2274,353 +2044,4 @@ class CRM_Contact_Import_Parser_Contact extends CRM_Contact_Import_Parser { } - /** - * Format contact parameters. - * - * @todo this function needs re-writing & re-merging into the main function. - * - * Here be dragons. - * - * @param array $values - * @param array $params - * - * @return bool - */ - protected function formatContactParameters(&$values, &$params) { - // Crawl through the possible classes: - // Contact - // Individual - // Household - // Organization - // Location - // Address - // Email - // Phone - // IM - // Note - // Custom - - // Cache the various object fields - static $fields = array(); - - // first add core contact values since for other Civi modules they are not added - $contactFields = CRM_Contact_DAO_Contact::fields(); - _civicrm_api3_store_values($contactFields, $values, $params); - - if (isset($values['contact_type'])) { - // we're an individual/household/org property - - $fields[$values['contact_type']] = CRM_Contact_DAO_Contact::fields(); - - _civicrm_api3_store_values($fields[$values['contact_type']], $values, $params); - return TRUE; - } - - if (isset($values['individual_prefix'])) { - if (!empty($params['prefix_id'])) { - $prefixes = CRM_Core_PseudoConstant::get('CRM_Contact_DAO_Contact', 'prefix_id'); - $params['prefix'] = $prefixes[$params['prefix_id']]; - } - else { - $params['prefix'] = $values['individual_prefix']; - } - return TRUE; - } - - if (isset($values['individual_suffix'])) { - if (!empty($params['suffix_id'])) { - $suffixes = CRM_Core_PseudoConstant::get('CRM_Contact_DAO_Contact', 'suffix_id'); - $params['suffix'] = $suffixes[$params['suffix_id']]; - } - else { - $params['suffix'] = $values['individual_suffix']; - } - return TRUE; - } - - // CRM-4575 - if (isset($values['email_greeting'])) { - if (!empty($params['email_greeting_id'])) { - $emailGreetingFilter = array( - 'contact_type' => CRM_Utils_Array::value('contact_type', $params), - 'greeting_type' => 'email_greeting', - ); - $emailGreetings = CRM_Core_PseudoConstant::greeting($emailGreetingFilter); - $params['email_greeting'] = $emailGreetings[$params['email_greeting_id']]; - } - else { - $params['email_greeting'] = $values['email_greeting']; - } - - return TRUE; - } - - if (isset($values['postal_greeting'])) { - if (!empty($params['postal_greeting_id'])) { - $postalGreetingFilter = array( - 'contact_type' => CRM_Utils_Array::value('contact_type', $params), - 'greeting_type' => 'postal_greeting', - ); - $postalGreetings = CRM_Core_PseudoConstant::greeting($postalGreetingFilter); - $params['postal_greeting'] = $postalGreetings[$params['postal_greeting_id']]; - } - else { - $params['postal_greeting'] = $values['postal_greeting']; - } - return TRUE; - } - - if (isset($values['addressee'])) { - if (!empty($params['addressee_id'])) { - $addresseeFilter = array( - 'contact_type' => CRM_Utils_Array::value('contact_type', $params), - 'greeting_type' => 'addressee', - ); - $addressee = CRM_Core_PseudoConstant::addressee($addresseeFilter); - $params['addressee'] = $addressee[$params['addressee_id']]; - } - else { - $params['addressee'] = $values['addressee']; - } - return TRUE; - } - - if (isset($values['gender'])) { - if (!empty($params['gender_id'])) { - $genders = CRM_Core_PseudoConstant::get('CRM_Contact_DAO_Contact', 'gender_id'); - $params['gender'] = $genders[$params['gender_id']]; - } - else { - $params['gender'] = $values['gender']; - } - return TRUE; - } - - if (!empty($values['preferred_communication_method'])) { - $comm = array(); - $pcm = array_change_key_case(array_flip(CRM_Core_PseudoConstant::get('CRM_Contact_DAO_Contact', 'preferred_communication_method')), CASE_LOWER); - - $preffComm = explode(',', $values['preferred_communication_method']); - foreach ($preffComm as $v) { - $v = strtolower(trim($v)); - if (array_key_exists($v, $pcm)) { - $comm[$pcm[$v]] = 1; - } - } - - $params['preferred_communication_method'] = $comm; - return TRUE; - } - - // format the website params. - if (!empty($values['url'])) { - static $websiteFields; - if (!is_array($websiteFields)) { - require_once 'CRM/Core/DAO/Website.php'; - $websiteFields = CRM_Core_DAO_Website::fields(); - } - if (!array_key_exists('website', $params) || - !is_array($params['website']) - ) { - $params['website'] = array(); - } - - $websiteCount = count($params['website']); - _civicrm_api3_store_values($websiteFields, $values, - $params['website'][++$websiteCount] - ); - - return TRUE; - } - - // get the formatted location blocks into params - w/ 3.0 format, CRM-4605 - if (!empty($values['location_type_id'])) { - $blockTypes = array( - 'phone' => 'Phone', - 'email' => 'Email', - 'im' => 'IM', - 'openid' => 'OpenID', - 'phone_ext' => 'Phone', - ); - foreach ($blockTypes as $blockFieldName => $block) { - if (!array_key_exists($blockFieldName, $values)) { - continue; - } - - // block present in value array. - if (!array_key_exists($blockFieldName, $params) || !is_array($params[$blockFieldName])) { - $params[$blockFieldName] = array(); - } - - if (!array_key_exists($block, $fields)) { - $className = "CRM_Core_DAO_$block"; - $fields[$block] = $className::fields(); - } - - $blockCnt = count($params[$blockFieldName]); - - // copy value to dao field name. - if ($blockFieldName == 'im') { - $values['name'] = $values[$blockFieldName]; - } - - _civicrm_api3_store_values($fields[$block], $values, - $params[$blockFieldName][++$blockCnt] - ); - - if ($values['location_type_id'] === 'Primary') { - if (!empty($params['id'])) { - $primary = civicrm_api3($block, 'get', array('return' => 'location_type_id', 'contact_id' => $params['id'], 'is_primary' => 1, 'sequential' => 1)); - } - $defaultLocationType = CRM_Core_BAO_LocationType::getDefault(); - $values['location_type_id'] = (isset($primary) && $primary['count']) ? $primary['values'][0]['location_type_id'] : $defaultLocationType->id; - $values['is_primary'] = 1; - } - - if (empty($params['id']) && ($blockCnt == 1)) { - $params[$blockFieldName][$blockCnt]['is_primary'] = TRUE; - } - - // we only process single block at a time. - return TRUE; - } - - // handle address fields. - if (!array_key_exists('address', $params) || !is_array($params['address'])) { - $params['address'] = array(); - } - - if (!array_key_exists('Address', $fields)) { - $fields['Address'] = CRM_Core_DAO_Address::fields(); - } - - // Note: we doing multiple value formatting here for address custom fields, plus putting into right format. - // The actual formatting (like date, country ..etc) for address custom fields is taken care of while saving - // the address in CRM_Core_BAO_Address::create method - if (!empty($values['location_type_id'])) { - static $customFields = array(); - if (empty($customFields)) { - $customFields = CRM_Core_BAO_CustomField::getFields('Address'); - } - // make a copy of values, as we going to make changes - $newValues = $values; - foreach ($values as $key => $val) { - $customFieldID = CRM_Core_BAO_CustomField::getKeyID($key); - if ($customFieldID && array_key_exists($customFieldID, $customFields)) { - // mark an entry in fields array since we want the value of custom field to be copied - $fields['Address'][$key] = NULL; - - $htmlType = CRM_Utils_Array::value('html_type', $customFields[$customFieldID]); - switch ($htmlType) { - case 'CheckBox': - case 'AdvMulti-Select': - case 'Multi-Select': - if ($val) { - $mulValues = explode(',', $val); - $customOption = CRM_Core_BAO_CustomOption::getCustomOption($customFieldID, TRUE); - $newValues[$key] = array(); - foreach ($mulValues as $v1) { - foreach ($customOption as $v2) { - if ((strtolower($v2['label']) == strtolower(trim($v1))) || - (strtolower($v2['value']) == strtolower(trim($v1))) - ) { - if ($htmlType == 'CheckBox') { - $newValues[$key][$v2['value']] = 1; - } - else { - $newValues[$key][] = $v2['value']; - } - } - } - } - } - break; - } - } - } - // consider new values - $values = $newValues; - } - - _civicrm_api3_store_values($fields['Address'], $values, $params['address'][$values['location_type_id']]); - - $addressFields = array( - 'county', - 'country', - 'state_province', - 'supplemental_address_1', - 'supplemental_address_2', - 'supplemental_address_3', - 'StateProvince.name', - ); - - foreach ($addressFields as $field) { - if (array_key_exists($field, $values)) { - if (!array_key_exists('address', $params)) { - $params['address'] = array(); - } - $params['address'][$values['location_type_id']][$field] = $values[$field]; - } - } - - if ($values['location_type_id'] === 'Primary') { - if (!empty($params['id'])) { - $primary = civicrm_api3('Address', 'get', array('return' => 'location_type_id', 'contact_id' => $params['id'], 'is_primary' => 1, 'sequential' => 1)); - } - $defaultLocationType = CRM_Core_BAO_LocationType::getDefault(); - $params['address'][$values['location_type_id']]['location_type_id'] = (isset($primary) && $primary['count']) ? $primary['values'][0]['location_type_id'] : $defaultLocationType->id; - $params['address'][$values['location_type_id']]['is_primary'] = 1; - - } - return TRUE; - } - - if (isset($values['note'])) { - // add a note field - if (!isset($params['note'])) { - $params['note'] = array(); - } - $noteBlock = count($params['note']) + 1; - - $params['note'][$noteBlock] = array(); - if (!isset($fields['Note'])) { - $fields['Note'] = CRM_Core_DAO_Note::fields(); - } - - // get the current logged in civicrm user - $session = CRM_Core_Session::singleton(); - $userID = $session->get('userID'); - - if ($userID) { - $values['contact_id'] = $userID; - } - - _civicrm_api3_store_values($fields['Note'], $values, $params['note'][$noteBlock]); - - return TRUE; - } - - // Check for custom field values - - if (empty($fields['custom'])) { - $fields['custom'] = &CRM_Core_BAO_CustomField::getFields(CRM_Utils_Array::value('contact_type', $values), - FALSE, FALSE, NULL, NULL, FALSE, FALSE, FALSE - ); - } - - foreach ($values as $key => $value) { - if ($customFieldID = CRM_Core_BAO_CustomField::getKeyID($key)) { - // check if it's a valid custom field id - - if (!array_key_exists($customFieldID, $fields['custom'])) { - return civicrm_api3_create_error('Invalid custom field ID'); - } - else { - $params[$key] = $value; - } - } - } - return TRUE; - } - } diff --git a/CRM/Custom/Import/Parser/Api.php b/CRM/Custom/Import/Parser/Api.php index 0f4f1fb5f5..dad22e5fd5 100644 --- a/CRM/Custom/Import/Parser/Api.php +++ b/CRM/Custom/Import/Parser/Api.php @@ -176,7 +176,7 @@ class CRM_Custom_Import_Parser_Api extends CRM_Custom_Import_Parser { } $setDateFields = array_intersect_key($this->_params, array_flip($this->_dateFields)); - CRM_Contact_Import_Parser_Contact::formatCommonData($this->_params, $formatted, $formatted); + $this->formatCommonData($this->_params, $formatted, $formatted); foreach ($formatted['custom'] as $key => $val) { $this->_params['custom_' . $key] = $val[-1]['value']; } -- 2.25.1