Merge pull request #6559 from jitendrapurohit/CRM-16877
[civicrm-core.git] / CRM / Core / BAO / Location.php
CommitLineData
6a488035
TO
1<?php
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 +--------------------------------------------------------------------+
e70a7fc0 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 class handle creation of location block elements.
6a488035
TO
36 */
37class CRM_Core_BAO_Location extends CRM_Core_DAO {
38
39 /**
fe482240 40 * Location block element array.
6a488035
TO
41 */
42 static $blocks = array('phone', 'email', 'im', 'openid', 'address');
43
44 /**
fe482240 45 * Create various elements of location block.
6a488035 46 *
6a0b768e
TO
47 * @param array $params
48 * (reference ) an assoc array of name/value pairs.
49 * @param bool $fixAddress
50 * True if you need to fix (format) address values.
6a488035
TO
51 * before inserting in db
52 *
77b97be7
EM
53 * @param null $entity
54 *
a6c01b45 55 * @return array
6a488035 56 */
00be9182 57 public static function create(&$params, $fixAddress = TRUE, $entity = NULL) {
6a488035
TO
58 $location = array();
59 if (!self::dataExists($params)) {
60 return $location;
61 }
62
63 // create location blocks.
64 foreach (self::$blocks as $block) {
65 if ($block != 'address') {
481a74f4 66 $location[$block] = CRM_Core_BAO_Block::create($block, $params, $entity);
6a488035
TO
67 }
68 else {
69 $location[$block] = CRM_Core_BAO_Address::create($params, $fixAddress, $entity);
70 }
71 }
72
73 if ($entity) {
74 // this is a special case for adding values in location block table
75 $entityElements = array(
76 'entity_table' => $params['entity_table'],
77 'entity_id' => $params['entity_id'],
78 );
79
80 $location['id'] = self::createLocBlock($location, $entityElements);
81 }
82 else {
83 // when we come from a form which displays all the location elements (like the edit form or the inline block
84 // elements, we can skip the below check. The below check adds quite a feq queries to an already overloaded
85 // form
86 if (!CRM_Utils_Array::value('updateBlankLocInfo', $params, FALSE)) {
87 // make sure contact should have only one primary block, CRM-5051
88 self::checkPrimaryBlocks(CRM_Utils_Array::value('contact_id', $params));
89 }
90 }
91
92 return $location;
93 }
94
8345c9d3
EM
95 /**
96 * Get the ID of the database billing location.
97 *
98 * @return int
99 * Billing location type id.
100 *
101 * @throws \CRM_Core_Exception
102 */
103 public static function getBillingLocationId() {
104 static $billingTypeID = NULL;
105 if ($billingTypeID) {
106 return $billingTypeID;
107 }
108 $locationTypes = CRM_Core_PseudoConstant::get('CRM_Core_DAO_Address', 'location_type_id', array(), 'validate');
109 $billingTypeID = array_search('Billing', $locationTypes);
110 if (!$billingTypeID) {
111 throw new CRM_Core_Exception(ts('Please set a location type of %1', array(1 => 'Billing')));
112 }
113 return $billingTypeID;
114 }
6a488035 115 /**
fe482240 116 * Creates the entry in the civicrm_loc_block.
6a488035 117 */
00be9182 118 public static function createLocBlock(&$location, &$entityElements) {
6a488035
TO
119 $locId = self::findExisting($entityElements);
120 $locBlock = array();
121
122 if ($locId) {
123 $locBlock['id'] = $locId;
124 }
125
126 foreach (array(
353ffa53
TO
127 'phone',
128 'email',
129 'im',
acb1052e 130 'address',
353ffa53 131 ) as $loc) {
0d8afee2
CW
132 $locBlock["{$loc}_id"] = !empty($location["$loc"][0]) ? $location["$loc"][0]->id : NULL;
133 $locBlock["{$loc}_2_id"] = !empty($location["$loc"][1]) ? $location["$loc"][1]->id : NULL;
6a488035
TO
134 }
135
136 $countNull = 0;
137 foreach ($locBlock as $key => $block) {
138 if (empty($locBlock[$key])) {
139 $locBlock[$key] = 'null';
140 $countNull++;
141 }
142 }
143
144 if (count($locBlock) == $countNull) {
145 // implies nothing is set.
146 return NULL;
147 }
148
149 $locBlockInfo = self::addLocBlock($locBlock);
150 return $locBlockInfo->id;
151 }
152
153 /**
fe482240 154 * Takes an entity array and finds the existing location block.
6a488035 155 */
00be9182 156 public static function findExisting($entityElements) {
353ffa53 157 $eid = $entityElements['entity_id'];
6a488035 158 $etable = $entityElements['entity_table'];
353ffa53 159 $query = "
6a488035
TO
160SELECT e.loc_block_id as locId
161FROM {$etable} e
162WHERE e.id = %1";
163
164 $params = array(1 => array($eid, 'Integer'));
165 $dao = CRM_Core_DAO::executeQuery($query, $params);
166 while ($dao->fetch()) {
167 $locBlockId = $dao->locId;
168 }
169 return $locBlockId;
170 }
171
172 /**
fe482240 173 * Takes an associative array and adds location block.
6a488035 174 *
6a0b768e
TO
175 * @param array $params
176 * (reference ) an assoc array of name/value pairs.
6a488035 177 *
a6c01b45
CW
178 * @return object
179 * CRM_Core_BAO_locBlock object on success, null otherwise
6a488035 180 */
00be9182 181 public static function addLocBlock(&$params) {
6a488035
TO
182 $locBlock = new CRM_Core_DAO_LocBlock();
183
184 $locBlock->copyValues($params);
185
186 return $locBlock->save();
187 }
188
189 /**
fe482240 190 * Delete the Location Block.
6a488035 191 *
6a0b768e
TO
192 * @param int $locBlockId
193 * Id of the Location Block.
6a488035
TO
194 */
195 public static function deleteLocBlock($locBlockId) {
196 if (!$locBlockId) {
197 return;
198 }
199
200 $locBlock = new CRM_Core_DAO_LocBlock();
201 $locBlock->id = $locBlockId;
202
203 $locBlock->find(TRUE);
204
205 //resolve conflict of having same ids for multiple blocks
206 $store = array(
207 'IM_1' => $locBlock->im_id,
208 'IM_2' => $locBlock->im_2_id,
209 'Email_1' => $locBlock->email_id,
210 'Email_2' => $locBlock->email_2_id,
211 'Phone_1' => $locBlock->phone_id,
212 'Phone_2' => $locBlock->phone_2_id,
213 'Address_1' => $locBlock->address_id,
214 'Address_2' => $locBlock->address_2_id,
215 );
216 $locBlock->delete();
217 foreach ($store as $daoName => $id) {
218 if ($id) {
4d5c2eb5 219 $daoName = 'CRM_Core_DAO_' . substr($daoName, 0, -2);
220 $dao = new $daoName();
6a488035
TO
221 $dao->id = $id;
222 $dao->find(TRUE);
223 $dao->delete();
224 $dao->free();
225 }
226 }
227 }
228
229 /**
fe482240 230 * Check if there is data to create the object.
6a488035 231 *
6a0b768e
TO
232 * @param array $params
233 * (reference ) an assoc array of name/value pairs.
6a488035 234 *
acb1052e 235 * @return bool
6a488035 236 */
00be9182 237 public static function dataExists(&$params) {
6a488035
TO
238 // return if no data present
239 $dataExists = FALSE;
240 foreach (self::$blocks as $block) {
241 if (array_key_exists($block, $params)) {
242 $dataExists = TRUE;
243 break;
244 }
245 }
246
247 return $dataExists;
248 }
249
250 /**
fd31fa4c
EM
251 * @param $entityBlock
252 * @param bool $microformat
253 *
a6c01b45
CW
254 * @return array
255 * array of objects(CRM_Core_BAO_Location)
6a488035 256 */
00be9182 257 public static function &getValues($entityBlock, $microformat = FALSE) {
6a488035
TO
258 if (empty($entityBlock)) {
259 return NULL;
260 }
4d5c2eb5 261 $blocks = array();
6a488035
TO
262 $name_map = array(
263 'im' => 'IM',
264 'openid' => 'OpenID',
265 );
e52506b0 266 $blocks = array();
6a488035
TO
267 //get all the blocks for this contact
268 foreach (self::$blocks as $block) {
269 if (array_key_exists($block, $name_map)) {
270 $name = $name_map[$block];
271 }
272 else {
273 $name = ucfirst($block);
274 }
4d5c2eb5 275 $baoString = 'CRM_Core_BAO_' . $name;
c490a46a 276 $blocks[$block] = $baoString::getValues($entityBlock, $microformat);
6a488035
TO
277 }
278 return $blocks;
279 }
280
281 /**
fe482240 282 * Delete all the block associated with the location.
6a488035 283 *
6a0b768e
TO
284 * @param int $contactId
285 * Contact id.
286 * @param int $locationTypeId
287 * Id of the location to delete.
6a488035 288 */
00be9182 289 public static function deleteLocationBlocks($contactId, $locationTypeId) {
6a488035
TO
290 // ensure that contactId has a value
291 if (empty($contactId) ||
292 !CRM_Utils_Rule::positiveInteger($contactId)
293 ) {
294 CRM_Core_Error::fatal();
295 }
296
297 if (empty($locationTypeId) ||
298 !CRM_Utils_Rule::positiveInteger($locationTypeId)
299 ) {
300 // so we only delete the blocks which DO NOT have a location type Id
301 // CRM-3581
302 $locationTypeId = 'null';
303 }
304
305 static $blocks = array('Address', 'Phone', 'IM', 'OpenID', 'Email');
306
307 $params = array('contact_id' => $contactId, 'location_type_id' => $locationTypeId);
308 foreach ($blocks as $name) {
309 CRM_Core_BAO_Block::blockDelete($name, $params);
310 }
311 }
312
c490a46a
CW
313 /**
314 * Copy or update location block.
6a488035 315 *
6a0b768e
TO
316 * @param int $locBlockId
317 * Location block id.
318 * @param int $updateLocBlockId
319 * Update location block id.
b5c2afd0 320 *
a6c01b45
CW
321 * @return int
322 * newly created/updated location block id.
b5c2afd0 323 */
00be9182 324 public static function copyLocBlock($locBlockId, $updateLocBlockId = NULL) {
6a488035
TO
325 //get the location info.
326 $defaults = $updateValues = array();
327 $locBlock = array('id' => $locBlockId);
328 CRM_Core_DAO::commonRetrieve('CRM_Core_DAO_LocBlock', $locBlock, $defaults);
329
330 if ($updateLocBlockId) {
331 //get the location info for update.
332 $copyLocationParams = array('id' => $updateLocBlockId);
333 CRM_Core_DAO::commonRetrieve('CRM_Core_DAO_LocBlock', $copyLocationParams, $updateValues);
334 foreach ($updateValues as $key => $value) {
335 if ($key != 'id') {
336 $copyLocationParams[$key] = 'null';
337 }
338 }
339 }
340
341 //copy all location blocks (email, phone, address, etc)
342 foreach ($defaults as $key => $value) {
343 if ($key != 'id') {
353ffa53
TO
344 $tbl = explode("_", $key);
345 $name = ucfirst($tbl[0]);
6a488035
TO
346 $updateParams = NULL;
347 if ($updateId = CRM_Utils_Array::value($key, $updateValues)) {
348 $updateParams = array('id' => $updateId);
349 }
350
351 $copy = CRM_Core_DAO::copyGeneric('CRM_Core_DAO_' . $name, array('id' => $value), $updateParams);
352 $copyLocationParams[$key] = $copy->id;
353 }
354 }
355
356 $copyLocation = &CRM_Core_DAO::copyGeneric('CRM_Core_DAO_LocBlock',
357 array('id' => $locBlock['id']),
358 $copyLocationParams
359 );
360 return $copyLocation->id;
361 }
362
363 /**
364 * If contact has data for any location block, make sure
365 * contact should have only one primary block, CRM-5051
366 *
6a0b768e
TO
367 * @param int $contactId
368 * Contact id.
6a488035 369 *
6a488035 370 */
00be9182 371 public static function checkPrimaryBlocks($contactId) {
6a488035
TO
372 if (!$contactId) {
373 return;
374 }
375
376 // get the loc block ids.
377 $primaryLocBlockIds = CRM_Contact_BAO_Contact::getLocBlockIds($contactId, array('is_primary' => 1));
378 $nonPrimaryBlockIds = CRM_Contact_BAO_Contact::getLocBlockIds($contactId, array('is_primary' => 0));
379
380 foreach (array(
353ffa53
TO
381 'Email',
382 'IM',
383 'Phone',
384 'Address',
acb1052e 385 'OpenID',
353ffa53 386 ) as $block) {
6a488035
TO
387 $name = strtolower($block);
388 if (array_key_exists($name, $primaryLocBlockIds) &&
389 !CRM_Utils_System::isNull($primaryLocBlockIds[$name])
390 ) {
391 if (count($primaryLocBlockIds[$name]) > 1) {
392 // keep only single block as primary.
393 $primaryId = array_pop($primaryLocBlockIds[$name]);
394 $resetIds = "(" . implode(',', $primaryLocBlockIds[$name]) . ")";
395 // reset all primary except one.
396 CRM_Core_DAO::executeQuery("UPDATE civicrm_$name SET is_primary = 0 WHERE id IN $resetIds");
397 }
398 }
399 elseif (array_key_exists($name, $nonPrimaryBlockIds) &&
400 !CRM_Utils_System::isNull($nonPrimaryBlockIds[$name])
401 ) {
402 // data exists and no primary block - make one primary.
403 CRM_Core_DAO::setFieldValue("CRM_Core_DAO_" . $block,
404 array_pop($nonPrimaryBlockIds[$name]), 'is_primary', 1
405 );
406 }
407 }
408 }
1d07e7ab
CW
409
410 /**
411 * @param mixed $values
412 * @param string $valueType
413 * @param bool $flatten
414 *
415 * @return array
416 */
00be9182 417 public static function getChainSelectValues($values, $valueType, $flatten = FALSE) {
1d07e7ab
CW
418 if (!$values) {
419 return array();
420 }
bc999cd1 421 $values = array_filter((array) $values);
1d07e7ab
CW
422 $elements = array();
423 $list = &$elements;
424 $method = $valueType == 'country' ? 'stateProvinceForCountry' : 'countyForState';
425 foreach ($values as $val) {
426 $result = CRM_Core_PseudoConstant::$method($val);
427
428 // Format for quickform
429 if ($flatten) {
430 // Option-groups for multiple categories
431 if ($result && count($values) > 1) {
432 $elements["crm_optgroup_$val"] = CRM_Core_PseudoConstant::$valueType($val, FALSE);
433 }
434 $elements += $result;
435 }
436
437 // Format for js
438 else {
353ffa53 439 // Option-groups for multiple categories
1d07e7ab
CW
440 if ($result && count($values) > 1) {
441 $elements[] = array(
442 'value' => CRM_Core_PseudoConstant::$valueType($val, FALSE),
443 'children' => array(),
444 );
353ffa53 445 $list = &$elements[count($elements) - 1]['children'];
1d07e7ab
CW
446 }
447 foreach ($result as $id => $name) {
448 $list[] = array(
449 'value' => $name,
450 'key' => $id,
451 );
452 }
453 }
454 }
455 return $elements;
456 }
96025800 457
6a488035 458}