MODE_MAILING = 16384;
/**
- * the default set of return properties
+ * The default set of return properties
*
* @var array
* @static
static $_defaultReturnProperties = NULL;
/**
- * the default set of hier return properties
+ * The default set of hier return properties
*
* @var array
* @static
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
*
}
/**
- * 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
*
}
/**
- * 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);
$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][] = "(
}
/**
- * 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
}
/**
- * 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
*/
* @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