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