Merge pull request #18745 from seamuslee001/backdrop_session
[civicrm-core.git] / CRM / Contact / BAO / Individual.php
1 <?php
2 /*
3 +--------------------------------------------------------------------+
4 | Copyright CiviCRM LLC. All rights reserved. |
5 | |
6 | This work is published under the GNU AGPLv3 license with some |
7 | permitted exceptions and without any warranty. For full license |
8 | and copyright information, see https://civicrm.org/licensing |
9 +--------------------------------------------------------------------+
10 */
11
12 /**
13 *
14 * @package CRM
15 * @copyright CiviCRM LLC https://civicrm.org/licensing
16 */
17
18 /**
19 * Class contains functions for individual contact type.
20 */
21 class CRM_Contact_BAO_Individual extends CRM_Contact_DAO_Contact {
22
23 /**
24 * Class constructor.
25 */
26 public function __construct() {
27 }
28
29 /**
30 * Function is used to format the individual contact values.
31 *
32 * @param array $params
33 * (reference ) an assoc array of name/value pairs.
34 * @param CRM_Contact_BAO_Contact $contact
35 * Contact object.
36 *
37 * @return CRM_Contact_BAO_Contact
38 */
39 public static function format(&$params, &$contact) {
40 if (!self::dataExists($params)) {
41 return NULL;
42 }
43
44 // "null" value for example is passed by dedupe merge in order to empty.
45 // Display name computation shouldn't consider such values.
46 foreach (['first_name', 'middle_name', 'last_name', 'nick_name', 'formal_title', 'birth_date', 'deceased_date'] as $displayField) {
47 if (CRM_Utils_Array::value($displayField, $params) == "null") {
48 $params[$displayField] = '';
49 }
50 }
51
52 $sortName = $displayName = '';
53 $firstName = trim($params['first_name'] ?? '');
54 $middleName = trim($params['middle_name'] ?? '');
55 $lastName = trim($params['last_name'] ?? '');
56 $nickName = CRM_Utils_Array::value('nick_name', $params, '');
57 $prefix_id = CRM_Utils_Array::value('prefix_id', $params, '');
58 $suffix_id = CRM_Utils_Array::value('suffix_id', $params, '');
59 $formalTitle = CRM_Utils_Array::value('formal_title', $params, '');
60
61 // get prefix and suffix names
62 $prefix = $suffix = NULL;
63 if ($prefix_id) {
64 $params['individual_prefix'] = $prefix = CRM_Core_PseudoConstant::getLabel('CRM_Contact_DAO_Contact', 'prefix_id', $prefix_id);
65 }
66 if ($suffix_id) {
67 $params['individual_suffix'] = $suffix = CRM_Core_PseudoConstant::getLabel('CRM_Contact_DAO_Contact', 'suffix_id', $suffix_id);
68 }
69
70 $params['is_deceased'] = CRM_Utils_Array::value('is_deceased', $params, FALSE);
71
72 $individual = NULL;
73 if ($contact->id) {
74 $individual = new CRM_Contact_BAO_Contact();
75 $individual->id = $contact->id;
76 if ($individual->find(TRUE)) {
77
78 //lets allow to update single name field though preserveDBName
79 //but if db having null value and params contain value, CRM-4330.
80 $useDBNames = [];
81
82 foreach (['last', 'middle', 'first', 'nick'] as $name) {
83 $dbName = "{$name}_name";
84 $value = $individual->$dbName;
85
86 // the db has name values
87 if ($value && !empty($params['preserveDBName'])) {
88 $useDBNames[] = $name;
89 }
90 }
91
92 foreach (['prefix', 'suffix'] as $name) {
93 $dbName = "{$name}_id";
94 $value = $individual->$dbName;
95 if ($value && !empty($params['preserveDBName'])) {
96 $useDBNames[] = $name;
97 }
98 }
99
100 if ($individual->formal_title && !empty($params['preserveDBName'])) {
101 $useDBNames[] = 'formal_title';
102 }
103
104 // CRM-4430
105 //1. preserve db name if want
106 //2. lets get value from param if exists.
107 //3. if not in params, lets get from db.
108
109 foreach (['last', 'middle', 'first', 'nick'] as $name) {
110 $phpName = "{$name}Name";
111 $dbName = "{$name}_name";
112 $value = $individual->$dbName;
113 if (in_array($name, $useDBNames)) {
114 $params[$dbName] = $value;
115 $contact->$dbName = $value;
116 $$phpName = $value;
117 }
118 elseif (array_key_exists($dbName, $params)) {
119 $$phpName = $params[$dbName];
120 }
121 elseif ($value) {
122 $$phpName = $value;
123 }
124 }
125
126 foreach (['prefix', 'suffix'] as $name) {
127 $dbName = "{$name}_id";
128
129 $value = $individual->$dbName;
130 if (in_array($name, $useDBNames)) {
131 $params[$dbName] = $value;
132 $contact->$dbName = $value;
133 if ($value) {
134 $$name = CRM_Core_PseudoConstant::getLabel('CRM_Contact_DAO_Contact', $dbName, $value);
135 }
136 else {
137 $$name = NULL;
138 }
139 }
140 elseif (array_key_exists($dbName, $params)) {
141 // CRM-5278
142 if (!empty($params[$dbName])) {
143 $$name = CRM_Core_PseudoConstant::getLabel('CRM_Contact_DAO_Contact', $dbName, $params[$dbName]);
144 }
145 }
146 elseif ($value) {
147 $$name = CRM_Core_PseudoConstant::getLabel('CRM_Contact_DAO_Contact', $dbName, $value);
148 }
149 }
150
151 if (in_array('formal_title', $useDBNames)) {
152 $params['formal_title'] = $individual->formal_title;
153 $contact->formal_title = $individual->formal_title;
154 $formalTitle = $individual->formal_title;
155 }
156 elseif (array_key_exists('formal_title', $params)) {
157 $formalTitle = $params['formal_title'];
158 }
159 elseif ($individual->formal_title) {
160 $formalTitle = $individual->formal_title;
161 }
162 }
163 }
164
165 if ($lastName || $firstName || $middleName) {
166 // make sure we have values for all the name fields.
167 $formatted = $params;
168 $nameParams = [
169 'first_name' => $firstName,
170 'middle_name' => $middleName,
171 'last_name' => $lastName,
172 'nick_name' => $nickName,
173 'individual_suffix' => $suffix,
174 'individual_prefix' => $prefix,
175 'prefix_id' => $prefix_id,
176 'suffix_id' => $suffix_id,
177 'formal_title' => $formalTitle,
178 ];
179 // make sure we have all the name fields.
180 foreach ($nameParams as $name => $value) {
181 if (empty($formatted[$name]) && $value) {
182 $formatted[$name] = $value;
183 }
184 }
185
186 $tokens = [];
187 CRM_Utils_Hook::tokens($tokens);
188 $tokenFields = [];
189 foreach ($tokens as $catTokens) {
190 foreach ($catTokens as $token => $label) {
191 $tokenFields[] = $token;
192 }
193 }
194
195 //build the sort name.
196 $format = Civi::settings()->get('sort_name_format');
197 $sortName = CRM_Utils_Address::format($formatted, $format,
198 FALSE, FALSE, $tokenFields
199 );
200 $sortName = trim($sortName);
201
202 //build the display name.
203 $format = Civi::settings()->get('display_name_format');
204 $displayName = CRM_Utils_Address::format($formatted, $format,
205 FALSE, FALSE, $tokenFields
206 );
207 $displayName = trim($displayName);
208 }
209
210 //start further check for email.
211 if (empty($sortName) || empty($displayName)) {
212 $email = NULL;
213 if (!empty($params['email']) &&
214 is_array($params['email'])
215 ) {
216 foreach ($params['email'] as $emailBlock) {
217 if (isset($emailBlock['is_primary'])) {
218 $email = $emailBlock['email'];
219 break;
220 }
221 }
222 }
223 $uniqId = $params['user_unique_id'] ?? NULL;
224 if (!$email && $contact->id) {
225 $email = CRM_Contact_BAO_Contact::getPrimaryEmail($contact->id);
226 }
227 }
228
229 //now set the names.
230 $names = ['displayName' => 'display_name', 'sortName' => 'sort_name'];
231 foreach ($names as $value => $name) {
232 if (empty($$value)) {
233 if ($email) {
234 $$value = $email;
235 }
236 elseif ($uniqId) {
237 $$value = $uniqId;
238 }
239 elseif (!empty($params[$name])) {
240 $$value = $params[$name];
241 }
242 // If we have nothing else going on set sort_name to display_name.
243 elseif ($displayName) {
244 $$value = $displayName;
245 }
246 }
247 //finally if we could not pass anything lets keep db.
248 if (!empty($$value)) {
249 $contact->$name = $$value;
250 }
251 }
252
253 $format = CRM_Utils_Date::getDateFormat('birth');
254 if ($date = CRM_Utils_Array::value('birth_date', $params)) {
255 if (in_array($format, [
256 'dd-mm',
257 'mm/dd',
258 ])) {
259 $separator = '/';
260 if ($format == 'dd-mm') {
261 $separator = '-';
262 }
263 $date = $date . $separator . '1902';
264 }
265 elseif (in_array($format, [
266 'yy-mm',
267 ])) {
268 $date = $date . '-01';
269 }
270 elseif (in_array($format, [
271 'M yy',
272 ])) {
273 $date = $date . '-01';
274 }
275 elseif (in_array($format, [
276 'yy',
277 ])) {
278 $date = $date . '-01-01';
279 }
280 $contact->birth_date = CRM_Utils_Date::processDate($date);
281 }
282 elseif ($contact->birth_date) {
283 $contact->birth_date = CRM_Utils_Date::isoToMysql($contact->birth_date);
284 }
285
286 if ($date = CRM_Utils_Array::value('deceased_date', $params)) {
287 if (in_array($format, [
288 'dd-mm',
289 'mm/dd',
290 ])) {
291 $separator = '/';
292 if ($format == 'dd-mm') {
293 $separator = '-';
294 }
295 $date = $date . $separator . '1902';
296 }
297 elseif (in_array($format, [
298 'yy-mm',
299 ])) {
300 $date = $date . '-01';
301 }
302 elseif (in_array($format, [
303 'M yy',
304 ])) {
305 $date = $date . '-01';
306 }
307 elseif (in_array($format, [
308 'yy',
309 ])) {
310 $date = $date . '-01-01';
311 }
312
313 $contact->deceased_date = CRM_Utils_Date::processDate($date);
314 }
315 elseif ($contact->deceased_date) {
316 $contact->deceased_date = CRM_Utils_Date::isoToMysql($contact->deceased_date);
317 }
318
319 if ($middle_name = CRM_Utils_Array::value('middle_name', $params)) {
320 $contact->middle_name = $middle_name;
321 }
322
323 return $contact;
324 }
325
326 /**
327 * Regenerates display_name for contacts with given prefixes/suffixes.
328 *
329 * @param array $ids
330 * The array with the prefix/suffix id governing which contacts to regenerate.
331 * @param int $action
332 * The action describing whether prefix/suffix was UPDATED or DELETED.
333 */
334 public static function updateDisplayNames(&$ids, $action) {
335 // get the proper field name (prefix_id or suffix_id) and its value
336 $fieldName = '';
337 foreach ($ids as $key => $value) {
338 switch ($key) {
339 case 'individualPrefix':
340 $fieldName = 'prefix_id';
341 $fieldValue = $value;
342 break 2;
343
344 case 'individualSuffix':
345 $fieldName = 'suffix_id';
346 $fieldValue = $value;
347 break 2;
348 }
349 }
350 if ($fieldName == '') {
351 return;
352 }
353
354 // query for the affected individuals
355 $fieldValue = CRM_Utils_Type::escape($fieldValue, 'Integer');
356 $contact = new CRM_Contact_BAO_Contact();
357 $contact->$fieldName = $fieldValue;
358 $contact->find();
359
360 // iterate through the affected individuals and rebuild their display_names
361 while ($contact->fetch()) {
362 $contact = new CRM_Contact_BAO_Contact();
363 $contact->id = $contact->contact_id;
364 if ($action == CRM_Core_Action::DELETE) {
365 $contact->$fieldName = 'NULL';
366 $contact->save();
367 }
368 $contact->display_name = $contact->displayName();
369 $contact->save();
370 }
371 }
372
373 /**
374 * Creates display name.
375 *
376 * @return string
377 * the constructed display name
378 */
379 public function displayName() {
380 $prefix = CRM_Core_PseudoConstant::get('CRM_Contact_DAO_Contact', 'prefix_id');
381 $suffix = CRM_Core_PseudoConstant::get('CRM_Contact_DAO_Contact', 'suffix_id');
382 return str_replace(' ', ' ', trim($prefix[$this->prefix_id] . ' ' . $this->first_name . ' ' . $this->middle_name . ' ' . $this->last_name . ' ' . $suffix[$this->suffix_id]));
383 }
384
385 /**
386 * Check if there is data to create the object.
387 *
388 * @param array $params
389 *
390 * @return bool
391 */
392 public static function dataExists($params) {
393 if ($params['contact_type'] == 'Individual') {
394 return TRUE;
395 }
396
397 return FALSE;
398 }
399
400 }