roles = isset($edit['roles']) ? $edit['roles'] : $user->roles;
$user->status = isset($edit['status']) ? $edit['status'] : TRUE;
gallery_user_modify($user, 'create');
}
/**
* Function gallery_user_update().
* (update a user with new information)
*/
function gallery_user_update(&$edit, $user) {
$user->language = isset($edit['language']) ? $edit['language'] : gallery_get_language($user);
$user->pass = !empty($edit['pass']) ? md5($edit['pass']) : $user->pass;
$user->status = isset($edit['status']) ? $edit['status'] : $user->status;
$user->mail = !empty($edit['mail']) ? $edit['mail'] : $user->mail;
$user->roles = isset($edit['roles']) ? $edit['roles'] : $user->roles;
// Fullname support
if (module_exists('profile') && variable_get('gallery_use_fullname', 0)) {
$fullname_field = variable_get('gallery_profile_fullname_field', 'profile_fullname');
$user->$fullname_field = isset($edit[$fullname_field]) ? $edit[$fullname_field] : $user->$fullname_field;
}
// Username is about to change
if ($namechange = (isset($edit['name']) && ($edit['name'] != $user->name))) {
// Make sure the original user is up to date
gallery_user_modify($user, 'update', TRUE);
}
$user->name = isset($edit['name']) ? $edit['name'] : $user->name;
if ($namechange) {
// Change username
gallery_user_modify($user, 'username');
}
else {
// Update user
gallery_user_modify($user, 'update', TRUE);
}
}
/**
* Function gallery_user_delete().
* (delete the user from the Gallery)
*/
function gallery_user_delete($user) {
gallery_user_modify($user, 'delete');
}
/**
* Function gallery_user_modify().
* (modify (create/update/delete) a user)
*/
function gallery_user_modify($user, $action = 'create', $groups = FALSE, $vars = NULL) {
if (!_gallery_init(TRUE, $vars)) {
return FALSE;
}
// Check for fullname support
$fullname_field = variable_get('gallery_profile_fullname_field', 'profile_fullname');
$usefullname = module_exists('profile') && variable_get('gallery_use_fullname', 0);
$fullname = $usefullname ? (isset($user->$fullname_field) ? $user->$fullname_field : '') : $user->name;
// Generate random password for G2 if user is blocked
$pass = ($user->status) ? $user->pass : user_password(20);
switch ($action) {
case 'username':
$ret = GalleryEmbed::updateUser($user->uid,
array('username' => $user->name,
'fullname' => $fullname,
'email' => $user->mail,
'language' => gallery_get_language($user),
'hashedpassword' => $pass,
'hashmethod' => 'md5'));
if ($ret) {
gallery_error(t('Error updating Gallery user (username changed)'), $ret);
return FALSE;
}
break;
case 'create' :
case 'update' :
// Get map state of the user
list($g2_user_state, $g2_user, $ret) = gallery_user_map_state($user);
if ($ret) {
gallery_error(t('Error determining user map state'), $ret);
return FALSE;
}
// Complete user mapping
switch ($g2_user_state) {
case G2MAP_USER_EXISTS_BUT_NEEDS_MAPPING:
// create map entry for the user
$ret = GalleryEmbed::addExternalIdMapEntry($user->uid, $g2_user->id, 'GalleryUser');
if ($ret) {
gallery_error(t('Error creating map entry (ExternlIdMapEntry)'), $ret);
return FALSE;
}
case G2MAP_USER_EXISTS:
// Update user (Drupal -> G2)
$ret = GalleryEmbed::updateUser($user->uid,
array('username' => $user->name,
'fullname' => $fullname,
'email' => $user->mail,
'language' => gallery_get_language($user),
'hashedpassword' => $pass,
'hashmethod' => 'md5'));
if ($ret) {
gallery_error(t('Error updating Gallery user'), $ret);
return FALSE;
}
break;
case G2MAP_USER_DOES_NOT_EXIST_BUT_IS_MAPPED:
// Remove mapping for non-existing user
// (also happens if gallery_user_modify() is called with a changed username)
$ret = GalleryCoreApi::removeMapEntry('ExternalIdMap', array('externalId' => $user->uid, 'entityType' => 'GalleryUser'));
if ($ret) {
gallery_error(t('Error removing map entry (ExternlIdMapEntry)'), $ret);
return FALSE;
}
case G2MAP_USER_DOES_NOT_EXIST:
// Create new user
if (!$user->uid)
return FALSE;
$ret = GalleryEmbed::createUser($user->uid,
array('username' => $user->name,
'email' => $user->mail,
'fullname' => $fullname,
'language' => gallery_get_language($user),
'hashedpassword' => $pass,
'hashmethod' => 'md5'));
if ($ret) {
gallery_error(t('Error creating Gallery user'), $ret);
return FALSE;
}
list($ret, $g2_user) = GalleryCoreApi::loadEntityByExternalId($user->uid, 'GalleryUser');
if ($ret) {
gallery_error(t('Error loading newly created Gallery user'), $ret);
return FALSE;
}
break;
}
// Update group info
_gallery_groups_user($user, $groups);
// Admin role mapping
$admin_role = variable_get('gallery_user_admin_role', 0);
if (($admin_role && in_array($admin_role, array_keys($user->roles))) || ($user->uid == 1)) {
// Get G2 admin group id
list($ret, $g2_admin_gid) = GalleryCoreApi::getPluginParameter('module', 'core', 'id.adminGroup');
if ($ret) {
gallery_error(t('Error getting \'adminGroup\' id'), $ret);
return FALSE;
}
// Add user to admin group
$ret = GalleryCoreApi::addUserToGroup($g2_user->id, $g2_admin_gid);
if ($ret) {
gallery_error(t('Error adding user to Gallery group (:gid)',
array(':gid' => $g2_admin_gid)), $ret);
return FALSE;
}
}
break;
case 'delete' :
$ret = GalleryEmbed::deleteUser($user->uid);
if ($ret) {
gallery_error(t('Error deleting Gallery user'), $ret);
return FALSE;
}
break;
}
// Set the 'locked' property for the user
if (variable_get('gallery_user_locked', 0) && ($action != 'delete') && ($user->uid > 1)) {
list($ret, $g2_user) = GalleryCoreApi::loadEntityByExternalId($user->uid, 'GalleryUser');
if ($ret) {
gallery_error(t('Error loading Gallery user'), $ret);
return FALSE;
}
if (!$g2_user->locked) {
list($ret, $lock_id) = GalleryCoreApi::acquireWriteLock($g2_user->id);
if ($ret) {
gallery_error(t('Error acquiring write lock'), $ret);
return FALSE;
}
$g2_user->setLocked(TRUE);
if ($g2_user->save()) {
gallery_error(t('Locking user account failed'), $ret);
return FALSE;
}
}
}
GalleryEmbed::done();
return TRUE;
}
/**
* Function _gallery_user_sync().
* (sync user info for $uid)
*/
function _gallery_user_sync($uid) {
$user = user_load(array('uid' => $uid));
gallery_user_modify($user, 'update', TRUE);
}
/**
* Function gallery_user_view().
* (view Gallery user details for a specific user)
*/
function gallery_user_view($user) {
if (variable_get('gallery_user_hide_profile', 0) || !_gallery_init(TRUE)) {
return;
}
// User album status
if ($useralbum = gallery_user_useralbum($user->uid)) {
$form['gallery_view_user_album'] = array(
'value' => l(t('User Album'), $useralbum),
'class' => 'send-message');
}
else {
$form['gallery_view_user_album'] = array(
'value' => t('User has not created an album yet'),
'class' => 'send-message');
}
// Sync/Map status info
$g2_userinfo = gallery_user_map_info($user);
if (($g2_userinfo['status']) && (user_access('administer users'))) {
$form['gallery_view_user'] = array(
'title' => t('Gallery2-Drupal Sync Status'),
'value' => implode(',
', gallery_user_map_info_status($g2_userinfo['status']))
);
}
GalleryEmbed::done();
if (!empty($form)) {
return array(t('Gallery2') => $form);
}
}
/**
* Function gallery_user_useralbum().
* (create link to user album)
*/
function gallery_user_useralbum($uid = NULL, $link = TRUE) {
if (!_gallery_init(TRUE)) {
return FALSE;
}
// Load G2 user
global $user;
list($ret, $g2_user) = GalleryCoreApi::loadEntityByExternalId(isset($uid) ? $uid : $user->uid, 'GalleryUser');
if ($ret) {
if (!($ret->getErrorCode() & ERROR_MISSING_OBJECT)) {
gallery_error(t('Error loading Gallery user'), $ret);
return FALSE;
}
}
// User album status
if ($g2_user && (gallery_single_plugin_status('useralbum') == GALLERY_PLUGIN_ENABLED)) {
// Fetch user album id
list($ret, $album_id) = GalleryCoreApi::getPluginParameter('module', 'useralbum', 'albumId', $g2_user->id);
if ($ret) {
gallery_error(t('Error fetching user album id'), $ret);
return FALSE;
}
// Generate link to user album
if (is_numeric($album_id) && $album_id > 0) {
return $link ? gallery_generate_url(array('view' => 'core.ShowItem', 'itemId' => $album_id), FALSE) : $album_id;
}
}
return FALSE;
}
/**
* Function gallery_user_map_info().
* (get info about user map status)
*/
function gallery_user_map_info($user, $noerror_status = TRUE) {
$g2_userinfo = array('g2_id' => -1, 'status' => array());
// User map entry
$ret = GalleryEmbed::isExternalIdMapped($user->uid, 'GalleryUser');
if ($ret && !($ret->getErrorCode() & ERROR_MISSING_OBJECT)) {
$g2_userinfo['status'][] = G2USERINFO_ERROR_MISSING;
return $g2_userinfo;
}
// But user not available
list($ret, $g2_user) = GalleryCoreApi::loadEntityByExternalId($user->uid, 'GalleryUser');
if ($ret) {
$g2_userinfo['status'][] = G2USERINFO_ERROR_MISSING;
return $g2_userinfo;
}
// Username
$g2_userinfo['g2_id'] = $g2_user->id;
if ($g2_user->userName != $user->name) {
$g2_userinfo['status'][] = G2USERINFO_ERROR_USERNAME;
}
// Fullname
if (module_exists('profile') && variable_get('gallery_use_fullname', 0)) {
$fullname_field = variable_get('gallery_profile_fullname_field', 'profile_fullname');
$fullname_result = db_query("SELECT v.value FROM {profile_values} v INNER JOIN {profile_fields} f ON v.fid = f.fid AND v.uid = %d WHERE f.name = '%s'", $user->uid, $fullname_field);
$fullname = db_fetch_object($fullname_result);
$fullname = $fullname->value;
if ($g2_user->fullName != $fullname) {
$g2_userinfo['status'][] = G2USERINFO_ERROR_FULLNAME;
}
elseif (!$fullname) {
$g2_userinfo['status'][] = G2USERINFO_ERROR_FULLNAME_MISSING;
}
}
// Email adress
if ($g2_user->email != $user->mail) {
$g2_userinfo['status'][] = G2USERINFO_ERROR_EMAIL;
}
// Password
if ($user->status && ($g2_user->hashedPassword != $user->pass)) {
if (strlen($g2_user->hashedPassword) != strlen($user->pass)) {
$g2_userinfo['status'][] = G2USERINFO_ERROR_HASHMETHOD;
}
$g2_userinfo['status'][] = G2USERINFO_ERROR_PASSWORD;
}
// Roles/Groups
if (!gallery_groups_map_info($g2_user, $user)) {
$g2_userinfo['status'][] = G2USERINFO_ERROR_GROUPS;
}
// Overall sync status
if ($noerror_status && !count($g2_userinfo['status'])) {
$g2_userinfo['status'][] = G2USERINFO_NOERROR;
}
return $g2_userinfo;
}
/**
* Function gallery_user_map_info_status().
* (get string representation of the use map status)
*/
function gallery_user_map_info_status($info = array(), $format = TRUE) {
$info_map = array(
G2USERINFO_NOERROR => t('OK'),
G2USERINFO_ERROR => t('Any Error'),
G2USERINFO_ERROR_MISSING => t('Missing from G2'),
G2USERINFO_ERROR_USERNAME => t('Different Usernames'),
G2USERINFO_ERROR_FULLNAME => t('Different Full Names'),
G2USERINFO_ERROR_FULLNAME_MISSING => t('G2 Full Name missing'),
G2USERINFO_ERROR_EMAIL => t('Different E-Mails'),
G2USERINFO_ERROR_PASSWORD => t('Different Passwords'),
G2USERINFO_ERROR_HASHMETHOD => t('Imported/Different hash method'),
G2USERINFO_ERROR_GROUPS => t('Roles <> Groups')
);
if ($format) {
$status = array();
if (!count($info)) {
$info[] = G2USERINFO_NOERROR;
}
foreach ($info as $key => $value) {
$status[] = $info_map[$value];
}
return $status;
}
return $info_map;
}
/**
* Function gallery_user_map_state().
* (get state of user mapping)
*/
function gallery_user_map_state($user) {
// See if user already exists in G2
list($ret, $g2_user) = GalleryCoreApi::fetchUserByUsername($user->name);
if (!$ret) {
// User is in G2, so map the user if needed
$ret2 = GalleryEmbed::isExternalIdMapped($user->uid, 'GalleryUser');
if ($ret2) {
if ($ret2->getErrorCode() & ERROR_MISSING_OBJECT) {
return array(G2MAP_USER_EXISTS_BUT_NEEDS_MAPPING, $g2_user, NULL);
}
else {
// Some other error
return array(G2MAP_UNKNOWN, $g2_user, $ret2);
}
}
else {
return array(G2MAP_USER_EXISTS, $g2_user, NULL);
}
}
elseif ($ret->getErrorCode() & ERROR_MISSING_OBJECT) {
// User does not yet exist in G2
// Check if the externalID was mapped (it should not be)
$ret2 = GalleryEmbed::isExternalIdMapped($user->uid, 'GalleryUser');
if ($ret2) {
if ($ret2->getErrorCode() & ERROR_MISSING_OBJECT) {
return array(G2MAP_USER_DOES_NOT_EXIST, $g2_user, NULL);
}
else {
// Some other error
return array(G2MAP_UNKNOWN, $g2_user, $ret2);
}
}
else {
// User is mapped
return array(G2MAP_USER_DOES_NOT_EXIST_BUT_IS_MAPPED, $g2_user, NULL);
}
}
else {
return array(NULL, $g2_user, $ret);
}
}
/**
* Function _gallery_user_import().
* (import Gallery users into Drupal)
*/
function _gallery_user_import($g2_users = array()) {
$messages = array();
$resolve_conflict = variable_get('gallery_user_import_conflict', array());
// Anonymous user id
list($ret, $guest) = GalleryCoreApi::getPluginParameter('module', 'core', 'id.anonymousUser');
if (!$ret) {
unset($g2_users[$guest]);
}
if (($g2_groups_map = _gallery_groups_map()) === FALSE) {
return FALSE;
}
if (($g2_extIdMap = _gallery_user_map(array_keys($g2_users))) === FALSE) {
return FALSE;
}
gallery_debug($g2_users, t('G2 Users'));
gallery_debug($g2_extIdMap, t('G2 ExternalIdMap'));
// Iterate over G2 users
foreach ($g2_users as $g2_id => $g2_username) {
$new_user = !array_key_exists($g2_id, $g2_extIdMap);
list($ret, $g2_user) = GalleryCoreApi::fetchUserByUsername($g2_username);
if ($ret) {
gallery_error(t('Error fetching user by username (:name)',
array(':name' => $g2_username)), $ret);
return FALSE;
}
// Collect user details and validate the values (name, mail, ...)
$values = array();
$values['name'] = $g2_user->userName;
if ($error = user_validate_name($values['name'])) {
$messages[] = t('G2 User Import (uid: :uid, name: \':name\'): !error',
array(':uid' => $g2_id, ':name' => $values['name'], '!error' => $error));
continue;
}
$values['fullname'] = $g2_user->fullName;
$values['pass'] = user_password(20);
$password_hash = $g2_user->hashedPassword;
$values['mail'] = $g2_user->email;
if ($error = user_validate_mail($values['mail'])) {
if ($resolve_conflict[G2IMPORT_CONFLICT_INVALID]) {
_gallery_user_resolve_mail($values['mail'], $values['name'], $messages);
$error = user_validate_mail($values['mail']) ? $error : FALSE;
}
if ($error) {
$messages[] = t('G2 User Import (uid: :uid, name: \':name\'): !error',
array(':uid' => $g2_id, ':name' => $values['name'], '!error' => $error));
continue;
}
}
else if ($new_user && db_num_rows(db_query("SELECT uid FROM {users} WHERE uid != 0 AND LOWER(mail) = LOWER('%s')", $values['mail'])) > 0) {
$error = TRUE;
if ($resolve_conflict[G2IMPORT_CONFLICT_DUPLICATE]) {
_gallery_user_resolve_mail($values['mail'], $values['name'], $messages);
$error = FALSE;
}
if ($error) {
$messages[] = t('G2 User Import (uid: :uid, name: \':name\'): The e-mail address :mail is already registered.',
array(':uid' => $g2_id, ':name' => $values['name'], ':mail' => $values['mail']));
continue;
}
}
$values['language'] = $g2_user->language;
$values['created'] = $g2_user->creationTimestamp;
$values['roles'] = array();
list($ret, $g2_groups) = GalleryCoreApi::fetchGroupsForUser($g2_user->id);
if ($ret) {
gallery_error(t('Error fetching groups for user (uid: :uid)',
array(':uid' => $g2_id)), $ret);
return FALSE;
}
foreach ($g2_groups as $g2_gid => $g2_groupname) {
if (isset($g2_groups_map[$g2_gid])) {
$values['roles'][$g2_groups_map[$g2_gid]] = $g2_groupname;
}
}
// Is the user blocked in G2
list($ret, $g2_user_blocked) = GalleryCoreApi::isDisabledUsername($g2_username);
if ($ret) {
gallery_error(t('Error calling isDisabledUsername() for \':name\'',
array(':name' => $g2_username)), $ret);
return FALSE;
}
$values['status'] = !$g2_user_blocked;
// Create new Drupal user (this will also override the G2 user
// during hook_user, but there is no 'clean' way to avoid this)
if ($new_user) {
$values['notify'] = FALSE;
if (!($user = user_save('', $values))) {
$messages[] = t('Error creating Drupal user for G2 user (uid: :uid)',
array(':uid' => $g2_id));
continue;
}
}
else {
$user = new stdClass();
$user->uid = $g2_extIdMap[$g2_id];
}
// Override user details if requested (or for new users)
if ($user->uid && ($new_user || variable_get('gallery_user_import_override', 0))) {
// Fullname support
if (module_exists('profile') && variable_get('gallery_use_fullname', 0)) {
$fullname_category = variable_get('gallery_profile_fullname_category', 'Personal Information');
$fullname_field = variable_get('gallery_profile_fullname_field', 'profile_fullname');
$values[$fullname_field] = $values['fullname'];
profile_save_profile($values, $user, $fullname_category);
}
// Do we have a md5 hash (unsalted hash)?
if (strlen($password_hash) == 32) {
db_query("UPDATE {users} SET pass = '%s' WHERE uid = %d", $password_hash, $user->uid);
unset($values['pass']);
}
// Update Drupal user with G2 user details (invokes hook_user)
user_save(user_load(array('uid' => $user->uid)), $values);
// Override/Restore password in G2 (in case we have a salted G2 hash)
// (Drupal hash will remain a dummy and user is authenticated in hook_auth against G2 directly)
if (strlen($password_hash) > 32) {
$ret = GalleryEmbed::updateUser($user->uid, array('hashedpassword' => $password_hash, 'hashmethod' => 'md5'));
if ($ret) {
gallery_error(t('Error updating Gallery user (password)'), $ret);
return FALSE;
}
}
}
}
if (count($messages)) {
if (isset($_SESSION['gallery_user_progress_messages'])) {
$_SESSION['gallery_user_progress_messages'] += $messages;
}
else {
drupal_set_message(theme('item_list', $messages, t('The following messages occured:')), 'notice');
drupal_set_message(''. t('Invalid user items were skipped.') .'', 'notice');
watchdog('gallery', theme('item_list', $messages, t('The following messages occured:')), WATCHDOG_NOTICE);
}
}
return TRUE;
}
/**
* Function _gallery_user_resolve_mail()
*/
function _gallery_user_resolve_mail(&$mail, $username, &$messages) {
// Replace all invalid chars in the username
$invalid_search = array(' ', '!', '#', '$', '%', '&', '*', '+', '/', '=', '?', '`', '|', '{', '}', '~', '\'');
$invalid_replace = array_fill(0, count($invalid_search), '_');
$user = str_replace($invalid_search, $invalid_replace, $username);
// Generate a new mail address using a simple 'username_#@drupaldomain' naming schema
// (=> username@drupaldomain, username_1@drupaldomain, username_2@drupaldomain, ...)
$i = 0;
do {
$newmail = $user . (($i > 0) ? ('_'. $i) : '') .'@'. $_SERVER['HTTP_HOST'];
$error = (db_num_rows(db_query("SELECT uid FROM {users} WHERE uid != 0 AND LOWER(mail) = LOWER('%s')", $newmail)) > 0);
} while ($error && $i++ < 10);
// Do we have a new mail address?
if (!$error) {
$messages[] = t('G2 User Import (name: \':name\'): e-mail address :oldmail changed to :newmail.',
array(':name' => $username, ':oldmail' => $mail, ':newmail' => $newmail));
$mail = $newmail;
}
}
/**
* Function _gallery_user_map().
* (fetch 'GalleryUser' entries from G2 'ExternalIdMap')
*/
function _gallery_user_map($ids = array(), $inverse = FALSE) {
// g2Id => externalId (default)
$ids = is_array($ids) ? $ids : array($ids);
$match = array('entityType' => 'GalleryUser');
if (count($ids) > 0) {
if ($inverse) {
$match['externalId'] = $ids;
}
else {
$match['entityId'] = $ids;
}
}
// Fetch the map entries
list($ret, $resultMap) = GalleryCoreApi::getMapEntry('ExternalIdMap', array('externalId', 'entityId'), $match);
if ($ret) {
gallery_error(t('Error fetching \'GalleryUser\' entries from \'ExternalIdMap\''), $ret);
return FALSE;
}
// Iterate over the results
$g2_extIdMap = array();
while (($row = $resultMap->nextResult()) !== FALSE) {
$g2_extIdMap[($inverse ? $row[0] : $row[1])] = ($inverse ? $row[1] : $row[0]);
}
return $g2_extIdMap;
}
/**
* Function _gallery_user_drupal_users().
* (fetch all existing Drupal users (uid => username))
*/
function _gallery_user_drupal_users() {
$users = array();
$result = db_query("SELECT uid, name FROM {users} WHERE uid > 0");
while ($user = db_fetch_object($result)) {
$users[$user->uid] = $user->name;
}
return $users;
}