INFRA-132 - Comment grammar cleanup
[civicrm-core.git] / CRM / Core / BAO / UFMatch.php
CommitLineData
6a488035
TO
1<?php
2/*
3 +--------------------------------------------------------------------+
39de6fd5 4 | CiviCRM version 4.6 |
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 * The basic class that interfaces with the external user framework
38 */
39class CRM_Core_BAO_UFMatch extends CRM_Core_DAO_UFMatch {
40
41 /*
42 * Create UF Match, Note that thsi function is here in it's simplest form @ the moment
43 *
44 *
6a0b768e
TO
45 * @param array $params
46 * Input parameters.
6a488035 47 */
b5c2afd0 48 /**
c490a46a 49 * @param array $params
b5c2afd0
EM
50 *
51 * @return CRM_Core_DAO_UFMatch
52 */
00be9182 53 public static function create($params) {
6a488035
TO
54 $hook = empty($params['id']) ? 'create' : 'edit';
55 CRM_Utils_Hook::pre($hook, 'UFMatch', CRM_Utils_Array::value('id', $params), $params);
22e263ad 56 if (empty($params['domain_id'])) {
e0e29b3c 57 $params['domain_id'] = CRM_Core_Config::domainID();
58 }
6a488035
TO
59 $dao = new CRM_Core_DAO_UFMatch();
60 $dao->copyValues($params);
61 $dao->save();
62 CRM_Utils_Hook::post($hook, 'UFMatch', $dao->id, $dao);
63 return $dao;
64 }
65
66
67 /**
68 * Given a UF user object, make sure there is a contact
69 * object for this user. If the user has new values, we need
70 * to update the CRM DB with the new values
71 *
6a0b768e
TO
72 * @param Object $user
73 * The drupal user object.
74 * @param bool $update
75 * Has the user object been edited.
77b97be7
EM
76 * @param $uf
77 *
78 * @param $ctype
79 * @param bool $isLogin
6a488035
TO
80 *
81 * @return void
6a488035
TO
82 * @static
83 */
00be9182 84 public static function synchronize(&$user, $update, $uf, $ctype, $isLogin = FALSE) {
2b617cb0 85 $userSystem = CRM_Core_Config::singleton()->userSystem;
6a488035
TO
86 $session = CRM_Core_Session::singleton();
87 if (!is_object($session)) {
88 CRM_Core_Error::fatal('wow, session is not an object?');
89 return;
90 }
91
2b617cb0
EM
92 $userSystemID = $userSystem->getBestUFID($user);
93 $uniqId = $userSystem->getBestUFUniqueIdentifier($user);
6a488035
TO
94
95 // if the id of the object is zero (true for anon users in drupal)
96 // have we already processed this user, if so early
97 // return.
98 $userID = $session->get('userID');
99 $ufID = $session->get('ufID');
100
32998c82 101 if (!$update && $ufID == $userSystemID) {
6a488035
TO
102 return;
103 }
104
105 //check do we have logged in user.
106 $isUserLoggedIn = CRM_Utils_System::isUserLoggedIn();
107
108 // reset the session if we are a different user
32998c82 109 if ($ufID && $ufID != $userSystemID) {
6a488035
TO
110 $session->reset();
111
112 //get logged in user ids, and set to session.
113 if ($isUserLoggedIn) {
114 $userIds = self::getUFValues();
115 $session->set('ufID', CRM_Utils_Array::value('uf_id', $userIds, ''));
116 $session->set('userID', CRM_Utils_Array::value('contact_id', $userIds, ''));
117 $session->set('ufUniqID', CRM_Utils_Array::value('uf_name', $userIds, ''));
118 }
119 }
120
121 // return early
32998c82 122 if ($userSystemID == 0) {
6a488035
TO
123 return;
124 }
125
32998c82 126 $ufmatch = self::synchronizeUFMatch($user, $userSystemID, $uniqId, $uf, NULL, $ctype, $isLogin);
6a488035
TO
127 if (!$ufmatch) {
128 return;
129 }
130
131 //make sure we have session w/ consistent ids.
132 $ufID = $ufmatch->uf_id;
133 $userID = $ufmatch->contact_id;
134 $ufUniqID = '';
135 if ($isUserLoggedIn) {
136 $loggedInUserUfID = CRM_Utils_System::getLoggedInUfID();
137 //are we processing logged in user.
138 if ($loggedInUserUfID && $loggedInUserUfID != $ufID) {
139 $userIds = self::getUFValues($loggedInUserUfID);
140 $ufID = CRM_Utils_Array::value('uf_id', $userIds, '');
141 $userID = CRM_Utils_Array::value('contact_id', $userIds, '');
142 $ufUniqID = CRM_Utils_Array::value('uf_name', $userIds, '');
143 }
144 }
145
146 //set user ids to session.
147 $session->set('ufID', $ufID);
148 $session->set('userID', $userID);
149 $session->set('ufUniqID', $ufUniqID);
150
151 // add current contact to recently viewed
152 if ($ufmatch->contact_id) {
153 list($displayName, $contactImage, $contactType, $contactSubtype, $contactImageUrl) =
154 CRM_Contact_BAO_Contact::getDisplayAndImage($ufmatch->contact_id, TRUE, TRUE);
155
156 $otherRecent = array(
157 'imageUrl' => $contactImageUrl,
158 'subtype' => $contactSubtype,
159 'editUrl' => CRM_Utils_System::url('civicrm/contact/add', "reset=1&action=update&cid={$ufmatch->contact_id}"),
160 );
161
162 CRM_Utils_Recent::add($displayName,
163 CRM_Utils_System::url('civicrm/contact/view', "reset=1&cid={$ufmatch->contact_id}"),
164 $ufmatch->contact_id,
165 $contactType,
166 $ufmatch->contact_id,
167 $displayName,
168 $otherRecent
169 );
170 }
171 }
172
173 /**
174 * Synchronize the object with the UF Match entry. Can be called stand-alone from
175 * the drupalUsers script
176 *
6a0b768e
TO
177 * @param Object $user
178 * The drupal user object.
179 * @param string $userKey
180 * The id of the user from the uf object.
181 * @param string $uniqId
182 * The OpenID of the user.
183 * @param string $uf
184 * The name of the user framework.
185 * @param int $status
186 * Returns the status if user created or already exits (used for CMS sync).
fd31fa4c
EM
187 *
188 * @param null $ctype
189 * @param bool $isLogin
6a488035
TO
190 *
191 * @return the ufmatch object that was found or created
6a488035
TO
192 * @static
193 */
00be9182 194 public static function &synchronizeUFMatch(&$user, $userKey, $uniqId, $uf, $status = NULL, $ctype = NULL, $isLogin = FALSE) {
6a488035
TO
195 $config = CRM_Core_Config::singleton();
196
197 if (!CRM_Utils_Rule::email($uniqId)) {
198 $retVal = $status ? NULL : FALSE;
199 return $retVal;
200 }
201
202 $newContact = FALSE;
203
204 // make sure that a contact id exists for this user id
205 $ufmatch = new CRM_Core_DAO_UFMatch();
206 $ufmatch->domain_id = CRM_Core_Config::domainID();
207 $ufmatch->uf_id = $userKey;
208
209 if (!$ufmatch->find(TRUE)) {
210 $transaction = new CRM_Core_Transaction();
211
212 $dao = NULL;
213 if (!empty($_POST) && !$isLogin) {
214 $params = $_POST;
215 $params['email'] = $uniqId;
216
217 $dedupeParams = CRM_Dedupe_Finder::formatParams($params, 'Individual');
218 $dedupeParams['check_permission'] = FALSE;
219 $ids = CRM_Dedupe_Finder::dupesByParams($dedupeParams, 'Individual');
220
221 if (!empty($ids) &&
222 CRM_Core_BAO_Setting::getItem(
223 CRM_Core_BAO_Setting::MULTISITE_PREFERENCES_NAME,
224 'uniq_email_per_site'
225 )
226 ) {
227 // restrict dupeIds to ones that belong to current domain/site.
228 $siteContacts = CRM_Core_BAO_Domain::getContactList();
229 foreach ($ids as $index => $dupeId) {
230 if (!in_array($dupeId, $siteContacts)) {
231 unset($ids[$index]);
232 }
233 }
234 // re-index the array
235 $ids = array_values($ids);
236 }
237 if (!empty($ids)) {
238 $dao = new CRM_Core_DAO();
239 $dao->contact_id = $ids[0];
240 }
241 }
242 else {
243 $dao = CRM_Contact_BAO_Contact::matchContactOnEmail($uniqId, $ctype);
244 }
245
246 $found = FALSE;
247 if ($dao) {
248 // ensure there does not exists a contact_id / uf_id pair
249 // in the DB. This might be due to multiple emails per contact
250 // CRM-9091
251 $sql = "
252SELECT id
253FROM civicrm_uf_match
254WHERE contact_id = %1
255AND domain_id = %2
256";
257 $params = array(
258 1 => array($dao->contact_id, 'Integer'),
259 2 => array(CRM_Core_Config::domainID(), 'Integer'),
260 );
261 $conflict = CRM_Core_DAO::singleValueQuery($sql, $params);
262
263 if (!$conflict) {
264 $found = TRUE;
265 $ufmatch->contact_id = $dao->contact_id;
266 $ufmatch->uf_name = $uniqId;
267 }
268 }
269
270 if (!$found) {
271 if ($config->userSystem->is_drupal) {
272 $mail = 'mail';
273 }
274 elseif ($uf == 'WordPress') {
275 $mail = 'user_email';
276 }
277 else {
278 $mail = 'email';
279 }
280
281 if (is_object($user)) {
282 $params = array('email-Primary' => $user->$mail);
283 }
284
285 if ($ctype == 'Organization') {
286 $params['organization_name'] = $uniqId;
287 }
288 elseif ($ctype == 'Household') {
289 $params['household_name'] = $uniqId;
290 }
291
292 if (!$ctype) {
293 $ctype = "Individual";
294 }
295 $params['contact_type'] = $ctype;
296
297 // extract first / middle / last name
298 // for joomla
299 if ($uf == 'Joomla' && $user->name) {
300 CRM_Utils_String::extractName($user->name, $params);
301 }
302
303 if ($uf == 'WordPress') {
304 if ($user->first_name) {
305 $params['first_name'] = $user->first_name;
306 }
307
308 if ($user->last_name) {
309 $params['last_name'] = $user->last_name;
310 }
311 }
312
313 $contactId = CRM_Contact_BAO_Contact::createProfileContact($params, CRM_Core_DAO::$_nullArray);
314 $ufmatch->contact_id = $contactId;
315 $ufmatch->uf_name = $uniqId;
316 }
317
318 // check that there are not two CMS IDs matching the same CiviCRM contact - this happens when a civicrm
319 // user has two e-mails and there is a cms match for each of them
320 // the gets rid of the nasty fata error but still reports the error
321 $sql = "
322SELECT uf_id
323FROM civicrm_uf_match
324WHERE ( contact_id = %1
325OR uf_name = %2
326OR uf_id = %3 )
327AND domain_id = %4
328";
329 $params = array(
330 1 => array($ufmatch->contact_id, 'Integer'),
331 2 => array($ufmatch->uf_name, 'String'),
332 3 => array($ufmatch->uf_id, 'Integer'),
333 4 => array($ufmatch->domain_id, 'Integer'),
334 );
335
336 $conflict = CRM_Core_DAO::singleValueQuery($sql, $params);
337
338 if (!$conflict) {
339 $ufmatch = CRM_Core_BAO_UFMatch::create((array) $ufmatch);
340 $ufmatch->free();
341 $newContact = TRUE;
342 $transaction->commit();
343 }
344 else {
345 $msg = ts("Contact ID %1 is a match for %2 user %3 but has already been matched to %4",
346 array(
347 1 => $ufmatch->contact_id,
348 2 => $uf,
349 3 => $ufmatch->uf_id,
21dfd5f5 350 4 => $conflict,
6a488035
TO
351 )
352 );
353 unset($conflict);
354 }
355 }
356
357 if ($status) {
358 return $newContact;
359 }
360 else {
361 return $ufmatch;
362 }
363 }
364
365 /**
100fef9d 366 * Update the uf_name in the user object
6a488035 367 *
6a0b768e
TO
368 * @param int $contactId
369 * Id of the contact to update.
6a488035
TO
370 *
371 * @return void
6a488035
TO
372 * @static
373 */
00be9182 374 public static function updateUFName($contactId) {
6a488035
TO
375 if (!$contactId) {
376 return;
377 }
378 $config = CRM_Core_Config::singleton();
379 $ufName = CRM_Contact_BAO_Contact::getPrimaryEmail($contactId);
380
381 if (!$ufName) {
382 return;
383 }
384
385 $update = FALSE;
386
387 // 1.do check for contact Id.
388 $ufmatch = new CRM_Core_DAO_UFMatch();
389 $ufmatch->contact_id = $contactId;
390 $ufmatch->domain_id = CRM_Core_Config::domainID();
391 if (!$ufmatch->find(TRUE)) {
392 return;
393 }
394 if ($ufmatch->uf_name != $ufName) {
395 $update = TRUE;
396 }
397
398 // CRM-6928
399 // 2.do check for duplicate ufName.
400 $ufDupeName = new CRM_Core_DAO_UFMatch();
401 $ufDupeName->uf_name = $ufName;
402 $ufDupeName->domain_id = CRM_Core_Config::domainID();
403 if ($ufDupeName->find(TRUE) &&
404 $ufDupeName->contact_id != $contactId
405 ) {
406 $update = FALSE;
407 }
408
409 if (!$update) {
410 return;
411 }
412
413 // save the updated ufmatch object
414 $ufmatch->uf_name = $ufName;
415 $ufmatch->save();
416 $config->userSystem->updateCMSName($ufmatch->uf_id, $ufName);
417 }
418
419 /**
420 * Update the email value for the contact and user profile
421 *
5a4f6742
CW
422 * @param int $contactId
423 * Contact ID of the user.
6a0b768e
TO
424 * @param $emailAddress
425 * Email to be modified for the user.
6a488035
TO
426 *
427 * @return void
6a488035
TO
428 * @static
429 */
00be9182 430 public static function updateContactEmail($contactId, $emailAddress) {
6a488035
TO
431 $strtolower = function_exists('mb_strtolower') ? 'mb_strtolower' : 'strtolower';
432 $emailAddress = $strtolower($emailAddress);
433
434 $ufmatch = new CRM_Core_DAO_UFMatch();
435 $ufmatch->contact_id = $contactId;
436 $ufmatch->domain_id = CRM_Core_Config::domainID();
437 if ($ufmatch->find(TRUE)) {
438 // Save the email in UF Match table
439 $ufmatch->uf_name = $emailAddress;
440 CRM_Core_BAO_UFMatch::create((array) $ufmatch);
441
442 //check if the primary email for the contact exists
443 //$contactDetails[1] - email
444 //$contactDetails[3] - email id
445 $contactDetails = CRM_Contact_BAO_Contact_Location::getEmailDetails($contactId);
446
447 if (trim($contactDetails[1])) {
448 $emailID = $contactDetails[3];
449 //update if record is found
450 $query = "UPDATE civicrm_email
451 SET email = %1
452 WHERE id = %2";
453 $p = array(
454 1 => array($emailAddress, 'String'),
455 2 => array($emailID, 'Integer'),
456 );
457 $dao = CRM_Core_DAO::executeQuery($query, $p);
458 }
459 else {
460 //else insert a new email record
461 $email = new CRM_Core_DAO_Email();
462 $email->contact_id = $contactId;
463 $email->is_primary = 1;
464 $email->email = $emailAddress;
465 $email->save();
466 $emailID = $email->id;
467 }
468
469 CRM_Core_BAO_Log::register($contactId,
470 'civicrm_email',
471 $emailID
472 );
473 }
474 }
475
476 /**
477 * Delete the object records that are associated with this cms user
478 *
6a0b768e
TO
479 * @param int $ufID
480 * Id of the user to delete.
6a488035
TO
481 *
482 * @return void
6a488035
TO
483 * @static
484 */
00be9182 485 public static function deleteUser($ufID) {
6a488035
TO
486 $ufmatch = new CRM_Core_DAO_UFMatch();
487
488 $ufmatch->uf_id = $ufID;
489 $ufmatch->domain_id = CRM_Core_Config::domainID();
490 $ufmatch->delete();
491 }
492
493 /**
100fef9d 494 * Get the contact_id given a uf_id
6a488035 495 *
6a0b768e
TO
496 * @param int $ufID
497 * Id of UF for which related contact_id is required.
6a488035
TO
498 *
499 * @return int contact_id on success, null otherwise
6a488035
TO
500 * @static
501 */
00be9182 502 public static function getContactId($ufID) {
6a488035
TO
503 if (!isset($ufID)) {
504 return NULL;
505 }
506
507 $ufmatch = new CRM_Core_DAO_UFMatch();
508
509 $ufmatch->uf_id = $ufID;
510 $ufmatch->domain_id = CRM_Core_Config::domainID();
511 if ($ufmatch->find(TRUE)) {
512 return (int ) $ufmatch->contact_id;
513 }
514 return NULL;
515 }
516
517 /**
100fef9d 518 * Get the uf_id given a contact_id
6a488035 519 *
6a0b768e
TO
520 * @param int $contactID
521 * ID of the contact for which related uf_id is required.
6a488035
TO
522 *
523 * @return int uf_id of the given contact_id on success, null otherwise
6a488035
TO
524 * @static
525 */
00be9182 526 public static function getUFId($contactID) {
6a488035
TO
527 if (!isset($contactID)) {
528 return NULL;
529 }
530 $domain = CRM_Core_BAO_Domain::getDomain();
531 $ufmatch = new CRM_Core_DAO_UFMatch();
532
533 $ufmatch->contact_id = $contactID;
534 $ufmatch->domain_id = $domain->id;
535 if ($ufmatch->find(TRUE)) {
536 return $ufmatch->uf_id;
537 }
538 return NULL;
539 }
540
b5c2afd0
EM
541 /**
542 * @return bool
543 */
00be9182 544 public static function isEmptyTable() {
6a488035
TO
545 $sql = "SELECT count(id) FROM civicrm_uf_match";
546 return CRM_Core_DAO::singleValueQuery($sql) > 0 ? FALSE : TRUE;
547 }
548
549 /**
100fef9d 550 * Get the list of contact_id
6a488035
TO
551 *
552 *
553 * @return int contact_id on success, null otherwise
6a488035
TO
554 * @static
555 */
00be9182 556 public static function getContactIDs() {
6a488035
TO
557 $id = array();
558 $dao = new CRM_Core_DAO_UFMatch();
559 $dao->find();
560 while ($dao->fetch()) {
561 $id[] = $dao->contact_id;
562 }
563 return $id;
564 }
565
566 /**
100fef9d 567 * See if this user exists, and if so, if they're allowed to login
6a488035
TO
568 *
569 *
100fef9d 570 * @param int $openId
2a6da8d7 571 *
6a488035 572 * @return bool true if allowed to login, false otherwise
6a488035
TO
573 * @static
574 */
00be9182 575 public static function getAllowedToLogin($openId) {
6a488035
TO
576 $ufmatch = new CRM_Core_DAO_UFMatch();
577 $ufmatch->uf_name = $openId;
578 $ufmatch->allowed_to_login = 1;
579 if ($ufmatch->find(TRUE)) {
580 return TRUE;
581 }
582 return FALSE;
583 }
584
585 /**
100fef9d 586 * Get the next unused uf_id value, since the standalone UF doesn't
6a488035
TO
587 * have id's (it uses OpenIDs, which go in a different field)
588 *
589 *
590 * @return int next highest unused value for uf_id
6a488035
TO
591 * @static
592 */
00be9182 593 public static function getNextUfIdValue() {
6a488035
TO
594 $query = "SELECT MAX(uf_id)+1 AS next_uf_id FROM civicrm_uf_match";
595 $dao = CRM_Core_DAO::executeQuery($query);
596 if ($dao->fetch()) {
597 $ufId = $dao->next_uf_id;
598 }
599
600 if (!isset($ufId)) {
601 $ufId = 1;
602 }
603 return $ufId;
604 }
605
b5c2afd0
EM
606 /**
607 * @param $email
608 *
609 * @return bool
610 */
00be9182 611 public static function isDuplicateUser($email) {
6a488035
TO
612 $session = CRM_Core_Session::singleton();
613 $contactID = $session->get('userID');
614 if (!empty($email) && isset($contactID)) {
615 $dao = new CRM_Core_DAO_UFMatch();
616 $dao->uf_name = $email;
617 if ($dao->find(TRUE) && $contactID != $dao->contact_id) {
618 return TRUE;
619 }
620 }
621 return FALSE;
622 }
623
624 /**
625 * Get uf match values for given uf id or logged in user.
626 *
6a0b768e
TO
627 * @param int $ufID
628 * Uf id.
6a488035
TO
629 *
630 * return array $ufValues uf values.
2aa397bc 631 * *
77b97be7
EM
632 *
633 * @return array
634 */
00be9182 635 public static function getUFValues($ufID = NULL) {
6a488035
TO
636 if (!$ufID) {
637 //get logged in user uf id.
638 $ufID = CRM_Utils_System::getLoggedInUfID();
639 }
640 if (!$ufID) {
641 return array();
642 }
643
644 static $ufValues;
645 if ($ufID && !isset($ufValues[$ufID])) {
646 $ufmatch = new CRM_Core_DAO_UFMatch();
647 $ufmatch->uf_id = $ufID;
648 $ufmatch->domain_id = CRM_Core_Config::domainID();
649 if ($ufmatch->find(TRUE)) {
650 $ufValues[$ufID] = array(
651 'uf_id' => $ufmatch->uf_id,
652 'uf_name' => $ufmatch->uf_name,
653 'contact_id' => $ufmatch->contact_id,
654 'domain_id' => $ufmatch->domain_id,
655 );
656 }
657 }
658 return $ufValues[$ufID];
659 }
660}