Merge pull request #4772 from jitendrapurohit/CRM-15750
authorKurund Jalmi <kurund@civicrm.org>
Tue, 23 Dec 2014 19:28:57 +0000 (00:58 +0530)
committerKurund Jalmi <kurund@civicrm.org>
Tue, 23 Dec 2014 19:28:57 +0000 (00:58 +0530)
Fix for CRM-15750 advanced search using relationship and smart group pro...

1  2 
CRM/Contact/BAO/Query.php

index 01e8afe19cd30ce6488a13fa202d0ab6440deaf6,79d9e99d1912f0ee07d994f21dd6e3f161df9a60..e7760714fbb15e7422d34e8feb5236d7ad344e32
@@@ -1,7 -1,7 +1,7 @@@
  <?php
  /*
   +--------------------------------------------------------------------+
 - | CiviCRM version 4.5                                                |
 + | CiviCRM version 4.6                                                |
   +--------------------------------------------------------------------+
   | Copyright CiviCRM LLC (c) 2004-2014                                |
   +--------------------------------------------------------------------+
@@@ -58,7 -58,7 +58,7 @@@ class CRM_Contact_BAO_Query 
      MODE_MAILING = 16384;
  
    /**
 -   * the default set of return properties
 +   * The default set of return properties
     *
     * @var array
     * @static
@@@ -66,7 -66,7 +66,7 @@@
    static $_defaultReturnProperties = NULL;
  
    /**
 -   * the default set of hier return properties
 +   * The default set of hier return properties
     *
     * @var array
     * @static
@@@ -74,7 -74,7 +74,7 @@@
    static $_defaultHierReturnProperties;
  
    /**
 -   * the set of input params
 +   * The set of input params
     *
     * @var array
     */
  
    public $_sort;
    /**
 -   * the set of output params
 +   * The set of output params
     *
     * @var array
     */
    public $_returnProperties;
  
    /**
 -   * the select clause
 +   * The select clause
     *
     * @var array
     */
    public $_select;
  
    /**
 -   * the name of the elements that are in the select clause
 +   * The name of the elements that are in the select clause
     * used to extract the values
     *
     * @var array
    public $_element;
  
    /**
 -   * the tables involved in the query
 +   * The tables involved in the query
     *
     * @var array
     */
    public $_tables;
  
    /**
 -   * the table involved in the where clause
 +   * The table involved in the where clause
     *
     * @var array
     */
    public $_whereTables;
  
    /**
 -   * the where clause
 +   * The where clause
     *
     * @var array
     */
    public $_where;
  
    /**
 -   * the where string
 +   * The where string
     *
     * @var string
     *
    public $_whereClause;
  
    /**
 -   * additional permission Where Clause
 +   * Additional permission Where Clause
     *
     * @var string
     *
    public $_permissionWhereClause;
  
    /**
 -   * the from string
 +   * The from string
     *
     * @var string
     *
    public $_fromClause;
  
    /**
 -   * additional permission from clause
 +   * Additional permission from clause
     *
     * @var string
     *
    public $_permissionFromClause;
  
    /**
 -   * the from clause for the simple select and alphabetical
 +   * The from clause for the simple select and alphabetical
     * select
     *
     * @var string
    public $_simpleFromClause;
  
    /**
 -   * the having values
 +   * The having values
     *
     * @var string
     *
    public $_options;
  
    /**
 -   * are we in search mode
 +   * Are we in search mode
     *
     * @var boolean
     */
    public $_search = TRUE;
  
    /**
 -   * should we skip permission checking
 +   * Should we skip permission checking
     *
     * @var boolean
     */
    public $_skipPermission = FALSE;
  
    /**
 -   * should we skip adding of delete clause
 +   * Should we skip adding of delete clause
     *
     * @var boolean
     */
    public $_skipDeleteClause = FALSE;
  
    /**
 -   * are we in strict mode (use equality over LIKE)
 +   * Are we in strict mode (use equality over LIKE)
     *
     * @var boolean
     */
    public $_primaryLocation = TRUE;
  
    /**
 -   * are contact ids part of the query
 +   * Are contact ids part of the query
     *
     * @var boolean
     */
    public $_displayRelationshipType = NULL;
  
    /**
 -   * reference to the query object for custom values
 +   * Reference to the query object for custom values
     *
     * @var Object
     */
    public $_customQuery;
  
    /**
 -   * should we enable the distinct clause, used if we are including
 +   * Should we enable the distinct clause, used if we are including
     * more than one group
     *
     * @var boolean
    public $_useGroupBy = FALSE;
  
    /**
 -   * the relationship type direction
 +   * The relationship type direction
     *
     * @var array
     * @static
    static $_relType;
  
    /**
 -   * the activity role
 +   * The activity role
     *
     * @var array
     * @static
    static $_withContactActivitiesOnly;
  
    /**
 -   * use distinct component clause for component searches
 +   * Use distinct component clause for component searches
     *
     * @var string
     */
    public $_rowCountClause;
  
    /**
 -   * use groupBy component clause for component searches
 +   * Use groupBy component clause for component searches
     *
     * @var string
     */
    public $_pseudoConstantsSelect = array();
  
    /**
 -   * class constructor which also does all the work
 +   * Class constructor which also does all the work
     *
     * @param array $params
     * @param array $returnProperties
    }
  
    /**
 -   * function which actually does all the work for the constructor
 +   * Function which actually does all the work for the constructor
     *
     * @return void
     * @access private
            // CRM-13011 : If location type is primary, do not restrict search to the phone
            // type id - we want the primary phone, regardless of what type it is.
            // Otherwise, restrict to the specified phone type for the given field.
 -          if ((!$cond) && ($elementName == 'phone') && $elements['location_type'] != 'Primary') {
 +          if ((!$cond) && ($elementName == 'phone')) {
              $cond = "phone_type_id = '$elementType'";
            }
            elseif ((!$cond) && ($elementName == 'im')) {
                  case 'civicrm_im':
                  case 'civicrm_openid':
  
 -                  $this->_tables[$tName] = "\nLEFT JOIN $tableName `$tName` ON contact_a.id = `$tName`.contact_id AND `$tName`.$lCond";
 +                  $this->_tables[$tName] = "\nLEFT JOIN $tableName `$tName` ON contact_a.id = `$tName`.contact_id";
 +                  if ($tableName != 'civicrm_phone') {
 +                    $this->_tables[$tName] .= " AND `$tName`.$lCond";
 +                  }
 +                  elseif (is_numeric($name)) {
 +                    $this->_select[$tName] = "IF (`$tName`.is_primary = $name, `$tName`.phone, NULL) as `$tName`";
 +                  }
 +
                    // this special case to add phone type
                    if ($cond) {
                      $phoneTypeCondition = " AND `$tName`.$cond ";
    }
  
    /**
 -   * generate the query based on what type of query we need
 +   * Generate the query based on what type of query we need
     *
     * @param boolean $count
     * @param boolean $sortByChar
    }
  
    /**
 -   * @param $name
 +   * @param string $name
     * @param $grouping
     *
     * @return null
    }
  
    /**
 -   * @param $id
 +   * @param int $id
     * @param $values
     * @param int $wildcard
     * @param bool $useEquals
    /**
     * Given a result dao, extract the values and return that array
     *
 -   * @param Object $dao
 +   * @param CRM_Core_DAO $dao
     *
     * @return array values for this query
     */
    }
  
    /**
 -   * getter for tables array
 +   * Getter for tables array
     *
     * @return array
     * @access public
    }
  
    /**
 -   * generate the where clause (used in match contacts and permissions)
 +   * Generate the where clause (used in match contacts and permissions)
     *
     * @param array $params
     * @param array $fields
    }
  
    /**
 -   * create the from clause
 +   * Create the from clause
     *
     * @param array $tables tables that need to be included in this from clause
     *                      if null, return mimimal from clause (i.e. civicrm_contact)
    }
  
    /**
 -   * where / qill clause for contact_type
 +   * Where / qill clause for contact_type
     *
     * @param $values
     *
    }
  
    /**
 -   * where / qill clause for contact_sub_type
 +   * Where / qill clause for contact_sub_type
     *
     * @param $values
     *
     */
    function contactSubType(&$values) {
      list($name, $op, $value, $grouping, $wildcard) = $values;
 -    $this->includeContactSubTypes($value, $grouping);
 +    $this->includeContactSubTypes($value, $grouping, $op);
    }
  
    /**
     * @param $value
     * @param $grouping
     */
 -  function includeContactSubTypes($value, $grouping) {
 +  function includeContactSubTypes($value, $grouping, $op = 'LIKE') {
  
      $clause = array();
      $alias = "contact_a.contact_sub_type";
 +    $qillOperators = array('NOT LIKE' => ts('Not Like')) + CRM_Core_SelectValues::getSearchBuilderOperators();
  
 -    if (is_array($value)) {
 +    $op = str_replace('IN', 'LIKE', $op);
 +    $op = str_replace('=', 'LIKE', $op);
 +    $op = str_replace('!', 'NOT ', $op);
 +
 +    if (strpos($op, 'NULL') !== FALSE || strpos($op, 'EMPTY') !== FALSE) {
 +      $this->_where[$grouping][] = self::buildClause($alias, $op, $value, 'String');
 +    }
 +    else if (is_array($value)) {
        foreach ($value as $k => $v) {
          if (!empty($k)) {
 -          $clause[$k] = "($alias like '%" . CRM_Core_DAO::VALUE_SEPARATOR . CRM_Utils_Type::escape($k, 'String') . CRM_Core_DAO::VALUE_SEPARATOR . "%')";
 +          $clause[$k] = "($alias $op '%" . CRM_Core_DAO::VALUE_SEPARATOR . CRM_Utils_Type::escape($k, 'String') . CRM_Core_DAO::VALUE_SEPARATOR . "%')";
          }
        }
      }
      else {
 -      $clause[$value] = "($alias like '%" . CRM_Core_DAO::VALUE_SEPARATOR . CRM_Utils_Type::escape($value, 'String') . CRM_Core_DAO::VALUE_SEPARATOR . "%')";
 +      $clause[$value] = "($alias $op '%" . CRM_Core_DAO::VALUE_SEPARATOR . CRM_Utils_Type::escape($value, 'String') . CRM_Core_DAO::VALUE_SEPARATOR . "%')";
      }
  
      if (!empty($clause)) {
        $this->_where[$grouping][] = "( " . implode(' OR ', $clause) . " )";
 -      $this->_qill[$grouping][] = ts('Contact Subtype') . ' - ' . implode(' ' . ts('or') . ' ', array_keys($clause));
      }
 +    $this->_qill[$grouping][] = ts('Contact Subtype %1 ', array(1 => $qillOperators[$op])) . implode(' ' . ts('or') . ' ', array_keys($clause));
    }
  
    /**
 -   * where / qill clause for groups
 +   * Where / qill clause for groups
     *
     * @param $values
     *
    }
  
    /**
 -   * where / qill clause for smart groups
 +   * Where / qill clause for smart groups
     *
     * @param $values
     *
@@@ -2903,19 -2888,19 +2903,19 @@@ WHERE  id IN ( $groupIDs 
        $groupIDsFiltered = implode(',', $groupsFiltered);
  
        if ($tableAlias == NULL) {
-         $tableAlias = "civicrm_group_contact_cache_{$groupIDsFiltered}";
+         $tableAlias = "`civicrm_group_contact_cache_{$groupIDsFiltered}`";
        }
  
-       $this->_tables["`{$tableAlias}`"] = $this->_whereTables["`{$tableAlias}`"] = " LEFT JOIN civicrm_group_contact_cache `{$tableAlias}` ON {$joinTable}.id = `{$tableAlias}`.contact_id ";
+       $this->_tables[$tableAlias] = $this->_whereTables[$tableAlias] = " LEFT JOIN civicrm_group_contact_cache {$tableAlias} ON {$joinTable}.id = {$tableAlias}.contact_id ";
  
-       return "`{$tableAlias}`.group_id IN (" . $groupIDsFiltered . ")";
+       return "{$tableAlias}.group_id IN (" . $groupIDsFiltered . ")";
      }
  
      return NULL;
    }
  
    /**
 -   * where / qill clause for cms users
 +   * Where / qill clause for cms users
     *
     * @param $values
     *
    }
  
    /**
 -   * all tag search specific
 +   * All tag search specific
     *
     * @param $values
     *
            LEFT JOIN civicrm_tag {$tActTable} ON ( {$etActTable}.tag_id = {$tActTable}.id  )";
  
        $this->_where[$grouping][] = "({$tTable}.name $op '". $value . "' OR {$tCaseTable}.name $op '". $value . "' OR {$tActTable}.name $op '". $value . "')";
 -      $this->_qill[$grouping][] = ts('Tag %1 %2 ', array(1 => $tagTypesText[2], 2 => $op)) . ' ' . $value;
 +      $this->_qill[$grouping][] = ts('Tag %1 %2', array(1 => $tagTypesText[2], 2 => $op)) . ' ' . $value;
      } else {
        $etTable = "`civicrm_entity_tag-" . $value . "`";
        $tTable = "`civicrm_tag-" . $value . "`";
    }
  
    /**
 -   * where / qill clause for tag
 +   * Where / qill clause for tag
     *
     * @param $values
     *
    }
  
    /**
 -   * where/qill clause for notes
 +   * Where/qill clause for notes
     *
     * @param $values
     *
    }
  
    /**
 -   * @param $name
 +   * @param string $name
     * @param $op
     * @param $grouping
     *
    }
  
    /**
 -   * where / qill clause for sort_name
 +   * Where / qill clause for sort_name
     *
     * @param $values
     *
     * @access public
     */
    function sortName(&$values) {
 -    list($name, $op, $value, $grouping, $wildcard) = $values;
 +    list($fieldName, $op, $value, $grouping, $wildcard) = $values;
  
      // handle IS NULL / IS NOT NULL / IS EMPTY / IS NOT EMPTY
 -    if ( $this->nameNullOrEmptyOp( $name, $op, $grouping ) ) {
 +    if ($this->nameNullOrEmptyOp($fieldName, $op, $grouping)) {
        return;
      }
  
 -    $newName = $name;
 -    $name = trim($value);
 +    $input = $value = trim($value);
  
 -    if (empty($name)) {
 +    if (!strlen($value)) {
        return;
      }
  
      $subGlue = ' OR ';
  
      $strtolower = function_exists('mb_strtolower') ? 'mb_strtolower' : 'strtolower';
 -    $locationType = CRM_Core_PseudoConstant::get('CRM_Core_DAO_Address', 'location_type_id');
  
 -    if (substr($name, 0, 1) == '"' &&
 -      substr($name, -1, 1) == '"'
 -    ) {
 -      //If name is encased in double quotes, the value should be taken to be the string in entirety and the
 -      $value = substr($name, 1, -1);
 -      $value = $strtolower(CRM_Core_DAO::escapeString($value));
 -      $wc = ($newName == 'sort_name') ? 'LOWER(contact_a.sort_name)' : 'LOWER(contact_a.display_name)';
 -      $sub[] = " ( $wc = '$value' ) ";
 -      if ($config->includeEmailInName) {
 -        $sub[] = " ( civicrm_email.email = '$value' ) ";
 -      }
 -    }
 -    elseif (strpos($name, ',') !== FALSE) {
 -      // if we have a comma in the string, search for the entire string
 -      $value = $strtolower(CRM_Core_DAO::escapeString($name));
 -      if ($wildcard) {
 +    $firstChar = substr($value, 0, 1);
 +    $lastChar = substr($value, -1, 1);
 +    $quotes = array("'", '"');
 +    // If string is quoted, strip quotes and otherwise don't alter it
 +    if ((strlen($value) > 2) && in_array($firstChar, $quotes) && in_array($lastChar, $quotes)) {
 +      $value = trim($value, implode('', $quotes));
 +    }
 +    // Replace spaces with wildcards for a LIKE operation
 +    // UNLESS string contains a comma (this exception is a tiny bit questionable)
 +    elseif ($op == 'LIKE' && strpos($value, ',') === FALSE) {
 +      $value = str_replace(' ', '%', $value);
 +    }
 +    $value = $strtolower(CRM_Core_DAO::escapeString(trim($value)));
 +    if (strlen($value)) {
 +      $fieldsub = array();
 +      if ($wildcard && $op == 'LIKE') {
          if ($config->includeWildCardInName) {
            $value = "'%$value%'";
          }
        else {
          $value = "'$value'";
        }
 -      if ($newName == 'sort_name') {
 +      if ($fieldName == 'sort_name') {
          $wc = self::caseImportant($op) ? "LOWER(contact_a.sort_name)" : "contact_a.sort_name";
        }
        else {
          $wc = self::caseImportant($op) ? "LOWER(contact_a.display_name)" : "contact_a.display_name";
        }
 -      $sub[] = " ( $wc $op $value )";
 +      $fieldsub[] = " ( $wc $op $value )";
        if ($config->includeNickNameInName) {
          $wc = self::caseImportant($op) ? "LOWER(contact_a.nick_name)" : "contact_a.nick_name";
 -        $sub[] = " ( $wc $op $value )";
 +        $fieldsub[] = " ( $wc $op $value )";
        }
        if ($config->includeEmailInName) {
 -        $sub[] = " ( civicrm_email.email $op $value ) ";
 -      }
 -    }
 -    else {
 -      // the string should be treated as a series of keywords to be matched with match ANY OR
 -      // match ALL depending on Civi config settings (see CiviAdmin)
 -
 -      // The Civi configuration setting can be overridden if the string *starts* with the case
 -      // insenstive strings 'AND:' or 'OR:'TO THINK ABOUT: what happens when someone searches
 -      // for the following "AND: 'a string in quotes'"? - probably nothing - it would make the
 -      // AND OR variable reduntant because there is only one search string?
 -
 -      // Check to see if the $subGlue is overridden in the search text
 -      if (strtolower(substr($name, 0, 4)) == 'and:') {
 -        $name = substr($name, 4);
 -        $subGlue = ' AND ';
 -      }
 -      if (strtolower(substr($name, 0, 3)) == 'or:') {
 -        $name = substr($name, 3);
 -        $subGlue = ' OR ';
 -      }
 -
 -      $firstChar = substr($name, 0, 1);
 -      $lastChar = substr($name, -1, 1);
 -      $quotes = array("'", '"');
 -      if ((strlen($name) > 2) && in_array($firstChar, $quotes) &&
 -        in_array($lastChar, $quotes)
 -      ) {
 -        $name = substr($name, 1);
 -        $name = substr($name, 0, -1);
 -        $pieces = array($name);
 -      }
 -      else {
 -        $pieces = explode(' ', $name);
 -      }
 -      foreach ($pieces as $piece) {
 -        $value = $strtolower(CRM_Core_DAO::escapeString(trim($piece)));
 -        if (strlen($value)) {
 -          // Added If as a sanitization - without it, when you do an OR search, any string with
 -          // double spaces (i.e. "  ") or that has a space after the keyword (e.g. "OR: ") will
 -          // return all contacts because it will include a condition similar to "OR contact
 -          // name LIKE '%'".  It might be better to replace this with array_filter.
 -          $fieldsub = array();
 -          if ($wildcard) {
 -            if ($config->includeWildCardInName) {
 -              $value = "'%$value%'";
 -            }
 -            else {
 -              $value = "'$value%'";
 -            }
 -            $op = 'LIKE';
 -          }
 -          else {
 -            $value = "'$value'";
 -          }
 -          if ($newName == 'sort_name') {
 -            $wc = self::caseImportant($op) ? "LOWER(contact_a.sort_name)" : "contact_a.sort_name";
 -          }
 -          else {
 -            $wc = self::caseImportant($op) ? "LOWER(contact_a.display_name)" : "contact_a.display_name";
 -          }
 -          $fieldsub[] = " ( $wc $op $value )";
 -          if ($config->includeNickNameInName) {
 -            $wc = self::caseImportant($op) ? "LOWER(contact_a.nick_name)" : "contact_a.nick_name";
 -            $fieldsub[] = " ( $wc $op $value )";
 -          }
 -          if ($config->includeEmailInName) {
 -            $fieldsub[] = " ( civicrm_email.email $op $value ) ";
 -          }
 -          $sub[] = ' ( ' . implode(' OR ', $fieldsub) . ' ) ';
 -          // I seperated the glueing in two.  The first stage should always be OR because we are searching for matches in *ANY* of these fields
 -        }
 +        $fieldsub[] = " ( civicrm_email.email $op $value ) ";
        }
 +      $sub[] = ' ( ' . implode(' OR ', $fieldsub) . ' ) ';
      }
  
      $sub = ' ( ' . implode($subGlue, $sub) . ' ) ';
      $this->_where[$grouping][] = $sub;
      if ($config->includeEmailInName) {
        $this->_tables['civicrm_email'] = $this->_whereTables['civicrm_email'] = 1;
 -      $this->_qill[$grouping][] = ts('Name or Email ') . "$op - '$name'";
 +      $this->_qill[$grouping][] = ts('Name or Email') . " $op - '$input'";
      }
      else {
 -      $this->_qill[$grouping][] = ts('Name like') . " - '$name'";
 +      $this->_qill[$grouping][] = ts('Name') . " $op - '$input'";
      }
    }
  
    /**
 -   * where / qill clause for email
 +   * Where / qill clause for email
     *
     * @param $values
     *
    }
  
    /**
 -   * where / qill clause for phone number
 +   * Where / qill clause for phone number
     *
     * @param $values
     *
    }
  
    /**
 -   * where / qill clause for phone type/location
 +   * Where / qill clause for phone type/location
     *
     * @param $values
     *
    }
  
    /**
 -   * where / qill clause for street_address
 +   * Where / qill clause for street_address
     *
     * @param $values
     *
    }
  
    /**
 -   * where / qill clause for street_unit
 +   * Where / qill clause for street_unit
     *
     * @param $values
     *
    }
  
    /**
 -   * where / qill clause for sorting by character
 +   * Where / qill clause for sorting by character
     *
     * @param $values
     *
    }
  
    /**
 -   * where / qill clause for including contact ids
 +   * Where / qill clause for including contact ids
     *
     * @return void
     * @access public
    }
  
    /**
 -   * where / qill clause for postal code
 +   * Where / qill clause for postal code
     *
     * @param $values
     *
    }
  
    /**
 -   * where / qill clause for location type
 +   * Where / qill clause for location type
     *
     * @param $values
     * @param null $status
    }
  
    /**
 -   * where / qill clause for county (if present)
 +   * Where / qill clause for county (if present)
     *
     * @param $values
     * @param null $status
    }
  
    /**
 -   * where / qill clause for state/province AND country (if present)
 +   * Where / qill clause for state/province AND country (if present)
     *
     * @param $values
     * @param null $status
    }
  
    /**
 -   * where / qill clause for change log
 +   * Where / qill clause for change log
     *
     * @param $values
     *
      $name = $targetName[4] ? "%$name%" : $name;
      $this->_where[$grouping][] = "contact_b_log.sort_name LIKE '%$name%'";
      $this->_tables['civicrm_log'] = $this->_whereTables['civicrm_log'] = 1;
 -    $this->_qill[$grouping][] = ts('Modified by') . ": $name";
 +    $this->_qill[$grouping][] = ts('Modified By') . " $name";
    }
  
    /**
    }
  
    /**
 -   * where / qill clause for relationship
 +   * Where / qill clause for relationship
     *
     * @param $values
     *
         return;
      }
      // also get values array for relation_target_name
 -    // for relatinship search we always do wildcard
 +    // for relationship search we always do wildcard
      $relationType = $this->getWhereValues('relation_type_id', $grouping);
      $targetName = $this->getWhereValues('relation_target_name', $grouping);
      $relStatus = $this->getWhereValues('relation_status', $grouping);
@@@ -4096,12 -4153,6 +4096,12 @@@ civicrm_relationship.start_date > {$tod
        $this->_qill[$grouping][] = ts('Relationship - Inactive or not Current');
      }
  
 +    $onlyDeleted = 0;
 +    if (in_array(array('deleted_contacts', '=', '1', '0', '0'), $this->_params)) {
 +      $onlyDeleted = 1;
 +    }
 +    $where[$grouping][] = "(contact_b.is_deleted = {$onlyDeleted})";
 +
      //check for permissioned, non-permissioned and all permissioned relations
      if ($relPermission[2] == 1) {
        $where[$grouping][] = "(
@@@ -4179,7 -4230,7 +4179,7 @@@ civicrm_relationship.is_permission_a_b 
    }
  
    /**
 -   * default set of return properties
 +   * Default set of return properties
     *
     * @param int $mode
     *
    }
  
    /**
 -   * get primary condition for a sql clause
 +   * Get primary condition for a sql clause
     *
     * @param int $value
     *
    }
  
    /**
 -   * wrapper for a simple search query
 +   * Wrapper for a simple search query
     *
     * @param array $params
     * @param array $returnProperties
     * @param string $sort
     * @param int $offset
     * @param int $row_count
 -   * @param bool $smartGroupCache
 +   * @param bool $smartGroupCache  ?? update smart group cache?
     * @param bool $count return count obnly
     * @param bool $skipPermissions Should permissions be ignored or should the logged in user's permissions be applied
     *
 -   * @params bool $smartGroupCache ?? update smart group cache?
     *
     * @return array
     * @access public
    }
  
    /**
 -   * create and query the db for an contact search
 +   * Create and query the db for an contact search
     *
     * @param int $offset the offset for the query
     * @param int $rowCount the number of rows to return
@@@ -4807,7 -4859,7 +4807,7 @@@ SELECT COUNT( conts.total_amount ) as c
    }
  
    /**
 -   * getter for the qill object
 +   * Getter for the qill object
     *
     * @return string
     * @access public
    }
  
    /**
 -   * default set of return default hier return properties
 +   * Default set of return default hier return properties
     *
     * @return array
     * @access public
  
    /**
     * @param $values
 -   * @param $tableName
 -   * @param $fieldName
 -   * @param $dbFieldName
 +   * @param string $tableName
 +   * @param string $fieldName
 +   * @param string $dbFieldName
     * @param $fieldTitle
     * @param bool $appendTimeStamp
     */
  
    /**
     * @param $values
 -   * @param $tableName
 -   * @param $fieldName
 -   * @param $dbFieldName
 +   * @param string $tableName
 +   * @param string $fieldName
 +   * @param string $dbFieldName
     * @param $fieldTitle
     * @param null $options
     */
@@@ -5329,12 -5381,14 +5329,12 @@@ AND   displayRelType.is_active = 
     * @param $op       string the sql operator, this function should handle ALL SQL operators
     * @param $value string|integer|array depends on the operator and who's calling the query builder
     * @param $grouping int    the index where to place the where clause
 -   * @param $selectValues
 +   * @param $selectValues the key value pairs for this element. This allows us to use this function for things besides option-value pairs
     * @param $field    array  an array that contains various properties of the field identified by $name
     * @param $label    string The label for this field element
     * @param $dataType string The data type for this element
 -   *
     * @param bool $useIDsOnly
     *
 -   * @internal param array $selectValue the key value pairs for this element. This allows us to use this function for things besides option-value pairs
     * @return void     adds the where clause and qill to the query object
     */
    function optionValueQuery(
    }
  
    /**
 -   * function to check and explode a user defined numeric string into an array
 +   * Check and explode a user defined numeric string into an array
     * this was the protocol used by search builder in the old old days before we had
     * super nice js widgets to do the hard work
     *
    }
  
    /**
 -   * convert the pseudo constants id's to their names
 +   * Convert the pseudo constants id's to their names
     *
     * @param CRM_Core_DAO dao
     * @param bool $return
    }
  
    /**
 -   * include pseudo fields LEFT JOIN
 +   * Include pseudo fields LEFT JOIN
     * @param string|array $sort  can be a object or string
     *
     * @return array