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