CRM-14106 - Regex targeting the first part of if statements
[civicrm-core.git] / CRM / Core / BAO / CMSUser.php
1 <?php
2 /*
3 +--------------------------------------------------------------------+
4 | CiviCRM version 4.4 |
5 +--------------------------------------------------------------------+
6 | Copyright CiviCRM LLC (c) 2004-2013 |
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-2013
32 * $Id$
33 *
34 */
35
36 /**
37 * this file contains functions for synchronizing cms users with CiviCRM contacts
38 */
39
40 require_once 'DB.php';
41 class CRM_Core_BAO_CMSUser {
42
43 /**
44 * Function for synchronizing cms users with CiviCRM contacts
45 *
46 * @param bool $is_interactive whether to show statuses & perform redirects
47 * This behavior is misplaced in the BAO layer, but we'll preserve it to avoid
48 * contract changes in the middle of the support cycle. In the next major
49 * release, we should remove & document it.
50 *
51 * @return void
52 *
53 * @static
54 * @access public
55 */
56 static function synchronize($is_interactive = TRUE) {
57 //start of schronization code
58 $config = CRM_Core_Config::singleton();
59
60 // Build an array of rows from UF users table.
61 $rows = array();
62 if ($config->userSystem->is_drupal == '1') {
63 $id = 'uid';
64 $mail = 'mail';
65 $name = 'name';
66
67 $result = db_query("SELECT uid, mail, name FROM {users} where mail != ''");
68
69 if ($config->userFramework == 'Drupal') {
70 while ($row = $result->fetchAssoc()) {
71 $rows[] = $row;
72 }
73 }
74 elseif ($config->userFramework == 'Drupal6') {
75 while ($row = db_fetch_array($result)) {
76 $rows[] = $row;
77 }
78 }
79 }
80 elseif ($config->userFramework == 'Joomla') {
81 $id = 'id';
82 $mail = 'email';
83 $name = 'name';
84 // TODO: Insert code here to populate $rows for Joomla;
85 }
86 elseif ($config->userFramework == 'WordPress') {
87 $id = 'ID';
88 $mail = 'user_email';
89 }
90 else {
91 CRM_Core_Error::fatal('CMS user creation not supported for this framework');
92 }
93
94 set_time_limit(300);
95
96 if ($config->userSystem->is_drupal == '1') {
97 $user = new StdClass();
98 $uf = $config->userFramework;
99 $contactCount = 0;
100 $contactCreated = 0;
101 $contactMatching = 0;
102 foreach ($rows as $row) {
103 $user->$id = $row[$id];
104 $user->$mail = $row[$mail];
105 $user->$name = $row[$name];
106 $contactCount++;
107 if ($match = CRM_Core_BAO_UFMatch::synchronizeUFMatch($user, $row[$id], $row[$mail], $uf, 1, 'Individual', TRUE)) {
108 $contactCreated++;
109 }
110 else {
111 $contactMatching++;
112 }
113 if (is_object($match)) {
114 $match->free();
115 }
116 }
117 }
118 elseif ($config->userFramework == 'Joomla') {
119
120 $JUserTable = &JTable::getInstance('User', 'JTable');
121
122 $db = $JUserTable->getDbo();
123 $query = $db->getQuery(TRUE);
124 $query->select($id . ', ' . $mail . ', ' . $name);
125 $query->from($JUserTable->getTableName());
126 $query->where($mail != '');
127
128 $db->setQuery($query, 0, $limit);
129 $users = $db->loadObjectList();
130
131 $user = new StdClass();
132 $uf = $config->userFramework;
133 $contactCount = 0;
134 $contactCreated = 0;
135 $contactMatching = 0;
136 for ($i = 0; $i < count($users); $i++) {
137 $user->$id = $users[$i]->$id;
138 $user->$mail = $users[$i]->$mail;
139 $user->$name = $users[$i]->$name;
140 $contactCount++;
141 if ($match = CRM_Core_BAO_UFMatch::synchronizeUFMatch($user,
142 $users[$i]->$id,
143 $users[$i]->$mail,
144 $uf,
145 1,
146 'Individual',
147 TRUE
148 )) {
149 $contactCreated++;
150 }
151 else {
152 $contactMatching++;
153 }
154 if (is_object($match)) {
155 $match->free();
156 }
157 }
158 }
159 elseif ($config->userFramework == 'WordPress') {
160 $uf = $config->userFramework;
161 $contactCount = 0;
162 $contactCreated = 0;
163 $contactMatching = 0;
164
165 global $wpdb;
166 $wpUserIds = $wpdb->get_col("SELECT $wpdb->users.ID FROM $wpdb->users");
167
168 foreach ($wpUserIds as $wpUserId) {
169 $wpUserData = get_userdata($wpUserId);
170 $contactCount++;
171 if ($match = CRM_Core_BAO_UFMatch::synchronizeUFMatch($wpUserData,
172 $wpUserData->$id,
173 $wpUserData->$mail,
174 $uf,
175 1,
176 'Individual',
177 TRUE
178 )) {
179 $contactCreated++;
180 }
181 else {
182 $contactMatching++;
183 }
184 if (is_object($match)) {
185 $match->free();
186 }
187 }
188 }
189 //end of synchronization code
190
191 if ($is_interactive) {
192 $status = ts('Synchronize Users to Contacts completed.');
193 $status .= ' ' . ts('Checked one user record.',
194 array(
195 'count' => $contactCount,
196 'plural' => 'Checked %count user records.'
197 )
198 );
199 if ($contactMatching) {
200 $status .= ' ' . ts('Found one matching contact record.',
201 array(
202 'count' => $contactMatching,
203 'plural' => 'Found %count matching contact records.'
204 )
205 );
206 }
207
208 $status .= ' ' . ts('Created one new contact record.',
209 array(
210 'count' => $contactCreated,
211 'plural' => 'Created %count new contact records.'
212 )
213 );
214 CRM_Core_Session::setStatus($status, ts('Saved'), 'success');
215 CRM_Utils_System::redirect(CRM_Utils_System::url('civicrm/admin', 'reset=1'));
216 }
217 }
218
219 /**
220 * Function to create CMS user using Profile
221 *
222 * @param array $params associated array
223 * @param string $mail email id for cms user
224 *
225 * @return int contact id that has been created
226 * @access public
227 * @static
228 */
229 static function create(&$params, $mail) {
230 $config = CRM_Core_Config::singleton();
231
232 $ufID = $config->userSystem->createUser($params, $mail);
233
234 //if contact doesn't already exist create UF Match
235 if ($ufID !== FALSE &&
236 isset($params['contactID'])
237 ) {
238 // create the UF Match record
239 $ufmatch = new CRM_Core_DAO_UFMatch();
240 $ufmatch->domain_id = CRM_Core_Config::domainID();
241 $ufmatch->uf_id = $ufID;
242 $ufmatch->contact_id = $params['contactID'];
243 $ufmatch->uf_name = $params[$mail];
244
245 if (!$ufmatch->find(TRUE)) {
246 $ufmatch->save();
247 }
248 }
249
250 return $ufID;
251 }
252
253 /**
254 * Function to create Form for CMS user using Profile
255 *
256 * @param object $form
257 * @param integer $gid id of group of profile
258 * @param bool $emailPresent true if the profile field has email(primary)
259 * @return FALSE|void WTF
260 *
261 * @access public
262 * @static
263 */
264 static function buildForm(&$form, $gid, $emailPresent, $action = CRM_Core_Action::NONE) {
265 $config = CRM_Core_Config::singleton();
266 $showCMS = FALSE;
267
268 $isDrupal = $config->userSystem->is_drupal;
269 $isJoomla = ucfirst($config->userFramework) == 'Joomla' ? TRUE : FALSE;
270 $isWordPress = $config->userFramework == 'WordPress' ? TRUE : FALSE;
271
272 //if CMS is configured for not to allow creating new CMS user,
273 //don't build the form,Fixed for CRM-4036
274 if ($isJoomla) {
275 $userParams = JComponentHelper::getParams('com_users');
276 if (!$userParams->get('allowUserRegistration')) {
277 return FALSE;
278 }
279 }
280 elseif ($isDrupal && !variable_get('user_register', TRUE)) {
281 return FALSE;
282 }
283 elseif ($isWordPress && !get_option('users_can_register')) {
284 return FALSE;
285 }
286
287 if ($gid) {
288 $isCMSUser = CRM_Core_DAO::getFieldValue('CRM_Core_DAO_UFGroup', $gid, 'is_cms_user');
289 }
290
291 // $cms is true when there is email(primary location) is set in the profile field.
292 $session = CRM_Core_Session::singleton();
293 $userID = $session->get('userID');
294 $showUserRegistration = FALSE;
295 if ($action) {
296 $showUserRegistration = TRUE;
297 }
298 elseif (!$action && !$userID) {
299 $showUserRegistration = TRUE;
300 }
301
302 if ($isCMSUser && $emailPresent) {
303 if ($showUserRegistration) {
304 if ($isCMSUser != 2) {
305 $extra = array(
306 'onclick' => "return showHideByValue('cms_create_account','','details','block','radio',false );",
307 );
308 $form->addElement('checkbox', 'cms_create_account', ts('Create an account?'), NULL, $extra);
309 $required = FALSE;
310 }
311 else {
312 $form->add('hidden', 'cms_create_account', 1);
313 $required = TRUE;
314 }
315
316 $form->assign('isCMS', $required);
317 if (!$userID || $action & CRM_Core_Action::PREVIEW || $action & CRM_Core_Action::PROFILE) {
318 $form->add('text', 'cms_name', ts('Username'), NULL, $required);
319 if (($isDrupal && !variable_get('user_email_verification', TRUE)) OR ($isJoomla) OR ($isWordPress)) {
320 $form->add('password', 'cms_pass', ts('Password'));
321 $form->add('password', 'cms_confirm_pass', ts('Confirm Password'));
322 }
323
324 $form->addFormRule(array('CRM_Core_BAO_CMSUser', 'formRule'), $form);
325 }
326 $showCMS = TRUE;
327 }
328 }
329
330 $destination = $config->userSystem->getLoginDestination($form);
331 $loginURL = $config->userSystem->getLoginURL($destination);
332 $form->assign('loginURL', $loginURL);
333 $form->assign('showCMS', $showCMS);
334 }
335
336 /*
337 * Checks that there is a valid username & email
338 * optionally checks password is present & matches DB & gets the CMS to validate
339 *
340 * @params array $fields Posted values of form
341 * @param array $files uploaded files if any
342 * @param array $self reference to form object
343 *
344 */
345 static function formRule($fields, $files, $self) {
346 if (empty($fields['cms_create_account'])) {
347 return TRUE;
348 }
349
350 $config = CRM_Core_Config::singleton();
351
352 $isDrupal = $config->userSystem->is_drupal;
353 $isJoomla = ucfirst($config->userFramework) == 'Joomla' ? TRUE : FALSE;
354 $isWordPress = $config->userFramework == 'WordPress' ? TRUE : FALSE;
355
356 $errors = array();
357 if ($isDrupal || $isJoomla || $isWordPress) {
358 $emailName = NULL;
359 if (!empty($self->_bltID) && array_key_exists("email-{$self->_bltID}", $fields)) {
360 // this is a transaction related page
361 $emailName = 'email-' . $self->_bltID;
362 } else {
363 // find the email field in a profile page
364 foreach ($fields as $name => $dontCare) {
365 if (substr($name, 0, 5) == 'email') {
366 $emailName = $name;
367 break;
368 }
369 }
370 }
371
372 if ($emailName == NULL) {
373 $errors['_qf_default'] == ts('Could not find an email address.');
374 return $errors;
375 }
376
377 if (empty($fields['cms_name'])) {
378 $errors['cms_name'] = ts('Please specify a username.');
379 }
380
381 if (empty($fields[$emailName])) {
382 $errors[$emailName] = ts('Please specify a valid email address.');
383 }
384
385 if (($isDrupal && !variable_get('user_email_verification', TRUE)) OR ($isJoomla) OR ($isWordPress)) {
386 if (empty($fields['cms_pass']) ||
387 empty($fields['cms_confirm_pass'])
388 ) {
389 $errors['cms_pass'] = ts('Please enter a password.');
390 }
391 if ($fields['cms_pass'] != $fields['cms_confirm_pass']) {
392 $errors['cms_pass'] = ts('Password and Confirm Password values are not the same.');
393 }
394 }
395
396 if (!empty($errors)) {
397 return $errors;
398 }
399
400 // now check that the cms db does not have the user name and/or email
401 if ($isDrupal OR $isJoomla OR $isWordPress) {
402 $params = array(
403 'name' => $fields['cms_name'],
404 'mail' => $fields[$emailName],
405 );
406 }
407
408 $config->userSystem->checkUserNameEmailExists($params, $errors, $emailName);
409 }
410 return (!empty($errors)) ? $errors : TRUE;
411 }
412
413 /**
414 * Function to check if a cms user already exists.
415 *
416 * @param Array $contact array of contact-details
417 *
418 * @return uid if user exists, false otherwise
419 *
420 * @access public
421 * @static
422 */
423 static function userExists(&$contact) {
424 $config = CRM_Core_Config::singleton();
425
426 $isDrupal = $config->userSystem->is_drupal;
427 $isJoomla = ucfirst($config->userFramework) == 'Joomla' ? TRUE : FALSE;
428 $isWordPress = $config->userFramework == 'WordPress' ? TRUE : FALSE;
429
430 if (!$isDrupal && !$isJoomla && !$isWordPress) {
431 die('Unknown user framework');
432 }
433
434 // Use UF native framework to fetch data from UF user table
435 if ($isDrupal) {
436 $uid = db_query(
437 "SELECT uid FROM {users} where mail = :email",
438 array(':email' => $contact['email'])
439 )->fetchField();
440
441 if ($uid) {
442 $contact['user_exists'] = TRUE;
443 $result = $uid;
444 }
445 }
446 elseif ($isJoomla) {
447 $mail = $contact['email'];
448
449 $JUserTable = &JTable::getInstance('User', 'JTable');
450
451 $db = $JUserTable->getDbo();
452 $query = $db->getQuery(TRUE);
453 $query->select('username, email');
454 $query->from($JUserTable->getTableName());
455 $query->where('(LOWER(email) = LOWER(\'' . $email . '\'))');
456 $db->setQuery($query, 0, $limit);
457 $users = $db->loadAssocList();
458
459 $row = array();;
460 if (count($users)) {
461 $row = $users[0];
462 }
463
464 if (!empty($row)) {
465 $uid = CRM_Utils_Array::value('id', $row);
466 $contact['user_exists'] = TRUE;
467 $result = $uid;
468 }
469 }
470 elseif ($isWordPress) {
471 if (email_exists($params['mail'])) {
472 $contact['user_exists'] = TRUE;
473 $userObj = get_user_by('email', $params['mail']);
474 return $userObj->ID;
475 }
476 }
477
478 return $result;
479 }
480
481 static function &dbHandle(&$config) {
482 CRM_Core_Error::ignoreException();
483 $db_uf = DB::connect($config->userFrameworkDSN);
484 CRM_Core_Error::setCallback();
485 if (!$db_uf ||
486 DB::isError($db_uf)
487 ) {
488 $session = CRM_Core_Session::singleton();
489 $session->pushUserContext(CRM_Utils_System::url('civicrm/admin', 'reset=1'));
490 CRM_Core_Error::statusBounce(ts("Cannot connect to UF db via %1. Please check the CIVICRM_UF_DSN value in your civicrm.settings.php file",
491 array(1 => $db_uf->getMessage())
492 ));
493 }
494 $db_uf->query('/*!40101 SET NAMES utf8 */');
495 return $db_uf;
496 }
497 }
498