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