3 +--------------------------------------------------------------------+
4 | CiviCRM version 4.5 |
5 +--------------------------------------------------------------------+
6 | Copyright CiviCRM LLC (c) 2004-2014 |
7 +--------------------------------------------------------------------+
8 | This file is a part of CiviCRM. |
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. |
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. |
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 +--------------------------------------------------------------------+
31 * @copyright CiviCRM LLC (c) 2004-2014
37 * The basic class that interfaces with the external user framework
39 class CRM_Core_BAO_UFMatch
extends CRM_Core_DAO_UFMatch
{
42 * Create UF Match, Note that thsi function is here in it's simplest form @ the moment
45 * @param array $params input parameters
48 * @param array $params
50 * @return CRM_Core_DAO_UFMatch
52 static function create($params) {
53 $hook = empty($params['id']) ?
'create' : 'edit';
54 CRM_Utils_Hook
::pre($hook, 'UFMatch', CRM_Utils_Array
::value('id', $params), $params);
55 if(empty($params['domain_id'])) {
56 $params['domain_id'] = CRM_Core_Config
::domainID();
58 $dao = new CRM_Core_DAO_UFMatch();
59 $dao->copyValues($params);
61 CRM_Utils_Hook
::post($hook, 'UFMatch', $dao->id
, $dao);
67 * Given a UF user object, make sure there is a contact
68 * object for this user. If the user has new values, we need
69 * to update the CRM DB with the new values
71 * @param Object $user the drupal user object
72 * @param boolean $update has the user object been edited
76 * @param bool $isLogin
82 static function synchronize(&$user, $update, $uf, $ctype, $isLogin = FALSE) {
83 $userSystem = CRM_Core_Config
::singleton()->userSystem
;
84 $session = CRM_Core_Session
::singleton();
85 if (!is_object($session)) {
86 CRM_Core_Error
::fatal('wow, session is not an object?');
90 $userSystemID = $userSystem->getBestUFID($user);
91 $uniqId = $userSystem->getBestUFUniqueIdentifier($user);
93 // if the id of the object is zero (true for anon users in drupal)
94 // have we already processed this user, if so early
96 $userID = $session->get('userID');
97 $ufID = $session->get('ufID');
99 if (!$update && $ufID == $userSystemID) {
103 //check do we have logged in user.
104 $isUserLoggedIn = CRM_Utils_System
::isUserLoggedIn();
106 // reset the session if we are a different user
107 if ($ufID && $ufID != $userSystemID) {
110 //get logged in user ids, and set to session.
111 if ($isUserLoggedIn) {
112 $userIds = self
::getUFValues();
113 $session->set('ufID', CRM_Utils_Array
::value('uf_id', $userIds, ''));
114 $session->set('userID', CRM_Utils_Array
::value('contact_id', $userIds, ''));
115 $session->set('ufUniqID', CRM_Utils_Array
::value('uf_name', $userIds, ''));
120 if ($userSystemID == 0) {
124 $ufmatch = self
::synchronizeUFMatch($user, $userSystemID, $uniqId, $uf, NULL, $ctype, $isLogin);
129 //make sure we have session w/ consistent ids.
130 $ufID = $ufmatch->uf_id
;
131 $userID = $ufmatch->contact_id
;
133 if ($isUserLoggedIn) {
134 $loggedInUserUfID = CRM_Utils_System
::getLoggedInUfID();
135 //are we processing logged in user.
136 if ($loggedInUserUfID && $loggedInUserUfID != $ufID) {
137 $userIds = self
::getUFValues($loggedInUserUfID);
138 $ufID = CRM_Utils_Array
::value('uf_id', $userIds, '');
139 $userID = CRM_Utils_Array
::value('contact_id', $userIds, '');
140 $ufUniqID = CRM_Utils_Array
::value('uf_name', $userIds, '');
144 //set user ids to session.
145 $session->set('ufID', $ufID);
146 $session->set('userID', $userID);
147 $session->set('ufUniqID', $ufUniqID);
149 // add current contact to recently viewed
150 if ($ufmatch->contact_id
) {
151 list($displayName, $contactImage, $contactType, $contactSubtype, $contactImageUrl) =
152 CRM_Contact_BAO_Contact
::getDisplayAndImage($ufmatch->contact_id
, TRUE, TRUE);
154 $otherRecent = array(
155 'imageUrl' => $contactImageUrl,
156 'subtype' => $contactSubtype,
157 'editUrl' => CRM_Utils_System
::url('civicrm/contact/add', "reset=1&action=update&cid={$ufmatch->contact_id}"),
160 CRM_Utils_Recent
::add($displayName,
161 CRM_Utils_System
::url('civicrm/contact/view', "reset=1&cid={$ufmatch->contact_id}"),
162 $ufmatch->contact_id
,
164 $ufmatch->contact_id
,
172 * Synchronize the object with the UF Match entry. Can be called stand-alone from
173 * the drupalUsers script
175 * @param Object $user the drupal user object
176 * @param string $userKey the id of the user from the uf object
177 * @param string $uniqId the OpenID of the user
178 * @param string $uf the name of the user framework
179 * @param integer $status returns the status if user created or already exits (used for CMS sync)
182 * @param bool $isLogin
184 * @return the ufmatch object that was found or created
188 static function &synchronizeUFMatch(&$user, $userKey, $uniqId, $uf, $status = NULL, $ctype = NULL, $isLogin = FALSE) {
189 $config = CRM_Core_Config
::singleton();
191 if (!CRM_Utils_Rule
::email($uniqId)) {
192 $retVal = $status ?
NULL : FALSE;
198 // make sure that a contact id exists for this user id
199 $ufmatch = new CRM_Core_DAO_UFMatch();
200 $ufmatch->domain_id
= CRM_Core_Config
::domainID();
201 $ufmatch->uf_id
= $userKey;
203 if (!$ufmatch->find(TRUE)) {
204 $transaction = new CRM_Core_Transaction();
207 if (!empty($_POST) && !$isLogin) {
209 $params['email'] = $uniqId;
211 $dedupeParams = CRM_Dedupe_Finder
::formatParams($params, 'Individual');
212 $dedupeParams['check_permission'] = FALSE;
213 $ids = CRM_Dedupe_Finder
::dupesByParams($dedupeParams, 'Individual');
216 CRM_Core_BAO_Setting
::getItem(
217 CRM_Core_BAO_Setting
::MULTISITE_PREFERENCES_NAME
,
218 'uniq_email_per_site'
221 // restrict dupeIds to ones that belong to current domain/site.
222 $siteContacts = CRM_Core_BAO_Domain
::getContactList();
223 foreach ($ids as $index => $dupeId) {
224 if (!in_array($dupeId, $siteContacts)) {
228 // re-index the array
229 $ids = array_values($ids);
232 $dao = new CRM_Core_DAO();
233 $dao->contact_id
= $ids[0];
237 $dao = CRM_Contact_BAO_Contact
::matchContactOnEmail($uniqId, $ctype);
242 // ensure there does not exists a contact_id / uf_id pair
243 // in the DB. This might be due to multiple emails per contact
247 FROM civicrm_uf_match
248 WHERE contact_id = %1
252 1 => array($dao->contact_id
, 'Integer'),
253 2 => array(CRM_Core_Config
::domainID(), 'Integer'),
255 $conflict = CRM_Core_DAO
::singleValueQuery($sql, $params);
259 $ufmatch->contact_id
= $dao->contact_id
;
260 $ufmatch->uf_name
= $uniqId;
265 if ($config->userSystem
->is_drupal
) {
268 elseif ($uf == 'WordPress') {
269 $mail = 'user_email';
275 if (is_object($user)) {
276 $params = array('email-Primary' => $user->$mail);
279 if ($ctype == 'Organization') {
280 $params['organization_name'] = $uniqId;
282 elseif ($ctype == 'Household') {
283 $params['household_name'] = $uniqId;
287 $ctype = "Individual";
289 $params['contact_type'] = $ctype;
291 // extract first / middle / last name
293 if ($uf == 'Joomla' && $user->name
) {
294 CRM_Utils_String
::extractName($user->name
, $params);
297 if ($uf == 'WordPress') {
298 if ($user->first_name
) {
299 $params['first_name'] = $user->first_name
;
302 if ($user->last_name
) {
303 $params['last_name'] = $user->last_name
;
307 $contactId = CRM_Contact_BAO_Contact
::createProfileContact($params, CRM_Core_DAO
::$_nullArray);
308 $ufmatch->contact_id
= $contactId;
309 $ufmatch->uf_name
= $uniqId;
312 // check that there are not two CMS IDs matching the same CiviCRM contact - this happens when a civicrm
313 // user has two e-mails and there is a cms match for each of them
314 // the gets rid of the nasty fata error but still reports the error
317 FROM civicrm_uf_match
318 WHERE ( contact_id = %1
324 1 => array($ufmatch->contact_id
, 'Integer'),
325 2 => array($ufmatch->uf_name
, 'String'),
326 3 => array($ufmatch->uf_id
, 'Integer'),
327 4 => array($ufmatch->domain_id
, 'Integer'),
330 $conflict = CRM_Core_DAO
::singleValueQuery($sql, $params);
333 $ufmatch = CRM_Core_BAO_UFMatch
::create((array) $ufmatch);
336 $transaction->commit();
339 $msg = ts("Contact ID %1 is a match for %2 user %3 but has already been matched to %4",
341 1 => $ufmatch->contact_id
,
343 3 => $ufmatch->uf_id
,
360 * Update the uf_name in the user object
362 * @param int $contactId id of the contact to update
368 static function updateUFName($contactId) {
372 $config = CRM_Core_Config
::singleton();
373 $ufName = CRM_Contact_BAO_Contact
::getPrimaryEmail($contactId);
381 // 1.do check for contact Id.
382 $ufmatch = new CRM_Core_DAO_UFMatch();
383 $ufmatch->contact_id
= $contactId;
384 $ufmatch->domain_id
= CRM_Core_Config
::domainID();
385 if (!$ufmatch->find(TRUE)) {
388 if ($ufmatch->uf_name
!= $ufName) {
393 // 2.do check for duplicate ufName.
394 $ufDupeName = new CRM_Core_DAO_UFMatch();
395 $ufDupeName->uf_name
= $ufName;
396 $ufDupeName->domain_id
= CRM_Core_Config
::domainID();
397 if ($ufDupeName->find(TRUE) &&
398 $ufDupeName->contact_id
!= $contactId
407 // save the updated ufmatch object
408 $ufmatch->uf_name
= $ufName;
410 $config->userSystem
->updateCMSName($ufmatch->uf_id
, $ufName);
414 * Update the email value for the contact and user profile
416 * @param $contactId Int Contact ID of the user
417 * @param $emailAddress email to be modified for the user
423 static function updateContactEmail($contactId, $emailAddress) {
424 $strtolower = function_exists('mb_strtolower') ?
'mb_strtolower' : 'strtolower';
425 $emailAddress = $strtolower($emailAddress);
427 $ufmatch = new CRM_Core_DAO_UFMatch();
428 $ufmatch->contact_id
= $contactId;
429 $ufmatch->domain_id
= CRM_Core_Config
::domainID();
430 if ($ufmatch->find(TRUE)) {
431 // Save the email in UF Match table
432 $ufmatch->uf_name
= $emailAddress;
433 CRM_Core_BAO_UFMatch
::create((array) $ufmatch);
435 //check if the primary email for the contact exists
436 //$contactDetails[1] - email
437 //$contactDetails[3] - email id
438 $contactDetails = CRM_Contact_BAO_Contact_Location
::getEmailDetails($contactId);
440 if (trim($contactDetails[1])) {
441 $emailID = $contactDetails[3];
442 //update if record is found
443 $query = "UPDATE civicrm_email
447 1 => array($emailAddress, 'String'),
448 2 => array($emailID, 'Integer'),
450 $dao = CRM_Core_DAO
::executeQuery($query, $p);
453 //else insert a new email record
454 $email = new CRM_Core_DAO_Email();
455 $email->contact_id
= $contactId;
456 $email->is_primary
= 1;
457 $email->email
= $emailAddress;
459 $emailID = $email->id
;
462 CRM_Core_BAO_Log
::register($contactId,
470 * Delete the object records that are associated with this cms user
472 * @param int $ufID id of the user to delete
478 static function deleteUser($ufID) {
479 $ufmatch = new CRM_Core_DAO_UFMatch();
481 $ufmatch->uf_id
= $ufID;
482 $ufmatch->domain_id
= CRM_Core_Config
::domainID();
487 * Get the contact_id given a uf_id
489 * @param int $ufID Id of UF for which related contact_id is required
491 * @return int contact_id on success, null otherwise
495 static function getContactId($ufID) {
500 $ufmatch = new CRM_Core_DAO_UFMatch();
502 $ufmatch->uf_id
= $ufID;
503 $ufmatch->domain_id
= CRM_Core_Config
::domainID();
504 if ($ufmatch->find(TRUE)) {
505 return (int ) $ufmatch->contact_id
;
511 * Get the uf_id given a contact_id
513 * @param int $contactID ID of the contact for which related uf_id is required
515 * @return int uf_id of the given contact_id on success, null otherwise
519 static function getUFId($contactID) {
520 if (!isset($contactID)) {
523 $domain = CRM_Core_BAO_Domain
::getDomain();
524 $ufmatch = new CRM_Core_DAO_UFMatch();
526 $ufmatch->contact_id
= $contactID;
527 $ufmatch->domain_id
= $domain->id
;
528 if ($ufmatch->find(TRUE)) {
529 return $ufmatch->uf_id
;
537 static function isEmptyTable() {
538 $sql = "SELECT count(id) FROM civicrm_uf_match";
539 return CRM_Core_DAO
::singleValueQuery($sql) > 0 ?
FALSE : TRUE;
543 * Get the list of contact_id
546 * @return int contact_id on success, null otherwise
550 static function getContactIDs() {
552 $dao = new CRM_Core_DAO_UFMatch();
554 while ($dao->fetch()) {
555 $id[] = $dao->contact_id
;
561 * See if this user exists, and if so, if they're allowed to login
566 * @return bool true if allowed to login, false otherwise
570 static function getAllowedToLogin($openId) {
571 $ufmatch = new CRM_Core_DAO_UFMatch();
572 $ufmatch->uf_name
= $openId;
573 $ufmatch->allowed_to_login
= 1;
574 if ($ufmatch->find(TRUE)) {
581 * Get the next unused uf_id value, since the standalone UF doesn't
582 * have id's (it uses OpenIDs, which go in a different field)
585 * @return int next highest unused value for uf_id
589 static function getNextUfIdValue() {
590 $query = "SELECT MAX(uf_id)+1 AS next_uf_id FROM civicrm_uf_match";
591 $dao = CRM_Core_DAO
::executeQuery($query);
593 $ufId = $dao->next_uf_id
;
607 static function isDuplicateUser($email) {
608 $session = CRM_Core_Session
::singleton();
609 $contactID = $session->get('userID');
610 if (!empty($email) && isset($contactID)) {
611 $dao = new CRM_Core_DAO_UFMatch();
612 $dao->uf_name
= $email;
613 if ($dao->find(TRUE) && $contactID != $dao->contact_id
) {
621 * Get uf match values for given uf id or logged in user.
623 * @param int $ufID uf id.
625 * return array $ufValues uf values.
630 static function getUFValues($ufID = NULL) {
632 //get logged in user uf id.
633 $ufID = CRM_Utils_System
::getLoggedInUfID();
640 if ($ufID && !isset($ufValues[$ufID])) {
641 $ufmatch = new CRM_Core_DAO_UFMatch();
642 $ufmatch->uf_id
= $ufID;
643 $ufmatch->domain_id
= CRM_Core_Config
::domainID();
644 if ($ufmatch->find(TRUE)) {
645 $ufValues[$ufID] = array(
646 'uf_id' => $ufmatch->uf_id
,
647 'uf_name' => $ufmatch->uf_name
,
648 'contact_id' => $ufmatch->contact_id
,
649 'domain_id' => $ufmatch->domain_id
,
653 return $ufValues[$ufID];