Merge pull request #10946 from mattwire/CRM-21037_activity_sendsms_unittests
[civicrm-core.git] / Civi / API / Api3SelectQuery.php
1 <?php
2 /*
3 +--------------------------------------------------------------------+
4 | CiviCRM version 5 |
5 +--------------------------------------------------------------------+
6 | Copyright CiviCRM LLC (c) 2004-2018 |
7 +--------------------------------------------------------------------+
8 | This file is a part of CiviCRM. |
9 | |
10 | CiviCRM is free software; you can copy, modify, and distribute it |
11 | under the terms of the GNU Affero General Public License |
12 | Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
13 | |
14 | CiviCRM is distributed in the hope that it will be useful, but |
15 | WITHOUT ANY WARRANTY; without even the implied warranty of |
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
17 | See the GNU Affero General Public License for more details. |
18 | |
19 | You should have received a copy of the GNU Affero General Public |
20 | License and the CiviCRM Licensing Exception along |
21 | with this program; if not, contact CiviCRM LLC |
22 | at info[AT]civicrm[DOT]org. If you have questions about the |
23 | GNU Affero General Public License or the licensing of CiviCRM, |
24 | see the CiviCRM license FAQ at http://civicrm.org/licensing |
25 +--------------------------------------------------------------------+
26 */
27 namespace Civi\API;
28
29 /**
30 */
31 class Api3SelectQuery extends SelectQuery {
32
33 protected $apiVersion = 3;
34
35 /**
36 * @inheritDoc
37 */
38 protected function buildWhereClause() {
39 $filters = array();
40 foreach ($this->where as $key => $value) {
41 $table_name = NULL;
42 $column_name = NULL;
43
44 if (substr($key, 0, 7) == 'filter.') {
45 // Legacy support for old filter syntax per the test contract.
46 // (Convert the style to the later one & then deal with them).
47 $filterArray = explode('.', $key);
48 $value = array($filterArray[1] => $value);
49 $key = 'filters';
50 }
51
52 // Legacy support for 'filter's construct.
53 if ($key == 'filters') {
54 foreach ($value as $filterKey => $filterValue) {
55 if (substr($filterKey, -4, 4) == 'high') {
56 $key = substr($filterKey, 0, -5);
57 $value = array('<=' => $filterValue);
58 }
59
60 if (substr($filterKey, -3, 3) == 'low') {
61 $key = substr($filterKey, 0, -4);
62 $value = array('>=' => $filterValue);
63 }
64
65 if ($filterKey == 'is_current' || $filterKey == 'isCurrent') {
66 // Is current is almost worth creating as a 'sql filter' in the DAO function since several entities have the concept.
67 $todayStart = date('Ymd000000', strtotime('now'));
68 $todayEnd = date('Ymd235959', strtotime('now'));
69 $a = self::MAIN_TABLE_ALIAS;
70 $this->query->where("($a.start_date <= '$todayStart' OR $a.start_date IS NULL)
71 AND ($a.end_date >= '$todayEnd' OR $a.end_date IS NULL)
72 AND a.is_active = 1");
73 }
74 }
75 }
76 // Ignore the "options" param if it is referring to api options and not a field in this entity
77 if (
78 $key === 'options' && is_array($value)
79 && !in_array(\CRM_Utils_Array::first(array_keys($value)), \CRM_Core_DAO::acceptedSQLOperators())
80 ) {
81 continue;
82 }
83 $field = $this->getField($key);
84 if ($field) {
85 $key = $field['name'];
86 }
87 if (in_array($key, $this->entityFieldNames)) {
88 $table_name = self::MAIN_TABLE_ALIAS;
89 $column_name = $key;
90 }
91 elseif (($cf_id = \CRM_Core_BAO_CustomField::getKeyID($key)) != FALSE) {
92 // If we check a custom field on 'IS NULL', it should also work when there is no
93 // record in the custom value table, see CRM-20740.
94 $side = empty($value['IS NULL']) ? 'INNER' : 'LEFT OUTER';
95 list($table_name, $column_name) = $this->addCustomField($this->apiFieldSpec['custom_' . $cf_id], $side);
96 }
97 elseif (strpos($key, '.')) {
98 $fkInfo = $this->addFkField($key, 'INNER');
99 if ($fkInfo) {
100 list($table_name, $column_name) = $fkInfo;
101 $this->validateNestedInput($key, $value);
102 }
103 }
104 // I don't know why I had to specifically exclude 0 as a key - wouldn't the others have caught it?
105 // We normally silently ignore null values passed in - if people want IS_NULL they can use acceptedSqlOperator syntax.
106 if ((!$table_name) || empty($key) || is_null($value)) {
107 // No valid filter field. This might be a chained call or something.
108 // Just ignore this for the $where_clause.
109 continue;
110 }
111 $operator = is_array($value) ? \CRM_Utils_Array::first(array_keys($value)) : NULL;
112 if (!in_array($operator, \CRM_Core_DAO::acceptedSQLOperators(), TRUE)) {
113 $value = array('=' => $value);
114 }
115 $filters[$key] = \CRM_Core_DAO::createSQLFilter("{$table_name}.{$column_name}", $value);
116 }
117 // Support OR groups
118 if (!empty($this->where['options']['or'])) {
119 $orGroups = $this->where['options']['or'];
120 if (is_string($orGroups)) {
121 $orGroups = array_map('trim', explode(',', $orGroups));
122 }
123 if (!is_array(\CRM_Utils_Array::first($orGroups))) {
124 $orGroups = array($orGroups);
125 }
126 foreach ($orGroups as $orGroup) {
127 $orClause = array();
128 foreach ($orGroup as $key) {
129 if (!isset($filters[$key])) {
130 throw new \CiviCRM_API3_Exception("'$key' specified in OR group but not added to params");
131 }
132 $orClause[] = $filters[$key];
133 unset($filters[$key]);
134 }
135 $this->query->where(implode(' OR ', $orClause));
136 }
137 }
138 // Add the remaining params using AND
139 foreach ($filters as $filter) {
140 $this->query->where($filter);
141 }
142 }
143
144 /**
145 * @inheritDoc
146 */
147 protected function getFields() {
148 require_once 'api/v3/Generic.php';
149 // Call this function directly instead of using the api wrapper to force unique field names off
150 $apiSpec = \civicrm_api3_generic_getfields(array(
151 'entity' => $this->entity,
152 'version' => 3,
153 'params' => array('action' => 'get'),
154 ), FALSE);
155 return $apiSpec['values'];
156 }
157
158 /**
159 * Fetch a field from the getFields list
160 *
161 * Searches by name, uniqueName, and api.aliases
162 *
163 * @param string $fieldName
164 * Field name.
165 * @return NULL|mixed
166 */
167 protected function getField($fieldName) {
168 if (!$fieldName) {
169 return NULL;
170 }
171 if (isset($this->apiFieldSpec[$fieldName])) {
172 return $this->apiFieldSpec[$fieldName];
173 }
174 foreach ($this->apiFieldSpec as $field) {
175 if (
176 $fieldName == \CRM_Utils_Array::value('uniqueName', $field) ||
177 array_search($fieldName, \CRM_Utils_Array::value('api.aliases', $field, array())) !== FALSE
178 ) {
179 return $field;
180 }
181 }
182 return NULL;
183 }
184
185 }