Commit | Line | Data |
---|---|---|
6a488035 TO |
1 | <?php |
2 | /* | |
3 | +--------------------------------------------------------------------+ | |
fee14197 | 4 | | CiviCRM version 5 | |
6a488035 | 5 | +--------------------------------------------------------------------+ |
f299f7db | 6 | | Copyright CiviCRM LLC (c) 2004-2020 | |
6a488035 TO |
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 | +--------------------------------------------------------------------+ | |
d25dd0ee | 26 | */ |
6a488035 TO |
27 | |
28 | /** | |
c2c09cb4 | 29 | * |
30 | * This search now functions as a subset of advanced search since at some point it | |
31 | * was added to advanced search. | |
6a488035 TO |
32 | * |
33 | * @package CRM | |
f299f7db | 34 | * @copyright CiviCRM LLC (c) 2004-2020 |
6a488035 TO |
35 | */ |
36 | class CRM_Contact_Form_Search_Custom_Proximity extends CRM_Contact_Form_Search_Custom_Base implements CRM_Contact_Form_Search_Interface { | |
37 | ||
38 | protected $_latitude = NULL; | |
39 | protected $_longitude = NULL; | |
430ae6dd | 40 | protected $_distance = NULL; |
d14ccbdc SL |
41 | protected $_aclFrom = NULL; |
42 | protected $_aclWhere = NULL; | |
430ae6dd | 43 | |
86538308 | 44 | /** |
5a409b50 | 45 | * Class constructor. |
46 | * | |
47 | * @param array $formValues | |
86538308 EM |
48 | * |
49 | * @throws Exception | |
50 | */ | |
00be9182 | 51 | public function __construct(&$formValues) { |
6a488035 TO |
52 | parent::__construct($formValues); |
53 | ||
54 | // unset search profile and other search params if set | |
55 | unset($this->_formValues['uf_group_id']); | |
56 | unset($this->_formValues['component_mode']); | |
57 | unset($this->_formValues['operator']); | |
58 | ||
59 | if (!empty($this->_formValues)) { | |
60 | // add the country and state | |
bef4d7ee | 61 | self::addGeocodingData($this->_formValues); |
6a488035 TO |
62 | $this->_latitude = $this->_formValues['geo_code_1']; |
63 | $this->_longitude = $this->_formValues['geo_code_2']; | |
64 | ||
65 | if ($this->_formValues['prox_distance_unit'] == "miles") { | |
66 | $conversionFactor = 1609.344; | |
67 | } | |
68 | else { | |
69 | $conversionFactor = 1000; | |
70 | } | |
71 | $this->_distance = $this->_formValues['distance'] * $conversionFactor; | |
72 | } | |
73 | $this->_group = CRM_Utils_Array::value('group', $this->_formValues); | |
74 | ||
75 | $this->_tag = CRM_Utils_Array::value('tag', $this->_formValues); | |
76 | ||
be2fb01f | 77 | $this->_columns = [ |
6a488035 TO |
78 | ts('Name') => 'sort_name', |
79 | ts('Street Address') => 'street_address', | |
80 | ts('City') => 'city', | |
81 | ts('Postal Code') => 'postal_code', | |
82 | ts('State') => 'state_province', | |
83 | ts('Country') => 'country', | |
be2fb01f | 84 | ]; |
6a488035 TO |
85 | } |
86 | ||
c2c09cb4 | 87 | /** |
88 | * Get the query object for this selector. | |
89 | * | |
90 | * @return CRM_Contact_BAO_Query | |
91 | */ | |
92 | public function getQueryObj() { | |
93 | return $this->_query; | |
94 | } | |
95 | ||
86538308 | 96 | /** |
c927c151 | 97 | * @param CRM_Core_Form $form |
86538308 | 98 | */ |
00be9182 | 99 | public function buildForm(&$form) { |
6a488035 TO |
100 | |
101 | $config = CRM_Core_Config::singleton(); | |
102 | $countryDefault = $config->defaultContactCountry; | |
103 | ||
104 | $form->add('text', 'distance', ts('Distance'), NULL, TRUE); | |
105 | ||
be2fb01f | 106 | $proxUnits = ['km' => ts('km'), 'miles' => ts('miles')]; |
6a488035 TO |
107 | $form->add('select', 'prox_distance_unit', ts('Units'), $proxUnits, TRUE); |
108 | ||
109 | $form->add('text', | |
110 | 'street_address', | |
111 | ts('Street Address') | |
112 | ); | |
113 | ||
114 | $form->add('text', | |
115 | 'city', | |
116 | ts('City') | |
117 | ); | |
118 | ||
119 | $form->add('text', | |
120 | 'postal_code', | |
121 | ts('Postal Code') | |
122 | ); | |
c927c151 | 123 | |
be2fb01f | 124 | $defaults = []; |
6a488035 | 125 | if ($countryDefault) { |
6a488035 TO |
126 | $defaults['country_id'] = $countryDefault; |
127 | } | |
c927c151 | 128 | $form->addChainSelect('state_province_id'); |
6a488035 | 129 | |
be2fb01f CW |
130 | $country = ['' => ts('- select -')] + CRM_Core_PseudoConstant::country(); |
131 | $form->add('select', 'country_id', ts('Country'), $country, TRUE, ['class' => 'crm-select2']); | |
6a488035 | 132 | |
4b2d36d7 | 133 | $form->add('text', 'geo_code_1', ts('Latitude')); |
134 | $form->add('text', 'geo_code_2', ts('Longitude')); | |
135 | ||
be2fb01f CW |
136 | $group = ['' => ts('- any group -')] + CRM_Core_PseudoConstant::nestedGroup(); |
137 | $form->addElement('select', 'group', ts('Group'), $group, ['class' => 'crm-select2 huge']); | |
6a488035 | 138 | |
be2fb01f CW |
139 | $tag = ['' => ts('- any tag -')] + CRM_Core_PseudoConstant::get('CRM_Core_DAO_EntityTag', 'tag_id', ['onlyActive' => FALSE]); |
140 | $form->addElement('select', 'tag', ts('Tag'), $tag, ['class' => 'crm-select2 huge']); | |
6a488035 | 141 | |
6a488035 TO |
142 | /** |
143 | * You can define a custom title for the search form | |
144 | */ | |
145 | $this->setTitle('Proximity Search'); | |
146 | ||
147 | /** | |
148 | * if you are using the standard template, this array tells the template what elements | |
149 | * are part of the search criteria | |
150 | */ | |
be2fb01f | 151 | $form->assign('elements', [ |
6a488035 | 152 | 'distance', |
353ffa53 TO |
153 | 'prox_distance_unit', |
154 | 'street_address', | |
155 | 'city', | |
156 | 'postal_code', | |
157 | 'country_id', | |
158 | 'state_province_id', | |
159 | 'group', | |
160 | 'tag', | |
be2fb01f | 161 | ]); |
6a488035 TO |
162 | } |
163 | ||
86538308 EM |
164 | /** |
165 | * @param int $offset | |
166 | * @param int $rowcount | |
167 | * @param null $sort | |
168 | * @param bool $includeContactIDs | |
169 | * @param bool $justIDs | |
170 | * | |
171 | * @return string | |
172 | */ | |
79d7553f | 173 | public function all( |
51ccfbbe | 174 | $offset = 0, $rowcount = 0, $sort = NULL, |
6a488035 TO |
175 | $includeContactIDs = FALSE, $justIDs = FALSE |
176 | ) { | |
c2c09cb4 | 177 | $selectClause = $justIDs ? "contact_a.id as contact_id" : NULL; |
6a488035 TO |
178 | |
179 | return $this->sql($selectClause, | |
180 | $offset, $rowcount, $sort, | |
181 | $includeContactIDs, NULL | |
182 | ); | |
183 | } | |
184 | ||
86538308 | 185 | /** |
c2c09cb4 | 186 | * Override sql() function to use the Query object rather than generating on the form. |
187 | * | |
188 | * @param string $selectClause | |
189 | * @param int $offset | |
190 | * @param int $rowcount | |
191 | * @param null $sort | |
192 | * @param bool $includeContactIDs | |
193 | * @param null $groupBy | |
194 | * | |
86538308 EM |
195 | * @return string |
196 | */ | |
c2c09cb4 | 197 | public function sql( |
198 | $selectClause, | |
199 | $offset = 0, | |
200 | $rowcount = 0, | |
201 | $sort = NULL, | |
202 | $includeContactIDs = FALSE, | |
203 | $groupBy = NULL | |
204 | ) { | |
205 | ||
206 | $isCountOnly = FALSE; | |
207 | if ($selectClause === 'count(distinct contact_a.id) as total') { | |
208 | $isCountOnly = TRUE; | |
209 | } | |
210 | ||
211 | $searchParams = [ | |
212 | ['prox_distance_unit', '=', $this->_formValues['prox_distance_unit'], 0, 0], | |
213 | ['prox_distance', '=', $this->_formValues['distance'], 0, 0], | |
214 | ['prox_geo_code_1', '=', $this->_formValues['geo_code_1'], 0, 0], | |
215 | ['prox_geo_code_2', '=', $this->_formValues['geo_code_2'], 0, 0], | |
216 | ]; | |
217 | if (!empty($this->_formValues['group'])) { | |
218 | $searchParams[] = ['group', '=', ['IN', (array) $this->_formValues['group']][1], 0, 0]; | |
219 | } | |
220 | if (!empty($this->_formValues['tag'])) { | |
221 | $searchParams[] = ['contact_tags', '=', ['IN', (array) $this->_formValues['tag']][1], 0, 0]; | |
6a488035 | 222 | } |
c2c09cb4 | 223 | |
224 | $display = array_fill_keys(['city', 'state_province', 'country', 'postal_code', 'street_address', 'display_name', 'sort_name'], 1); | |
225 | if ($selectClause === 'contact_a.id as contact_id') { | |
226 | // Not sure when this would happen but calling all with 'justIDs' gets us here. | |
227 | $display = ['contact_id' => 1]; | |
6a488035 TO |
228 | } |
229 | ||
c2c09cb4 | 230 | $this->_query = new CRM_Contact_BAO_Query($searchParams, $display); |
231 | return $this->_query->searchQuery( | |
232 | $offset, | |
233 | $rowcount, | |
234 | $sort, | |
235 | $isCountOnly, | |
236 | $includeContactIDs, | |
237 | FALSE, | |
238 | $isCountOnly, | |
239 | $returnQuery = TRUE | |
240 | ); | |
241 | ||
6a488035 TO |
242 | } |
243 | ||
c2c09cb4 | 244 | /** |
245 | * @return string | |
246 | */ | |
247 | public function from() { | |
248 | //unused | |
249 | return ''; | |
250 | } | |
69078420 | 251 | |
86538308 EM |
252 | /** |
253 | * @param bool $includeContactIDs | |
254 | * | |
255 | * @return string | |
256 | */ | |
00be9182 | 257 | public function where($includeContactIDs = FALSE) { |
c2c09cb4 | 258 | //unused |
259 | return ''; | |
6a488035 TO |
260 | } |
261 | ||
86538308 EM |
262 | /** |
263 | * @return string | |
264 | */ | |
00be9182 | 265 | public function templateFile() { |
6a488035 TO |
266 | return 'CRM/Contact/Form/Search/Custom/Proximity.tpl'; |
267 | } | |
268 | ||
86538308 EM |
269 | /** |
270 | * @return array|null | |
271 | */ | |
00be9182 | 272 | public function setDefaultValues() { |
06d67d53 | 273 | if (!empty($this->_formValues)) { |
274 | return $this->_formValues; | |
275 | } | |
6a488035 TO |
276 | $config = CRM_Core_Config::singleton(); |
277 | $countryDefault = $config->defaultContactCountry; | |
278 | $stateprovinceDefault = $config->defaultContactStateProvince; | |
be2fb01f | 279 | $defaults = []; |
6a488035 TO |
280 | |
281 | if ($countryDefault) { | |
282 | if ($countryDefault == '1228' || $countryDefault == '1226') { | |
283 | $defaults['prox_distance_unit'] = 'miles'; | |
284 | } | |
285 | else { | |
286 | $defaults['prox_distance_unit'] = 'km'; | |
287 | } | |
288 | $defaults['country_id'] = $countryDefault; | |
289 | if ($stateprovinceDefault) { | |
290 | $defaults['state_province_id'] = $stateprovinceDefault; | |
291 | } | |
292 | return $defaults; | |
293 | } | |
294 | return NULL; | |
295 | } | |
296 | ||
86538308 EM |
297 | /** |
298 | * @param $row | |
299 | */ | |
51ccfbbe TO |
300 | public function alterRow(&$row) { |
301 | } | |
6a488035 | 302 | |
86538308 EM |
303 | /** |
304 | * @param $title | |
305 | */ | |
00be9182 | 306 | public function setTitle($title) { |
6a488035 TO |
307 | if ($title) { |
308 | CRM_Utils_System::setTitle($title); | |
309 | } | |
310 | else { | |
311 | CRM_Utils_System::setTitle(ts('Search')); | |
312 | } | |
313 | } | |
96025800 | 314 | |
bef4d7ee | 315 | /** |
316 | * Validate form input. | |
317 | * | |
318 | * @param array $fields | |
319 | * @param array $files | |
320 | * @param CRM_Core_Form $self | |
321 | * | |
322 | * @return array | |
323 | * Input errors from the form. | |
324 | */ | |
325 | public function formRule($fields, $files, $self) { | |
326 | $this->addGeocodingData($fields); | |
327 | ||
328 | if (!is_numeric(CRM_Utils_Array::value('geo_code_1', $fields)) || | |
329 | !is_numeric(CRM_Utils_Array::value('geo_code_2', $fields)) || | |
330 | !isset($fields['distance']) | |
331 | ) { | |
332 | $errorMessage = ts('Could not determine co-ordinates for provided data'); | |
333 | return array_fill_keys(['street_address', 'city', 'postal_code', 'country_id', 'state_province_id'], $errorMessage); | |
334 | } | |
335 | return []; | |
336 | } | |
337 | ||
338 | /** | |
339 | * Add the geocoding data to the fields supplied. | |
340 | * | |
341 | * @param array $fields | |
342 | */ | |
343 | protected function addGeocodingData(&$fields) { | |
344 | if (!empty($fields['country_id'])) { | |
345 | $fields['country'] = CRM_Core_PseudoConstant::country($fields['country_id']); | |
346 | } | |
347 | ||
348 | if (!empty($fields['state_province_id'])) { | |
349 | $fields['state_province'] = CRM_Core_PseudoConstant::stateProvince($fields['state_province_id']); | |
350 | } | |
351 | CRM_Core_BAO_Address::addGeocoderData($fields); | |
352 | } | |
353 | ||
6a488035 | 354 | } |