Esempio n. 1
0
 /**
  * Build a queue of tasks by dividing dupe pairs in batches.
  */
 public static function getRunner()
 {
     $rgid = CRM_Utils_Request::retrieve('rgid', 'Positive', $this, FALSE, 0);
     $gid = CRM_Utils_Request::retrieve('gid', 'Positive', $this, FALSE, 0);
     $action = CRM_Utils_Request::retrieve('action', 'String', CRM_Core_DAO::$_nullObject);
     $mode = CRM_Utils_Request::retrieve('mode', 'String', CRM_Core_DAO::$_nullObject, FALSE, 'safe');
     $contactType = CRM_Core_DAO::getFieldValue('CRM_Dedupe_DAO_RuleGroup', $rgid, 'contact_type');
     $cacheKeyString = "merge {$contactType}";
     $cacheKeyString .= $rgid ? "_{$rgid}" : '_0';
     $cacheKeyString .= $gid ? "_{$gid}" : '_0';
     $urlQry = "reset=1&action=update&rgid={$rgid}";
     $urlQry = $gid ? $urlQry . "&gid={$gid}" : $urlQry;
     if ($mode == 'aggressive' && !CRM_Core_Permission::check('force merge duplicate contacts')) {
         CRM_Core_Session::setStatus(ts('You do not have permission to force merge duplicate contact records'), ts('Permission Denied'), 'error');
         CRM_Utils_System::redirect(CRM_Utils_System::url('civicrm/contact/dedupefind', $urlQry));
     }
     // Setup the Queue
     $queue = CRM_Queue_Service::singleton()->create(array('name' => $cacheKeyString, 'type' => 'Sql', 'reset' => TRUE));
     $where = NULL;
     if ($action == CRM_Core_Action::MAP) {
         $where = "pn.is_selected = 1";
         $isSelected = 1;
     } else {
         // else merge all (2)
         $isSelected = 2;
     }
     $total = CRM_Core_BAO_PrevNextCache::getCount($cacheKeyString, NULL, $where);
     if ($total <= 0) {
         // Nothing to do.
         CRM_Utils_System::redirect(CRM_Utils_System::url('civicrm/contact/dedupefind', $urlQry));
     }
     // reset merge stats, so we compute new stats
     CRM_Dedupe_Merger::resetMergeStats($cacheKeyString);
     for ($i = 1; $i <= ceil($total / self::BATCHLIMIT); $i++) {
         $task = new CRM_Queue_Task(array('CRM_Contact_Page_DedupeMerge', 'callBatchMerge'), array($rgid, $gid, $mode, TRUE, self::BATCHLIMIT, $isSelected), "Processed " . $i * self::BATCHLIMIT . " pair of duplicates out of " . $total);
         // Add the Task to the Queue
         $queue->createItem($task);
     }
     // Setup the Runner
     $urlQry .= "&context=conflicts";
     $runner = new CRM_Queue_Runner(array('title' => ts('Merging Duplicates..'), 'queue' => $queue, 'errorMode' => CRM_Queue_Runner::ERROR_ABORT, 'onEndUrl' => CRM_Utils_System::url('civicrm/contact/dedupefind', $urlQry, TRUE, NULL, FALSE)));
     return $runner;
 }
Esempio n. 2
0
 /**
  * @param $sort
  *
  * @return string
  */
 function buildPrevNextCache($sort)
 {
     $cacheKey = 'civicrm search ' . $this->_key;
     // Get current page requested
     $pageNum = CRM_Utils_Request::retrieve('crmPID', 'Integer', CRM_Core_DAO::$_nullObject);
     // When starting from scratch, clear any old cache
     if (!$pageNum) {
         CRM_Core_BAO_PrevNextCache::deleteItem(NULL, $cacheKey, 'civicrm_contact');
         $pageNum = 1;
     }
     $pageSize = CRM_Utils_Request::retrieve('crmRowCount', 'Integer', CRM_Core_DAO::$_nullObject, FALSE, 50);
     $firstRecord = ($pageNum - 1) * $pageSize;
     //for alphabetic pagination selection save
     $sortByCharacter = CRM_Utils_Request::retrieve('sortByCharacter', 'String', CRM_Core_DAO::$_nullObject);
     //for text field pagination selection save
     $countRow = CRM_Core_BAO_PrevNextCache::getCount($cacheKey, NULL, "entity_table = 'civicrm_contact'");
     // $sortByCharacter triggers a refresh in the prevNext cache
     if ($sortByCharacter && $sortByCharacter != 'all') {
         $cacheKey .= "_alphabet";
         $this->fillupPrevNextCache($sort, $cacheKey);
     } elseif ($firstRecord >= $countRow) {
         $this->fillupPrevNextCache($sort, $cacheKey, $countRow, 500);
     }
     return $cacheKey;
 }
Esempio n. 3
0
 /**
  * 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>&nbsp;|&nbsp;";
             $searchRows[$count]['actions'] .= CRM_Utils_System::href(ts('merge'), 'civicrm/contact/merge', $mergeParams);
             $searchRows[$count]['actions'] .= "&nbsp;|&nbsp;<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);
 }
Esempio n. 4
0
 public static function getDedupes()
 {
     $sEcho = CRM_Utils_Type::escape($_REQUEST['sEcho'], 'Integer');
     $offset = isset($_REQUEST['iDisplayStart']) ? CRM_Utils_Type::escape($_REQUEST['iDisplayStart'], 'Integer') : 0;
     $rowCount = isset($_REQUEST['iDisplayLength']) ? CRM_Utils_Type::escape($_REQUEST['iDisplayLength'], 'Integer') : 25;
     $sort = 'sort_name';
     $sortOrder = isset($_REQUEST['sSortDir_0']) ? CRM_Utils_Type::escape($_REQUEST['sSortDir_0'], 'String') : 'asc';
     $gid = isset($_REQUEST['gid']) ? CRM_Utils_Type::escape($_REQUEST['gid'], 'Integer') : 0;
     $rgid = isset($_REQUEST['rgid']) ? CRM_Utils_Type::escape($_REQUEST['rgid'], 'Integer') : 0;
     $contactType = '';
     if ($rgid) {
         $contactType = CRM_Core_DAO::getFieldValue('CRM_Dedupe_DAO_RuleGroup', $rgid, 'contact_type');
     }
     $cacheKeyString = "merge {$contactType}_{$rgid}_{$gid}";
     $searchRows = array();
     $selectorElements = array('src', 'dst', 'weight', 'actions');
     $join = "LEFT JOIN civicrm_dedupe_exception de ON ( pn.entity_id1 = de.contact_id1 AND\n                                                             pn.entity_id2 = de.contact_id2 )";
     $where = "de.id IS NULL";
     $iFilteredTotal = $iTotal = CRM_Core_BAO_PrevNextCache::getCount($cacheKeyString, $join, $where);
     $mainContacts = CRM_Core_BAO_PrevNextCache::retrieve($cacheKeyString, $join, $where, $offset, $rowCount);
     foreach ($mainContacts as $mainId => $main) {
         $searchRows[$mainId]['src'] = CRM_Utils_System::href($main['srcName'], 'civicrm/contact/view', "reset=1&cid={$main['srcID']}");
         $searchRows[$mainId]['dst'] = CRM_Utils_System::href($main['dstName'], 'civicrm/contact/view', "reset=1&cid={$main['dstID']}");
         $searchRows[$mainId]['weight'] = CRM_Utils_Array::value('weight', $main);
         if (!empty($main['canMerge'])) {
             $mergeParams = "reset=1&cid={$main['srcID']}&oid={$main['dstID']}&action=update&rgid={$rgid}";
             if ($gid) {
                 $mergeParams .= "&gid={$gid}";
             }
             $searchRows[$mainId]['actions'] = '<a class="action-item crm-hover-button" href="' . CRM_Utils_System::url('civicrm/contact/merge', $mergeParams) . '">' . ts('merge') . '</a>';
             $searchRows[$mainId]['actions'] .= "<a class='action-item crm-hover-button crm-notDuplicate' href='#' onClick=\"processDupes( {$main['srcID']}, {$main['dstID']}, 'dupe-nondupe', 'dupe-listing'); return false;\">" . ts('not a duplicate') . "</a>";
         } else {
             $searchRows[$mainId]['actions'] = '<em>' . ts('Insufficient access rights - cannot merge') . '</em>';
         }
     }
     CRM_Utils_System::setHttpHeader('Content-Type', 'application/json');
     echo CRM_Utils_JSON::encodeDataTableSelector($searchRows, $sEcho, $iTotal, $iFilteredTotal, $selectorElements);
     CRM_Utils_System::civiExit();
 }
Esempio n. 5
0
 /**
  * @param CRM_Utils_Sort $sort
  *
  * @return string
  */
 public function buildPrevNextCache($sort)
 {
     $cacheKey = 'civicrm search ' . $this->_key;
     // We should clear the cache in following conditions:
     // 1. when starting from scratch, i.e new search
     // 2. if records are sorted
     // get current page requested
     $pageNum = CRM_Utils_Request::retrieve('crmPID', 'Integer', CRM_Core_DAO::$_nullObject);
     // get the current sort order
     $currentSortID = CRM_Utils_Request::retrieve('crmSID', 'String', CRM_Core_DAO::$_nullObject);
     $session = CRM_Core_Session::singleton();
     // get previous sort id
     $previousSortID = $session->get('previousSortID');
     // check for current != previous to ensure cache is not reset if paging is done without changing
     // sort criteria
     if (!$pageNum || !empty($currentSortID) && $currentSortID != $previousSortID) {
         CRM_Core_BAO_PrevNextCache::deleteItem(NULL, $cacheKey, 'civicrm_contact');
         // this means it's fresh search, so set pageNum=1
         if (!$pageNum) {
             $pageNum = 1;
         }
     }
     // set the current sort as previous sort
     if (!empty($currentSortID)) {
         $session->set('previousSortID', $currentSortID);
     }
     $pageSize = CRM_Utils_Request::retrieve('crmRowCount', 'Integer', CRM_Core_DAO::$_nullObject, FALSE, 50);
     $firstRecord = ($pageNum - 1) * $pageSize;
     //for alphabetic pagination selection save
     $sortByCharacter = CRM_Utils_Request::retrieve('sortByCharacter', 'String', CRM_Core_DAO::$_nullObject);
     //for text field pagination selection save
     $countRow = CRM_Core_BAO_PrevNextCache::getCount($cacheKey, NULL, "entity_table = 'civicrm_contact'");
     // $sortByCharacter triggers a refresh in the prevNext cache
     if ($sortByCharacter && $sortByCharacter != 'all') {
         $cacheKey .= "_alphabet";
         $this->fillupPrevNextCache($sort, $cacheKey);
     } elseif ($firstRecord >= $countRow) {
         $this->fillupPrevNextCache($sort, $cacheKey, $countRow, 500 + $firstRecord - $countRow);
     }
     return $cacheKey;
 }
Esempio n. 6
0
 /**
  * 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 = isset($_REQUEST['gid']) ? CRM_Utils_Type::escape($_REQUEST['gid'], 'Integer') : 0;
     $rgid = isset($_REQUEST['rgid']) ? CRM_Utils_Type::escape($_REQUEST['rgid'], 'Integer') : 0;
     $selected = isset($_REQUEST['selected']) ? CRM_Utils_Type::escape($_REQUEST['selected'], 'Integer') : 0;
     if ($rowCount < 0) {
         $rowCount = 0;
     }
     $contactType = '';
     if ($rgid) {
         $contactType = CRM_Core_DAO::getFieldValue('CRM_Dedupe_DAO_RuleGroup', $rgid, 'contact_type');
     }
     $cacheKeyString = "merge {$contactType}_{$rgid}_{$gid}";
     $searchRows = array();
     $selectorElements = array('is_selected', 'is_selected_input', 'src_image', 'src', 'src_email', 'src_street', 'src_postcode', 'dst_image', 'dst', 'dst_email', 'dst_street', 'dst_postcode', 'conflicts', 'weight', 'actions');
     foreach ($_REQUEST['columns'] as $columnInfo) {
         if (!empty($columnInfo['search']['value'])) {
             ${$columnInfo['data']} = CRM_Utils_Type::escape($columnInfo['search']['value'], 'String');
         }
     }
     $join = '';
     $where = array();
     $searchData = CRM_Utils_Array::value('search', $_REQUEST);
     $searchData['value'] = CRM_Utils_Type::escape($searchData['value'], 'String');
     if ($src || !empty($searchData['value'])) {
         $src = $src ? $src : $searchData['value'];
         $where[] = " cc1.display_name LIKE '%{$src}%'";
     }
     if ($dst || !empty($searchData['value'])) {
         $dst = $dst ? $dst : $searchData['value'];
         $where[] = " cc2.display_name LIKE '%{$dst}%'";
     }
     if ($src_email || !empty($searchData['value'])) {
         $src_email = $src_email ? $src_email : $searchData['value'];
         $where[] = " (ce1.is_primary = 1 AND ce1.email LIKE '%{$src_email}%')";
     }
     if ($dst_email || !empty($searchData['value'])) {
         $dst_email = $dst_email ? $dst_email : $searchData['value'];
         $where[] = " (ce2.is_primary = 1 AND ce2.email LIKE '%{$dst_email}%')";
     }
     if ($src_postcode || !empty($searchData['value'])) {
         $src_postcode = $src_postcode ? $src_postcode : $searchData['value'];
         $where[] = " (ca1.is_primary = 1 AND ca1.postal_code LIKE '%{$src_postcode}%')";
     }
     if ($dst_postcode || !empty($searchData['value'])) {
         $dst_postcode = $dst_postcode ? $dst_postcode : $searchData['value'];
         $where[] = " (ca2.is_primary = 1 AND ca2.postal_code LIKE '%{$dst_postcode}%')";
     }
     if ($src_street || !empty($searchData['value'])) {
         $src_street = $src_street ? $src_street : $searchData['value'];
         $where[] = " (ca1.is_primary = 1 AND ca1.street_address LIKE '%{$src_street}%')";
     }
     if ($dst_street || !empty($searchData['value'])) {
         $dst_street = $dst_street ? $dst_street : $searchData['value'];
         $where[] = " (ca2.is_primary = 1 AND ca2.street_address LIKE '%{$dst_street}%')";
     }
     if (!empty($searchData['value'])) {
         $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 .= " LEFT JOIN civicrm_dedupe_exception de ON ( pn.entity_id1 = de.contact_id1 AND pn.entity_id2 = de.contact_id2 )";
     $select = array('cc1.contact_type' => 'src_contact_type', 'cc1.display_name' => 'src_display_name', 'cc1.contact_sub_type' => 'src_contact_sub_type', 'cc2.contact_type' => 'dst_contact_type', 'cc2.display_name' => 'dst_display_name', 'cc2.contact_sub_type' => 'dst_contact_sub_type', 'ce1.email' => 'src_email', 'ce2.email' => 'dst_email', 'ca1.postal_code' => 'src_postcode', 'ca2.postal_code' => 'dst_postcode', 'ca1.street_address' => 'src_street', 'ca2.street_address' => 'dst_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);
     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':
                 $whereClause .= " ORDER BY cc1.display_name {$dir}";
                 break;
             case 'src_email':
                 $whereClause .= " ORDER BY ce1.email {$dir}";
                 break;
             case 'src_street':
                 $whereClause .= " ORDER BY ca1.street_address {$dir}";
                 break;
             case 'src_postcode':
                 $whereClause .= " ORDER BY ca1.postal_code {$dir}";
                 break;
             case 'dst':
                 $whereClause .= " ORDER BY cc2.display_name {$dir}";
                 break;
             case 'dst_email':
                 $whereClause .= " ORDER BY ce2.email {$dir}";
                 break;
             case 'dst_street':
                 $whereClause .= " ORDER BY ca2.street_address {$dir}";
                 break;
             case 'dst_postcode':
                 $whereClause .= " ORDER BY ca2.postal_code {$dir}";
                 break;
             default:
                 break;
         }
     }
     $dupePairs = CRM_Core_BAO_PrevNextCache::retrieve($cacheKeyString, $join, $whereClause, $offset, $rowCount, $select);
     $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_id1']);
         $dstTypeImage = CRM_Contact_BAO_Contact_Utils::getImage($dstContactSubType ? $dstContactSubType : $pairInfo['dst_contact_type'], FALSE, $pairInfo['entity_id2']);
         $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_id1']}");
         $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_id2']}");
         $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}";
             if ($gid) {
                 $mergeParams .= "&gid={$gid}";
             }
             $searchRows[$count]['actions'] = "<a class='crm-dedupe-flip' href='#' data-pnid={$pairInfo['prevnext_id']}>" . ts('flip') . "</a>&nbsp;|&nbsp;";
             $searchRows[$count]['actions'] .= CRM_Utils_System::href(ts('merge'), 'civicrm/contact/merge', $mergeParams);
             $searchRows[$count]['actions'] .= "&nbsp;|&nbsp;<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);
     CRM_Utils_JSON::output($dupePairs);
 }
 function buildPrevNextCache($sort)
 {
     $cacheKey = CRM_Utils_Array::value('qfKey', $this->_formValues);
     //for prev/next pagination
     $crmPID = CRM_Utils_Request::retrieve('crmPID', 'Integer', CRM_Core_DAO::$_nullObject);
     //for alphabetic pagination selection save
     $sortByCharacter = CRM_Utils_Request::retrieve('sortByCharacter', 'String', CRM_Core_DAO::$_nullObject);
     //for text field pagination selection save
     $countRow = CRM_Core_BAO_PrevNextCache::getCount("%civicrm search {$cacheKey}%", NULL, "entity_table = 'civicrm_contact'", "LIKE");
     if (!$crmPID && $countRow == 0 && !$sortByCharacter) {
         $this->fillupPrevNextCache($sort);
     } elseif ($sortByCharacter) {
         $cacheKeyCharacter = "civicrm search {$cacheKey}_alphabet";
         if ($sortByCharacter == 'all') {
             //delete the alphabet key corresponding records in prevnext_cache
             CRM_Core_BAO_PrevNextCache::deleteItem(NULL, $cacheKeyCharacter, 'civicrm_contact');
         } else {
             $this->fillupPrevNextCache($sort, $cacheKeyCharacter);
         }
     }
 }