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