Merge pull request #10638 from mattwire/CRM-20772_statusbounce
[civicrm-core.git] / CRM / Core / BAO / Address.php
CommitLineData
6a488035 1<?php
6a488035
TO
2/*
3 +--------------------------------------------------------------------+
7e9e8871 4 | CiviCRM version 4.7 |
6a488035 5 +--------------------------------------------------------------------+
0f03f337 6 | Copyright CiviCRM LLC (c) 2004-2017 |
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
0f03f337 31 * @copyright CiviCRM LLC (c) 2004-2017
6a488035
TO
32 */
33
34/**
192d36c5 35 * This is class to handle address related functions.
6a488035
TO
36 */
37class 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
b48c1467
WDC
381 // check if geocode should be skipped (can be forced with an optional parameter through the api)
382 $skip_geocode = (isset($params['skip_geocode']) && $params['skip_geocode']) ? TRUE : FALSE;
383
6a488035 384 // add latitude and longitude and format address if needed
b48c1467 385 if (!$skip_geocode && !empty($config->geocodeMethod) && ($config->geocodeMethod != 'CRM_Utils_Geocode_OpenStreetMaps') && empty($params['manual_geo_code'])) {
6a488035
TO
386 $class = $config->geocodeMethod;
387 $class::format($params);
388 }
389 }
390
391 /**
fe482240 392 * Check if there is data to create the object.
6a488035 393 *
6a0b768e
TO
394 * @param array $params
395 * (reference ) an assoc array of name/value pairs.
6a488035 396 *
5c766a0b 397 * @return bool
6a488035 398 */
00be9182 399 public static function dataExists(&$params) {
6a488035
TO
400 //check if location type is set if not return false
401 if (!isset($params['location_type_id'])) {
402 return FALSE;
403 }
404
405 $config = CRM_Core_Config::singleton();
406 foreach ($params as $name => $value) {
407 if (in_array($name, array(
353ffa53
TO
408 'is_primary',
409 'location_type_id',
410 'id',
411 'contact_id',
412 'is_billing',
413 'display',
af9b09df 414 'master_id',
353ffa53 415 ))) {
6a488035
TO
416 continue;
417 }
418 elseif (!CRM_Utils_System::isNull($value)) {
419 // name could be country or country id
420 if (substr($name, 0, 7) == 'country') {
421 // make sure its different from the default country
422 // iso code
423 $defaultCountry = $config->defaultContactCountry();
424 // full name
425 $defaultCountryName = $config->defaultContactCountryName();
426
427 if ($defaultCountry) {
428 if ($value == $defaultCountry ||
429 $value == $defaultCountryName ||
430 $value == $config->defaultContactCountry
431 ) {
432 // do nothing
433 }
434 else {
435 return TRUE;
436 }
437 }
438 else {
439 // return if null default
440 return TRUE;
441 }
442 }
443 else {
444 return TRUE;
445 }
446 }
447 }
448
449 return FALSE;
450 }
451
452 /**
453 * Given the list of params in the params array, fetch the object
454 * and store the values in the values array
455 *
6a0b768e
TO
456 * @param array $entityBlock
457 * Associated array of fields.
458 * @param bool $microformat
459 * If microformat output is required.
e63aff1c 460 * @param int|string $fieldName conditional field name
6a488035 461 *
a6c01b45
CW
462 * @return array
463 * array with address fields
6a488035 464 */
00be9182 465 public static function &getValues($entityBlock, $microformat = FALSE, $fieldName = 'contact_id') {
6a488035
TO
466 if (empty($entityBlock)) {
467 return NULL;
468 }
469 $addresses = array();
470 $address = new CRM_Core_BAO_Address();
471
a7488080 472 if (empty($entityBlock['entity_table'])) {
6a488035
TO
473 $address->$fieldName = CRM_Utils_Array::value($fieldName, $entityBlock);
474 }
475 else {
476 $addressIds = array();
477 $addressIds = self::allEntityAddress($entityBlock);
478
479 if (!empty($addressIds[1])) {
480 $address->id = $addressIds[1];
481 }
482 else {
483 return $addresses;
484 }
485 }
001a6635
JV
486 if (isset($entityBlock['is_billing']) && $entityBlock['is_billing'] == 1) {
487 $address->orderBy('is_billing desc, id');
488 }
489 else {
490 //get primary address as a first block.
491 $address->orderBy('is_primary desc, id');
492 }
6a488035
TO
493
494 $address->find();
495
ac44bb1c 496 $locationTypes = CRM_Core_PseudoConstant::get('CRM_Core_DAO_Address', 'location_type_id');
6a488035
TO
497 $count = 1;
498 while ($address->fetch()) {
499 // deprecate reference.
500 if ($count > 1) {
501 foreach (array(
353ffa53
TO
502 'state',
503 'state_name',
504 'country',
af9b09df 505 'world_region',
353ffa53 506 ) as $fld) {
4f99ca55
TO
507 if (isset($address->$fld)) {
508 unset($address->$fld);
2aa397bc 509 }
6a488035
TO
510 }
511 }
512 $stree = $address->street_address;
513 $values = array();
514 CRM_Core_DAO::storeValues($address, $values);
515
516 // add state and country information: CRM-369
ac44bb1c
WA
517 if (!empty($address->location_type_id)) {
518 $values['location_type'] = CRM_Utils_Array::value($address->location_type_id, $locationTypes);
519 }
6a488035
TO
520 if (!empty($address->state_province_id)) {
521 $address->state = CRM_Core_PseudoConstant::stateProvinceAbbreviation($address->state_province_id, FALSE);
522 $address->state_name = CRM_Core_PseudoConstant::stateProvince($address->state_province_id, FALSE);
523 }
524
525 if (!empty($address->country_id)) {
526 $address->country = CRM_Core_PseudoConstant::country($address->country_id);
527
528 //get world region
529 $regionId = CRM_Core_DAO::getFieldValue('CRM_Core_DAO_Country', $address->country_id, 'region_id');
530
531 $address->world_region = CRM_Core_PseudoConstant::worldregion($regionId);
532 }
533
534 $address->addDisplay($microformat);
535
536 $values['display'] = $address->display;
537 $values['display_text'] = $address->display_text;
538
539 if (is_numeric($address->master_id)) {
540 $values['use_shared_address'] = 1;
541 }
542
543 $addresses[$count] = $values;
544
545 //unset is_primary after first block. Due to some bug in earlier version
546 //there might be more than one primary blocks, hence unset is_primary other than first
547 if ($count > 1) {
548 unset($addresses[$count]['is_primary']);
549 }
550
551 $count++;
552 }
553
554 return $addresses;
555 }
556
557 /**
192d36c5 558 * Add the formatted address to $this-> display.
6a488035 559 *
2a6da8d7 560 * @param bool $microformat
192d36c5 561 * Unexplained parameter that I've always wondered about.
6a488035 562 */
00be9182 563 public function addDisplay($microformat = FALSE) {
6a488035
TO
564 $fields = array(
565 // added this for CRM 1200
566 'address_id' => $this->id,
567 // CRM-4003
568 'address_name' => str_replace('\ 1', ' ', $this->name),
569 'street_address' => $this->street_address,
570 'supplemental_address_1' => $this->supplemental_address_1,
571 'supplemental_address_2' => $this->supplemental_address_2,
207f62c6 572 'supplemental_address_3' => $this->supplemental_address_3,
6a488035
TO
573 'city' => $this->city,
574 'state_province_name' => isset($this->state_name) ? $this->state_name : "",
575 'state_province' => isset($this->state) ? $this->state : "",
576 'postal_code' => isset($this->postal_code) ? $this->postal_code : "",
577 'postal_code_suffix' => isset($this->postal_code_suffix) ? $this->postal_code_suffix : "",
578 'country' => isset($this->country) ? $this->country : "",
579 'world_region' => isset($this->world_region) ? $this->world_region : "",
580 );
581
582 if (isset($this->county_id) && $this->county_id) {
583 $fields['county'] = CRM_Core_PseudoConstant::county($this->county_id);
584 }
585 else {
586 $fields['county'] = NULL;
587 }
588
589 $this->display = CRM_Utils_Address::format($fields, NULL, $microformat);
590 $this->display_text = CRM_Utils_Address::format($fields);
591 }
592
593 /**
594 * Get all the addresses for a specified contact_id, with the primary address being first
595 *
6a0b768e
TO
596 * @param int $id
597 * The contact id.
6a488035 598 *
dfcbddc8
DG
599 * @param bool $updateBlankLocInfo
600 *
a6c01b45 601 * @return array
dfcbddc8 602 * the array of adrress data
6a488035 603 */
dfcbddc8 604 public static function allAddress($id, $updateBlankLocInfo = FALSE) {
6a488035
TO
605 if (!$id) {
606 return NULL;
607 }
608
609 $query = "
610SELECT civicrm_address.id as address_id, civicrm_address.location_type_id as location_type_id
611FROM civicrm_contact, civicrm_address
612WHERE civicrm_address.contact_id = civicrm_contact.id AND civicrm_contact.id = %1
613ORDER BY civicrm_address.is_primary DESC, address_id ASC";
76034cf5 614 $params = array(1 => array($id, 'Integer'));
dfcbddc8
DG
615
616 $addresses = array();
6a488035 617 $dao = CRM_Core_DAO::executeQuery($query, $params);
dfcbddc8 618 $count = 1;
6a488035 619 while ($dao->fetch()) {
dfcbddc8
DG
620 if ($updateBlankLocInfo) {
621 $addresses[$count++] = $dao->address_id;
622 }
623 else {
624 $addresses[$dao->location_type_id] = $dao->address_id;
625 }
6a488035
TO
626 }
627 return $addresses;
628 }
629
630 /**
631 * Get all the addresses for a specified location_block id, with the primary address being first
632 *
6a0b768e
TO
633 * @param array $entityElements
634 * The array containing entity_id and.
16b10e64 635 * entity_table name
6a488035 636 *
a6c01b45 637 * @return array
dfcbddc8 638 * the array of adrress data
6a488035 639 */
00be9182 640 public static function allEntityAddress(&$entityElements) {
c927c151 641 $addresses = array();
6a488035
TO
642 if (empty($entityElements)) {
643 return $addresses;
644 }
645
646 $entityId = $entityElements['entity_id'];
647 $entityTable = $entityElements['entity_table'];
648
649 $sql = "
dfcbddc8 650SELECT civicrm_address.id as address_id
6a488035
TO
651FROM civicrm_loc_block loc, civicrm_location_type ltype, civicrm_address, {$entityTable} ev
652WHERE ev.id = %1
653 AND loc.id = ev.loc_block_id
654 AND civicrm_address.id IN (loc.address_id, loc.address_2_id)
655 AND ltype.id = civicrm_address.location_type_id
656ORDER BY civicrm_address.is_primary DESC, civicrm_address.location_type_id DESC, address_id ASC ";
657
658 $params = array(1 => array($entityId, 'Integer'));
6a488035 659 $dao = CRM_Core_DAO::executeQuery($sql, $params);
dfcbddc8 660 $locationCount = 1;
6a488035 661 while ($dao->fetch()) {
dfcbddc8
DG
662 $addresses[$locationCount] = $dao->address_id;
663 $locationCount++;
6a488035
TO
664 }
665 return $addresses;
666 }
667
6a488035 668 /**
fe482240 669 * Get address sequence.
6a488035 670 *
a6c01b45 671 * @return array
16b10e64 672 * Array of address sequence.
6a488035 673 */
00be9182 674 public static function addressSequence() {
6a488035
TO
675 $config = CRM_Core_Config::singleton();
676 $addressSequence = $config->addressSequence();
677
678 $countryState = $cityPostal = FALSE;
679 foreach ($addressSequence as $key => $field) {
680 if (
681 in_array($field, array('country', 'state_province')) &&
682 !$countryState
683 ) {
684 $countryState = TRUE;
685 $addressSequence[$key] = 'country_state_province';
686 }
687 elseif (
688 in_array($field, array('city', 'postal_code')) &&
689 !$cityPostal
690 ) {
691 $cityPostal = TRUE;
692 $addressSequence[$key] = 'city_postal_code';
693 }
694 elseif (
353ffa53 695 in_array($field, array('country', 'state_province', 'city', 'postal_code'))
6a488035
TO
696 ) {
697 unset($addressSequence[$key]);
698 }
699 }
700
701 return $addressSequence;
702 }
703
704 /**
705 * Parse given street address string in to street_name,
706 * street_unit, street_number and street_number_suffix
707 * eg "54A Excelsior Ave. Apt 1C", or "917 1/2 Elm Street"
708 *
709 * NB: civic street formats for en_CA and fr_CA used by default if those locales are active
710 * otherwise en_US format is default action
711 *
6c552737
TO
712 * @param string $streetAddress
713 * Street address including number and apt.
714 * @param string $locale
715 * Locale used to parse address.
6a488035 716 *
a6c01b45
CW
717 * @return array
718 * parsed fields values.
6a488035 719 */
00be9182 720 public static function parseStreetAddress($streetAddress, $locale = NULL) {
6a488035
TO
721 $config = CRM_Core_Config::singleton();
722
723 /* locales supported include:
724 * en_US - http://pe.usps.com/cpim/ftp/pubs/pub28/pub28.pdf
725 * en_CA - http://www.canadapost.ca/tools/pg/manual/PGaddress-e.asp
726 * fr_CA - http://www.canadapost.ca/tools/pg/manual/PGaddress-f.asp
727 * NB: common use of comma after street number also supported
728 * default is en_US
729 */
730
731 $supportedLocalesForParsing = array('en_US', 'en_CA', 'fr_CA');
732 if (!$locale) {
733 $locale = $config->lcMessages;
734 }
735 // as different locale explicitly requested but is not available, display warning message and set $locale = 'en_US'
736 if (!in_array($locale, $supportedLocalesForParsing)) {
737 CRM_Core_Session::setStatus(ts('Unsupported locale specified to parseStreetAddress: %1. Proceeding with en_US locale.', array(1 => $locale)), ts('Unsupported Locale'), 'alert');
738 $locale = 'en_US';
739 }
689cecfd 740 $emptyParseFields = $parseFields = array(
6a488035
TO
741 'street_name' => '',
742 'street_unit' => '',
743 'street_number' => '',
744 'street_number_suffix' => '',
745 );
746
747 if (empty($streetAddress)) {
748 return $parseFields;
749 }
750
751 $streetAddress = trim($streetAddress);
752
753 $matches = array();
754 if (in_array($locale, array(
353ffa53 755 'en_CA',
af9b09df 756 'fr_CA',
353ffa53
TO
757 )) && preg_match('/^([A-Za-z0-9]+)[ ]*\-[ ]*/', $streetAddress, $matches)
758 ) {
6a488035
TO
759 $parseFields['street_unit'] = $matches[1];
760 // unset from rest of street address
761 $streetAddress = preg_replace('/^([A-Za-z0-9]+)[ ]*\-[ ]*/', '', $streetAddress);
762 }
763
764 // get street number and suffix.
765 $matches = array();
766 //alter street number/suffix handling so that we accept -digit
767 if (preg_match('/^[A-Za-z0-9]+([\S]+)/', $streetAddress, $matches)) {
768 // check that $matches[0] is numeric, else assume no street number
769 if (preg_match('/^(\d+)/', $matches[0])) {
770 $streetNumAndSuffix = $matches[0];
771
772 // get street number.
773 $matches = array();
774 if (preg_match('/^(\d+)/', $streetNumAndSuffix, $matches)) {
775 $parseFields['street_number'] = $matches[0];
776 $suffix = preg_replace('/^(\d+)/', '', $streetNumAndSuffix);
777 $parseFields['street_number_suffix'] = trim($suffix);
778 }
779
780 // unset from main street address.
781 $streetAddress = preg_replace('/^[A-Za-z0-9]+([\S]+)/', '', $streetAddress);
782 $streetAddress = trim($streetAddress);
783 }
784 }
785 elseif (preg_match('/^(\d+)/', $streetAddress, $matches)) {
786 $parseFields['street_number'] = $matches[0];
787 // unset from main street address.
788 $streetAddress = preg_replace('/^(\d+)/', '', $streetAddress);
789 $streetAddress = trim($streetAddress);
790 }
791
792 // suffix might be like 1/2
793 $matches = array();
794 if (preg_match('/^\d\/\d/', $streetAddress, $matches)) {
795 $parseFields['street_number_suffix'] .= $matches[0];
796
797 // unset from main street address.
798 $streetAddress = preg_replace('/^\d+\/\d+/', '', $streetAddress);
799 $streetAddress = trim($streetAddress);
800 }
801
802 // now get the street unit.
803 // supportable street unit formats.
804 $streetUnitFormats = array(
353ffa53
TO
805 'APT',
806 'APARTMENT',
807 'BSMT',
808 'BASEMENT',
809 'BLDG',
810 'BUILDING',
811 'DEPT',
812 'DEPARTMENT',
813 'FL',
814 'FLOOR',
815 'FRNT',
816 'FRONT',
817 'HNGR',
818 'HANGER',
819 'LBBY',
820 'LOBBY',
821 'LOWR',
822 'LOWER',
823 'OFC',
824 'OFFICE',
825 'PH',
826 'PENTHOUSE',
827 'TRLR',
828 'TRAILER',
829 'UPPR',
830 'RM',
831 'ROOM',
832 'SIDE',
833 'SLIP',
834 'KEY',
835 'LOT',
836 'PIER',
837 'REAR',
838 'SPC',
839 'SPACE',
840 'STOP',
841 'STE',
842 'SUITE',
843 'UNIT',
844 '#',
6a488035
TO
845 );
846
847 // overwriting $streetUnitFormats for 'en_CA' and 'fr_CA' locale
848 if (in_array($locale, array(
353ffa53 849 'en_CA',
af9b09df 850 'fr_CA',
353ffa53 851 ))) {
6a488035
TO
852 $streetUnitFormats = array('APT', 'APP', 'SUITE', 'BUREAU', 'UNIT');
853 }
689cecfd
EM
854 //@todo per CRM-14459 this regex picks up words with the string in them - e.g APT picks up
855 //Captain - presuming fixing regex (& adding test) to ensure a-z does not preced string will fix
6a488035
TO
856 $streetUnitPreg = '/(' . implode('|\s', $streetUnitFormats) . ')(.+)?/i';
857 $matches = array();
858 if (preg_match($streetUnitPreg, $streetAddress, $matches)) {
859 $parseFields['street_unit'] = trim($matches[0]);
860 $streetAddress = str_replace($matches[0], '', $streetAddress);
861 $streetAddress = trim($streetAddress);
862 }
863
864 // consider remaining string as street name.
865 $parseFields['street_name'] = $streetAddress;
866
867 //run parsed fields through stripSpaces to clean
868 foreach ($parseFields as $parseField => $value) {
869 $parseFields[$parseField] = CRM_Utils_String::stripSpaces($value);
870 }
689cecfd
EM
871 //CRM-14459 if the field is too long we should assume it didn't get it right & skip rather than allow
872 // the DB to fatal
873 $fields = CRM_Core_BAO_Address::fields();
874 foreach ($fields as $fieldname => $field) {
22e263ad 875 if (!empty($field['maxlength']) && strlen(CRM_Utils_Array::value($fieldname, $parseFields)) > $field['maxlength']) {
689cecfd
EM
876 return $emptyParseFields;
877 }
878 }
6a488035
TO
879
880 return $parseFields;
881 }
882
883 /**
eceb18cc 884 * Validate the address fields based on the address options enabled.
6a488035
TO
885 * in the Address Settings
886 *
6a0b768e
TO
887 * @param array $fields
888 * An array of importable/exportable contact fields.
6a488035 889 *
a6c01b45
CW
890 * @return array
891 * an array of contact fields and only the enabled address options
6a488035 892 */
00be9182 893 public static function validateAddressOptions($fields) {
6a488035
TO
894 static $addressOptions = NULL;
895 if (!$addressOptions) {
6c552737
TO
896 $addressOptions = CRM_Core_BAO_Setting::valueOptions(
897 CRM_Core_BAO_Setting::SYSTEM_PREFERENCES_NAME,
898 'address_options'
899 );
6a488035
TO
900 }
901
902 if (is_array($fields) && !empty($fields)) {
903 foreach ($addressOptions as $key => $value) {
904 if (!$value && isset($fields[$key])) {
905 unset($fields[$key]);
906 }
907 }
908 }
909 return $fields;
910 }
911
912 /**
fe482240 913 * Check if current address is used by any other contacts.
6a488035 914 *
6a0b768e
TO
915 * @param int $addressId
916 * Address id.
6a488035 917 *
72b3a70c
CW
918 * @return int
919 * count of contacts that use this shared address
6a488035 920 */
00be9182 921 public static function checkContactSharedAddress($addressId) {
6a488035
TO
922 $query = 'SELECT count(id) FROM civicrm_address WHERE master_id = %1';
923 return CRM_Core_DAO::singleValueQuery($query, array(1 => array($addressId, 'Integer')));
924 }
925
926 /**
fe482240 927 * Check if current address fields are shared with any other address.
6a488035 928 *
6a0b768e
TO
929 * @param array $fields
930 * Address fields in profile.
931 * @param int $contactId
932 * Contact id.
6a488035 933 *
6a488035 934 */
00be9182 935 public static function checkContactSharedAddressFields(&$fields, $contactId) {
6a488035
TO
936 if (!$contactId || !is_array($fields) || empty($fields)) {
937 return;
938 }
939
940 $sharedLocations = array();
941
942 $query = "
943SELECT is_primary,
944 location_type_id
945 FROM civicrm_address
946 WHERE contact_id = %1
947 AND master_id IS NOT NULL";
948
949 $dao = CRM_Core_DAO::executeQuery($query, array(1 => array($contactId, 'Positive')));
950 while ($dao->fetch()) {
951 $sharedLocations[$dao->location_type_id] = $dao->location_type_id;
952 if ($dao->is_primary) {
953 $sharedLocations['Primary'] = 'Primary';
954 }
955 }
956
957 //no need to process further.
958 if (empty($sharedLocations)) {
959 return;
960 }
961
962 $addressFields = array(
963 'city',
964 'county',
965 'country',
966 'geo_code_1',
967 'geo_code_2',
968 'postal_code',
969 'address_name',
970 'state_province',
971 'street_address',
972 'postal_code_suffix',
973 'supplemental_address_1',
974 'supplemental_address_2',
207f62c6 975 'supplemental_address_3',
6a488035
TO
976 );
977
978 foreach ($fields as $name => & $values) {
979 if (!is_array($values) || empty($values)) {
980 continue;
981 }
982
983 $nameVal = explode('-', $values['name']);
984 $fldName = CRM_Utils_Array::value(0, $nameVal);
985 $locType = CRM_Utils_Array::value(1, $nameVal);
a7488080 986 if (!empty($values['location_type_id'])) {
6a488035
TO
987 $locType = $values['location_type_id'];
988 }
989
990 if (in_array($fldName, $addressFields) &&
991 in_array($locType, $sharedLocations)
992 ) {
993 $values['is_shared'] = TRUE;
994 }
995 }
996 }
997
998 /**
fe482240 999 * Update the shared addresses if master address is modified.
6a488035 1000 *
6a0b768e
TO
1001 * @param int $addressId
1002 * Address id.
1003 * @param array $params
1004 * Associated array of address params.
6a488035 1005 */
00be9182 1006 public static function processSharedAddress($addressId, $params) {
6a488035
TO
1007 $query = 'SELECT id FROM civicrm_address WHERE master_id = %1';
1008 $dao = CRM_Core_DAO::executeQuery($query, array(1 => array($addressId, 'Integer')));
1009
1010 // unset contact id
1011 $skipFields = array('is_primary', 'location_type_id', 'is_billing', 'master_id', 'contact_id');
1012 foreach ($skipFields as $value) {
1013 unset($params[$value]);
1014 }
1015
1016 $addressDAO = new CRM_Core_DAO_Address();
1017 while ($dao->fetch()) {
1018 $addressDAO->copyValues($params);
1019 $addressDAO->id = $dao->id;
1020 $addressDAO->save();
1021 $addressDAO->free();
1022 }
1023 }
1024
8bdfc216 1025 /**
fe482240 1026 * Merge contacts with the Same address to get one shared label.
6a0b768e
TO
1027 * @param array $rows
1028 * Array[contact_id][contactDetails].
8bdfc216 1029 */
1030 public static function mergeSameAddress(&$rows) {
1031 $uniqueAddress = array();
1032 foreach (array_keys($rows) as $rowID) {
1033 // load complete address as array key
6c552737
TO
1034 $address = trim($rows[$rowID]['street_address'])
1035 . trim($rows[$rowID]['city'])
1036 . trim($rows[$rowID]['state_province'])
1037 . trim($rows[$rowID]['postal_code'])
1038 . trim($rows[$rowID]['country']);
8bdfc216 1039 if (isset($rows[$rowID]['last_name'])) {
1040 $name = $rows[$rowID]['last_name'];
1041 }
1042 else {
1043 $name = $rows[$rowID]['display_name'];
1044 }
1045
1046 // CRM-15120
1047 $formatted = array(
1048 'first_name' => $rows[$rowID]['first_name'],
21dfd5f5 1049 'individual_prefix' => $rows[$rowID]['individual_prefix'],
8bdfc216 1050 );
aaffa79f 1051 $format = Civi::settings()->get('display_name_format');
8bdfc216 1052 $firstNameWithPrefix = CRM_Utils_Address::format($formatted, $format, FALSE, FALSE, TRUE);
1053 $firstNameWithPrefix = trim($firstNameWithPrefix);
1054
1055 // fill uniqueAddress array with last/first name tree
1056 if (isset($uniqueAddress[$address])) {
1057 $uniqueAddress[$address]['names'][$name][$firstNameWithPrefix]['first_name'] = $rows[$rowID]['first_name'];
1058 $uniqueAddress[$address]['names'][$name][$firstNameWithPrefix]['addressee_display'] = $rows[$rowID]['addressee_display'];
1059 // drop unnecessary rows
1060 unset($rows[$rowID]);
1061 // this is the first listing at this address
1062 }
1063 else {
1064 $uniqueAddress[$address]['ID'] = $rowID;
1065 $uniqueAddress[$address]['names'][$name][$firstNameWithPrefix]['first_name'] = $rows[$rowID]['first_name'];
1066 $uniqueAddress[$address]['names'][$name][$firstNameWithPrefix]['addressee_display'] = $rows[$rowID]['addressee_display'];
1067 }
1068 }
1069 foreach ($uniqueAddress as $address => $data) {
1070 // copy data back to $rows
1071 $count = 0;
1072 // one last name list per row
1073 foreach ($data['names'] as $last_name => $first_names) {
1074 // too many to list
1075 if ($count > 2) {
1076 break;
1077 }
9b873358 1078 if (count($first_names) == 1) {
2aa397bc
TO
1079 $family = $first_names[current(array_keys($first_names))]['addressee_display'];
1080 }
1081 else {
1082 // collapse the tree to summarize
1083 $family = trim(implode(" & ", array_keys($first_names)) . " " . $last_name);
1084 }
1085 if ($count) {
1086 $processedNames .= "\n" . $family;
1087 }
1088 else {
1089 // build display_name string
1090 $processedNames = $family;
1091 }
8bdfc216 1092 $count++;
1093 }
1094 $rows[$data['ID']]['addressee'] = $rows[$data['ID']]['addressee_display'] = $rows[$data['ID']]['display_name'] = $processedNames;
1095 }
1096 }
1097
6a488035 1098 /**
fe482240 1099 * Create relationship between contacts who share an address.
6a488035
TO
1100 *
1101 * Note that currently we create relationship only for Individual contacts
1102 * Individual + Household and Individual + Orgnization
1103 *
6a0b768e
TO
1104 * @param int $masterAddressId
1105 * Master address id.
1106 * @param array $params
1107 * Associated array of submitted values.
6a488035 1108 */
00be9182 1109 public static function processSharedAddressRelationship($masterAddressId, $params) {
6a488035
TO
1110 // get the contact type of contact being edited / created
1111 $currentContactType = CRM_Contact_BAO_Contact::getContactType($params['contact_id']);
1112 $currentContactId = $params['contact_id'];
1113
1114 // if current contact is not of type individual return
1115 if ($currentContactType != 'Individual') {
1116 return;
1117 }
1118
1119 // get the contact id and contact type of shared contact
1120 // check the contact type of shared contact, return if it is of type Individual
6a488035
TO
1121 $query = 'SELECT cc.id, cc.contact_type
1122 FROM civicrm_contact cc INNER JOIN civicrm_address ca ON cc.id = ca.contact_id
1123 WHERE ca.id = %1';
1124
1125 $dao = CRM_Core_DAO::executeQuery($query, array(1 => array($masterAddressId, 'Integer')));
6a488035
TO
1126 $dao->fetch();
1127
1128 // if current contact is not of type individual return, since we don't create relationship between
1129 // 2 individuals
1130 if ($dao->contact_type == 'Individual') {
1131 return;
1132 }
1133 $sharedContactType = $dao->contact_type;
1134 $sharedContactId = $dao->id;
1135
1136 // create relationship between ontacts who share an address
1137 if ($sharedContactType == 'Organization') {
1138 return CRM_Contact_BAO_Contact_Utils::createCurrentEmployerRelationship($currentContactId, $sharedContactId);
1139 }
6a488035 1140
82ffeed5 1141 // get the relationship type id of "Household Member of"
1142 $relTypeId = CRM_Core_DAO::getFieldValue('CRM_Contact_DAO_RelationshipType', 'Household Member of', 'id', 'name_a_b');
6a488035
TO
1143
1144 if (!$relTypeId) {
82ffeed5 1145 CRM_Core_Error::fatal(ts("You seem to have deleted the relationship type 'Household Member of'"));
1146 }
1147
1148 $relParam = array(
1149 'is_active' => TRUE,
1150 'relationship_type_id' => $relTypeId,
1151 'contact_id_a' => $currentContactId,
1152 'contact_id_b' => $sharedContactId,
1153 );
1154
1155 // If already there is a relationship record of $relParam criteria, avoid creating relationship again or else
1156 // it will casue CRM-16588 as the Duplicate Relationship Exception will revert other contact field values on update
9272d8b5 1157 if (CRM_Contact_BAO_Relationship::checkDuplicateRelationship($relParam, $currentContactId, $sharedContactId)) {
82ffeed5 1158 return;
6a488035
TO
1159 }
1160
a7ef8c9d
EM
1161 try {
1162 // create relationship
82ffeed5 1163 civicrm_api3('relationship', 'create', $relParam);
a7ef8c9d
EM
1164 }
1165 catch (CiviCRM_API3_Exception $e) {
1166 // We catch and ignore here because this has historically been a best-effort relationship create call.
1167 // presumably it could refuse due to duplication or similar and we would ignore that.
1168 }
6a488035
TO
1169 }
1170
1171 /**
fe482240 1172 * Check and set the status for shared address delete.
6a488035 1173 *
6a0b768e
TO
1174 * @param int $addressId
1175 * Address id.
1176 * @param int $contactId
1177 * Contact id.
1178 * @param bool $returnStatus
1179 * By default false.
6a488035 1180 *
a6c01b45 1181 * @return string
6a488035 1182 */
00be9182 1183 public static function setSharedAddressDeleteStatus($addressId = NULL, $contactId = NULL, $returnStatus = FALSE) {
6a488035
TO
1184 // check if address that is being deleted has any shared
1185 if ($addressId) {
1186 $entityId = $addressId;
1187 $query = 'SELECT cc.id, cc.display_name
1188 FROM civicrm_contact cc INNER JOIN civicrm_address ca ON cc.id = ca.contact_id
1189 WHERE ca.master_id = %1';
1190 }
1191 else {
1192 $entityId = $contactId;
1193 $query = 'SELECT cc.id, cc.display_name
1194 FROM civicrm_address ca1
1195 INNER JOIN civicrm_address ca2 ON ca1.id = ca2.master_id
1196 INNER JOIN civicrm_contact cc ON ca2.contact_id = cc.id
1197 WHERE ca1.contact_id = %1';
1198 }
1199
1200 $dao = CRM_Core_DAO::executeQuery($query, array(1 => array($entityId, 'Integer')));
1201
1202 $deleteStatus = array();
1203 $sharedContactList = array();
1204 $statusMessage = NULL;
1205 $addressCount = 0;
1206 while ($dao->fetch()) {
1207 if (empty($deleteStatus)) {
1208 $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.');
1209 }
1210
1211 $contactViewUrl = CRM_Utils_System::url('civicrm/contact/view', "reset=1&cid={$dao->id}");
1212 $sharedContactList[] = "<a href='{$contactViewUrl}'>{$dao->display_name}</a>";
1213 $deleteStatus[] = "<a href='{$contactViewUrl}'>{$dao->display_name}</a>";
1214
1215 $addressCount++;
1216 }
1217
1218 if (!empty($deleteStatus)) {
1219 $statusMessage = implode('<br/>', $deleteStatus) . '<br/>';
1220 }
1221
1222 if (!$returnStatus) {
1223 CRM_Core_Session::setStatus($statusMessage, '', 'info');
1224 }
1225 else {
1226 return array(
1227 'contactList' => $sharedContactList,
1228 'count' => $addressCount,
1229 );
1230 }
1231 }
12445e1c
CW
1232
1233 /**
fe482240 1234 * Call common delete function.
ad37ac8e 1235 *
1236 * @param int $id
1237 *
1238 * @return bool
12445e1c 1239 */
00be9182 1240 public static function del($id) {
a65e2e55 1241 return CRM_Contact_BAO_Contact::deleteObjectWithPrimary('Address', $id);
12445e1c 1242 }
dc86f881
CW
1243
1244 /**
1245 * Get options for a given address field.
1246 * @see CRM_Core_DAO::buildOptions
1247 *
1248 * TODO: Should we always assume chainselect? What fn should be responsible for controlling that flow?
1249 * TODO: In context of chainselect, what to return if e.g. a country has no states?
1250 *
6a0b768e
TO
1251 * @param string $fieldName
1252 * @param string $context
a1a2a83d 1253 * @see CRM_Core_DAO::buildOptionsContext
6a0b768e 1254 * @param array $props
16b10e64 1255 * whatever is known about this dao object.
77b97be7 1256 *
5c766a0b 1257 * @return array|bool
dc86f881
CW
1258 */
1259 public static function buildOptions($fieldName, $context = NULL, $props = array()) {
1260 $params = array();
1261 // Special logic for fields whose options depend on context or properties
1262 switch ($fieldName) {
1263 // Filter state_province list based on chosen country or site defaults
1264 case 'state_province_id':
d0bfb983 1265 case 'state_province_name':
1266 case 'state_province':
1267 // change $fieldName to DB specific names.
1268 $fieldName = 'state_province_id';
dc86f881
CW
1269 if (empty($props['country_id'])) {
1270 $config = CRM_Core_Config::singleton();
1271 if (!empty($config->provinceLimit)) {
1272 $props['country_id'] = $config->provinceLimit;
1273 }
1274 else {
1275 $props['country_id'] = $config->defaultContactCountry;
1276 }
1277 }
578d346d 1278 if (!empty($props['country_id']) && $context !== 'validate') {
dc86f881
CW
1279 $params['condition'] = 'country_id IN (' . implode(',', (array) $props['country_id']) . ')';
1280 }
1281 break;
2aa397bc 1282
dc86f881
CW
1283 // Filter country list based on site defaults
1284 case 'country_id':
d0bfb983 1285 case 'country':
1286 // change $fieldName to DB specific names.
1287 $fieldName = 'country_id';
786ad6e1
CW
1288 if ($context != 'get' && $context != 'validate') {
1289 $config = CRM_Core_Config::singleton();
1290 if (!empty($config->countryLimit) && is_array($config->countryLimit)) {
1291 $params['condition'] = 'id IN (' . implode(',', $config->countryLimit) . ')';
1292 }
dc86f881
CW
1293 }
1294 break;
2aa397bc 1295
dc86f881
CW
1296 // Filter county list based on chosen state
1297 case 'county_id':
1298 if (!empty($props['state_province_id'])) {
1299 $params['condition'] = 'state_province_id IN (' . implode(',', (array) $props['state_province_id']) . ')';
1300 }
1301 break;
2aa397bc 1302
c7130c3e
CW
1303 // Not a real field in this entity
1304 case 'world_region':
3493947a 1305 case 'worldregion':
1306 case 'worldregion_id':
c7130c3e 1307 return CRM_Core_PseudoConstant::worldRegion();
dc86f881 1308 }
786ad6e1 1309 return CRM_Core_PseudoConstant::get(__CLASS__, $fieldName, $params, $context);
dc86f881 1310 }
96025800 1311
a7488080 1312}