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); }
/** * 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 * * @static void * @access public */ function &getRowsElementsAndInfo($mainId, $otherId) { $qfZeroBug = 'e8cddb72-a257-11dc-b9cc-0016d3330ee9'; $mainParams = array('contact_id' => $mainId, 'return.display_name' => 1, 'return.contact_sub_type' => 1); $otherParams = array('contact_id' => $otherId, 'return.display_name' => 1, 'return.contact_sub_type' => 1); $mainParams['version'] = $otherParams['version'] = 3; foreach (CRM_Dedupe_Merger::$validFields as $field) { $mainParams["return.{$field}"] = $otherParams["return.{$field}"] = 1; } $main = civicrm_api('contact', 'get', $mainParams); // CRM-4524 $main = reset($main['values']); if ($main['contact_id'] != $mainId) { // FIXME: The main contact record does not exist return FALSE; } $other = civicrm_api('contact', 'get', $otherParams); // CRM-4524 $other = reset($other['values']); if ($other['contact_id'] != $otherId) { // FIXME: The other contact record does not exist return FALSE; } static $fields = array(); if (empty($fields)) { $fields = CRM_Contact_DAO_Contact::fields(); CRM_Core_DAO::freeResult(); } // FIXME: there must be a better way $monikers = array('main', 'other'); foreach ($monikers 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); // 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); } static $optionValueFields = array(); if (empty($optionValueFields)) { $optionValueFields = CRM_Core_OptionValue::getFields(); } foreach ($optionValueFields as $field => $params) { $fields[$field]['title'] = $params['title']; } $diffs = CRM_Dedupe_Merger::findDifferences($mainId, $otherId); if (!isset($diffs['contact'])) { $diffs['contact'] = array(); } $rows = $elements = $relTableElements = $migrationInfo = array(); foreach ($diffs['contact'] as $field) { foreach (array('main', 'other') as $moniker) { $contact =& ${$moniker}; $value = CRM_Utils_Array::value($field, $contact); if (isset($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]) ? $specialValues[$moniker]["{$field}_display"] : $value; if (CRM_Utils_Array::value('type', $fields[$field]) && $fields[$field]['type'] == CRM_Utils_Type::T_DATE) { if ($value) { $value = str_replace('-', '', $value); $label = CRM_Utils_Date::customFormat($label); } else { $value = "null"; } } elseif (CRM_Utils_Array::value('type', $fields[$field]) && $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('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('suffix', $contact); $value = CRM_Utils_Array::value('suffix_id', $contact); $field = 'suffix_id'; } $rows["move_{$field}"][$moniker] = $label; if ($moniker == 'other') { if ($value === NULL) { $value = 'null'; } if ($value === 0 or $value === '0') { $value = $qfZeroBug; } if (is_array($value) && !CRM_Utils_Array::value(1, $value)) { $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'); foreach ($locationBlocks as $block) { foreach (array('main', 'other') as $locBlocks) { $cnt = 1; $blockName = "{$locBlocks}Params"; $values = civicrm_api($block, 'get', ${$blockName}); $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[$locBlocks][$block][$cnt] = $value; $locations[$locBlocks][$block][$cnt]['display'] = $display; } else { $locations[$locBlocks][$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[$locBlocks][$block][$cnt] = $values['values'][$id]; $locations[$locBlocks][$block][$cnt]['display'] = $display; } else { $locations[$locBlocks][$block][$cnt] = $values['values'][$id]; } } } } } $allLocationTypes = CRM_Core_PseudoConstant::locationType(); $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) { $blockValue = CRM_Utils_Array::value($name, $locations[$moniker], 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(); 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 (CRM_Utils_Array::value('customValue', $mainTree[$gid]['fields'][$fid])) { 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 (CRM_Utils_Array::value('customValue', $otherTree[$gid]['fields'][$fid])) { 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']; // unset all vars to avoid any possible leaks unset($diffs, $contact, $mainTree, $otherTree, $rows, $elements, $relTableElements, $mainLocBlock, $relTables, $main, $other, $migrationInfo); return $result; }