/** * A function to build an array of information required by merge function and the merge UI. * * @param int $mainId * Main contact with whom merge has to happen. * @param int $otherId * Duplicate contact which would be deleted after merge operation. * * @return array|bool|int * 'main_loc_block' => Stores all location blocks associated with the 'main' contact */ public static function getRowsElementsAndInfo($mainId, $otherId) { $qfZeroBug = 'e8cddb72-a257-11dc-b9cc-0016d3330ee9'; // Fetch contacts foreach (array('main' => $mainId, 'other' => $otherId) as $moniker => $cid) { $params = array('contact_id' => $cid, 'version' => 3, 'return' => array_merge(array('display_name'), self::getContactFields())); $result = civicrm_api('contact', 'get', $params); if (empty($result['values'][$cid]['contact_type'])) { return FALSE; } ${$moniker} = $result['values'][$cid]; } $fields = CRM_Contact_DAO_Contact::fields(); // FIXME: there must be a better way foreach (array('main', 'other') as $moniker) { $contact =& ${$moniker}; $preferred_communication_method = CRM_Utils_array::value('preferred_communication_method', $contact); $value = empty($preferred_communication_method) ? array() : $preferred_communication_method; $specialValues[$moniker] = array('preferred_communication_method' => $value, 'communication_style_id' => $value); if (!empty($contact['preferred_communication_method'])) { // api 3 returns pref_comm_method as an array, which breaks the lookup; so we reconstruct $prefCommList = is_array($specialValues[$moniker]['preferred_communication_method']) ? implode(CRM_Core_DAO::VALUE_SEPARATOR, $specialValues[$moniker]['preferred_communication_method']) : $specialValues[$moniker]['preferred_communication_method']; $specialValues[$moniker]['preferred_communication_method'] = CRM_Core_DAO::VALUE_SEPARATOR . $prefCommList . CRM_Core_DAO::VALUE_SEPARATOR; } $names = array('preferred_communication_method' => array('newName' => 'preferred_communication_method_display', 'groupName' => 'preferred_communication_method')); CRM_Core_OptionGroup::lookupValues($specialValues[$moniker], $names); if (!empty($contact['communication_style'])) { $specialValues[$moniker]['communication_style_id_display'] = $contact['communication_style']; } } static $optionValueFields = array(); if (empty($optionValueFields)) { $optionValueFields = CRM_Core_OptionValue::getFields(); } foreach ($optionValueFields as $field => $params) { $fields[$field]['title'] = $params['title']; } $compareFields = self::retrieveFields($main, $other); $rows = $elements = $relTableElements = $migrationInfo = array(); foreach ($compareFields['contact'] as $field) { if ($field == 'contact_sub_type') { // CRM-15681 don't display sub-types in UI continue; } foreach (array('main', 'other') as $moniker) { $contact =& ${$moniker}; $value = CRM_Utils_Array::value($field, $contact); if (isset($specialValues[$moniker][$field]) && is_string($specialValues[$moniker][$field])) { $value = CRM_Core_DAO::VALUE_SEPARATOR . trim($specialValues[$moniker][$field], CRM_Core_DAO::VALUE_SEPARATOR) . CRM_Core_DAO::VALUE_SEPARATOR; } $label = isset($specialValues[$moniker]["{$field}_display"]) ? $specialValues[$moniker]["{$field}_display"] : $value; if (!empty($fields[$field]['type']) && $fields[$field]['type'] == CRM_Utils_Type::T_DATE) { if ($value) { $value = str_replace('-', '', $value); $label = CRM_Utils_Date::customFormat($label); } else { $value = "null"; } } elseif (!empty($fields[$field]['type']) && $fields[$field]['type'] == CRM_Utils_Type::T_BOOLEAN) { if ($label === '0') { $label = ts('[ ]'); } if ($label === '1') { $label = ts('[x]'); } } elseif ($field == 'individual_prefix' || $field == 'prefix_id') { $label = CRM_Utils_Array::value('individual_prefix', $contact); $value = CRM_Utils_Array::value('prefix_id', $contact); $field = 'prefix_id'; } elseif ($field == 'individual_suffix' || $field == 'suffix_id') { $label = CRM_Utils_Array::value('individual_suffix', $contact); $value = CRM_Utils_Array::value('suffix_id', $contact); $field = 'suffix_id'; } elseif ($field == 'gender_id' && !empty($value)) { $genderOptions = civicrm_api3('contact', 'getoptions', array('field' => 'gender_id')); $label = $genderOptions['values'][$value]; } elseif ($field == 'current_employer_id' && !empty($value)) { $label = "{$value} (" . CRM_Contact_BAO_Contact::displayName($value) . ")"; } $rows["move_{$field}"][$moniker] = $label; if ($moniker == 'other') { //CRM-14334 if ($value === NULL || $value == '') { $value = 'null'; } if ($value === 0 or $value === '0') { $value = $qfZeroBug; } if (is_array($value) && empty($value[1])) { $value[1] = NULL; } // Display a checkbox to migrate, only if the values are different if ($value != $main[$field]) { $elements[] = array('advcheckbox', "move_{$field}", NULL, NULL, NULL, $value); } $migrationInfo["move_{$field}"] = $value; } } $rows["move_{$field}"]['title'] = $fields[$field]['title']; } // Handle location blocks. // @todo OpenID not in API yet, so is not supported here. // Set up useful information about the location blocks $locationBlocks = self::getLocationBlockInfo(); $locations = array('main' => array(), 'other' => array()); $mainLocBlock = array(); // @todo This could probably be defined and used earlier $mergeTargets = array('main' => $mainId, 'other' => $otherId); foreach ($locationBlocks as $blockName => $blockInfo) { // Collect existing fields from both 'main' and 'other' contacts first // This allows us to match up location/types when building the table rows foreach ($mergeTargets as $moniker => $cid) { $cnt = 1; $searchParams = array('version' => 3, 'contact_id' => $cid, 'options' => array('sort' => $blockInfo['sortString'])); $values = civicrm_api($blockName, 'get', $searchParams); if ($values['count']) { $cnt = 0; foreach ($values['values'] as $index => $value) { $locations[$moniker][$blockName][$cnt] = $value; // Fix address display $display = ''; if ($blockName == 'address') { CRM_Core_BAO_Address::fixAddress($value); $display = CRM_Utils_Address::format($value); $locations[$moniker][$blockName][$cnt]['display'] = $display; } // Add any 'main' contact block values to an array for the JS // @todo The JS should just access the main_details to find this info? if ($moniker == 'main') { if ($blockInfo['hasType']) { // Handle websites, no location type ID // @todo Remove the need for this specific 'if' if ($blockName == 'website') { $value['location_type_id'] = 0; } $mainLocBlock["main_" . $blockName . "_" . $value['location_type_id'] . "_" . $value[$blockInfo['hasType']]]['display'] = $value[$blockInfo['displayField']]; $mainLocBlock["main_" . $blockName . "_" . $value['location_type_id'] . "_" . $value[$blockInfo['hasType']]]['id'] = $value['id']; } else { // Get the correct display value for addresses // @todo Remove the need for this if... if ($blockName == 'address') { $mainLocBlock["main_" . $blockName . "_" . $value['location_type_id']]['display'] = $display; $mainLocBlock["main_" . $blockName . "_" . $value['location_type_id']]['id'] = $value['id']; } else { $mainLocBlock["main_" . $blockName . "_" . $value['location_type_id']]['display'] = $value[$blockInfo['displayField']]; $mainLocBlock["main_" . $blockName . "_" . $value['location_type_id']]['id'] = $value['id']; } } } $cnt++; } } } // Now, build the table rows appropriately, based off the information on // the 'other' contact if (!empty($locations['other']) && !empty($locations['other'][$blockName])) { foreach ($locations['other'][$blockName] as $count => $value) { $displayValue = $value[$blockInfo['displayField']]; // Add this value to the table rows $rows["move_location_{$blockName}_{$count}"]['other'] = $displayValue; // CRM-17556 Only display 'main' contact value if it's the same location + type // Look it up from main values... $lookupLocation = FALSE; if ($blockInfo['hasLocation']) { $lookupLocation = $value['location_type_id']; } $lookupType = FALSE; if ($blockInfo['hasType']) { $lookupType = $value[$blockInfo['hasType']]; } // Hold ID of main contact's matching block $mainContactBlockId = 0; if (!empty($locations['main'][$blockName])) { foreach ($locations['main'][$blockName] as $mainValueCheck) { // No location/type, or matching location and type if ((empty($lookupLocation) || $lookupLocation == $mainValueCheck['location_type_id']) && (empty($lookupType) || $lookupType == $mainValueCheck[$blockInfo['hasType']])) { // Set this value as the default against the 'other' contact value $rows["move_location_{$blockName}_{$count}"]['main'] = $mainValueCheck[$blockInfo['displayField']]; $mainContactBlockId = $mainValueCheck['id']; break; } } } // Add checkbox to migrate data from 'other' to 'main' $elements[] = array('advcheckbox', "move_location_{$blockName}_{$count}"); // Flag up this field to skipMerge function (@todo: do we need to?) $migrationInfo["move_location_{$blockName}_{$count}"] = 1; // Add a hidden field to store the ID of the target main contact block $elements[] = array('hidden', "location[{$blockName}][{$count}][mainContactBlockId]", $mainContactBlockId); // Setup variables $thisTypeId = FALSE; $thisLocId = FALSE; // Provide a select drop-down for the location's location type // eg: Home, Work... $js = NULL; if ($blockInfo['hasLocation']) { // Load the location options for this entity $locationOptions = civicrm_api3($blockName, 'getoptions', array('field' => 'location_type_id')); // JS lookup 'main' contact's location (if there are any) if (!empty($locations['main'][$blockName])) { $js = array('onChange' => "mergeBlock('{$blockName}', this, {$count}, 'locTypeId' );"); } $thisLocId = $value['location_type_id']; // Put this field's location type at the top of the list $tmpIdList = $locationOptions['values']; $defaultLocId = array($thisLocId => $tmpIdList[$thisLocId]); unset($tmpIdList[$thisLocId]); // Add the element $elements[] = array('select', "location[{$blockName}][{$count}][locTypeId]", NULL, $defaultLocId + $tmpIdList, $js); // Add the relevant information to the $migrationInfo // Keep location-type-id same as that of other-contact // @todo Check this logic out $migrationInfo['location_blocks'][$blockName][$count]['locTypeId'] = $thisLocId; if ($blockName != 'address') { $elements[] = array('advcheckbox', "location[{$blockName}][{$count}][operation]", NULL, ts('add new')); // always use add operation $migrationInfo['location_blocks'][$blockName][$count]['operation'] = 1; } } // Provide a select drop-down for the location's type/provider // eg websites: Google+, Facebook... $js = NULL; if ($blockInfo['hasType']) { // Load the type options for this entity $typeOptions = civicrm_api3($blockName, 'getoptions', array('field' => $blockInfo['hasType'])); // CRM-17556 Set up JS lookup of 'main' contact's value by type if (!empty($locations['main'][$blockName])) { $js = array('onChange' => "mergeBlock('{$blockName}', this, {$count}, 'typeTypeId' );"); } $thisTypeId = $value[$blockInfo['hasType']]; // Put this field's location type at the top of the list $tmpIdList = $typeOptions['values']; $defaultTypeId = array($thisTypeId => $tmpIdList[$thisTypeId]); unset($tmpIdList[$thisTypeId]); // Add the element $elements[] = array('select', "location[{$blockName}][{$count}][typeTypeId]", NULL, $defaultTypeId + $tmpIdList, $js); // Add the information to the migrationInfo (@todo Why?) $migrationInfo['location_blocks'][$blockName][$count]['typeTypeId'] = $thisTypeId; } // Set the label for this row $rowTitle = $blockInfo['label'] . ' ' . ($count + 1); if (!empty($thisLocId)) { $rowTitle .= ' (' . $locationOptions['values'][$thisLocId] . ')'; } if (!empty($thisTypeId)) { $rowTitle .= ' (' . $typeOptions['values'][$thisTypeId] . ')'; } $rows["move_location_{$blockName}_{$count}"]['title'] = $rowTitle; } // End loop through 'other' locations of this type } // End if 'other' location for this type exists } // End loop through each location block entity // add the related tables and unset the ones that don't sport any of the duplicate contact's info $config = CRM_Core_Config::singleton(); $mainUfId = CRM_Core_BAO_UFMatch::getUFId($mainId); $mainUser = NULL; if ($mainUfId) { // d6 compatible if ($config->userSystem->is_drupal == '1' && function_exists($mainUser)) { $mainUser = user_load($mainUfId); } elseif ($config->userFramework == 'Joomla') { $mainUser = JFactory::getUser($mainUfId); } } $otherUfId = CRM_Core_BAO_UFMatch::getUFId($otherId); $otherUser = NULL; if ($otherUfId) { // d6 compatible if ($config->userSystem->is_drupal == '1' && function_exists($mainUser)) { $otherUser = user_load($otherUfId); } elseif ($config->userFramework == 'Joomla') { $otherUser = JFactory::getUser($otherUfId); } } $relTables = CRM_Dedupe_Merger::relTables(); $activeRelTables = CRM_Dedupe_Merger::getActiveRelTables($otherId); $activeMainRelTables = CRM_Dedupe_Merger::getActiveRelTables($mainId); foreach ($relTables as $name => $null) { if (!in_array($name, $activeRelTables) && !($name == 'rel_table_users' && in_array($name, $activeMainRelTables))) { unset($relTables[$name]); continue; } $relTableElements[] = array('checkbox', "move_{$name}"); $migrationInfo["move_{$name}"] = 1; $relTables[$name]['main_url'] = str_replace('$cid', $mainId, $relTables[$name]['url']); $relTables[$name]['other_url'] = str_replace('$cid', $otherId, $relTables[$name]['url']); if ($name == 'rel_table_users') { $relTables[$name]['main_url'] = str_replace('%ufid', $mainUfId, $relTables[$name]['url']); $relTables[$name]['other_url'] = str_replace('%ufid', $otherUfId, $relTables[$name]['url']); $find = array('$ufid', '$ufname'); if ($mainUser) { $replace = array($mainUfId, $mainUser->name); $relTables[$name]['main_title'] = str_replace($find, $replace, $relTables[$name]['title']); } if ($otherUser) { $replace = array($otherUfId, $otherUser->name); $relTables[$name]['other_title'] = str_replace($find, $replace, $relTables[$name]['title']); } } if ($name == 'rel_table_memberships') { $elements[] = array('checkbox', "operation[move_{$name}][add]", NULL, ts('add new')); $migrationInfo["operation"]["move_{$name}"]['add'] = 1; } } foreach ($relTables as $name => $null) { $relTables["move_{$name}"] = $relTables[$name]; unset($relTables[$name]); } // handle custom fields $mainTree = CRM_Core_BAO_CustomGroup::getTree($main['contact_type'], CRM_Core_DAO::$_nullObject, $mainId, -1, CRM_Utils_Array::value('contact_sub_type', $main)); $otherTree = CRM_Core_BAO_CustomGroup::getTree($main['contact_type'], CRM_Core_DAO::$_nullObject, $otherId, -1, CRM_Utils_Array::value('contact_sub_type', $other)); CRM_Core_DAO::freeResult(); foreach ($otherTree as $gid => $group) { $foundField = FALSE; if (!isset($group['fields'])) { continue; } foreach ($group['fields'] as $fid => $field) { if (in_array($fid, $compareFields['custom'])) { if (!$foundField) { $rows["custom_group_{$gid}"]['title'] = $group['title']; $foundField = TRUE; } if (!empty($mainTree[$gid]['fields'][$fid]['customValue'])) { foreach ($mainTree[$gid]['fields'][$fid]['customValue'] as $valueId => $values) { $rows["move_custom_{$fid}"]['main'] = CRM_Core_BAO_CustomField::displayValue($values['data'], $fid); } } $value = "null"; if (!empty($otherTree[$gid]['fields'][$fid]['customValue'])) { foreach ($otherTree[$gid]['fields'][$fid]['customValue'] as $valueId => $values) { $rows["move_custom_{$fid}"]['other'] = CRM_Core_BAO_CustomField::displayValue($values['data'], $fid); if ($values['data'] === 0 || $values['data'] === '0') { $values['data'] = $qfZeroBug; } $value = $values['data'] ? $values['data'] : $value; } } $rows["move_custom_{$fid}"]['title'] = $field['label']; $elements[] = array('advcheckbox', "move_custom_{$fid}", NULL, NULL, NULL, $value); $migrationInfo["move_custom_{$fid}"] = $value; } } } $result = array('rows' => $rows, 'elements' => $elements, 'rel_table_elements' => $relTableElements, 'main_loc_block' => $mainLocBlock, 'rel_tables' => $relTables, 'main_details' => $main, 'other_details' => $other, 'migration_info' => $migrationInfo); $result['main_details']['location_blocks'] = $locations['main']; $result['other_details']['location_blocks'] = $locations['other']; return $result; }
/** * A function to build an array of information required by merge function and the merge UI. * * @param int $mainId * Main contact with whom merge has to happen. * @param int $otherId * Duplicate contact which would be deleted after merge operation. * * @return array|bool|int */ public static function getRowsElementsAndInfo($mainId, $otherId) { $qfZeroBug = 'e8cddb72-a257-11dc-b9cc-0016d3330ee9'; // Fetch contacts foreach (array('main' => $mainId, 'other' => $otherId) as $moniker => $cid) { $params = array('contact_id' => $cid, 'version' => 3, 'return' => array_merge(array('display_name'), self::getContactFields())); $result = civicrm_api('contact', 'get', $params); if (empty($result['values'][$cid]['contact_type'])) { return FALSE; } ${$moniker} = $result['values'][$cid]; } static $fields = array(); if (empty($fields)) { $fields = CRM_Contact_DAO_Contact::fields(); CRM_Core_DAO::freeResult(); } // FIXME: there must be a better way foreach (array('main', 'other') as $moniker) { $contact =& ${$moniker}; $preferred_communication_method = CRM_Utils_array::value('preferred_communication_method', $contact); $value = empty($preferred_communication_method) ? array() : $preferred_communication_method; $specialValues[$moniker] = array('preferred_communication_method' => $value, 'communication_style_id' => $value); if (!empty($contact['preferred_communication_method'])) { // api 3 returns pref_comm_method as an array, which breaks the lookup; so we reconstruct $prefCommList = is_array($specialValues[$moniker]['preferred_communication_method']) ? implode(CRM_Core_DAO::VALUE_SEPARATOR, $specialValues[$moniker]['preferred_communication_method']) : $specialValues[$moniker]['preferred_communication_method']; $specialValues[$moniker]['preferred_communication_method'] = CRM_Core_DAO::VALUE_SEPARATOR . $prefCommList . CRM_Core_DAO::VALUE_SEPARATOR; } $names = array('preferred_communication_method' => array('newName' => 'preferred_communication_method_display', 'groupName' => 'preferred_communication_method')); CRM_Core_OptionGroup::lookupValues($specialValues[$moniker], $names); if (!empty($contact['communication_style'])) { $specialValues[$moniker]['communication_style_id_display'] = $contact['communication_style']; } } static $optionValueFields = array(); if (empty($optionValueFields)) { $optionValueFields = CRM_Core_OptionValue::getFields(); } foreach ($optionValueFields as $field => $params) { $fields[$field]['title'] = $params['title']; } $diffs = self::findDifferences($main, $other); $rows = $elements = $relTableElements = $migrationInfo = array(); $genders = CRM_Core_PseudoConstant::get('CRM_Contact_DAO_Contact', 'gender_id'); foreach ($diffs['contact'] as $field) { if ($field == 'contact_sub_type') { // CRM-15681 don't display sub-types in UI continue; } foreach (array('main', 'other') as $moniker) { $contact =& ${$moniker}; $value = CRM_Utils_Array::value($field, $contact); if (isset($specialValues[$moniker][$field]) && is_string($specialValues[$moniker][$field])) { $value = CRM_Core_DAO::VALUE_SEPARATOR . trim($specialValues[$moniker][$field], CRM_Core_DAO::VALUE_SEPARATOR) . CRM_Core_DAO::VALUE_SEPARATOR; } $label = isset($specialValues[$moniker]["{$field}_display"]) ? $specialValues[$moniker]["{$field}_display"] : $value; if (!empty($fields[$field]['type']) && $fields[$field]['type'] == CRM_Utils_Type::T_DATE) { if ($value) { $value = str_replace('-', '', $value); $label = CRM_Utils_Date::customFormat($label); } else { $value = "null"; } } elseif (!empty($fields[$field]['type']) && $fields[$field]['type'] == CRM_Utils_Type::T_BOOLEAN) { if ($label === '0') { $label = ts('[ ]'); } if ($label === '1') { $label = ts('[x]'); } } elseif ($field == 'individual_prefix' || $field == 'prefix_id') { $label = CRM_Utils_Array::value('individual_prefix', $contact); $value = CRM_Utils_Array::value('prefix_id', $contact); $field = 'prefix_id'; } elseif ($field == 'individual_suffix' || $field == 'suffix_id') { $label = CRM_Utils_Array::value('individual_suffix', $contact); $value = CRM_Utils_Array::value('suffix_id', $contact); $field = 'suffix_id'; } elseif ($field == 'gender_id' && !empty($value)) { $label = $genders[$value]; } elseif ($field == 'current_employer_id' && !empty($value)) { $label = "{$value} (" . CRM_Contact_BAO_Contact::displayName($value) . ")"; } $rows["move_{$field}"][$moniker] = $label; if ($moniker == 'other') { //CRM-14334 if ($value === NULL || $value == '') { $value = 'null'; } if ($value === 0 or $value === '0') { $value = $qfZeroBug; } if (is_array($value) && empty($value[1])) { $value[1] = NULL; } $elements[] = array('advcheckbox', "move_{$field}", NULL, NULL, NULL, $value); $migrationInfo["move_{$field}"] = $value; } } $rows["move_{$field}"]['title'] = $fields[$field]['title']; } // handle location blocks. $locationBlocks = array('email', 'phone', 'address'); $locations = array(); foreach ($locationBlocks as $block) { foreach (array('main' => $mainId, 'other' => $otherId) as $moniker => $cid) { $cnt = 1; $values = civicrm_api($block, 'get', array('contact_id' => $cid, 'version' => 3)); $count = $values['count']; if ($count) { if ($count > $cnt) { foreach ($values['values'] as $value) { if ($block == 'address') { CRM_Core_BAO_Address::fixAddress($value); $display = CRM_Utils_Address::format($value); $locations[$moniker][$block][$cnt] = $value; $locations[$moniker][$block][$cnt]['display'] = $display; } else { $locations[$moniker][$block][$cnt] = $value; } $cnt++; } } else { $id = $values['id']; if ($block == 'address') { CRM_Core_BAO_Address::fixAddress($values['values'][$id]); $display = CRM_Utils_Address::format($values['values'][$id]); $locations[$moniker][$block][$cnt] = $values['values'][$id]; $locations[$moniker][$block][$cnt]['display'] = $display; } else { $locations[$moniker][$block][$cnt] = $values['values'][$id]; } } } } } $allLocationTypes = CRM_Core_PseudoConstant::get('CRM_Core_DAO_Address', 'location_type_id'); $mainLocBlock = $locBlockIds = array(); $locBlockIds['main'] = $locBlockIds['other'] = array(); foreach (array('Email', 'Phone', 'IM', 'OpenID', 'Address') as $block) { $name = strtolower($block); foreach (array('main', 'other') as $moniker) { $locIndex = CRM_Utils_Array::value($moniker, $locations); $blockValue = CRM_Utils_Array::value($name, $locIndex, array()); if (empty($blockValue)) { $locValue[$moniker][$name] = 0; $locLabel[$moniker][$name] = $locTypes[$moniker][$name] = array(); } else { $locValue[$moniker][$name] = TRUE; foreach ($blockValue as $count => $blkValues) { $fldName = $name; $locTypeId = $blkValues['location_type_id']; if ($name == 'im') { $fldName = 'name'; } if ($name == 'address') { $fldName = 'display'; } $locLabel[$moniker][$name][$count] = CRM_Utils_Array::value($fldName, $blkValues); $locTypes[$moniker][$name][$count] = $locTypeId; if ($moniker == 'main' && in_array($name, $locationBlocks)) { $mainLocBlock["main_{$name}{$locTypeId}"] = CRM_Utils_Array::value($fldName, $blkValues); $locBlockIds['main'][$name][$locTypeId] = $blkValues['id']; } else { $locBlockIds[$moniker][$name][$count] = $blkValues['id']; } } } } if ($locValue['other'][$name] != 0) { foreach ($locLabel['other'][$name] as $count => $value) { $locTypeId = $locTypes['other'][$name][$count]; $rows["move_location_{$name}_{$count}"]['other'] = $value; $rows["move_location_{$name}_{$count}"]['main'] = CRM_Utils_Array::value($count, $locLabel['main'][$name]); $rows["move_location_{$name}_{$count}"]['title'] = ts('%1:%2:%3', array(1 => $block, 2 => $count, 3 => $allLocationTypes[$locTypeId])); $elements[] = array('advcheckbox', "move_location_{$name}_{$count}"); $migrationInfo["move_location_{$name}_{$count}"] = 1; // make sure default location type is always on top $mainLocTypeId = CRM_Utils_Array::value($count, $locTypes['main'][$name], $locTypeId); $locTypeValues = $allLocationTypes; $defaultLocType = array($mainLocTypeId => $locTypeValues[$mainLocTypeId]); unset($locTypeValues[$mainLocTypeId]); // keep 1-1 mapping for address - location type. $js = NULL; if (in_array($name, $locationBlocks) && !empty($mainLocBlock)) { $js = array('onChange' => "mergeBlock('{$name}', this, {$count} );"); } $elements[] = array('select', "location[{$name}][{$count}][locTypeId]", NULL, $defaultLocType + $locTypeValues, $js); // keep location-type-id same as that of other-contact $migrationInfo['location'][$name][$count]['locTypeId'] = $locTypeId; if ($name != 'address') { $elements[] = array('advcheckbox', "location[{$name}][{$count}][operation]", NULL, ts('add new')); // always use add operation $migrationInfo['location'][$name][$count]['operation'] = 1; } } } } // add the related tables and unset the ones that don't sport any of the duplicate contact's info $config = CRM_Core_Config::singleton(); $mainUfId = CRM_Core_BAO_UFMatch::getUFId($mainId); $mainUser = NULL; if ($mainUfId) { // d6 compatible if ($config->userSystem->is_drupal == '1' && function_exists($mainUser)) { $mainUser = user_load($mainUfId); } elseif ($config->userFramework == 'Joomla') { $mainUser = JFactory::getUser($mainUfId); } } $otherUfId = CRM_Core_BAO_UFMatch::getUFId($otherId); $otherUser = NULL; if ($otherUfId) { // d6 compatible if ($config->userSystem->is_drupal == '1' && function_exists($mainUser)) { $otherUser = user_load($otherUfId); } elseif ($config->userFramework == 'Joomla') { $otherUser = JFactory::getUser($otherUfId); } } $relTables = CRM_Dedupe_Merger::relTables(); $activeRelTables = CRM_Dedupe_Merger::getActiveRelTables($otherId); $activeMainRelTables = CRM_Dedupe_Merger::getActiveRelTables($mainId); foreach ($relTables as $name => $null) { if (!in_array($name, $activeRelTables) && !($name == 'rel_table_users' && in_array($name, $activeMainRelTables))) { unset($relTables[$name]); continue; } $relTableElements[] = array('checkbox', "move_{$name}"); $migrationInfo["move_{$name}"] = 1; $relTables[$name]['main_url'] = str_replace('$cid', $mainId, $relTables[$name]['url']); $relTables[$name]['other_url'] = str_replace('$cid', $otherId, $relTables[$name]['url']); if ($name == 'rel_table_users') { $relTables[$name]['main_url'] = str_replace('%ufid', $mainUfId, $relTables[$name]['url']); $relTables[$name]['other_url'] = str_replace('%ufid', $otherUfId, $relTables[$name]['url']); $find = array('$ufid', '$ufname'); if ($mainUser) { $replace = array($mainUfId, $mainUser->name); $relTables[$name]['main_title'] = str_replace($find, $replace, $relTables[$name]['title']); } if ($otherUser) { $replace = array($otherUfId, $otherUser->name); $relTables[$name]['other_title'] = str_replace($find, $replace, $relTables[$name]['title']); } } if ($name == 'rel_table_memberships') { $elements[] = array('checkbox', "operation[move_{$name}][add]", NULL, ts('add new')); $migrationInfo["operation"]["move_{$name}"]['add'] = 1; } } foreach ($relTables as $name => $null) { $relTables["move_{$name}"] = $relTables[$name]; unset($relTables[$name]); } // handle custom fields $mainTree = CRM_Core_BAO_CustomGroup::getTree($main['contact_type'], CRM_Core_DAO::$_nullObject, $mainId, -1, CRM_Utils_Array::value('contact_sub_type', $main)); $otherTree = CRM_Core_BAO_CustomGroup::getTree($main['contact_type'], CRM_Core_DAO::$_nullObject, $otherId, -1, CRM_Utils_Array::value('contact_sub_type', $other)); CRM_Core_DAO::freeResult(); foreach ($otherTree as $gid => $group) { $foundField = FALSE; if (!isset($group['fields'])) { continue; } foreach ($group['fields'] as $fid => $field) { if (in_array($fid, $diffs['custom'])) { if (!$foundField) { $rows["custom_group_{$gid}"]['title'] = $group['title']; $foundField = TRUE; } if (!empty($mainTree[$gid]['fields'][$fid]['customValue'])) { foreach ($mainTree[$gid]['fields'][$fid]['customValue'] as $valueId => $values) { $rows["move_custom_{$fid}"]['main'] = CRM_Core_BAO_CustomGroup::formatCustomValues($values, $field, TRUE); } } $value = "null"; if (!empty($otherTree[$gid]['fields'][$fid]['customValue'])) { foreach ($otherTree[$gid]['fields'][$fid]['customValue'] as $valueId => $values) { $rows["move_custom_{$fid}"]['other'] = CRM_Core_BAO_CustomGroup::formatCustomValues($values, $field, TRUE); if ($values['data'] === 0 || $values['data'] === '0') { $values['data'] = $qfZeroBug; } $value = $values['data'] ? $values['data'] : $value; } } $rows["move_custom_{$fid}"]['title'] = $field['label']; $elements[] = array('advcheckbox', "move_custom_{$fid}", NULL, NULL, NULL, $value); $migrationInfo["move_custom_{$fid}"] = $value; } } } $result = array('rows' => $rows, 'elements' => $elements, 'rel_table_elements' => $relTableElements, 'main_loc_block' => $mainLocBlock, 'rel_tables' => $relTables, 'main_details' => $main, 'other_details' => $other, 'migration_info' => $migrationInfo); $result['main_details']['loc_block_ids'] = $locBlockIds['main']; $result['other_details']['loc_block_ids'] = $locBlockIds['other']; return $result; }
function preProcess() { require_once 'api/v2/Contact.php'; require_once 'CRM/Core/BAO/CustomGroup.php'; require_once 'CRM/Core/OptionGroup.php'; require_once 'CRM/Core/OptionValue.php'; if (!CRM_Core_Permission::check('administer CiviCRM')) { CRM_Core_Error::fatal(ts('You do not have access to this page')); } $cid = CRM_Utils_Request::retrieve('cid', 'Positive', $this, true); $oid = CRM_Utils_Request::retrieve('oid', 'Positive', $this, true); $rgid = CRM_Utils_Request::retrieve('rgid', 'Positive', $this, false); $gid = CRM_Utils_Request::retrieve('gid', 'Positive', $this, false); $session =& CRM_Core_Session::singleton(); // context fixed. if ($rgid) { $urlParam = "reset=1&action=browse&rgid={$rgid}"; if ($gid) { $urlParam .= "&gid={$gid}"; } $session->pushUserContext(CRM_Utils_system::url('civicrm/admin/dedupefind', $urlParam)); } // ensure that oid is not the current user, if so refuse to do the merge if ($session->get('userID') == $oid) { $display_name = CRM_Core_DAO::getFieldValue('CRM_Contact_DAO_Contact', $oid, 'display_name'); $message = ts('The contact record which is linked to the currently logged in user account - \'%1\' - cannot be deleted.', array(1 => $display_name)); CRM_Core_Error::statusBounce($message); } $diffs = CRM_Dedupe_Merger::findDifferences($cid, $oid); $mainParams = array('contact_id' => $cid, 'return.display_name' => 1); $otherParams = array('contact_id' => $oid, 'return.display_name' => 1); // API 2 has to have the requested fields spelt-out for it foreach (CRM_Dedupe_Merger::$validFields as $field) { $mainParams["return.{$field}"] = $otherParams["return.{$field}"] = 1; } $main =& civicrm_contact_get($mainParams); //CRM-4524 $main = reset($main); if ($main['contact_id'] != $cid) { CRM_Core_Error::fatal(ts('The main contact record does not exist')); } $other =& civicrm_contact_get($otherParams); //CRM-4524 $other = reset($other); if ($other['contact_id'] != $oid) { CRM_Core_Error::fatal(ts('The other contact record does not exist')); } $this->assign('contact_type', $main['contact_type']); $this->assign('main_name', $main['display_name']); $this->assign('other_name', $other['display_name']); $this->assign('main_cid', $main['contact_id']); $this->assign('other_cid', $other['contact_id']); $this->_cid = $cid; $this->_oid = $oid; $this->_rgid = $rgid; $this->_contactType = $main['contact_type']; $this->addElement('checkbox', 'toggleSelect', null, null, array('onclick' => "return toggleCheckboxVals('move_',this);")); require_once "CRM/Contact/DAO/Contact.php"; $fields =& CRM_Contact_DAO_Contact::fields(); // FIXME: there must be a better way foreach (array('main', 'other') as $moniker) { $contact =& ${$moniker}; $specialValues[$moniker] = array('preferred_communication_method' => $contact['preferred_communication_method']); $names = array('preferred_communication_method' => array('newName' => 'preferred_communication_method_display', 'groupName' => 'preferred_communication_method')); CRM_Core_OptionGroup::lookupValues($specialValues[$moniker], $names); } foreach (CRM_Core_OptionValue::getFields() as $field => $params) { $fields[$field]['title'] = $params['title']; } if (!isset($diffs['contact'])) { $diffs['contact'] = array(); } foreach ($diffs['contact'] as $field) { foreach (array('main', 'other') as $moniker) { $contact =& ${$moniker}; $value = CRM_Utils_Array::value($field, $contact); $label = isset($specialValues[$moniker][$field]) ? $specialValues[$moniker]["{$field}_display"] : $value; if ($fields[$field]['type'] == CRM_Utils_Type::T_DATE) { if ($value) { $value = str_replace('-', '', $value); $label = CRM_Utils_Date::customFormat($label); } else { $value = "null"; } } elseif ($fields[$field]['type'] == CRM_Utils_Type::T_BOOLEAN) { if ($label === '0') { $label = ts('[ ]'); } if ($label === '1') { $label = ts('[x]'); } } $rows["move_{$field}"][$moniker] = $label; if ($moniker == 'other') { if ($value === null) { $value = 'null'; } if ($value === 0 or $value === '0') { $value = $this->_qfZeroBug; } $this->addElement('advcheckbox', "move_{$field}", null, null, null, $value); } } $rows["move_{$field}"]['title'] = $fields[$field]['title']; } // handle location blocks. require_once 'api/v2/Location.php'; $mainParams['version'] = $otherParams['version'] = '3.0'; $locations['main'] =& civicrm_location_get($mainParams); $locations['other'] =& civicrm_location_get($otherParams); $allLocationTypes = CRM_Core_PseudoConstant::locationType(); $mainLocAddress = array(); foreach (array('Email', 'Phone', 'IM', 'OpenID', 'Address') as $block) { $name = strtolower($block); foreach (array('main', 'other') as $moniker) { $blockValue = CRM_Utils_Array::value($name, $locations[$moniker], array()); if (empty($blockValue)) { $locValue[$moniker][$name] = 0; $locLabel[$moniker][$name] = array(); $locTypes[$moniker][$name] = array(); } else { $locValue[$moniker][$name] = true; foreach ($blockValue as $count => $blkValues) { $fldName = $name; $locTypeId = $blkValues['location_type_id']; if ($name == 'im') { $fldName = 'name'; } if ($name == 'address') { $fldName = 'display'; } $locLabel[$moniker][$name][$count] = $blkValues[$fldName]; $locTypes[$moniker][$name][$count] = $locTypeId; if ($moniker == 'main' && $name == 'address') { $mainLocAddress["main_{$locTypeId}"] = $blkValues[$fldName]; $this->_locBlockIds['main']['address'][$locTypeId] = $blkValues['id']; } else { $this->_locBlockIds[$moniker][$name][$count] = $blkValues['id']; } } } } if ($locValue['other'][$name] != 0) { foreach ($locLabel['other'][$name] as $count => $value) { $locTypeId = $locTypes['other'][$name][$count]; $rows["move_location_{$name}_{$count}"]['other'] = $value; $rows["move_location_{$name}_{$count}"]['main'] = $locLabel['main'][$name][$count]; $rows["move_location_{$name}_{$count}"]['title'] = ts('%1:%2:%3', array(1 => $block, 2 => $count, 3 => $allLocationTypes[$locTypeId])); $this->addElement('advcheckbox', "move_location_{$name}_{$count}"); // make sure default location type is always on top $mainLocTypeId = CRM_Utils_Array::value($count, $locTypes['main'][$name], $locTypeId); $locTypeValues = $allLocationTypes; $defaultLocType = array($mainLocTypeId => $locTypeValues[$mainLocTypeId]); unset($locTypeValues[$mainLocTypeId]); // keep 1-1 mapping for address - location type. $js = null; if ($name == 'address' && !empty($mainLocAddress)) { $js = array('onChange' => "mergeAddress( this, {$count} );"); } $this->addElement('select', "location[{$name}][{$count}][locTypeId]", null, $defaultLocType + $locTypeValues, $js); if ($name != 'address') { $this->addElement('advcheckbox', "location[{$name}][{$count}][operation]", null, ts('add new')); } } } } $this->assign('mainLocAddress', json_encode($mainLocAddress)); // handle custom fields $mainTree =& CRM_Core_BAO_CustomGroup::getTree($this->_contactType, $this, $this->_cid, -1); $otherTree =& CRM_Core_BAO_CustomGroup::getTree($this->_contactType, $this, $this->_oid, -1); if (!isset($diffs['custom'])) { $diffs['custom'] = array(); } foreach ($otherTree as $gid => $group) { $foundField = false; if (!isset($group['fields'])) { continue; } foreach ($group['fields'] as $fid => $field) { if (in_array($fid, $diffs['custom'])) { if (!$foundField) { $rows["custom_group_{$gid}"]['title'] = $group['title']; $foundField = true; } if (is_array($mainTree[$gid]['fields'][$fid]['customValue'])) { foreach ($mainTree[$gid]['fields'][$fid]['customValue'] as $valueId => $values) { $rows["move_custom_{$fid}"]['main'] = CRM_Core_BAO_CustomGroup::formatCustomValues($values, $field); } } if (is_array($otherTree[$gid]['fields'][$fid]['customValue'])) { foreach ($otherTree[$gid]['fields'][$fid]['customValue'] as $valueId => $values) { $rows["move_custom_{$fid}"]['other'] = CRM_Core_BAO_CustomGroup::formatCustomValues($values, $field); $value = $values['data'] ? $values['data'] : $this->_qfZeroBug; } } $rows["move_custom_{$fid}"]['title'] = $field['label']; $this->addElement('advcheckbox', "move_custom_{$fid}", null, null, null, $value); } } } $this->assign('rows', $rows); // add the related tables and unset the ones that don't sport any of the duplicate contact's info $relTables = CRM_Dedupe_Merger::relTables(); $activeRelTables = CRM_Dedupe_Merger::getActiveRelTables($oid); foreach ($relTables as $name => $null) { if (!in_array($name, $activeRelTables)) { unset($relTables[$name]); continue; } $this->addElement('checkbox', "move_{$name}"); $relTables[$name]['main_url'] = str_replace('$cid', $cid, $relTables[$name]['url']); $relTables[$name]['other_url'] = str_replace('$cid', $oid, $relTables[$name]['url']); } foreach ($relTables as $name => $null) { $relTables["move_{$name}"] = $relTables[$name]; unset($relTables[$name]); } $this->assign('rel_tables', $relTables); }