public function postProcess() { $formValues = $this->exportValues(); // reset all selected contact ids from session // when we came from search context, CRM-3526 $session = CRM_Core_Session::singleton(); if ($session->get('selectedSearchContactIds')) { $session->resetScope('selectedSearchContactIds'); } $formValues['main_details'] = $this->_mainDetails; $formValues['other_details'] = $this->_otherDetails; $migrationData = array('migration_info' => $formValues); CRM_Utils_Hook::merge('form', $migrationData, $this->_cid, $this->_oid); CRM_Dedupe_Merger::moveAllBelongings($this->_cid, $this->_oid, $migrationData['migration_info']); $name = CRM_Core_DAO::getFieldValue('CRM_Contact_DAO_Contact', $this->_cid, 'display_name'); $message = '<ul><li>' . ts('%1 has been updated.', array(1 => $name)) . '</li><li>' . ts('Contact ID %1 has been deleted.', array(1 => $this->_oid)) . '</li></ul>'; CRM_Core_Session::setStatus($message, ts('Contacts Merged'), 'success'); $url = CRM_Utils_System::url('civicrm/contact/view', "reset=1&cid={$this->_cid}"); $urlParams = "reset=1&gid={$this->_gid}&rgid={$this->_rgid}&limit={$this->limit}"; if (!empty($formValues['_qf_Merge_submit'])) { $urlParams .= "&action=update"; $lisitingURL = CRM_Utils_System::url('civicrm/contact/dedupefind', $urlParams); CRM_Utils_System::redirect($lisitingURL); } if (!empty($formValues['_qf_Merge_done'])) { CRM_Utils_System::redirect($url); } if ($this->next && $this->_mergeId) { $cacheKey = CRM_Dedupe_Merger::getMergeCacheKeyString($this->_rgid, $this->_gid); $join = CRM_Dedupe_Merger::getJoinOnDedupeTable(); $where = "de.id IS NULL"; $pos = CRM_Core_BAO_PrevNextCache::getPositions($cacheKey, NULL, NULL, $this->_mergeId, $join, $where); if (!empty($pos) && $pos['next']['id1'] && $pos['next']['id2']) { $urlParams .= "&cid={$pos['next']['id1']}&oid={$pos['next']['id2']}&mergeId={$pos['next']['mergeId']}&action=update"; $url = CRM_Utils_System::url('civicrm/contact/merge', $urlParams); } } CRM_Utils_System::redirect($url); }
/** * Retrieve list of duplicate pairs from cache table. */ public static function getDedupes() { $offset = isset($_REQUEST['start']) ? CRM_Utils_Type::escape($_REQUEST['start'], 'Integer') : 0; $rowCount = isset($_REQUEST['length']) ? CRM_Utils_Type::escape($_REQUEST['length'], 'Integer') : 25; $gid = CRM_Utils_Request::retrieve('gid', 'Positive'); $rgid = CRM_Utils_Request::retrieve('rgid', 'Positive'); $selected = isset($_REQUEST['selected']) ? CRM_Utils_Type::escape($_REQUEST['selected'], 'Integer') : 0; if ($rowCount < 0) { $rowCount = 0; } $whereClause = $orderByClause = ''; $cacheKeyString = CRM_Dedupe_Merger::getMergeCacheKeyString($rgid, $gid); $searchRows = array(); $searchParams = self::getSearchOptionsFromRequest(); $queryParams = array(); $join = ''; $where = array(); $isOrQuery = self::isOrQuery(); $nextParamKey = 3; $mappings = array('dst' => 'cc1.display_name', 'src' => 'cc2.display_name', 'dst_email' => 'ce1.email', 'src_email' => 'ce2.email', 'dst_postcode' => 'ca1.postal_code', 'src_postcode' => 'ca2.postal_code', 'dst_street' => 'ca1.street', 'src_street' => 'ca2.street'); foreach ($mappings as $key => $dbName) { if (!empty($searchParams[$key])) { $queryParams[$nextParamKey] = array('%' . $searchParams[$key] . '%', 'String'); $where[] = $dbName . " LIKE %{$nextParamKey} "; $nextParamKey++; } } if ($isOrQuery) { $whereClause = ' ( ' . implode(' OR ', $where) . ' ) '; } else { if (!empty($where)) { $whereClause = implode(' AND ', $where); } } $whereClause .= $whereClause ? ' AND de.id IS NULL' : ' de.id IS NULL'; if ($selected) { $whereClause .= ' AND pn.is_selected = 1'; } $join .= CRM_Dedupe_Merger::getJoinOnDedupeTable(); $select = array('cc1.contact_type' => 'dst_contact_type', 'cc1.display_name' => 'dst_display_name', 'cc1.contact_sub_type' => 'dst_contact_sub_type', 'cc2.contact_type' => 'src_contact_type', 'cc2.display_name' => 'src_display_name', 'cc2.contact_sub_type' => 'src_contact_sub_type', 'ce1.email' => 'dst_email', 'ce2.email' => 'src_email', 'ca1.postal_code' => 'dst_postcode', 'ca2.postal_code' => 'src_postcode', 'ca1.street_address' => 'dst_street', 'ca2.street_address' => 'src_street'); if ($select) { $join .= " INNER JOIN civicrm_contact cc1 ON cc1.id = pn.entity_id1"; $join .= " INNER JOIN civicrm_contact cc2 ON cc2.id = pn.entity_id2"; $join .= " LEFT JOIN civicrm_email ce1 ON (ce1.contact_id = pn.entity_id1 AND ce1.is_primary = 1 )"; $join .= " LEFT JOIN civicrm_email ce2 ON (ce2.contact_id = pn.entity_id2 AND ce2.is_primary = 1 )"; $join .= " LEFT JOIN civicrm_address ca1 ON (ca1.contact_id = pn.entity_id1 AND ca1.is_primary = 1 )"; $join .= " LEFT JOIN civicrm_address ca2 ON (ca2.contact_id = pn.entity_id2 AND ca2.is_primary = 1 )"; } $iTotal = CRM_Core_BAO_PrevNextCache::getCount($cacheKeyString, $join, $whereClause, '=', $queryParams); if (!empty($_REQUEST['order'])) { foreach ($_REQUEST['order'] as $orderInfo) { if (!empty($orderInfo['column'])) { $orderColumnNumber = $orderInfo['column']; $dir = $orderInfo['dir']; } } $columnDetails = CRM_Utils_Array::value($orderColumnNumber, $_REQUEST['columns']); } if (!empty($columnDetails)) { switch ($columnDetails['data']) { case 'src': $orderByClause = " ORDER BY cc2.display_name {$dir}"; break; case 'src_email': $orderByClause = " ORDER BY ce2.email {$dir}"; break; case 'src_street': $orderByClause = " ORDER BY ca2.street_address {$dir}"; break; case 'src_postcode': $orderByClause = " ORDER BY ca2.postal_code {$dir}"; break; case 'dst': $orderByClause = " ORDER BY cc1.display_name {$dir}"; break; case 'dst_email': $orderByClause = " ORDER BY ce1.email {$dir}"; break; case 'dst_street': $orderByClause = " ORDER BY ca1.street_address {$dir}"; break; case 'dst_postcode': $orderByClause = " ORDER BY ca1.postal_code {$dir}"; break; default: $orderByClause = " ORDER BY cc1.display_name ASC"; break; } } $dupePairs = CRM_Core_BAO_PrevNextCache::retrieve($cacheKeyString, $join, $whereClause, $offset, $rowCount, $select, $orderByClause, TRUE, $queryParams); $iFilteredTotal = CRM_Core_DAO::singleValueQuery("SELECT FOUND_ROWS()"); $count = 0; foreach ($dupePairs as $key => $pairInfo) { $pair = $pairInfo['data']; $srcContactSubType = CRM_Utils_Array::value('src_contact_sub_type', $pairInfo); $dstContactSubType = CRM_Utils_Array::value('dst_contact_sub_type', $pairInfo); $srcTypeImage = CRM_Contact_BAO_Contact_Utils::getImage($srcContactSubType ? $srcContactSubType : $pairInfo['src_contact_type'], FALSE, $pairInfo['entity_id2']); $dstTypeImage = CRM_Contact_BAO_Contact_Utils::getImage($dstContactSubType ? $dstContactSubType : $pairInfo['dst_contact_type'], FALSE, $pairInfo['entity_id1']); $searchRows[$count]['is_selected'] = $pairInfo['is_selected']; $searchRows[$count]['is_selected_input'] = "<input type='checkbox' class='crm-dedupe-select' name='pnid_{$pairInfo['prevnext_id']}' value='{$pairInfo['is_selected']}' onclick='toggleDedupeSelect(this)'>"; $searchRows[$count]['src_image'] = $srcTypeImage; $searchRows[$count]['src'] = CRM_Utils_System::href($pair['srcName'], 'civicrm/contact/view', "reset=1&cid={$pairInfo['entity_id2']}"); $searchRows[$count]['src_email'] = CRM_Utils_Array::value('src_email', $pairInfo); $searchRows[$count]['src_street'] = CRM_Utils_Array::value('src_street', $pairInfo); $searchRows[$count]['src_postcode'] = CRM_Utils_Array::value('src_postcode', $pairInfo); $searchRows[$count]['dst_image'] = $dstTypeImage; $searchRows[$count]['dst'] = CRM_Utils_System::href($pair['dstName'], 'civicrm/contact/view', "reset=1&cid={$pairInfo['entity_id1']}"); $searchRows[$count]['dst_email'] = CRM_Utils_Array::value('dst_email', $pairInfo); $searchRows[$count]['dst_street'] = CRM_Utils_Array::value('dst_street', $pairInfo); $searchRows[$count]['dst_postcode'] = CRM_Utils_Array::value('dst_postcode', $pairInfo); $searchRows[$count]['conflicts'] = str_replace("',", "',<br/>", CRM_Utils_Array::value('conflicts', $pair)); $searchRows[$count]['weight'] = CRM_Utils_Array::value('weight', $pair); if (!empty($pairInfo['data']['canMerge'])) { $mergeParams = "reset=1&cid={$pairInfo['entity_id1']}&oid={$pairInfo['entity_id2']}&action=update&rgid={$rgid}&limit=" . CRM_Utils_Request::retrieve('limit', 'Integer'); if ($gid) { $mergeParams .= "&gid={$gid}"; } $searchRows[$count]['actions'] = "<a class='crm-dedupe-flip' href='#' data-pnid={$pairInfo['prevnext_id']}>" . ts('flip') . "</a> | "; $searchRows[$count]['actions'] .= CRM_Utils_System::href(ts('merge'), 'civicrm/contact/merge', $mergeParams); $searchRows[$count]['actions'] .= " | <a id='notDuplicate' href='#' onClick=\"processDupes( {$pairInfo['entity_id1']}, {$pairInfo['entity_id2']}, 'dupe-nondupe', 'dupe-listing'); return false;\">" . ts('not a duplicate') . "</a>"; } else { $searchRows[$count]['actions'] = '<em>' . ts('Insufficient access rights - cannot merge') . '</em>'; } $count++; } $dupePairs = array('data' => $searchRows, 'recordsTotal' => $iTotal, 'recordsFiltered' => $iFilteredTotal); if (!empty($_REQUEST['is_unit_test'])) { return $dupePairs; } CRM_Utils_JSON::output($dupePairs); }
/** * Browse all rule groups. */ public function run() { $gid = CRM_Utils_Request::retrieve('gid', 'Positive', $this, FALSE, 0); $action = CRM_Utils_Request::retrieve('action', 'String', $this, FALSE, 0); $context = CRM_Utils_Request::retrieve('context', 'String', $this); $limit = CRM_Utils_Request::retrieve('limit', 'Integer', $this); $rgid = CRM_Utils_Request::retrieve('rgid', 'Positive'); $urlQry = "reset=1&rgid={$rgid}&gid={$gid}&limit={$limit}"; $this->assign('urlQuery', $urlQry); $session = CRM_Core_Session::singleton(); $contactIds = $session->get('selectedSearchContactIds'); if ($context == 'search' || !empty($contactIds)) { $context = 'search'; $this->assign('backURL', $session->readUserContext()); } if ($action & CRM_Core_Action::RENEW) { // empty cache if ($rgid) { CRM_Core_BAO_PrevNextCache::deleteItem(NULL, CRM_Dedupe_Merger::getMergeCacheKeyString($rgid, $gid)); } CRM_Utils_System::redirect(CRM_Utils_System::url('civicrm/contact/dedupefind', $urlQry . "&action=update")); } elseif ($action & CRM_Core_Action::MAP) { // do a batch merge if requested $result = CRM_Dedupe_Merger::batchMerge($rgid, $gid, 'safe', TRUE, 75); $skippedCount = CRM_Utils_Request::retrieve('skipped', 'Positive', $this, FALSE, 0); $skippedCount = $skippedCount + count($result['skipped']); $mergedCount = CRM_Utils_Request::retrieve('merged', 'Positive', $this, FALSE, 0); $mergedCount = $mergedCount + count($result['merged']); if (empty($result['merged']) && empty($result['skipped'])) { $message = ''; if ($mergedCount >= 1) { $message = ts("%1 pairs of duplicates were merged", array(1 => $mergedCount)); } if ($skippedCount >= 1) { $message = $message ? "{$message} and " : ''; $message .= ts("%1 pairs of duplicates were skipped due to conflict", array(1 => $skippedCount)); } $message .= ts(" during the batch merge process with safe mode."); CRM_Core_Session::setStatus($message, ts('Merge Complete'), 'success'); CRM_Utils_System::redirect(CRM_Utils_System::url('civicrm/contact/dedupefind', $urlQry . "&action=update")); } else { $urlQry .= "&action=map&skipped={$skippedCount}&merged={$mergedCount}"; CRM_Utils_System::jsRedirect(CRM_Utils_System::url('civicrm/contact/dedupefind', $urlQry), ts('Batch Merge Task in progress'), ts('The batch merge task is still in progress. This page will be refreshed automatically.')); } } if ($action & CRM_Core_Action::UPDATE || $action & CRM_Core_Action::BROWSE) { $cid = CRM_Utils_Request::retrieve('cid', 'Positive', $this, FALSE, 0); $this->action = CRM_Core_Action::UPDATE; $urlQry .= '&snippet=4'; if ($context == 'conflicts') { $urlQry .= "&selected=1"; } $this->assign('sourceUrl', CRM_Utils_System::url('civicrm/ajax/dedupefind', $urlQry, FALSE, NULL, FALSE)); //reload from cache table $cacheKeyString = CRM_Dedupe_Merger::getMergeCacheKeyString($rgid, $gid); $stats = CRM_Dedupe_Merger::getMergeStatsMsg($cacheKeyString); if ($stats) { CRM_Core_Session::setStatus($stats); // reset so we not displaying same message again CRM_Dedupe_Merger::resetMergeStats($cacheKeyString); } $join = CRM_Dedupe_Merger::getJoinOnDedupeTable(); $where = "de.id IS NULL"; if ($context == 'conflicts') { $where .= " AND pn.is_selected = 1"; } $this->_mainContacts = CRM_Core_BAO_PrevNextCache::retrieve($cacheKeyString, $join, $where); if (empty($this->_mainContacts)) { if ($context == 'conflicts') { // if the current screen was intended to list only selected contacts, move back to full dupe list CRM_Utils_System::redirect(CRM_Utils_System::url(CRM_Utils_System::currentPath(), $urlQry . '&action=update')); } if ($gid) { $foundDupes = $this->get("dedupe_dupes_{$gid}"); if (!$foundDupes) { $foundDupes = CRM_Dedupe_Finder::dupesInGroup($rgid, $gid, $limit); } $this->set("dedupe_dupes_{$gid}", $foundDupes); } elseif (!empty($contactIds)) { $foundDupes = $this->get("search_dedupe_dupes_{$gid}"); if (!$foundDupes) { $foundDupes = CRM_Dedupe_Finder::dupes($rgid, $contactIds); } $this->set("search_dedupe_dupes_{$gid}", $foundDupes); } else { $foundDupes = $this->get('dedupe_dupes'); if (!$foundDupes) { $foundDupes = CRM_Dedupe_Finder::dupes($rgid, array(), TRUE, $limit); } $this->set('dedupe_dupes', $foundDupes); } if (!$foundDupes) { $ruleGroup = new CRM_Dedupe_BAO_RuleGroup(); $ruleGroup->id = $rgid; $ruleGroup->find(TRUE); $session = CRM_Core_Session::singleton(); $session->setStatus(ts('No possible duplicates were found using %1 rule.', array(1 => $ruleGroup->name)), ts('None Found'), 'info'); $url = CRM_Utils_System::url('civicrm/contact/deduperules', 'reset=1'); if ($context == 'search') { $url = $session->readUserContext(); } CRM_Utils_System::redirect($url); } else { $mainContacts = CRM_Dedupe_Finder::parseAndStoreDupePairs($foundDupes, $cacheKeyString); if ($cid) { $this->_cid = $cid; } if ($gid) { $this->_gid = $gid; } $this->_rgid = $rgid; $this->_mainContacts = $mainContacts; $session = CRM_Core_Session::singleton(); if ($this->_cid) { $session->pushUserContext(CRM_Utils_System::url('civicrm/contact/deduperules', $urlQry . "&action=update&cid={$this->_cid}")); } else { $session->pushUserContext(CRM_Utils_System::url('civicrm/contact/dedupefind', $urlQry . "&action=update")); } } } else { if ($cid) { $this->_cid = $cid; } if ($gid) { $this->_gid = $gid; } $this->_rgid = $rgid; } $this->assign('action', $this->action); $this->browse(); } else { $this->action = CRM_Core_Action::UPDATE; $this->edit($this->action); $this->assign('action', $this->action); } $this->assign('context', $context); // parent run return parent::run(); }