X-Git-Url: https://vcs.fsf.org/?a=blobdiff_plain;f=CRM%2FContact%2FBAO%2FQuery.php;h=017e64e0415099c53e8d24f9703980435e66551a;hb=aa0b568b0563900aa6ddc792014cc17af2c3fc90;hp=a1a70ae095b317495368e39293c569865342b376;hpb=f73d4b56f02e0834294e6e1e15f60dbc406acf9c;p=civicrm-core.git diff --git a/CRM/Contact/BAO/Query.php b/CRM/Contact/BAO/Query.php index a1a70ae095..017e64e041 100644 --- a/CRM/Contact/BAO/Query.php +++ b/CRM/Contact/BAO/Query.php @@ -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 @@ class CRM_Contact_BAO_Query { static $_defaultReturnProperties = NULL; /** - * the default set of hier return properties + * The default set of hier return properties * * @var array * @static @@ -74,7 +74,7 @@ class CRM_Contact_BAO_Query { static $_defaultHierReturnProperties; /** - * the set of input params + * The set of input params * * @var array */ @@ -86,21 +86,21 @@ class CRM_Contact_BAO_Query { 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 @@ -108,28 +108,28 @@ class CRM_Contact_BAO_Query { 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 * @@ -137,7 +137,7 @@ class CRM_Contact_BAO_Query { public $_whereClause; /** - * additional permission Where Clause + * Additional permission Where Clause * * @var string * @@ -145,7 +145,7 @@ class CRM_Contact_BAO_Query { public $_permissionWhereClause; /** - * the from string + * The from string * * @var string * @@ -153,7 +153,7 @@ class CRM_Contact_BAO_Query { public $_fromClause; /** - * additional permission from clause + * Additional permission from clause * * @var string * @@ -161,7 +161,7 @@ class CRM_Contact_BAO_Query { public $_permissionFromClause; /** - * the from clause for the simple select and alphabetical + * The from clause for the simple select and alphabetical * select * * @var string @@ -169,7 +169,7 @@ class CRM_Contact_BAO_Query { public $_simpleFromClause; /** - * the having values + * The having values * * @var string * @@ -199,28 +199,28 @@ class CRM_Contact_BAO_Query { 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 */ @@ -243,7 +243,7 @@ class CRM_Contact_BAO_Query { public $_primaryLocation = TRUE; /** - * are contact ids part of the query + * Are contact ids part of the query * * @var boolean */ @@ -264,14 +264,14 @@ class CRM_Contact_BAO_Query { 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 @@ -284,7 +284,7 @@ class CRM_Contact_BAO_Query { public $_useGroupBy = FALSE; /** - * the relationship type direction + * The relationship type direction * * @var array * @static @@ -292,7 +292,7 @@ class CRM_Contact_BAO_Query { static $_relType; /** - * the activity role + * The activity role * * @var array * @static @@ -318,7 +318,7 @@ class CRM_Contact_BAO_Query { static $_withContactActivitiesOnly; /** - * use distinct component clause for component searches + * Use distinct component clause for component searches * * @var string */ @@ -327,7 +327,7 @@ class CRM_Contact_BAO_Query { public $_rowCountClause; /** - * use groupBy component clause for component searches + * Use groupBy component clause for component searches * * @var string */ @@ -405,7 +405,7 @@ class CRM_Contact_BAO_Query { 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 @@ -476,7 +476,7 @@ class CRM_Contact_BAO_Query { } /** - * function which actually does all the work for the constructor + * Function which actually does all the work for the constructor * * @return void * @access private @@ -1000,7 +1000,7 @@ class CRM_Contact_BAO_Query { // 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')) { @@ -1130,7 +1130,14 @@ class CRM_Contact_BAO_Query { 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 "; @@ -1257,7 +1264,7 @@ class CRM_Contact_BAO_Query { } /** - * 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 @@ -1376,7 +1383,7 @@ class CRM_Contact_BAO_Query { } /** - * @param $name + * @param string $name * @param $grouping * * @return null @@ -1473,7 +1480,7 @@ class CRM_Contact_BAO_Query { } /** - * @param $id + * @param int $id * @param $values * @param int $wildcard * @param bool $useEquals @@ -2256,7 +2263,7 @@ class CRM_Contact_BAO_Query { /** * 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 */ @@ -2301,7 +2308,7 @@ class CRM_Contact_BAO_Query { } /** - * getter for tables array + * Getter for tables array * * @return array * @access public @@ -2321,7 +2328,7 @@ class CRM_Contact_BAO_Query { } /** - * 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 @@ -2345,7 +2352,7 @@ class CRM_Contact_BAO_Query { } /** - * 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) @@ -2613,7 +2620,7 @@ class CRM_Contact_BAO_Query { } /** - * where / qill clause for contact_type + * Where / qill clause for contact_type * * @param $values * @@ -2681,7 +2688,7 @@ class CRM_Contact_BAO_Query { } /** - * where / qill clause for contact_sub_type + * Where / qill clause for contact_sub_type * * @param $values * @@ -2720,7 +2727,7 @@ class CRM_Contact_BAO_Query { } /** - * where / qill clause for groups + * Where / qill clause for groups * * @param $values * @@ -2834,7 +2841,7 @@ class CRM_Contact_BAO_Query { } /** - * where / qill clause for smart groups + * Where / qill clause for smart groups * * @param $values * @@ -2900,7 +2907,7 @@ WHERE id IN ( $groupIDs ) } /** - * where / qill clause for cms users + * Where / qill clause for cms users * * @param $values * @@ -2924,7 +2931,7 @@ WHERE id IN ( $groupIDs ) } /** - * all tag search specific + * All tag search specific * * @param $values * @@ -2978,7 +2985,7 @@ WHERE id IN ( $groupIDs ) 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 . "`"; @@ -2992,7 +2999,7 @@ WHERE id IN ( $groupIDs ) } /** - * where / qill clause for tag + * Where / qill clause for tag * * @param $values * @@ -3079,7 +3086,7 @@ WHERE id IN ( $groupIDs ) } /** - * where/qill clause for notes + * Where/qill clause for notes * * @param $values * @@ -3127,7 +3134,7 @@ WHERE id IN ( $groupIDs ) } /** - * @param $name + * @param string $name * @param $op * @param $grouping * @@ -3157,7 +3164,7 @@ WHERE id IN ( $groupIDs ) } /** - * where / qill clause for sort_name + * Where / qill clause for sort_name * * @param $values * @@ -3165,17 +3172,16 @@ WHERE id IN ( $groupIDs ) * @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; } @@ -3187,24 +3193,23 @@ WHERE id IN ( $groupIDs ) $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%'"; } @@ -3216,91 +3221,21 @@ WHERE id IN ( $groupIDs ) 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) . ' ) '; @@ -3308,15 +3243,15 @@ WHERE id IN ( $groupIDs ) $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 * @@ -3359,7 +3294,7 @@ WHERE id IN ( $groupIDs ) } /** - * where / qill clause for phone number + * Where / qill clause for phone number * * @param $values * @@ -3382,7 +3317,7 @@ WHERE id IN ( $groupIDs ) } /** - * where / qill clause for phone type/location + * Where / qill clause for phone type/location * * @param $values * @@ -3400,7 +3335,7 @@ WHERE id IN ( $groupIDs ) } /** - * where / qill clause for street_address + * Where / qill clause for street_address * * @param $values * @@ -3435,7 +3370,7 @@ WHERE id IN ( $groupIDs ) } /** - * where / qill clause for street_unit + * Where / qill clause for street_unit * * @param $values * @@ -3470,7 +3405,7 @@ WHERE id IN ( $groupIDs ) } /** - * where / qill clause for sorting by character + * Where / qill clause for sorting by character * * @param $values * @@ -3487,7 +3422,7 @@ WHERE id IN ( $groupIDs ) } /** - * where / qill clause for including contact ids + * Where / qill clause for including contact ids * * @return void * @access public @@ -3509,7 +3444,7 @@ WHERE id IN ( $groupIDs ) } /** - * where / qill clause for postal code + * Where / qill clause for postal code * * @param $values * @@ -3551,7 +3486,7 @@ WHERE id IN ( $groupIDs ) } /** - * where / qill clause for location type + * Where / qill clause for location type * * @param $values * @param null $status @@ -3671,7 +3606,7 @@ WHERE id IN ( $groupIDs ) } /** - * where / qill clause for county (if present) + * Where / qill clause for county (if present) * * @param $values * @param null $status @@ -3740,7 +3675,7 @@ WHERE id IN ( $groupIDs ) } /** - * 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 @@ -3835,7 +3770,7 @@ WHERE id IN ( $groupIDs ) } /** - * where / qill clause for change log + * Where / qill clause for change log * * @param $values * @@ -3855,7 +3790,7 @@ WHERE id IN ( $groupIDs ) $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"; } /** @@ -4016,7 +3951,7 @@ WHERE id IN ( $groupIDs ) } /** - * where / qill clause for relationship + * Where / qill clause for relationship * * @param $values * @@ -4029,7 +3964,7 @@ WHERE id IN ( $groupIDs ) 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); @@ -4059,7 +3994,7 @@ WHERE id IN ( $groupIDs ) $params = array('id' => $rel[0]); $rType = CRM_Contact_BAO_RelationshipType::retrieve($params, $rTypeValues); } - if (empty($rTypeValues)) { + if (!empty($rTypeValues) && $rTypeValues['name_a_b'] == $rTypeValues['name_b_a']) { // if we don't know which end of the relationship we are dealing with we'll create a temp table //@todo unless we are dealing with a target group self::$_relType = 'reciprocal'; @@ -4153,6 +4088,12 @@ civicrm_relationship.start_date > {$today} $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][] = "( @@ -4230,7 +4171,7 @@ civicrm_relationship.is_permission_a_b = 0 } /** - * default set of return properties + * Default set of return properties * * @param int $mode * @@ -4312,7 +4253,7 @@ civicrm_relationship.is_permission_a_b = 0 } /** - * get primary condition for a sql clause + * Get primary condition for a sql clause * * @param int $value * @@ -4328,7 +4269,7 @@ civicrm_relationship.is_permission_a_b = 0 } /** - * wrapper for a simple search query + * Wrapper for a simple search query * * @param array $params * @param array $returnProperties @@ -4359,11 +4300,10 @@ civicrm_relationship.is_permission_a_b = 0 * @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 @@ -4446,7 +4386,7 @@ civicrm_relationship.is_permission_a_b = 0 } /** - * 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 @@ -4859,7 +4799,7 @@ SELECT COUNT( conts.total_amount ) as cancel_count, } /** - * getter for the qill object + * Getter for the qill object * * @return string * @access public @@ -4869,7 +4809,7 @@ SELECT COUNT( conts.total_amount ) as cancel_count, } /** - * default set of return default hier return properties + * Default set of return default hier return properties * * @return array * @access public @@ -4954,9 +4894,9 @@ SELECT COUNT( conts.total_amount ) as cancel_count, /** * @param $values - * @param $tableName - * @param $fieldName - * @param $dbFieldName + * @param string $tableName + * @param string $fieldName + * @param string $dbFieldName * @param $fieldTitle * @param bool $appendTimeStamp */ @@ -5067,9 +5007,9 @@ SELECT COUNT( conts.total_amount ) as cancel_count, /** * @param $values - * @param $tableName - * @param $fieldName - * @param $dbFieldName + * @param string $tableName + * @param string $fieldName + * @param string $dbFieldName * @param $fieldTitle * @param null $options */ @@ -5381,14 +5321,12 @@ AND displayRelType.is_active = 1 * @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( @@ -5459,7 +5397,7 @@ AND displayRelType.is_active = 1 } /** - * 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 * @@ -5501,7 +5439,7 @@ AND displayRelType.is_active = 1 } /** - * 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 @@ -5577,7 +5515,7 @@ AND displayRelType.is_active = 1 } /** - * include pseudo fields LEFT JOIN + * Include pseudo fields LEFT JOIN * @param string|array $sort can be a object or string * * @return array