Commit | Line | Data |
---|---|---|
6a488035 | 1 | <?php |
6a488035 TO |
2 | /* |
3 | +--------------------------------------------------------------------+ | |
7e9e8871 | 4 | | CiviCRM version 4.7 | |
6a488035 | 5 | +--------------------------------------------------------------------+ |
e7112fa7 | 6 | | Copyright CiviCRM LLC (c) 2004-2015 | |
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 | /** | |
29 | * | |
30 | * @package CRM | |
e7112fa7 | 31 | * @copyright CiviCRM LLC (c) 2004-2015 |
6a488035 TO |
32 | */ |
33 | ||
34 | /** | |
192d36c5 | 35 | * This is class to handle address related functions. |
6a488035 TO |
36 | */ |
37 | class CRM_Core_BAO_Address extends CRM_Core_DAO_Address { | |
38 | ||
39 | /** | |
fe482240 | 40 | * Takes an associative array and creates a address. |
6a488035 | 41 | * |
6a0b768e TO |
42 | * @param array $params |
43 | * (reference ) an assoc array of name/value pairs. | |
44 | * @param bool $fixAddress | |
45 | * True if you need to fix (format) address values. | |
6a488035 TO |
46 | * before inserting in db |
47 | * | |
e63aff1c EM |
48 | * @param null $entity |
49 | * | |
a1a2a83d | 50 | * @return array|NULL |
a6c01b45 | 51 | * array of created address |
6a488035 | 52 | */ |
00be9182 | 53 | public static function create(&$params, $fixAddress = TRUE, $entity = NULL) { |
6a488035 | 54 | if (!isset($params['address']) || !is_array($params['address'])) { |
a1a2a83d | 55 | return NULL; |
6a488035 TO |
56 | } |
57 | CRM_Core_BAO_Block::sortPrimaryFirst($params['address']); | |
58 | $addresses = array(); | |
59 | $contactId = NULL; | |
60 | ||
61 | $updateBlankLocInfo = CRM_Utils_Array::value('updateBlankLocInfo', $params, FALSE); | |
62 | if (!$entity) { | |
63 | $contactId = $params['contact_id']; | |
64 | //get all the addresses for this contact | |
85c882c5 | 65 | $addresses = self::allAddress($contactId); |
6a488035 TO |
66 | } |
67 | else { | |
68 | // get all address from location block | |
69 | $entityElements = array( | |
70 | 'entity_table' => $params['entity_table'], | |
71 | 'entity_id' => $params['entity_id'], | |
72 | ); | |
73 | $addresses = self::allEntityAddress($entityElements); | |
74 | } | |
75 | ||
76 | $isPrimary = $isBilling = TRUE; | |
77 | $blocks = array(); | |
78 | foreach ($params['address'] as $key => $value) { | |
79 | if (!is_array($value)) { | |
80 | continue; | |
81 | } | |
82 | ||
83 | $addressExists = self::dataExists($value); | |
dfcbddc8 | 84 | if (empty($value['id'])) { |
85c882c5 | 85 | if (!empty($addresses) && array_key_exists(CRM_Utils_Array::value('location_type_id', $value), $addresses)) { |
86 | $value['id'] = $addresses[CRM_Utils_Array::value('location_type_id', $value)]; | |
6a488035 TO |
87 | } |
88 | } | |
89 | ||
90 | // Note there could be cases when address info already exist ($value[id] is set) for a contact/entity | |
91 | // BUT info is not present at this time, and therefore we should be really careful when deleting the block. | |
92 | // $updateBlankLocInfo will help take appropriate decision. CRM-5969 | |
dfcbddc8 | 93 | if (isset($value['id']) && !$addressExists && $updateBlankLocInfo) { |
6a488035 TO |
94 | //delete the existing record |
95 | CRM_Core_BAO_Block::blockDelete('Address', array('id' => $value['id'])); | |
96 | continue; | |
97 | } | |
98 | elseif (!$addressExists) { | |
99 | continue; | |
100 | } | |
101 | ||
8cc574cf | 102 | if ($isPrimary && !empty($value['is_primary'])) { |
6a488035 TO |
103 | $isPrimary = FALSE; |
104 | } | |
105 | else { | |
106 | $value['is_primary'] = 0; | |
107 | } | |
108 | ||
8cc574cf | 109 | if ($isBilling && !empty($value['is_billing'])) { |
6a488035 TO |
110 | $isBilling = FALSE; |
111 | } | |
112 | else { | |
113 | $value['is_billing'] = 0; | |
114 | } | |
115 | ||
a7488080 | 116 | if (empty($value['manual_geo_code'])) { |
6a488035 TO |
117 | $value['manual_geo_code'] = 0; |
118 | } | |
119 | $value['contact_id'] = $contactId; | |
120 | $blocks[] = self::add($value, $fixAddress); | |
121 | } | |
122 | ||
123 | return $blocks; | |
124 | } | |
125 | ||
126 | /** | |
fe482240 | 127 | * Takes an associative array and adds address. |
6a488035 | 128 | * |
6a0b768e TO |
129 | * @param array $params |
130 | * (reference ) an assoc array of name/value pairs. | |
131 | * @param bool $fixAddress | |
132 | * True if you need to fix (format) address values. | |
6a488035 TO |
133 | * before inserting in db |
134 | * | |
906e6120 | 135 | * @return CRM_Core_BAO_Address|null |
6a488035 | 136 | */ |
00be9182 | 137 | public static function add(&$params, $fixAddress) { |
e9ff5391 | 138 | |
6a488035 | 139 | $address = new CRM_Core_DAO_Address(); |
e9ff5391 | 140 | $checkPermissions = isset($params['check_permissions']) ? $params['check_permissions'] : TRUE; |
6a488035 TO |
141 | |
142 | // fixAddress mode to be done | |
143 | if ($fixAddress) { | |
144 | CRM_Core_BAO_Address::fixAddress($params); | |
145 | } | |
146 | ||
147 | $hook = empty($params['id']) ? 'create' : 'edit'; | |
148 | CRM_Utils_Hook::pre($hook, 'Address', CRM_Utils_Array::value('id', $params), $params); | |
149 | ||
150 | // if id is set & is_primary isn't we can assume no change | |
151 | if (is_numeric(CRM_Utils_Array::value('is_primary', $params)) || empty($params['id'])) { | |
152 | CRM_Core_BAO_Block::handlePrimary($params, get_class()); | |
153 | } | |
e9ff5391 | 154 | |
6a488035 TO |
155 | $address->copyValues($params); |
156 | ||
157 | $address->save(); | |
158 | ||
159 | if ($address->id) { | |
e9ff5391 | 160 | $customFields = CRM_Core_BAO_CustomField::getFields('Address', FALSE, TRUE, NULL, NULL, FALSE, FALSE, $checkPermissions); |
161 | ||
6a488035 TO |
162 | if (!empty($customFields)) { |
163 | $addressCustom = CRM_Core_BAO_CustomField::postProcess($params, | |
6a488035 TO |
164 | $address->id, |
165 | 'Address', | |
e9ff5391 | 166 | FALSE, |
167 | $checkPermissions | |
6a488035 TO |
168 | ); |
169 | } | |
170 | if (!empty($addressCustom)) { | |
171 | CRM_Core_BAO_CustomValueTable::store($addressCustom, 'civicrm_address', $address->id); | |
172 | } | |
173 | ||
174 | //call the function to sync shared address | |
175 | self::processSharedAddress($address->id, $params); | |
176 | ||
177 | // call the function to create shared relationships | |
178 | // we only create create relationship if address is shared by Individual | |
82ffeed5 | 179 | if (!CRM_Utils_System::isNull($address->master_id)) { |
6a488035 TO |
180 | self::processSharedAddressRelationship($address->master_id, $params); |
181 | } | |
182 | ||
183 | // lets call the post hook only after we've done all the follow on processing | |
184 | CRM_Utils_Hook::post($hook, 'Address', $address->id, $address); | |
185 | } | |
186 | ||
187 | return $address; | |
188 | } | |
189 | ||
190 | /** | |
fe482240 | 191 | * Format the address params to have reasonable values. |
6a488035 | 192 | * |
6a0b768e TO |
193 | * @param array $params |
194 | * (reference ) an assoc array of name/value pairs. | |
6a488035 | 195 | */ |
00be9182 | 196 | public static function fixAddress(&$params) { |
a7488080 | 197 | if (!empty($params['billing_street_address'])) { |
b44e3f84 | 198 | //Check address is coming from online contribution / registration page |
6a488035 TO |
199 | //Fixed :CRM-5076 |
200 | $billing = array( | |
201 | 'street_address' => 'billing_street_address', | |
202 | 'city' => 'billing_city', | |
203 | 'postal_code' => 'billing_postal_code', | |
204 | 'state_province' => 'billing_state_province', | |
205 | 'state_province_id' => 'billing_state_province_id', | |
206 | 'country' => 'billing_country', | |
207 | 'country_id' => 'billing_country_id', | |
208 | ); | |
209 | ||
210 | foreach ($billing as $key => $val) { | |
211 | if ($value = CRM_Utils_Array::value($val, $params)) { | |
a7488080 | 212 | if (!empty($params[$key])) { |
6a488035 TO |
213 | unset($params[$val]); |
214 | } | |
215 | else { | |
216 | //add new key and removed old | |
217 | $params[$key] = $value; | |
218 | unset($params[$val]); | |
219 | } | |
220 | } | |
221 | } | |
222 | } | |
223 | ||
224 | /* Split the zip and +4, if it's in US format */ | |
a7488080 | 225 | if (!empty($params['postal_code']) && |
6a488035 TO |
226 | preg_match('/^(\d{4,5})[+-](\d{4})$/', |
227 | $params['postal_code'], | |
228 | $match | |
229 | ) | |
230 | ) { | |
231 | $params['postal_code'] = $match[1]; | |
232 | $params['postal_code_suffix'] = $match[2]; | |
233 | } | |
234 | ||
235 | // add country id if not set | |
236 | if ((!isset($params['country_id']) || !is_numeric($params['country_id'])) && | |
237 | isset($params['country']) | |
238 | ) { | |
239 | $country = new CRM_Core_DAO_Country(); | |
240 | $country->name = $params['country']; | |
241 | if (!$country->find(TRUE)) { | |
242 | $country->name = NULL; | |
243 | $country->iso_code = $params['country']; | |
244 | $country->find(TRUE); | |
245 | } | |
246 | $params['country_id'] = $country->id; | |
247 | } | |
248 | ||
249 | // add state_id if state is set | |
250 | if ((!isset($params['state_province_id']) || !is_numeric($params['state_province_id'])) | |
251 | && isset($params['state_province']) | |
252 | ) { | |
253 | if (!empty($params['state_province'])) { | |
254 | $state_province = new CRM_Core_DAO_StateProvince(); | |
255 | $state_province->name = $params['state_province']; | |
256 | ||
257 | // add country id if present | |
258 | if (!empty($params['country_id'])) { | |
259 | $state_province->country_id = $params['country_id']; | |
260 | } | |
261 | ||
262 | if (!$state_province->find(TRUE)) { | |
263 | unset($state_province->name); | |
264 | $state_province->abbreviation = $params['state_province']; | |
265 | $state_province->find(TRUE); | |
266 | } | |
267 | $params['state_province_id'] = $state_province->id; | |
268 | if (empty($params['country_id'])) { | |
269 | // set this here since we have it | |
270 | $params['country_id'] = $state_province->country_id; | |
271 | } | |
272 | } | |
273 | else { | |
274 | $params['state_province_id'] = 'null'; | |
275 | } | |
276 | } | |
277 | ||
278 | // add county id if county is set | |
279 | // CRM-7837 | |
280 | if ((!isset($params['county_id']) || !is_numeric($params['county_id'])) | |
281 | && isset($params['county']) && !empty($params['county']) | |
282 | ) { | |
283 | $county = new CRM_Core_DAO_County(); | |
284 | $county->name = $params['county']; | |
285 | ||
286 | if (isset($params['state_province_id'])) { | |
287 | $county->state_province_id = $params['state_province_id']; | |
288 | } | |
289 | ||
290 | if ($county->find(TRUE)) { | |
291 | $params['county_id'] = $county->id; | |
292 | } | |
293 | } | |
294 | ||
295 | // currently copy values populates empty fields with the string "null" | |
296 | // and hence need to check for the string null | |
297 | if (isset($params['state_province_id']) && | |
298 | is_numeric($params['state_province_id']) && | |
299 | (!isset($params['country_id']) || empty($params['country_id'])) | |
300 | ) { | |
301 | // since state id present and country id not present, hence lets populate it | |
302 | // jira issue http://issues.civicrm.org/jira/browse/CRM-56 | |
303 | $params['country_id'] = CRM_Core_DAO::getFieldValue('CRM_Core_DAO_StateProvince', | |
304 | $params['state_province_id'], | |
305 | 'country_id' | |
306 | ); | |
307 | } | |
308 | ||
309 | //special check to ignore non numeric values if they are not | |
310 | //detected by formRule(sometimes happens due to internet latency), also allow user to unselect state/country | |
311 | if (isset($params['state_province_id'])) { | |
312 | if (empty($params['state_province_id'])) { | |
313 | $params['state_province_id'] = 'null'; | |
314 | } | |
315 | elseif (!is_numeric($params['state_province_id']) || | |
316 | ((int ) $params['state_province_id'] < 1000) | |
317 | ) { | |
318 | // CRM-3393 ( the hacky 1000 check) | |
319 | $params['state_province_id'] = 'null'; | |
320 | } | |
321 | } | |
322 | ||
323 | if (isset($params['country_id'])) { | |
324 | if (empty($params['country_id'])) { | |
325 | $params['country_id'] = 'null'; | |
326 | } | |
327 | elseif (!is_numeric($params['country_id']) || | |
328 | ((int ) $params['country_id'] < 1000) | |
329 | ) { | |
330 | // CRM-3393 ( the hacky 1000 check) | |
331 | $params['country_id'] = 'null'; | |
332 | } | |
333 | } | |
334 | ||
335 | // add state and country names from the ids | |
336 | if (isset($params['state_province_id']) && is_numeric($params['state_province_id'])) { | |
337 | $params['state_province'] = CRM_Core_PseudoConstant::stateProvinceAbbreviation($params['state_province_id']); | |
338 | } | |
339 | ||
340 | if (isset($params['country_id']) && is_numeric($params['country_id'])) { | |
341 | $params['country'] = CRM_Core_PseudoConstant::country($params['country_id']); | |
342 | } | |
343 | ||
344 | $config = CRM_Core_Config::singleton(); | |
345 | ||
aaffa79f | 346 | $asp = Civi::settings()->get('address_standardization_provider'); |
6a488035 TO |
347 | // clean up the address via USPS web services if enabled |
348 | if ($asp === 'USPS' && | |
349 | $params['country_id'] == 1228 | |
350 | ) { | |
351 | CRM_Utils_Address_USPS::checkAddress($params); | |
352 | ||
353 | // do street parsing again if enabled, since street address might have changed | |
6c552737 TO |
354 | $parseStreetAddress = CRM_Utils_Array::value( |
355 | 'street_address_parsing', | |
356 | CRM_Core_BAO_Setting::valueOptions( | |
357 | CRM_Core_BAO_Setting::SYSTEM_PREFERENCES_NAME, | |
358 | 'address_options' | |
359 | ), | |
360 | FALSE | |
361 | ); | |
6a488035 TO |
362 | |
363 | if ($parseStreetAddress && !empty($params['street_address'])) { | |
364 | foreach (array( | |
353ffa53 TO |
365 | 'street_number', |
366 | 'street_name', | |
367 | 'street_unit', | |
af9b09df | 368 | 'street_number_suffix', |
353ffa53 | 369 | ) as $fld) { |
6a488035 TO |
370 | unset($params[$fld]); |
371 | } | |
372 | // main parse string. | |
373 | $parseString = CRM_Utils_Array::value('street_address', $params); | |
374 | $parsedFields = CRM_Core_BAO_Address::parseStreetAddress($parseString); | |
375 | ||
376 | // merge parse address in to main address block. | |
377 | $params = array_merge($params, $parsedFields); | |
378 | } | |
379 | } | |
380 | ||
381 | // add latitude and longitude and format address if needed | |
382 | if (!empty($config->geocodeMethod) && ($config->geocodeMethod != 'CRM_Utils_Geocode_OpenStreetMaps') && empty($params['manual_geo_code'])) { | |
383 | $class = $config->geocodeMethod; | |
384 | $class::format($params); | |
385 | } | |
386 | } | |
387 | ||
388 | /** | |
fe482240 | 389 | * Check if there is data to create the object. |
6a488035 | 390 | * |
6a0b768e TO |
391 | * @param array $params |
392 | * (reference ) an assoc array of name/value pairs. | |
6a488035 | 393 | * |
5c766a0b | 394 | * @return bool |
6a488035 | 395 | */ |
00be9182 | 396 | public static function dataExists(&$params) { |
6a488035 TO |
397 | //check if location type is set if not return false |
398 | if (!isset($params['location_type_id'])) { | |
399 | return FALSE; | |
400 | } | |
401 | ||
402 | $config = CRM_Core_Config::singleton(); | |
403 | foreach ($params as $name => $value) { | |
404 | if (in_array($name, array( | |
353ffa53 TO |
405 | 'is_primary', |
406 | 'location_type_id', | |
407 | 'id', | |
408 | 'contact_id', | |
409 | 'is_billing', | |
410 | 'display', | |
af9b09df | 411 | 'master_id', |
353ffa53 | 412 | ))) { |
6a488035 TO |
413 | continue; |
414 | } | |
415 | elseif (!CRM_Utils_System::isNull($value)) { | |
416 | // name could be country or country id | |
417 | if (substr($name, 0, 7) == 'country') { | |
418 | // make sure its different from the default country | |
419 | // iso code | |
420 | $defaultCountry = $config->defaultContactCountry(); | |
421 | // full name | |
422 | $defaultCountryName = $config->defaultContactCountryName(); | |
423 | ||
424 | if ($defaultCountry) { | |
425 | if ($value == $defaultCountry || | |
426 | $value == $defaultCountryName || | |
427 | $value == $config->defaultContactCountry | |
428 | ) { | |
429 | // do nothing | |
430 | } | |
431 | else { | |
432 | return TRUE; | |
433 | } | |
434 | } | |
435 | else { | |
436 | // return if null default | |
437 | return TRUE; | |
438 | } | |
439 | } | |
440 | else { | |
441 | return TRUE; | |
442 | } | |
443 | } | |
444 | } | |
445 | ||
446 | return FALSE; | |
447 | } | |
448 | ||
449 | /** | |
450 | * Given the list of params in the params array, fetch the object | |
451 | * and store the values in the values array | |
452 | * | |
6a0b768e TO |
453 | * @param array $entityBlock |
454 | * Associated array of fields. | |
455 | * @param bool $microformat | |
456 | * If microformat output is required. | |
e63aff1c | 457 | * @param int|string $fieldName conditional field name |
6a488035 | 458 | * |
a6c01b45 CW |
459 | * @return array |
460 | * array with address fields | |
6a488035 | 461 | */ |
00be9182 | 462 | public static function &getValues($entityBlock, $microformat = FALSE, $fieldName = 'contact_id') { |
6a488035 TO |
463 | if (empty($entityBlock)) { |
464 | return NULL; | |
465 | } | |
466 | $addresses = array(); | |
467 | $address = new CRM_Core_BAO_Address(); | |
468 | ||
a7488080 | 469 | if (empty($entityBlock['entity_table'])) { |
6a488035 TO |
470 | $address->$fieldName = CRM_Utils_Array::value($fieldName, $entityBlock); |
471 | } | |
472 | else { | |
473 | $addressIds = array(); | |
474 | $addressIds = self::allEntityAddress($entityBlock); | |
475 | ||
476 | if (!empty($addressIds[1])) { | |
477 | $address->id = $addressIds[1]; | |
478 | } | |
479 | else { | |
480 | return $addresses; | |
481 | } | |
482 | } | |
483 | //get primary address as a first block. | |
484 | $address->orderBy('is_primary desc, id'); | |
485 | ||
486 | $address->find(); | |
487 | ||
ac44bb1c | 488 | $locationTypes = CRM_Core_PseudoConstant::get('CRM_Core_DAO_Address', 'location_type_id'); |
6a488035 TO |
489 | $count = 1; |
490 | while ($address->fetch()) { | |
491 | // deprecate reference. | |
492 | if ($count > 1) { | |
493 | foreach (array( | |
353ffa53 TO |
494 | 'state', |
495 | 'state_name', | |
496 | 'country', | |
af9b09df | 497 | 'world_region', |
353ffa53 | 498 | ) as $fld) { |
4f99ca55 TO |
499 | if (isset($address->$fld)) { |
500 | unset($address->$fld); | |
2aa397bc | 501 | } |
6a488035 TO |
502 | } |
503 | } | |
504 | $stree = $address->street_address; | |
505 | $values = array(); | |
506 | CRM_Core_DAO::storeValues($address, $values); | |
507 | ||
508 | // add state and country information: CRM-369 | |
ac44bb1c WA |
509 | if (!empty($address->location_type_id)) { |
510 | $values['location_type'] = CRM_Utils_Array::value($address->location_type_id, $locationTypes); | |
511 | } | |
6a488035 TO |
512 | if (!empty($address->state_province_id)) { |
513 | $address->state = CRM_Core_PseudoConstant::stateProvinceAbbreviation($address->state_province_id, FALSE); | |
514 | $address->state_name = CRM_Core_PseudoConstant::stateProvince($address->state_province_id, FALSE); | |
515 | } | |
516 | ||
517 | if (!empty($address->country_id)) { | |
518 | $address->country = CRM_Core_PseudoConstant::country($address->country_id); | |
519 | ||
520 | //get world region | |
521 | $regionId = CRM_Core_DAO::getFieldValue('CRM_Core_DAO_Country', $address->country_id, 'region_id'); | |
522 | ||
523 | $address->world_region = CRM_Core_PseudoConstant::worldregion($regionId); | |
524 | } | |
525 | ||
526 | $address->addDisplay($microformat); | |
527 | ||
528 | $values['display'] = $address->display; | |
529 | $values['display_text'] = $address->display_text; | |
530 | ||
531 | if (is_numeric($address->master_id)) { | |
532 | $values['use_shared_address'] = 1; | |
533 | } | |
534 | ||
535 | $addresses[$count] = $values; | |
536 | ||
537 | //unset is_primary after first block. Due to some bug in earlier version | |
538 | //there might be more than one primary blocks, hence unset is_primary other than first | |
539 | if ($count > 1) { | |
540 | unset($addresses[$count]['is_primary']); | |
541 | } | |
542 | ||
543 | $count++; | |
544 | } | |
545 | ||
546 | return $addresses; | |
547 | } | |
548 | ||
549 | /** | |
192d36c5 | 550 | * Add the formatted address to $this-> display. |
6a488035 | 551 | * |
2a6da8d7 | 552 | * @param bool $microformat |
192d36c5 | 553 | * Unexplained parameter that I've always wondered about. |
6a488035 | 554 | */ |
00be9182 | 555 | public function addDisplay($microformat = FALSE) { |
6a488035 TO |
556 | $fields = array( |
557 | // added this for CRM 1200 | |
558 | 'address_id' => $this->id, | |
559 | // CRM-4003 | |
560 | 'address_name' => str_replace('\ 1', ' ', $this->name), | |
561 | 'street_address' => $this->street_address, | |
562 | 'supplemental_address_1' => $this->supplemental_address_1, | |
563 | 'supplemental_address_2' => $this->supplemental_address_2, | |
564 | 'city' => $this->city, | |
565 | 'state_province_name' => isset($this->state_name) ? $this->state_name : "", | |
566 | 'state_province' => isset($this->state) ? $this->state : "", | |
567 | 'postal_code' => isset($this->postal_code) ? $this->postal_code : "", | |
568 | 'postal_code_suffix' => isset($this->postal_code_suffix) ? $this->postal_code_suffix : "", | |
569 | 'country' => isset($this->country) ? $this->country : "", | |
570 | 'world_region' => isset($this->world_region) ? $this->world_region : "", | |
571 | ); | |
572 | ||
573 | if (isset($this->county_id) && $this->county_id) { | |
574 | $fields['county'] = CRM_Core_PseudoConstant::county($this->county_id); | |
575 | } | |
576 | else { | |
577 | $fields['county'] = NULL; | |
578 | } | |
579 | ||
580 | $this->display = CRM_Utils_Address::format($fields, NULL, $microformat); | |
581 | $this->display_text = CRM_Utils_Address::format($fields); | |
582 | } | |
583 | ||
584 | /** | |
585 | * Get all the addresses for a specified contact_id, with the primary address being first | |
586 | * | |
6a0b768e TO |
587 | * @param int $id |
588 | * The contact id. | |
6a488035 | 589 | * |
dfcbddc8 DG |
590 | * @param bool $updateBlankLocInfo |
591 | * | |
a6c01b45 | 592 | * @return array |
dfcbddc8 | 593 | * the array of adrress data |
6a488035 | 594 | */ |
dfcbddc8 | 595 | public static function allAddress($id, $updateBlankLocInfo = FALSE) { |
6a488035 TO |
596 | if (!$id) { |
597 | return NULL; | |
598 | } | |
599 | ||
600 | $query = " | |
601 | SELECT civicrm_address.id as address_id, civicrm_address.location_type_id as location_type_id | |
602 | FROM civicrm_contact, civicrm_address | |
603 | WHERE civicrm_address.contact_id = civicrm_contact.id AND civicrm_contact.id = %1 | |
604 | ORDER BY civicrm_address.is_primary DESC, address_id ASC"; | |
76034cf5 | 605 | $params = array(1 => array($id, 'Integer')); |
dfcbddc8 DG |
606 | |
607 | $addresses = array(); | |
6a488035 | 608 | $dao = CRM_Core_DAO::executeQuery($query, $params); |
dfcbddc8 | 609 | $count = 1; |
6a488035 | 610 | while ($dao->fetch()) { |
dfcbddc8 DG |
611 | if ($updateBlankLocInfo) { |
612 | $addresses[$count++] = $dao->address_id; | |
613 | } | |
614 | else { | |
615 | $addresses[$dao->location_type_id] = $dao->address_id; | |
616 | } | |
6a488035 TO |
617 | } |
618 | return $addresses; | |
619 | } | |
620 | ||
621 | /** | |
622 | * Get all the addresses for a specified location_block id, with the primary address being first | |
623 | * | |
6a0b768e TO |
624 | * @param array $entityElements |
625 | * The array containing entity_id and. | |
16b10e64 | 626 | * entity_table name |
6a488035 | 627 | * |
a6c01b45 | 628 | * @return array |
dfcbddc8 | 629 | * the array of adrress data |
6a488035 | 630 | */ |
00be9182 | 631 | public static function allEntityAddress(&$entityElements) { |
c927c151 | 632 | $addresses = array(); |
6a488035 TO |
633 | if (empty($entityElements)) { |
634 | return $addresses; | |
635 | } | |
636 | ||
637 | $entityId = $entityElements['entity_id']; | |
638 | $entityTable = $entityElements['entity_table']; | |
639 | ||
640 | $sql = " | |
dfcbddc8 | 641 | SELECT civicrm_address.id as address_id |
6a488035 TO |
642 | FROM civicrm_loc_block loc, civicrm_location_type ltype, civicrm_address, {$entityTable} ev |
643 | WHERE ev.id = %1 | |
644 | AND loc.id = ev.loc_block_id | |
645 | AND civicrm_address.id IN (loc.address_id, loc.address_2_id) | |
646 | AND ltype.id = civicrm_address.location_type_id | |
647 | ORDER BY civicrm_address.is_primary DESC, civicrm_address.location_type_id DESC, address_id ASC "; | |
648 | ||
649 | $params = array(1 => array($entityId, 'Integer')); | |
6a488035 | 650 | $dao = CRM_Core_DAO::executeQuery($sql, $params); |
dfcbddc8 | 651 | $locationCount = 1; |
6a488035 | 652 | while ($dao->fetch()) { |
dfcbddc8 DG |
653 | $addresses[$locationCount] = $dao->address_id; |
654 | $locationCount++; | |
6a488035 TO |
655 | } |
656 | return $addresses; | |
657 | } | |
658 | ||
6a488035 | 659 | /** |
fe482240 | 660 | * Get address sequence. |
6a488035 | 661 | * |
a6c01b45 | 662 | * @return array |
16b10e64 | 663 | * Array of address sequence. |
6a488035 | 664 | */ |
00be9182 | 665 | public static function addressSequence() { |
6a488035 TO |
666 | $config = CRM_Core_Config::singleton(); |
667 | $addressSequence = $config->addressSequence(); | |
668 | ||
669 | $countryState = $cityPostal = FALSE; | |
670 | foreach ($addressSequence as $key => $field) { | |
671 | if ( | |
672 | in_array($field, array('country', 'state_province')) && | |
673 | !$countryState | |
674 | ) { | |
675 | $countryState = TRUE; | |
676 | $addressSequence[$key] = 'country_state_province'; | |
677 | } | |
678 | elseif ( | |
679 | in_array($field, array('city', 'postal_code')) && | |
680 | !$cityPostal | |
681 | ) { | |
682 | $cityPostal = TRUE; | |
683 | $addressSequence[$key] = 'city_postal_code'; | |
684 | } | |
685 | elseif ( | |
353ffa53 | 686 | in_array($field, array('country', 'state_province', 'city', 'postal_code')) |
6a488035 TO |
687 | ) { |
688 | unset($addressSequence[$key]); | |
689 | } | |
690 | } | |
691 | ||
692 | return $addressSequence; | |
693 | } | |
694 | ||
695 | /** | |
696 | * Parse given street address string in to street_name, | |
697 | * street_unit, street_number and street_number_suffix | |
698 | * eg "54A Excelsior Ave. Apt 1C", or "917 1/2 Elm Street" | |
699 | * | |
700 | * NB: civic street formats for en_CA and fr_CA used by default if those locales are active | |
701 | * otherwise en_US format is default action | |
702 | * | |
6c552737 TO |
703 | * @param string $streetAddress |
704 | * Street address including number and apt. | |
705 | * @param string $locale | |
706 | * Locale used to parse address. | |
6a488035 | 707 | * |
a6c01b45 CW |
708 | * @return array |
709 | * parsed fields values. | |
6a488035 | 710 | */ |
00be9182 | 711 | public static function parseStreetAddress($streetAddress, $locale = NULL) { |
6a488035 TO |
712 | $config = CRM_Core_Config::singleton(); |
713 | ||
714 | /* locales supported include: | |
715 | * en_US - http://pe.usps.com/cpim/ftp/pubs/pub28/pub28.pdf | |
716 | * en_CA - http://www.canadapost.ca/tools/pg/manual/PGaddress-e.asp | |
717 | * fr_CA - http://www.canadapost.ca/tools/pg/manual/PGaddress-f.asp | |
718 | * NB: common use of comma after street number also supported | |
719 | * default is en_US | |
720 | */ | |
721 | ||
722 | $supportedLocalesForParsing = array('en_US', 'en_CA', 'fr_CA'); | |
723 | if (!$locale) { | |
724 | $locale = $config->lcMessages; | |
725 | } | |
726 | // as different locale explicitly requested but is not available, display warning message and set $locale = 'en_US' | |
727 | if (!in_array($locale, $supportedLocalesForParsing)) { | |
728 | CRM_Core_Session::setStatus(ts('Unsupported locale specified to parseStreetAddress: %1. Proceeding with en_US locale.', array(1 => $locale)), ts('Unsupported Locale'), 'alert'); | |
729 | $locale = 'en_US'; | |
730 | } | |
689cecfd | 731 | $emptyParseFields = $parseFields = array( |
6a488035 TO |
732 | 'street_name' => '', |
733 | 'street_unit' => '', | |
734 | 'street_number' => '', | |
735 | 'street_number_suffix' => '', | |
736 | ); | |
737 | ||
738 | if (empty($streetAddress)) { | |
739 | return $parseFields; | |
740 | } | |
741 | ||
742 | $streetAddress = trim($streetAddress); | |
743 | ||
744 | $matches = array(); | |
745 | if (in_array($locale, array( | |
353ffa53 | 746 | 'en_CA', |
af9b09df | 747 | 'fr_CA', |
353ffa53 TO |
748 | )) && preg_match('/^([A-Za-z0-9]+)[ ]*\-[ ]*/', $streetAddress, $matches) |
749 | ) { | |
6a488035 TO |
750 | $parseFields['street_unit'] = $matches[1]; |
751 | // unset from rest of street address | |
752 | $streetAddress = preg_replace('/^([A-Za-z0-9]+)[ ]*\-[ ]*/', '', $streetAddress); | |
753 | } | |
754 | ||
755 | // get street number and suffix. | |
756 | $matches = array(); | |
757 | //alter street number/suffix handling so that we accept -digit | |
758 | if (preg_match('/^[A-Za-z0-9]+([\S]+)/', $streetAddress, $matches)) { | |
759 | // check that $matches[0] is numeric, else assume no street number | |
760 | if (preg_match('/^(\d+)/', $matches[0])) { | |
761 | $streetNumAndSuffix = $matches[0]; | |
762 | ||
763 | // get street number. | |
764 | $matches = array(); | |
765 | if (preg_match('/^(\d+)/', $streetNumAndSuffix, $matches)) { | |
766 | $parseFields['street_number'] = $matches[0]; | |
767 | $suffix = preg_replace('/^(\d+)/', '', $streetNumAndSuffix); | |
768 | $parseFields['street_number_suffix'] = trim($suffix); | |
769 | } | |
770 | ||
771 | // unset from main street address. | |
772 | $streetAddress = preg_replace('/^[A-Za-z0-9]+([\S]+)/', '', $streetAddress); | |
773 | $streetAddress = trim($streetAddress); | |
774 | } | |
775 | } | |
776 | elseif (preg_match('/^(\d+)/', $streetAddress, $matches)) { | |
777 | $parseFields['street_number'] = $matches[0]; | |
778 | // unset from main street address. | |
779 | $streetAddress = preg_replace('/^(\d+)/', '', $streetAddress); | |
780 | $streetAddress = trim($streetAddress); | |
781 | } | |
782 | ||
783 | // suffix might be like 1/2 | |
784 | $matches = array(); | |
785 | if (preg_match('/^\d\/\d/', $streetAddress, $matches)) { | |
786 | $parseFields['street_number_suffix'] .= $matches[0]; | |
787 | ||
788 | // unset from main street address. | |
789 | $streetAddress = preg_replace('/^\d+\/\d+/', '', $streetAddress); | |
790 | $streetAddress = trim($streetAddress); | |
791 | } | |
792 | ||
793 | // now get the street unit. | |
794 | // supportable street unit formats. | |
795 | $streetUnitFormats = array( | |
353ffa53 TO |
796 | 'APT', |
797 | 'APARTMENT', | |
798 | 'BSMT', | |
799 | 'BASEMENT', | |
800 | 'BLDG', | |
801 | 'BUILDING', | |
802 | 'DEPT', | |
803 | 'DEPARTMENT', | |
804 | 'FL', | |
805 | 'FLOOR', | |
806 | 'FRNT', | |
807 | 'FRONT', | |
808 | 'HNGR', | |
809 | 'HANGER', | |
810 | 'LBBY', | |
811 | 'LOBBY', | |
812 | 'LOWR', | |
813 | 'LOWER', | |
814 | 'OFC', | |
815 | 'OFFICE', | |
816 | 'PH', | |
817 | 'PENTHOUSE', | |
818 | 'TRLR', | |
819 | 'TRAILER', | |
820 | 'UPPR', | |
821 | 'RM', | |
822 | 'ROOM', | |
823 | 'SIDE', | |
824 | 'SLIP', | |
825 | 'KEY', | |
826 | 'LOT', | |
827 | 'PIER', | |
828 | 'REAR', | |
829 | 'SPC', | |
830 | 'SPACE', | |
831 | 'STOP', | |
832 | 'STE', | |
833 | 'SUITE', | |
834 | 'UNIT', | |
835 | '#', | |
6a488035 TO |
836 | ); |
837 | ||
838 | // overwriting $streetUnitFormats for 'en_CA' and 'fr_CA' locale | |
839 | if (in_array($locale, array( | |
353ffa53 | 840 | 'en_CA', |
af9b09df | 841 | 'fr_CA', |
353ffa53 | 842 | ))) { |
6a488035 TO |
843 | $streetUnitFormats = array('APT', 'APP', 'SUITE', 'BUREAU', 'UNIT'); |
844 | } | |
689cecfd EM |
845 | //@todo per CRM-14459 this regex picks up words with the string in them - e.g APT picks up |
846 | //Captain - presuming fixing regex (& adding test) to ensure a-z does not preced string will fix | |
6a488035 TO |
847 | $streetUnitPreg = '/(' . implode('|\s', $streetUnitFormats) . ')(.+)?/i'; |
848 | $matches = array(); | |
849 | if (preg_match($streetUnitPreg, $streetAddress, $matches)) { | |
850 | $parseFields['street_unit'] = trim($matches[0]); | |
851 | $streetAddress = str_replace($matches[0], '', $streetAddress); | |
852 | $streetAddress = trim($streetAddress); | |
853 | } | |
854 | ||
855 | // consider remaining string as street name. | |
856 | $parseFields['street_name'] = $streetAddress; | |
857 | ||
858 | //run parsed fields through stripSpaces to clean | |
859 | foreach ($parseFields as $parseField => $value) { | |
860 | $parseFields[$parseField] = CRM_Utils_String::stripSpaces($value); | |
861 | } | |
689cecfd EM |
862 | //CRM-14459 if the field is too long we should assume it didn't get it right & skip rather than allow |
863 | // the DB to fatal | |
864 | $fields = CRM_Core_BAO_Address::fields(); | |
865 | foreach ($fields as $fieldname => $field) { | |
22e263ad | 866 | if (!empty($field['maxlength']) && strlen(CRM_Utils_Array::value($fieldname, $parseFields)) > $field['maxlength']) { |
689cecfd EM |
867 | return $emptyParseFields; |
868 | } | |
869 | } | |
6a488035 TO |
870 | |
871 | return $parseFields; | |
872 | } | |
873 | ||
874 | /** | |
eceb18cc | 875 | * Validate the address fields based on the address options enabled. |
6a488035 TO |
876 | * in the Address Settings |
877 | * | |
6a0b768e TO |
878 | * @param array $fields |
879 | * An array of importable/exportable contact fields. | |
6a488035 | 880 | * |
a6c01b45 CW |
881 | * @return array |
882 | * an array of contact fields and only the enabled address options | |
6a488035 | 883 | */ |
00be9182 | 884 | public static function validateAddressOptions($fields) { |
6a488035 TO |
885 | static $addressOptions = NULL; |
886 | if (!$addressOptions) { | |
6c552737 TO |
887 | $addressOptions = CRM_Core_BAO_Setting::valueOptions( |
888 | CRM_Core_BAO_Setting::SYSTEM_PREFERENCES_NAME, | |
889 | 'address_options' | |
890 | ); | |
6a488035 TO |
891 | } |
892 | ||
893 | if (is_array($fields) && !empty($fields)) { | |
894 | foreach ($addressOptions as $key => $value) { | |
895 | if (!$value && isset($fields[$key])) { | |
896 | unset($fields[$key]); | |
897 | } | |
898 | } | |
899 | } | |
900 | return $fields; | |
901 | } | |
902 | ||
903 | /** | |
fe482240 | 904 | * Check if current address is used by any other contacts. |
6a488035 | 905 | * |
6a0b768e TO |
906 | * @param int $addressId |
907 | * Address id. | |
6a488035 | 908 | * |
72b3a70c CW |
909 | * @return int |
910 | * count of contacts that use this shared address | |
6a488035 | 911 | */ |
00be9182 | 912 | public static function checkContactSharedAddress($addressId) { |
6a488035 TO |
913 | $query = 'SELECT count(id) FROM civicrm_address WHERE master_id = %1'; |
914 | return CRM_Core_DAO::singleValueQuery($query, array(1 => array($addressId, 'Integer'))); | |
915 | } | |
916 | ||
917 | /** | |
fe482240 | 918 | * Check if current address fields are shared with any other address. |
6a488035 | 919 | * |
6a0b768e TO |
920 | * @param array $fields |
921 | * Address fields in profile. | |
922 | * @param int $contactId | |
923 | * Contact id. | |
6a488035 | 924 | * |
6a488035 | 925 | */ |
00be9182 | 926 | public static function checkContactSharedAddressFields(&$fields, $contactId) { |
6a488035 TO |
927 | if (!$contactId || !is_array($fields) || empty($fields)) { |
928 | return; | |
929 | } | |
930 | ||
931 | $sharedLocations = array(); | |
932 | ||
933 | $query = " | |
934 | SELECT is_primary, | |
935 | location_type_id | |
936 | FROM civicrm_address | |
937 | WHERE contact_id = %1 | |
938 | AND master_id IS NOT NULL"; | |
939 | ||
940 | $dao = CRM_Core_DAO::executeQuery($query, array(1 => array($contactId, 'Positive'))); | |
941 | while ($dao->fetch()) { | |
942 | $sharedLocations[$dao->location_type_id] = $dao->location_type_id; | |
943 | if ($dao->is_primary) { | |
944 | $sharedLocations['Primary'] = 'Primary'; | |
945 | } | |
946 | } | |
947 | ||
948 | //no need to process further. | |
949 | if (empty($sharedLocations)) { | |
950 | return; | |
951 | } | |
952 | ||
953 | $addressFields = array( | |
954 | 'city', | |
955 | 'county', | |
956 | 'country', | |
957 | 'geo_code_1', | |
958 | 'geo_code_2', | |
959 | 'postal_code', | |
960 | 'address_name', | |
961 | 'state_province', | |
962 | 'street_address', | |
963 | 'postal_code_suffix', | |
964 | 'supplemental_address_1', | |
965 | 'supplemental_address_2', | |
966 | ); | |
967 | ||
968 | foreach ($fields as $name => & $values) { | |
969 | if (!is_array($values) || empty($values)) { | |
970 | continue; | |
971 | } | |
972 | ||
973 | $nameVal = explode('-', $values['name']); | |
974 | $fldName = CRM_Utils_Array::value(0, $nameVal); | |
975 | $locType = CRM_Utils_Array::value(1, $nameVal); | |
a7488080 | 976 | if (!empty($values['location_type_id'])) { |
6a488035 TO |
977 | $locType = $values['location_type_id']; |
978 | } | |
979 | ||
980 | if (in_array($fldName, $addressFields) && | |
981 | in_array($locType, $sharedLocations) | |
982 | ) { | |
983 | $values['is_shared'] = TRUE; | |
984 | } | |
985 | } | |
986 | } | |
987 | ||
988 | /** | |
fe482240 | 989 | * Update the shared addresses if master address is modified. |
6a488035 | 990 | * |
6a0b768e TO |
991 | * @param int $addressId |
992 | * Address id. | |
993 | * @param array $params | |
994 | * Associated array of address params. | |
6a488035 | 995 | */ |
00be9182 | 996 | public static function processSharedAddress($addressId, $params) { |
6a488035 TO |
997 | $query = 'SELECT id FROM civicrm_address WHERE master_id = %1'; |
998 | $dao = CRM_Core_DAO::executeQuery($query, array(1 => array($addressId, 'Integer'))); | |
999 | ||
1000 | // unset contact id | |
1001 | $skipFields = array('is_primary', 'location_type_id', 'is_billing', 'master_id', 'contact_id'); | |
1002 | foreach ($skipFields as $value) { | |
1003 | unset($params[$value]); | |
1004 | } | |
1005 | ||
1006 | $addressDAO = new CRM_Core_DAO_Address(); | |
1007 | while ($dao->fetch()) { | |
1008 | $addressDAO->copyValues($params); | |
1009 | $addressDAO->id = $dao->id; | |
1010 | $addressDAO->save(); | |
1011 | $addressDAO->free(); | |
1012 | } | |
1013 | } | |
1014 | ||
8bdfc216 | 1015 | /** |
fe482240 | 1016 | * Merge contacts with the Same address to get one shared label. |
6a0b768e TO |
1017 | * @param array $rows |
1018 | * Array[contact_id][contactDetails]. | |
8bdfc216 | 1019 | */ |
1020 | public static function mergeSameAddress(&$rows) { | |
1021 | $uniqueAddress = array(); | |
1022 | foreach (array_keys($rows) as $rowID) { | |
1023 | // load complete address as array key | |
6c552737 TO |
1024 | $address = trim($rows[$rowID]['street_address']) |
1025 | . trim($rows[$rowID]['city']) | |
1026 | . trim($rows[$rowID]['state_province']) | |
1027 | . trim($rows[$rowID]['postal_code']) | |
1028 | . trim($rows[$rowID]['country']); | |
8bdfc216 | 1029 | if (isset($rows[$rowID]['last_name'])) { |
1030 | $name = $rows[$rowID]['last_name']; | |
1031 | } | |
1032 | else { | |
1033 | $name = $rows[$rowID]['display_name']; | |
1034 | } | |
1035 | ||
1036 | // CRM-15120 | |
1037 | $formatted = array( | |
1038 | 'first_name' => $rows[$rowID]['first_name'], | |
21dfd5f5 | 1039 | 'individual_prefix' => $rows[$rowID]['individual_prefix'], |
8bdfc216 | 1040 | ); |
aaffa79f | 1041 | $format = Civi::settings()->get('display_name_format'); |
8bdfc216 | 1042 | $firstNameWithPrefix = CRM_Utils_Address::format($formatted, $format, FALSE, FALSE, TRUE); |
1043 | $firstNameWithPrefix = trim($firstNameWithPrefix); | |
1044 | ||
1045 | // fill uniqueAddress array with last/first name tree | |
1046 | if (isset($uniqueAddress[$address])) { | |
1047 | $uniqueAddress[$address]['names'][$name][$firstNameWithPrefix]['first_name'] = $rows[$rowID]['first_name']; | |
1048 | $uniqueAddress[$address]['names'][$name][$firstNameWithPrefix]['addressee_display'] = $rows[$rowID]['addressee_display']; | |
1049 | // drop unnecessary rows | |
1050 | unset($rows[$rowID]); | |
1051 | // this is the first listing at this address | |
1052 | } | |
1053 | else { | |
1054 | $uniqueAddress[$address]['ID'] = $rowID; | |
1055 | $uniqueAddress[$address]['names'][$name][$firstNameWithPrefix]['first_name'] = $rows[$rowID]['first_name']; | |
1056 | $uniqueAddress[$address]['names'][$name][$firstNameWithPrefix]['addressee_display'] = $rows[$rowID]['addressee_display']; | |
1057 | } | |
1058 | } | |
1059 | foreach ($uniqueAddress as $address => $data) { | |
1060 | // copy data back to $rows | |
1061 | $count = 0; | |
1062 | // one last name list per row | |
1063 | foreach ($data['names'] as $last_name => $first_names) { | |
1064 | // too many to list | |
1065 | if ($count > 2) { | |
1066 | break; | |
1067 | } | |
9b873358 | 1068 | if (count($first_names) == 1) { |
2aa397bc TO |
1069 | $family = $first_names[current(array_keys($first_names))]['addressee_display']; |
1070 | } | |
1071 | else { | |
1072 | // collapse the tree to summarize | |
1073 | $family = trim(implode(" & ", array_keys($first_names)) . " " . $last_name); | |
1074 | } | |
1075 | if ($count) { | |
1076 | $processedNames .= "\n" . $family; | |
1077 | } | |
1078 | else { | |
1079 | // build display_name string | |
1080 | $processedNames = $family; | |
1081 | } | |
8bdfc216 | 1082 | $count++; |
1083 | } | |
1084 | $rows[$data['ID']]['addressee'] = $rows[$data['ID']]['addressee_display'] = $rows[$data['ID']]['display_name'] = $processedNames; | |
1085 | } | |
1086 | } | |
1087 | ||
6a488035 | 1088 | /** |
fe482240 | 1089 | * Create relationship between contacts who share an address. |
6a488035 TO |
1090 | * |
1091 | * Note that currently we create relationship only for Individual contacts | |
1092 | * Individual + Household and Individual + Orgnization | |
1093 | * | |
6a0b768e TO |
1094 | * @param int $masterAddressId |
1095 | * Master address id. | |
1096 | * @param array $params | |
1097 | * Associated array of submitted values. | |
6a488035 | 1098 | */ |
00be9182 | 1099 | public static function processSharedAddressRelationship($masterAddressId, $params) { |
6a488035 TO |
1100 | // get the contact type of contact being edited / created |
1101 | $currentContactType = CRM_Contact_BAO_Contact::getContactType($params['contact_id']); | |
1102 | $currentContactId = $params['contact_id']; | |
1103 | ||
1104 | // if current contact is not of type individual return | |
1105 | if ($currentContactType != 'Individual') { | |
1106 | return; | |
1107 | } | |
1108 | ||
1109 | // get the contact id and contact type of shared contact | |
1110 | // check the contact type of shared contact, return if it is of type Individual | |
6a488035 TO |
1111 | $query = 'SELECT cc.id, cc.contact_type |
1112 | FROM civicrm_contact cc INNER JOIN civicrm_address ca ON cc.id = ca.contact_id | |
1113 | WHERE ca.id = %1'; | |
1114 | ||
1115 | $dao = CRM_Core_DAO::executeQuery($query, array(1 => array($masterAddressId, 'Integer'))); | |
6a488035 TO |
1116 | $dao->fetch(); |
1117 | ||
1118 | // if current contact is not of type individual return, since we don't create relationship between | |
1119 | // 2 individuals | |
1120 | if ($dao->contact_type == 'Individual') { | |
1121 | return; | |
1122 | } | |
1123 | $sharedContactType = $dao->contact_type; | |
1124 | $sharedContactId = $dao->id; | |
1125 | ||
1126 | // create relationship between ontacts who share an address | |
1127 | if ($sharedContactType == 'Organization') { | |
1128 | return CRM_Contact_BAO_Contact_Utils::createCurrentEmployerRelationship($currentContactId, $sharedContactId); | |
1129 | } | |
6a488035 | 1130 | |
82ffeed5 | 1131 | // get the relationship type id of "Household Member of" |
1132 | $relTypeId = CRM_Core_DAO::getFieldValue('CRM_Contact_DAO_RelationshipType', 'Household Member of', 'id', 'name_a_b'); | |
6a488035 TO |
1133 | |
1134 | if (!$relTypeId) { | |
82ffeed5 | 1135 | CRM_Core_Error::fatal(ts("You seem to have deleted the relationship type 'Household Member of'")); |
1136 | } | |
1137 | ||
1138 | $relParam = array( | |
1139 | 'is_active' => TRUE, | |
1140 | 'relationship_type_id' => $relTypeId, | |
1141 | 'contact_id_a' => $currentContactId, | |
1142 | 'contact_id_b' => $sharedContactId, | |
1143 | ); | |
1144 | ||
1145 | // If already there is a relationship record of $relParam criteria, avoid creating relationship again or else | |
1146 | // it will casue CRM-16588 as the Duplicate Relationship Exception will revert other contact field values on update | |
9272d8b5 | 1147 | if (CRM_Contact_BAO_Relationship::checkDuplicateRelationship($relParam, $currentContactId, $sharedContactId)) { |
82ffeed5 | 1148 | return; |
6a488035 TO |
1149 | } |
1150 | ||
a7ef8c9d EM |
1151 | try { |
1152 | // create relationship | |
82ffeed5 | 1153 | civicrm_api3('relationship', 'create', $relParam); |
a7ef8c9d EM |
1154 | } |
1155 | catch (CiviCRM_API3_Exception $e) { | |
1156 | // We catch and ignore here because this has historically been a best-effort relationship create call. | |
1157 | // presumably it could refuse due to duplication or similar and we would ignore that. | |
1158 | } | |
6a488035 TO |
1159 | } |
1160 | ||
1161 | /** | |
fe482240 | 1162 | * Check and set the status for shared address delete. |
6a488035 | 1163 | * |
6a0b768e TO |
1164 | * @param int $addressId |
1165 | * Address id. | |
1166 | * @param int $contactId | |
1167 | * Contact id. | |
1168 | * @param bool $returnStatus | |
1169 | * By default false. | |
6a488035 | 1170 | * |
a6c01b45 | 1171 | * @return string |
6a488035 | 1172 | */ |
00be9182 | 1173 | public static function setSharedAddressDeleteStatus($addressId = NULL, $contactId = NULL, $returnStatus = FALSE) { |
6a488035 TO |
1174 | // check if address that is being deleted has any shared |
1175 | if ($addressId) { | |
1176 | $entityId = $addressId; | |
1177 | $query = 'SELECT cc.id, cc.display_name | |
1178 | FROM civicrm_contact cc INNER JOIN civicrm_address ca ON cc.id = ca.contact_id | |
1179 | WHERE ca.master_id = %1'; | |
1180 | } | |
1181 | else { | |
1182 | $entityId = $contactId; | |
1183 | $query = 'SELECT cc.id, cc.display_name | |
1184 | FROM civicrm_address ca1 | |
1185 | INNER JOIN civicrm_address ca2 ON ca1.id = ca2.master_id | |
1186 | INNER JOIN civicrm_contact cc ON ca2.contact_id = cc.id | |
1187 | WHERE ca1.contact_id = %1'; | |
1188 | } | |
1189 | ||
1190 | $dao = CRM_Core_DAO::executeQuery($query, array(1 => array($entityId, 'Integer'))); | |
1191 | ||
1192 | $deleteStatus = array(); | |
1193 | $sharedContactList = array(); | |
1194 | $statusMessage = NULL; | |
1195 | $addressCount = 0; | |
1196 | while ($dao->fetch()) { | |
1197 | if (empty($deleteStatus)) { | |
1198 | $deleteStatus[] = ts('The following contact(s) have address records which were shared with the address you removed from this contact. These address records are no longer shared - but they have not been removed or altered.'); | |
1199 | } | |
1200 | ||
1201 | $contactViewUrl = CRM_Utils_System::url('civicrm/contact/view', "reset=1&cid={$dao->id}"); | |
1202 | $sharedContactList[] = "<a href='{$contactViewUrl}'>{$dao->display_name}</a>"; | |
1203 | $deleteStatus[] = "<a href='{$contactViewUrl}'>{$dao->display_name}</a>"; | |
1204 | ||
1205 | $addressCount++; | |
1206 | } | |
1207 | ||
1208 | if (!empty($deleteStatus)) { | |
1209 | $statusMessage = implode('<br/>', $deleteStatus) . '<br/>'; | |
1210 | } | |
1211 | ||
1212 | if (!$returnStatus) { | |
1213 | CRM_Core_Session::setStatus($statusMessage, '', 'info'); | |
1214 | } | |
1215 | else { | |
1216 | return array( | |
1217 | 'contactList' => $sharedContactList, | |
1218 | 'count' => $addressCount, | |
1219 | ); | |
1220 | } | |
1221 | } | |
12445e1c CW |
1222 | |
1223 | /** | |
fe482240 | 1224 | * Call common delete function. |
ad37ac8e | 1225 | * |
1226 | * @param int $id | |
1227 | * | |
1228 | * @return bool | |
12445e1c | 1229 | */ |
00be9182 | 1230 | public static function del($id) { |
a65e2e55 | 1231 | return CRM_Contact_BAO_Contact::deleteObjectWithPrimary('Address', $id); |
12445e1c | 1232 | } |
dc86f881 CW |
1233 | |
1234 | /** | |
1235 | * Get options for a given address field. | |
1236 | * @see CRM_Core_DAO::buildOptions | |
1237 | * | |
1238 | * TODO: Should we always assume chainselect? What fn should be responsible for controlling that flow? | |
1239 | * TODO: In context of chainselect, what to return if e.g. a country has no states? | |
1240 | * | |
6a0b768e TO |
1241 | * @param string $fieldName |
1242 | * @param string $context | |
a1a2a83d | 1243 | * @see CRM_Core_DAO::buildOptionsContext |
6a0b768e | 1244 | * @param array $props |
16b10e64 | 1245 | * whatever is known about this dao object. |
77b97be7 | 1246 | * |
5c766a0b | 1247 | * @return array|bool |
dc86f881 CW |
1248 | */ |
1249 | public static function buildOptions($fieldName, $context = NULL, $props = array()) { | |
1250 | $params = array(); | |
1251 | // Special logic for fields whose options depend on context or properties | |
1252 | switch ($fieldName) { | |
1253 | // Filter state_province list based on chosen country or site defaults | |
1254 | case 'state_province_id': | |
d0bfb983 | 1255 | case 'state_province_name': |
1256 | case 'state_province': | |
1257 | // change $fieldName to DB specific names. | |
1258 | $fieldName = 'state_province_id'; | |
dc86f881 CW |
1259 | if (empty($props['country_id'])) { |
1260 | $config = CRM_Core_Config::singleton(); | |
1261 | if (!empty($config->provinceLimit)) { | |
1262 | $props['country_id'] = $config->provinceLimit; | |
1263 | } | |
1264 | else { | |
1265 | $props['country_id'] = $config->defaultContactCountry; | |
1266 | } | |
1267 | } | |
578d346d | 1268 | if (!empty($props['country_id']) && $context !== 'validate') { |
dc86f881 CW |
1269 | $params['condition'] = 'country_id IN (' . implode(',', (array) $props['country_id']) . ')'; |
1270 | } | |
1271 | break; | |
2aa397bc | 1272 | |
dc86f881 CW |
1273 | // Filter country list based on site defaults |
1274 | case 'country_id': | |
d0bfb983 | 1275 | case 'country': |
1276 | // change $fieldName to DB specific names. | |
1277 | $fieldName = 'country_id'; | |
786ad6e1 CW |
1278 | if ($context != 'get' && $context != 'validate') { |
1279 | $config = CRM_Core_Config::singleton(); | |
1280 | if (!empty($config->countryLimit) && is_array($config->countryLimit)) { | |
1281 | $params['condition'] = 'id IN (' . implode(',', $config->countryLimit) . ')'; | |
1282 | } | |
dc86f881 CW |
1283 | } |
1284 | break; | |
2aa397bc | 1285 | |
dc86f881 CW |
1286 | // Filter county list based on chosen state |
1287 | case 'county_id': | |
1288 | if (!empty($props['state_province_id'])) { | |
1289 | $params['condition'] = 'state_province_id IN (' . implode(',', (array) $props['state_province_id']) . ')'; | |
1290 | } | |
1291 | break; | |
2aa397bc | 1292 | |
c7130c3e CW |
1293 | // Not a real field in this entity |
1294 | case 'world_region': | |
3493947a | 1295 | case 'worldregion': |
1296 | case 'worldregion_id': | |
c7130c3e | 1297 | return CRM_Core_PseudoConstant::worldRegion(); |
dc86f881 | 1298 | } |
786ad6e1 | 1299 | return CRM_Core_PseudoConstant::get(__CLASS__, $fieldName, $params, $context); |
dc86f881 | 1300 | } |
96025800 | 1301 | |
a7488080 | 1302 | } |