Commit | Line | Data |
---|---|---|
8bcc0d86 CW |
1 | <?php |
2 | /* | |
3 | +--------------------------------------------------------------------+ | |
4 | | CiviCRM version 4.7 | | |
5 | +--------------------------------------------------------------------+ | |
3b8eef99 | 6 | | Copyright CiviCRM LLC (c) 2004-2017 | |
8bcc0d86 CW |
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() { | |
fe59b2a7 | 39 | $filters = array(); |
8bcc0d86 CW |
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 | list($table_name, $column_name) = $this->addCustomField($this->apiFieldSpec['custom_' . $cf_id], 'INNER'); | |
93 | } | |
94 | elseif (strpos($key, '.')) { | |
95 | $fkInfo = $this->addFkField($key, 'INNER'); | |
96 | if ($fkInfo) { | |
97 | list($table_name, $column_name) = $fkInfo; | |
98 | $this->validateNestedInput($key, $value); | |
99 | } | |
100 | } | |
101 | // I don't know why I had to specifically exclude 0 as a key - wouldn't the others have caught it? | |
102 | // We normally silently ignore null values passed in - if people want IS_NULL they can use acceptedSqlOperator syntax. | |
103 | if ((!$table_name) || empty($key) || is_null($value)) { | |
104 | // No valid filter field. This might be a chained call or something. | |
105 | // Just ignore this for the $where_clause. | |
106 | continue; | |
107 | } | |
fe59b2a7 | 108 | $operator = is_array($value) ? \CRM_Utils_Array::first(array_keys($value)) : NULL; |
17e0598e | 109 | if (!in_array($operator, \CRM_Core_DAO::acceptedSQLOperators(), TRUE)) { |
fe59b2a7 | 110 | $value = array('=' => $value); |
8bcc0d86 | 111 | } |
fe59b2a7 CW |
112 | $filters[$key] = \CRM_Core_DAO::createSQLFilter("{$table_name}.{$column_name}", $value); |
113 | } | |
114 | // Support OR groups | |
115 | if (!empty($this->where['options']['or'])) { | |
116 | $orGroups = $this->where['options']['or']; | |
117 | if (is_string($orGroups)) { | |
118 | $orGroups = array_map('trim', explode(',', $orGroups)); | |
119 | } | |
120 | if (!is_array(\CRM_Utils_Array::first($orGroups))) { | |
121 | $orGroups = array($orGroups); | |
122 | } | |
123 | foreach ($orGroups as $orGroup) { | |
124 | $orClause = array(); | |
125 | foreach ($orGroup as $key) { | |
126 | if (!isset($filters[$key])) { | |
127 | throw new \CiviCRM_API3_Exception("'$key' specified in OR group but not added to params"); | |
128 | } | |
129 | $orClause[] = $filters[$key]; | |
130 | unset($filters[$key]); | |
8bcc0d86 | 131 | } |
fe59b2a7 | 132 | $this->query->where(implode(' OR ', $orClause)); |
8bcc0d86 CW |
133 | } |
134 | } | |
fe59b2a7 CW |
135 | // Add the remaining params using AND |
136 | foreach ($filters as $filter) { | |
137 | $this->query->where($filter); | |
138 | } | |
8bcc0d86 CW |
139 | } |
140 | ||
141 | /** | |
142 | * @inheritDoc | |
143 | */ | |
144 | protected function getFields() { | |
145 | require_once 'api/v3/Generic.php'; | |
146 | // Call this function directly instead of using the api wrapper to force unique field names off | |
147 | $apiSpec = \civicrm_api3_generic_getfields(array( | |
148 | 'entity' => $this->entity, | |
149 | 'version' => 3, | |
150 | 'params' => array('action' => 'get'), | |
151 | ), FALSE); | |
152 | return $apiSpec['values']; | |
153 | } | |
154 | ||
155 | /** | |
156 | * Fetch a field from the getFields list | |
157 | * | |
158 | * Searches by name, uniqueName, and api.aliases | |
066c4638 TO |
159 | * |
160 | * @param string $fieldName | |
161 | * Field name. | |
162 | * @return NULL|mixed | |
8bcc0d86 CW |
163 | */ |
164 | protected function getField($fieldName) { | |
165 | if (!$fieldName) { | |
166 | return NULL; | |
167 | } | |
168 | if (isset($this->apiFieldSpec[$fieldName])) { | |
169 | return $this->apiFieldSpec[$fieldName]; | |
170 | } | |
171 | foreach ($this->apiFieldSpec as $field) { | |
172 | if ( | |
173 | $fieldName == \CRM_Utils_Array::value('uniqueName', $field) || | |
174 | array_search($fieldName, \CRM_Utils_Array::value('api.aliases', $field, array())) !== FALSE | |
175 | ) { | |
176 | return $field; | |
177 | } | |
178 | } | |
179 | return NULL; | |
180 | } | |
181 | ||
182 | } |