<?php
/*
+--------------------------------------------------------------------+
- | CiviCRM version 4.4 |
+ | CiviCRM version 4.5 |
+--------------------------------------------------------------------+
- | Copyright CiviCRM LLC (c) 2004-2013 |
+ | Copyright CiviCRM LLC (c) 2004-2014 |
+--------------------------------------------------------------------+
| This file is a part of CiviCRM. |
| |
/**
*
* @package CRM
- * @copyright CiviCRM LLC (c) 2004-2013
+ * @copyright CiviCRM LLC (c) 2004-2014
* $Id$
*
*/
/**
* Class constructor
*
+ * @param $customSearchClass
* @param array $formValues array of form values imported
- * @param array $params array of parameters for query
- * @param int $action - action of search basic or advanced.
+ * @param array $params array of parameters for query
+ * @param null $returnProperties
+ * @param \const|int $action - action of search basic or advanced.
+ *
+ * @param bool $includeContactIds
+ * @param bool $searchDescendentGroups
+ * @param string $searchContext
+ * @param null $contextMenu
*
* @return CRM_Contact_Selector
* @access public
/**
* getter for array of the parameters required for creating pager.
*
- * @param
+ * @param $action
+ * @param $params
+ *
+ * @internal param $
* @access public
*/
function getPagerParams($action, &$params) {
}
//end of function
+ /**
+ * @param null $action
+ * @param null $output
+ *
+ * @return array
+ */
function &getColHeads($action = NULL, $output = NULL) {
$colHeads = self::_getColumnHeaders();
$colHeads[] = array('desc' => ts('Actions'), 'name' => ts('Action'));
}
if ($output == CRM_Core_Selector_Controller::EXPORT) {
- $csvHeaders = array(ts('Contact Id'), ts('Contact Type'));
+ $csvHeaders = array(ts('Contact ID'), ts('Contact Type'));
foreach ($this->getColHeads($action, $output) as $column) {
if (array_key_exists('name', $column)) {
$csvHeaders[] = $column['name'];
if ($rowCount) {
$cacheKey = $this->buildPrevNextCache($sort);
$result = $this->_query->getCachedContacts($cacheKey, $offset, $rowCount, $includeContactIds);
-
- // CRM-13996: result is empty when selector columns are sorted. hence we need to run the query again
- if ( $result->N == 0) {
- $result = $this->_query->searchQuery($offset, $rowCount, $sort, FALSE, $includeContactIds);
- }
}
else {
$result = $this->_query->searchQuery($offset, $rowCount, $sort, FALSE, $includeContactIds);
$greeting = $property . '_display';
$row[$property] = $result->$greeting;
}
- elseif ($property == 'state_province') {
- $row[$property] = $result->state_province_name;
- }
elseif (isset($pseudoconstants[$property])) {
$row[$property] = CRM_Utils_Array::value(
$result->{$pseudoconstants[$property]['dbName']},
return $rows;
}
+ /**
+ * @param $sort
+ *
+ * @return string
+ */
function buildPrevNextCache($sort) {
$cacheKey = 'civicrm search ' . $this->_key;
- // Get current page requested
+ // 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);
- // When starting from scratch, clear any old cache
- if (!$pageNum) {
+
+ // 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');
- $pageNum = 1;
+ // 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);
$this->fillupPrevNextCache($sort, $cacheKey);
}
elseif ($firstRecord >= $countRow) {
- $this->fillupPrevNextCache($sort, $cacheKey, $countRow, $firstRecord + 500);
+ $this->fillupPrevNextCache($sort, $cacheKey, $countRow, 500);
}
return $cacheKey;
}
+ /**
+ * @param $rows
+ */
function addActions(&$rows) {
$config = CRM_Core_Config::singleton();
'name' => ts('View'),
'url' => 'civicrm/contact/view',
'qs' => 'reset=1&cid=%%id%%',
+ 'class' => 'no-popup',
'title' => ts('View Contact Details'),
),
array(
}
}
+ /**
+ * @param $rows
+ */
function removeActions(&$rows) {
foreach ($rows as $rid => & $rValue) {
unset($rValue['contact_type']);
* @param int $end
*/
function fillupPrevNextCache($sort, $cacheKey, $start = 0, $end = 500) {
-
+ $coreSearch = TRUE;
// For custom searches, use the contactIDs method
if (is_a($this, 'CRM_Contact_Selector_Custom')) {
$sql = $this->_search->contactIDs($start, $end, $sort, TRUE);
$replaceSQL = "SELECT contact_a.id as contact_id";
+ $coreSearch = FALSE;
}
// For core searches use the searchQuery method
else {
- $sql = $this->_query->searchQuery(
- $start, $end, $sort,
- FALSE, FALSE,
- FALSE, TRUE, TRUE, NULL
- );
+ $sql = $this->_query->searchQuery($start, $end, $sort, FALSE, $this->_query->_includeContactIds,
+ FALSE, TRUE, TRUE);
$replaceSQL = "SELECT contact_a.id as id";
}
$insertSQL = "
INSERT INTO civicrm_prevnext_cache ( entity_table, entity_id1, entity_id2, cacheKey, data )
-SELECT 'civicrm_contact', contact_a.id, contact_a.id, '$cacheKey', contact_a.display_name
+SELECT DISTINCT 'civicrm_contact', contact_a.id, contact_a.id, '$cacheKey', contact_a.display_name
";
$sql = str_replace($replaceSQL, $insertSQL, $sql);
- CRM_Core_Error::ignoreException();
+ $errorScope = CRM_Core_TemporaryErrorScope::ignoreException();
$result = CRM_Core_DAO::executeQuery($sql);
- CRM_Core_Error::setCallback();
+ unset($errorScope);
if (is_a($result, 'DB_Error')) {
- // oops the above query failed, so lets just ignore it
- // and return
- // we print a sorry cant figure it out on view page
- return;
+ // check if we get error during core search
+ if ($coreSearch) {
+ // in the case of error, try rebuilding cache using full sql which is used for search selector display
+ // this fixes the bugs reported in CRM-13996 & CRM-14438
+ $this->rebuildPreNextCache($start, $end, $sort, $cacheKey);
+ }
+ else {
+ // return if above query fails
+ return;
+ }
}
// also record an entry in the cache key table, so we can delete it periodically
CRM_Core_BAO_Cache::setItem($cacheKey, 'CiviCRM Search PrevNextCache', $cacheKey);
}
+ /**
+ * This function is called to rebuild prev next cache using full sql in case of core search ( excluding custom search)
+ *
+ * @param int $start start for limit clause
+ * @param int $end end for limit clause
+ * @param $sort
+ * @param string $cacheKey cache key
+ *
+ * @internal param $object $sort sort object
+ * @return void
+ */
+ function rebuildPreNextCache($start, $end, $sort, $cacheKey) {
+ // generate full SQL
+ $sql = $this->_query->searchQuery($start, $end, $sort, FALSE, $this->_query->_includeContactIds,
+ FALSE, FALSE, TRUE);
+
+ $dao = CRM_Core_DAO::executeQuery($sql);
+
+ // build insert query, note that currently we build cache for 500 contact records at a time, hence below approach
+ $insertValues = array();
+ while($dao->fetch()) {
+ $insertValues[] = "('civicrm_contact', {$dao->contact_id}, {$dao->contact_id}, '{$cacheKey}', '" . CRM_Core_DAO::escapeString($dao->sort_name) . "')";
+ }
+
+ //update pre/next cache using single insert query
+ if (!empty($insertValues)) {
+ $sql = 'INSERT INTO civicrm_prevnext_cache ( entity_table, entity_id1, entity_id2, cacheKey, data ) VALUES
+'.implode(',', $insertValues);
+
+ $result = CRM_Core_DAO::executeQuery($sql);
+ }
+ }
+
/**
* Given the current formValues, gets the query in local
* language
return self::$_columnHeaders;
}
+ /**
+ * @return CRM_Contact_BAO_Query
+ */
function &getQuery() {
return $this->_query;
}
+ /**
+ * @return CRM_Contact_DAO_Contact
+ */
function alphabetQuery() {
return $this->_query->searchQuery(NULL, NULL, NULL, FALSE, FALSE, TRUE);
}
+ /**
+ * @param $params
+ * @param $action
+ * @param $sortID
+ * @param null $displayRelationshipType
+ * @param string $queryOperator
+ *
+ * @return CRM_Contact_DAO_Contact
+ */
function contactIDQuery($params, $action, $sortID, $displayRelationshipType = NULL, $queryOperator = 'AND') {
$sortOrder = &$this->getSortOrder($this->_action);
$sort = new CRM_Utils_Sort($sortOrder, $sortID);
return $value;
}
+ /**
+ * @param $returnProperties
+ *
+ * @return array
+ */
function &makeProperties(&$returnProperties) {
$properties = array();
foreach ($returnProperties as $name => $value) {