send most action links thru hook_civicrm_links
[civicrm-core.git] / CRM / Contact / Selector.php
index 31d1aa2fb1a177be0afc65f9587cd29be986e7dd..f3523ffe92f274c56801d5e2fee429ec09efd18f 100644 (file)
@@ -1,7 +1,7 @@
 <?php
 /*
  +--------------------------------------------------------------------+
- | CiviCRM version 4.3                                                |
+ | CiviCRM version 4.4                                                |
  +--------------------------------------------------------------------+
  | Copyright CiviCRM LLC (c) 2004-2013                                |
  +--------------------------------------------------------------------+
@@ -307,10 +307,9 @@ class CRM_Contact_Selector extends CRM_Core_Selector_Base implements CRM_Core_Se
     $params['buttonBottom'] = 'PagerBottomButton';
   }
   //end of function
-  function &getColHeads($action = NULL, $output = NULL) {
 
+  function &getColHeads($action = NULL, $output = NULL) {
     $colHeads = self::_getColumnHeaders();
-
     $colHeads[] = array('desc' => ts('Actions'), 'name' => ts('Action'));
     return $colHeads;
   }
@@ -363,7 +362,7 @@ class CRM_Contact_Selector extends CRM_Core_Selector_Base implements CRM_Core_Se
           ),
         );
 
-        $locationTypes = CRM_Core_PseudoConstant::locationType();
+        $locationTypes = CRM_Core_PseudoConstant::get('CRM_Core_DAO_Address', 'location_type_id');
 
         foreach ($this->_fields as $name => $field) {
           if (CRM_Utils_Array::value('in_selector', $field) &&
@@ -419,7 +418,6 @@ class CRM_Contact_Selector extends CRM_Core_Selector_Base implements CRM_Core_Se
       $headers = self::$_columnHeaders;
     }
     elseif (!empty($this->_returnProperties)) {
-
       self::$_columnHeaders = array(array('name' => ''),
         array(
           'name' => ts('Name'),
@@ -469,7 +467,15 @@ class CRM_Contact_Selector extends CRM_Core_Selector_Base implements CRM_Core_Se
    * @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;
   }
 
   /**
@@ -500,7 +506,13 @@ class CRM_Contact_Selector extends CRM_Core_Selector_Base implements CRM_Core_Se
     // 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();
@@ -518,12 +530,13 @@ class CRM_Contact_Selector extends CRM_Core_Selector_Base implements CRM_Core_Se
     }
 
     if ($this->_ufGroupID) {
-      $locationTypes = CRM_Core_PseudoConstant::locationType();
+      $locationTypes = CRM_Core_PseudoConstant::get('CRM_Core_DAO_Address', 'location_type_id');
 
       $names = array();
       static $skipFields = array('group', 'tag');
       foreach ($this->_fields as $key => $field) {
-        if (CRM_Utils_Array::value('in_selector', $field) &&
+        if (
+          CRM_Utils_Array::value('in_selector', $field) &&
           !in_array($key, $skipFields)
         ) {
           if (strpos($key, '-') !== FALSE) {
@@ -575,22 +588,19 @@ class CRM_Contact_Selector extends CRM_Core_Selector_Base implements CRM_Core_Se
     //check explicitly added contact to a Smart Group.
     $groupID = CRM_Utils_Array::key('1', $this->_formValues['group']);
 
+    $pseudoconstants = array();
     // for CRM-3157 purposes
-    if (in_array('country', $names)) {
-      $countries = CRM_Core_PseudoConstant::country();
-    }
-
-    if (in_array('state_province', $names)) {
-      $provinces = CRM_Core_PseudoConstant::stateProvince();
-    }
-
     if (in_array('world_region', $names)) {
-      $regions = CRM_Core_PseudoConstant::worldRegion();
+      $pseudoconstants['world_region'] = array(
+        'dbName' => 'world_region_id',
+        'values' => CRM_Core_PseudoConstant::worldRegion()
+      );
     }
 
     $seenIDs = array();
     while ($result->fetch()) {
       $row = array();
+      $this->_query->convertToPseudoNames($result);
 
       // the columns we are interested in
       foreach ($names as $property) {
@@ -598,36 +608,28 @@ class CRM_Contact_Selector extends CRM_Core_Selector_Base implements CRM_Core_Se
           continue;
         }
         if ($cfID = CRM_Core_BAO_CustomField::getKeyID($property)) {
-          $row[$property] = CRM_Core_BAO_CustomField::getDisplayValue($result->$property,
+          $row[$property] = CRM_Core_BAO_CustomField::getDisplayValue(
+            $result->$property,
             $cfID,
             $this->_options,
             $result->contact_id
           );
         }
-        elseif ($multipleSelectFields &&
+        elseif (
+          $multipleSelectFields &&
           array_key_exists($property, $multipleSelectFields)
         ) {
-          //fix to display student checkboxes
           $key = $property;
           $paramsNew = array($key => $result->$property);
+          $name = array($key => array('newName' => $key, 'groupName' => $key));
 
-          if ($key == 'test_tutoring') {
-            $name = array($key => array('newName' => $key, 'groupName' => 'test'));
-            // for  readers group
-          }
-          elseif (substr($key, 0, 4) == 'cmr_') {
-            $name = array($key => array('newName' => $key, 'groupName' => substr($key, 0, -3)));
-          }
-          else {
-            $name = array($key => array('newName' => $key, 'groupName' => $key));
-          }
           CRM_Core_OptionGroup::lookupValues($paramsNew, $name, FALSE);
           $row[$key] = $paramsNew[$key];
         }
         elseif (strpos($property, '-im')) {
           $row[$property] = $result->$property;
           if (!empty($result->$property)) {
-            $imProviders    = CRM_Core_PseudoConstant::IMProvider();
+            $imProviders    = CRM_Core_PseudoConstant::get('CRM_Core_DAO_IM', 'provider_id');
             $providerId     = $property . "-provider_id";
             $providerName   = $imProviders[$result->$providerId];
             $row[$property] = $result->$property . " ({$providerName})";
@@ -638,14 +640,14 @@ class CRM_Contact_Selector extends CRM_Core_Selector_Base implements CRM_Core_Se
           $greeting = $property . '_display';
           $row[$property] = $result->$greeting;
         }
-        elseif ($property == 'country') {
-          $row[$property] = CRM_Utils_Array::value($result->country_id, $countries);
-        }
         elseif ($property == 'state_province') {
-          $row[$property] = CRM_Utils_Array::value($result->state_province_id, $provinces);
+          $row[$property] = $result->state_province_name;
         }
-        elseif ($property == 'world_region') {
-          $row[$property] = CRM_Utils_Array::value($result->worldregion_id, $regions);
+        elseif (isset($pseudoconstants[$property])) {
+          $row[$property] = CRM_Utils_Array::value(
+            $result->{$pseudoconstants[$property]['dbName']},
+            $pseudoconstants[$property]['values']
+          );
         }
         elseif (strpos($property, '-url') !== FALSE) {
           $websiteUrl = '';
@@ -653,7 +655,7 @@ class CRM_Contact_Selector extends CRM_Core_Selector_Base implements CRM_Core_Se
           $propertyArray = explode('-', $property);
           $websiteFld = $websiteKey . '-' . array_pop($propertyArray);
           if (!empty($result->$websiteFld)) {
-            $websiteTypes = CRM_Core_PseudoConstant::websiteType();
+            $websiteTypes = CRM_Core_PseudoConstant::get('CRM_Core_DAO_Website', 'website_type_id');
             $websiteType  = $websiteTypes[$result->{"$websiteKey-website_type_id"}];
             $websiteValue = $result->$websiteFld;
             $websiteUrl   = "<a href=\"{$websiteValue}\">{$websiteValue}  ({$websiteType})</a>";
@@ -729,7 +731,16 @@ class CRM_Contact_Selector extends CRM_Core_Selector_Base implements CRM_Core_Se
               'title' => ts('Permanently Delete Contact'),
             );
           }
-          $row['action'] = CRM_Core_Action::formLink($links, NULL, array('id' => $result->contact_id));
+          $row['action'] = CRM_Core_Action::formLink(
+            $links,
+            NULL,
+            array('id' => $result->contact_id),
+            ts('more'),
+            FALSE,
+            'contact.selector.row',
+            'Contact',
+            $result->contact_id
+          );
         }
         elseif ((is_numeric(CRM_Utils_Array::value('geo_code_1', $row))) ||
           ($config->mapGeoCoding &&
@@ -737,10 +748,28 @@ class CRM_Contact_Selector extends CRM_Core_Selector_Base implements CRM_Core_Se
             CRM_Utils_Array::value('state_province', $row)
           )
         ) {
-          $row['action'] = CRM_Core_Action::formLink($links, $mask, array('id' => $result->contact_id));
+          $row['action'] = CRM_Core_Action::formLink(
+            $links,
+            $mask,
+            array('id' => $result->contact_id),
+            ts('more'),
+            FALSE,
+            'contact.selector.row',
+            'Contact',
+            $result->contact_id
+          );
         }
         else {
-          $row['action'] = CRM_Core_Action::formLink($links, $mapMask, array('id' => $result->contact_id));
+          $row['action'] = CRM_Core_Action::formLink(
+            $links,
+            $mapMask,
+            array('id' => $result->contact_id),
+            ts('more'),
+            FALSE,
+            'contact.selector.row',
+            'Contact',
+            $result->contact_id
+          );
         }
 
         // allow components to add more actions
@@ -769,35 +798,38 @@ class CRM_Contact_Selector extends CRM_Core_Selector_Base implements CRM_Core_Se
       }
     }
 
-    $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) {
@@ -843,7 +875,16 @@ class CRM_Contact_Selector extends CRM_Core_Selector_Base implements CRM_Core_Se
             'title' => ts('Permanently Delete Contact'),
           );
         }
-        $row['action'] = CRM_Core_Action::formLink($links, NULL, array('id' => $row['contact_id']));
+        $row['action'] = CRM_Core_Action::formLink(
+          $links,
+          null,
+          array('id' => $row['contact_id']),
+          ts('more'),
+          FALSE,
+          'contact.selector.actions',
+          'Contact',
+          $row['contact_id']
+        );
       }
       elseif ((is_numeric(CRM_Utils_Array::value('geo_code_1', $row))) ||
         ($config->mapGeoCoding &&
@@ -851,10 +892,28 @@ class CRM_Contact_Selector extends CRM_Core_Selector_Base implements CRM_Core_Se
           CRM_Utils_Array::value('state_province', $row)
         )
       ) {
-        $row['action'] = CRM_Core_Action::formLink($links, $mask, array('id' => $row['contact_id']));
+        $row['action'] = CRM_Core_Action::formLink(
+          $links,
+          $mask,
+          array('id' => $row['contact_id']),
+          ts('more'),
+          FALSE,
+          'contact.selector.actions',
+          'Contact',
+          $row['contact_id']
+        );
       }
       else {
-        $row['action'] = CRM_Core_Action::formLink($links, $mapMask, array('id' => $row['contact_id']));
+        $row['action'] = CRM_Core_Action::formLink(
+          $links,
+          $mapMask,
+          array('id' => $row['contact_id']),
+          ts('more'),
+          FALSE,
+          'contact.selector.actions',
+          'Contact',
+          $row['contact_id']
+        );
       }
 
       // allow components to add more actions
@@ -874,21 +933,23 @@ class CRM_Contact_Selector extends CRM_Core_Selector_Base implements CRM_Core_Se
     }
   }
 
-  function fillupPrevNextCache($sort, $cacheKey = NULL) {
-    if (!$cacheKey) {
-      $cacheKey = "civicrm search {$this->_key}";
-    }
-
-    CRM_Core_BAO_PrevNextCache::deleteItem(NULL, $cacheKey, 'civicrm_contact');
+  /**
+   * @param object $sort
+   * @param string $cacheKey
+   * @param int $start
+   * @param int $end
+   */
+  function fillupPrevNextCache($sort, $cacheKey, $start = 0, $end = 500) {
 
-    // lets fill up the prev next cache here, so view can scroll thru
+    // 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";
     }
+    // For core searches use the searchQuery method
     else {
       $sql = $this->_query->searchQuery(
-        0, 0, $sort,
+        $start, $end, $sort,
         FALSE, FALSE,
         FALSE, TRUE, TRUE, NULL
       );
@@ -911,7 +972,6 @@ SELECT 'civicrm_contact', contact_a.id, contact_a.id, '$cacheKey', contact_a.dis
 
     $sql = str_replace($replaceSQL, $insertSQL, $sql);
 
-
     CRM_Core_Error::ignoreException();
     $result = CRM_Core_DAO::executeQuery($sql);
     CRM_Core_Error::setCallback();
@@ -968,7 +1028,8 @@ SELECT 'civicrm_contact', contact_a.id, contact_a.id, '$cacheKey', contact_a.dis
         'address_options', TRUE, NULL, TRUE
       );
 
-      self::$_columnHeaders = array('contact_type' => array('desc' => ts('Contact Type')),
+      self::$_columnHeaders = array(
+        'contact_type' => array('desc' => ts('Contact Type')),
         'sort_name' => array(
           'name' => ts('Name'),
           'sort' => 'sort_name',
@@ -976,20 +1037,25 @@ SELECT 'civicrm_contact', contact_a.id, contact_a.id, '$cacheKey', contact_a.dis
         ),
       );
 
-      $defaultAddress = array('street_address' => array('name' => ts('Address')),
-        'city' => array('name' => ts('City'),
+      $defaultAddress = array(
+        'street_address' => array('name' => ts('Address')),
+        'city' => array(
+          'name' => ts('City'),
           'sort' => 'city',
           'direction' => CRM_Utils_Sort::DONTCARE,
         ),
-        'state_province' => array('name' => ts('State'),
+        'state_province' => array(
+          'name' => ts('State'),
           'sort' => 'state_province',
           'direction' => CRM_Utils_Sort::DONTCARE,
         ),
-        'postal_code' => array('name' => ts('Postal'),
+        'postal_code' => array(
+          'name' => ts('Postal'),
           'sort' => 'postal_code',
           'direction' => CRM_Utils_Sort::DONTCARE,
         ),
-        'country' => array('name' => ts('Country'),
+        'country' => array(
+          'name' => ts('Country'),
           'sort' => 'country',
           'direction' => CRM_Utils_Sort::DONTCARE,
         ),
@@ -1001,7 +1067,8 @@ SELECT 'civicrm_contact', contact_a.id, contact_a.id, '$cacheKey', contact_a.dis
         }
       }
 
-      self::$_columnHeaders['email'] = array('name' => ts('Email'),
+      self::$_columnHeaders['email'] = array(
+        'name' => ts('Email'),
         'sort' => 'email',
         'direction' => CRM_Utils_Sort::DONTCARE,
       );
@@ -1055,6 +1122,16 @@ SELECT 'civicrm_contact', contact_a.id, contact_a.id, '$cacheKey', contact_a.dis
     $properties = array();
     foreach ($returnProperties as $name => $value) {
       if ($name != 'location') {
+        // special handling for group and tag
+        if (in_array($name, array('group', 'tag'))) {
+          $name = "{$name}s";
+        }
+
+        // special handling for notes
+        if (in_array($name, array('note', 'note_subject', 'note_body'))) {
+          $name = "notes";
+        }
+
         $properties[] = $name;
       }
       else {