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