<?php
/*
+--------------------------------------------------------------------+
- | CiviCRM version 4.3 |
+ | CiviCRM version 4.4 |
+--------------------------------------------------------------------+
| Copyright CiviCRM LLC (c) 2004-2013 |
+--------------------------------------------------------------------+
*/
function &getColumnHeaders($action = NULL, $output = NULL) {
$headers = NULL;
+
+ // unset return property elements that we don't care
+ if (!empty($this->_returnProperties)) {
+ $doNotCareElements = array(
+ 'contact_type',
+ 'contact_sub_type',
+ 'sort_name',
+ );
+ foreach ( $doNotCareElements as $value) {
+ unset($this->_returnProperties[$value]);
+ }
+ }
+
if ($output == CRM_Core_Selector_Controller::EXPORT) {
$csvHeaders = array(ts('Contact Id'), ts('Contact Type'));
foreach ($this->getColHeads($action, $output) as $column) {
$properties = self::makeProperties($this->_returnProperties);
foreach ($properties as $prop) {
- if ($prop == 'contact_type' || $prop == 'contact_sub_type' || $prop == 'sort_name') {
- continue;
- }
-
if (strpos($prop, '-')) {
list($loc, $fld, $phoneType) = CRM_Utils_System::explode('-', $prop, 3);
$title = $this->_query->_fields[$fld]['title'];
}
elseif (isset($this->_query->_fields[$prop]) && isset($this->_query->_fields[$prop]['title'])) {
$title = $this->_query->_fields[$prop]['title'];
- } else {
+ }
+ else {
$title = '';
}
* @access public
*/
function getTotalCount($action) {
- return $this->_query->searchQuery(0, 0, NULL, TRUE);
+ // Use count from cache during paging/sorting
+ if (!empty($_GET['crmPID']) || !empty($_GET['crmSID'])) {
+ $count = CRM_Core_BAO_Cache::getItem('Search Results Count', $this->_key);
+ }
+ if (empty($count)) {
+ $count = $this->_query->searchQuery(0, 0, NULL, TRUE);
+ CRM_Core_BAO_Cache::setItem($count, 'Search Results Count', $this->_key);
+ }
+ return $count;
}
/**
// note the formvalues were given by CRM_Contact_Form_Search to us
// and contain the search criteria (parameters)
// note that the default action is basic
- $result = $this->_query->searchQuery($offset, $rowCount, $sort, FALSE, $includeContactIds);
+ if ($rowCount) {
+ $cacheKey = $this->buildPrevNextCache($sort);
+ $result = $this->_query->getCachedContacts($cacheKey, $offset, $rowCount, $includeContactIds);
+ }
+ else {
+ $result = $this->_query->searchQuery($offset, $rowCount, $sort, FALSE, $includeContactIds);
+ }
// process the result of the query
$rows = array();
$groupID = CRM_Utils_Array::key('1', $this->_formValues['group']);
$pseudoconstants = array();
- if (!empty($this->_fields)) {
- // get all the pseudoconstant values
- foreach ($this->_fields as $name => $values) {
- if (isset($this->_fields[$name]['pseudoconstant'])) {
- $pseudoconstants[$name] =
- array(
- 'dbName' => $this->_fields[$name]['name'],
- 'values' => CRM_Core_PseudoConstant::get('CRM_Contact_DAO_Contact', $name),
- );
- }
- }
- }
-
// for CRM-3157 purposes
- if (in_array('country', $names)) {
- $pseudoconstants['country'] = array(
- 'dbName' => 'country_id',
- 'values' => CRM_Core_PseudoConstant::country()
- );
- }
-
- if (in_array('state_province', $names)) {
- $pseudoconstants['state_province'] = array(
- 'dbName' => 'state_province_id',
- 'values' => CRM_Core_PseudoConstant::stateProvince()
- );
- }
-
if (in_array('world_region', $names)) {
$pseudoconstants['world_region'] = array(
'dbName' => 'world_region_id',
$seenIDs = array();
while ($result->fetch()) {
$row = array();
+ $this->_query->convertToPseudoNames($result);
// the columns we are interested in
foreach ($names as $property) {
}
}
- $this->buildPrevNextCache($sort);
-
return $rows;
}
function buildPrevNextCache($sort) {
- $cacheKey = CRM_Utils_Array::value('qfKey', $this->_formValues);
+ $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;
+ }
- //for prev/next pagination
- $crmPID = CRM_Utils_Request::retrieve('crmPID', 'Integer', CRM_Core_DAO::$_nullObject);
+ $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("%civicrm search {$cacheKey}%", NULL, "entity_table = 'civicrm_contact'", "LIKE");
+ $countRow = CRM_Core_BAO_PrevNextCache::getCount($cacheKey, NULL, "entity_table = 'civicrm_contact'");
- if ((!$crmPID || $countRow == 0) && !$sortByCharacter) {
- $this->fillupPrevNextCache($sort);
+ // $sortByCharacter triggers a refresh in the prevNext cache
+ if ($sortByCharacter && $sortByCharacter != 'all') {
+ $cacheKey .= "_alphabet";
+ $this->fillupPrevNextCache($sort, $cacheKey);
}
- 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');
- $cacheKeyCharacter = NULL;
- }
- $this->fillupPrevNextCache($sort, $cacheKeyCharacter);
+ elseif ($firstRecord >= $countRow) {
+ $this->fillupPrevNextCache($sort, $cacheKey, $countRow, $firstRecord + 500);
}
+ return $cacheKey;
}
function addActions(&$rows) {
}
}
- function fillupPrevNextCache($sort, $cacheKey = NULL) {
- if (!$cacheKey) {
- $cacheKey = "civicrm search {$this->_key}";
- }
-
- CRM_Core_BAO_PrevNextCache::deleteItem(NULL, $cacheKey, 'civicrm_contact');
-
- // lets fill up the prev next cache here, so view can scroll thru
+ /**
+ * @param object $sort
+ * @param string $cacheKey
+ * @param int $start
+ * @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(0, 0, $sort, TRUE);
+ $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(
- 0, 0, $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";
}
$sql = str_replace($replaceSQL, $insertSQL, $sql);
-
CRM_Core_Error::ignoreException();
$result = CRM_Core_DAO::executeQuery($sql);
CRM_Core_Error::setCallback();
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 $object $sort sort object
+ * @param string $cacheKey cache key
+ *
+ * @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