uif.admin.inc in User Import Framework 7
Same filename and directory in other branches
Simple, extensible user import from a CSV file.
File
uif.admin.incView source
<?php
/**
* @file
* Simple, extensible user import from a CSV file.
*/
/**
* User import multi-part form.
*/
function uif_import_form($form, &$form_state) {
// Cause return to beginning if we just completed an import
if (isset($form_state['storage']['step']) && $form_state['storage']['step'] >= 3) {
unset($form_state['storage']);
}
$step = empty($form_state['storage']['step']) ? 1 : $form_state['storage']['step'];
$form_state['storage']['step'] = $step;
switch ($step) {
case 1:
$form['instructions'] = array(
'#type' => 'fieldset',
'#title' => t('User import help'),
'#collapsible' => TRUE,
'#collapsed' => TRUE,
);
$form['instructions']['help'] = array(
'#markup' => theme('uif_form_help'),
);
$file_size_msg = t('Your PHP settings limit the maximum file size per upload to %size. Depending on your server environment, these settings may be changed in the system-wide php.ini file, a php.ini file in your Drupal root directory, in your Drupal site\'s settings.php file, or in the .htaccess file in your Drupal root directory.', array(
'%size' => format_size(file_upload_max_size()),
));
$form['user_upload'] = array(
'#type' => 'file',
'#title' => t('Import file'),
'#size' => 40,
'#description' => t('Select the CSV file to be imported.') . '<br />' . $file_size_msg,
);
$form['field_delimiter'] = array(
'#type' => 'select',
'#title' => t('Field delimiter'),
'#default_value' => variable_get('uif_field_delimiter', ','),
'#options' => uif_field_delimiters(),
'#description' => t('Select field delimiter. Comma is typical for CSV export files.'),
);
$form['value_delimiter'] = array(
'#type' => 'select',
'#title' => t('Value delimiter'),
'#default_value' => variable_get('uif_value_delimiter', '|'),
'#options' => uif_value_delimiters(),
'#description' => t('Select value delimiter for fields receiving multiple values.'),
);
$form['preview_count'] = array(
'#type' => 'select',
'#title' => t('Users to preview'),
'#default_value' => variable_get('uif_users_to_preview', 10),
'#options' => uif_options_users_to_preview(),
'#description' => t('Number of users to preview before importing. Note: If you run out of memory set this lower or increase your memory.'),
);
$form['notify'] = array(
'#type' => 'checkbox',
'#title' => t('Notify new users of account'),
'#default_value' => variable_get('uif_notify', FALSE),
'#description' => t('If checked, each newly created user will receive the <em>Welcome, new user created by administrator</em> email using the template on the <a href="@url1">user settings page</a>. This is the same email sent for <a href="@url2">admin-created accounts</a>.', array(
'@url1' => url('admin/user/settings'),
'@url2' => url('admin/user/user/create'),
)),
);
$form['next'] = array(
'#type' => 'submit',
'#value' => t('Next'),
);
// Set form parameters so we can accept file uploads.
$form['#attributes'] = array(
'enctype' => 'multipart/form-data',
);
break;
case 2:
$form['instructions'] = array(
'#markup' => t('Preview these records and when ready to import click Import users.'),
'#prefix' => '<div id="uif_form_instructions">',
'#suffix' => '</div>',
);
$form['user_preview'] = array(
'#markup' => $form_state['storage']['user_preview'],
'#prefix' => '<div id="uif_user_preview">',
'#suffix' => '</div>',
);
$form['back'] = array(
'#type' => 'submit',
'#value' => t('Back'),
'#submit' => array(
'uif_import_form_back',
),
);
$form['submit'] = array(
'#type' => 'submit',
'#value' => t('Import users'),
);
break;
}
return $form;
}
/**
* Validate the import data.
*/
function uif_import_form_validate($form, &$form_state) {
$step = empty($form_state['storage']['step']) ? 1 : $form_state['storage']['step'];
switch ($step) {
case 1:
// Validate the upload file
$validators = array(
'file_validate_extensions' => array(
'csv',
),
'file_validate_size' => array(
file_upload_max_size(),
),
);
if ($user_file = file_save_upload('user_upload', $validators)) {
$errors = uif_validate_user_file($user_file->uri, $data, $form_state);
if (!empty($errors)) {
form_set_error('user_upload', '<ul><li>' . implode('</li><li>', $errors) . '</li></ul>');
return;
}
}
else {
form_set_error('user_upload', t('Cannot save the import file to temporary storage. Please try again.'));
return;
}
// Save the validated data to avoid reparsing
$form_state['storage']['data'] = $data;
break;
}
}
/**
* Form submission handler.
*/
function uif_import_form_submit($form, &$form_state) {
$step = empty($form_state['storage']['step']) ? 1 : $form_state['storage']['step'];
if (1 == $step) {
$form_state['rebuild'] = TRUE;
$form_state['storage']['notify'] = isset($form_state['values']['notify']) ? $form_state['values']['notify'] : FALSE;
$form_state['storage']['field_delimiter'] = $form_state['values']['field_delimiter'];
$form_state['storage']['value_delimiter'] = $form_state['values']['value_delimiter'];
$preview_count = $form_state['values']['preview_count'];
if ($preview_count) {
$form_state['storage']['preview_count'] = $preview_count;
$form_state['storage']['user_preview'] = theme('uif_preview_users', array(
'data' => $form_state['storage']['data'],
'limit' => $preview_count,
));
}
else {
$step = 2;
}
}
if (2 == $step) {
$form_state['rebuild'] = TRUE;
uif_batch_import_users($form_state);
}
$form_state['storage']['step'] = $step + 1;
}
/**
* Read the user import file and validate on the way.
*
* @param $uri
* filepath to the user import file
* @param $data
* returns with array of users
* @return
* FALSE if no errors found
* array of error strings if error found
*/
function uif_validate_user_file($uri, &$data, $form_state) {
$data = array();
$data['user'] = array();
$line = 0;
$delimiter = $form_state['values']['field_delimiter'];
// Without this fgetcsv() fails for Mac-created files
ini_set('auto_detect_line_endings', TRUE);
if ($fp = fopen($uri, 'r')) {
// Read the header and allow alterations
$header_row = fgetcsv($fp, NULL, $delimiter);
$header_row = uif_normalize_header($header_row);
uif_adjust_header_values($header_row);
drupal_alter('uif_header', $header_row);
$line++;
$errors = module_invoke_all('uif_validate_header', $header_row, $form_state);
uif_add_line_number($errors, $line);
if (!empty($errors)) {
return $errors;
}
$data['header'] = $header_row;
// Gather core and entity field info
$data['fields'] = uif_get_field_info($header_row);
// Read the data
$errors = array();
while (!feof($fp) && count($errors) < 20) {
// Read a row and allow alterations
$row = fgetcsv($fp, NULL, $delimiter);
drupal_alter('uif_row', $row, $header_row);
$line++;
if (uif_row_has_data($row)) {
$user_row = uif_clean_and_key_row($header_row, $row, $line);
$args = array(
':mail' => db_like($user_row['mail']),
);
$uid = db_query_range('SELECT uid FROM {users} WHERE mail LIKE :mail', 0, 1, $args)
->fetchField();
$more_errors = module_invoke_all('uif_validate_user', $user_row, $uid, $header_row, $form_state);
uif_add_line_number($more_errors, $line);
$errors = array_merge($errors, $more_errors);
$data['user'][] = $user_row;
}
}
// Any errors?
if (!empty($errors)) {
return $errors;
}
}
else {
return t('Cannot open that import file.');
}
// Final validation opportunity after header and all users validated individually.
$errors = module_invoke_all('uif_validate_all_users', $data['user'], $form_state);
if (!empty($errors)) {
return $errors;
}
}
/**
* Trim all elements of $row, and pad $row out to the number of columns in the
* $header. Then replace keys in $row with $header values.
*/
function uif_clean_and_key_row($header, $row, $line) {
$row = array_map('trim', $row);
$raw_row = $row;
$row = array_map('uif_clean_value', $row);
for ($i = 0; $i < count($row); $i++) {
if ($raw_row[$i] !== $row[$i]) {
$vars = array(
'@line' => $line,
'@column' => $header[$i],
);
drupal_set_message(t('Warning on row @line: Non UTF-8 characters were removed from @column column.', $vars), 'warning');
}
}
if (count($row) < count($header)) {
$row = array_merge($row, array_fill(count($row), count($header) - count($row), ''));
drupal_set_message(t('Warning on row @line: Empty values added for missing data.', array(
'@line' => $line,
)), 'warning');
}
elseif (count($row) > count($header)) {
array_splice($row, count($header));
drupal_set_message(t('Warning on row @line: Data values beyond header were truncated.', array(
'@line' => $line,
)), 'warning');
}
$row = array_combine($header, $row);
return $row;
}
/**
* Check that input is UTF-8.
*/
function uif_clean_value($value) {
if (!drupal_validate_utf8($value)) {
// Remove all chars except LF, CR, and basic ascii
return preg_replace('/[^\\x0A\\x0D\\x20-\\x7E]/', '', $value);
}
return $value;
}
/**
* Is there data in the row?
*/
function uif_row_has_data($row) {
if (isset($row) && is_array($row)) {
foreach ($row as $value) {
$value = trim($value);
if (!empty($value)) {
return TRUE;
}
}
}
return FALSE;
}
/**
* Normalize the header columns.
*/
function uif_normalize_header($header) {
$header = array_map('trim', $header);
$normal_header = array();
foreach ($header as $column) {
$normal_header[] = strtolower($column);
}
return $normal_header;
}
/**
* Implementation of hook_uif_validate_header().
*/
function uif_uif_validate_header($header) {
$errors = array();
if (!in_array('mail', $header)) {
$errors[] = t('There is no mail column in the import file.');
}
$labels = array();
foreach ($header as $label) {
if (isset($labels[$label])) {
$errors[] = t('Repeated columns in input file are not allowed: %label', array(
'%label' => $label,
));
}
$labels[$label] = 1;
}
return $errors;
}
/**
* Implementation of hook_uif_validate_user().
*/
function uif_uif_validate_user($user_data, $uid, $header = NULL) {
$errors = array();
if (!valid_email_address($user_data['mail'])) {
$errors[] = t('Missing or invalid email address: %mail', array(
'%mail' => $user_data['mail'],
));
}
if (isset($user_data['name']) && empty($user_data['name'])) {
$errors[] = t('Username is empty. Leave this column out to create a unique username based on email address.', array());
}
if (isset($user_data['pass']) && empty($user_data['pass'])) {
$errors[] = t('Password is empty. Leave this column out to have an automatically generated password.', array());
}
if (isset($user_data['roles'])) {
uif_parse_roles($user_data['roles'], $roles_errors);
$errors = array_merge($errors, $roles_errors);
}
return $errors;
}
/**
* Prepend the line number on the error.
*/
function uif_add_line_number(&$errors, $line) {
foreach ($errors as &$error) {
$error = t('Error on row !line:', array(
'!line' => $line,
)) . ' ' . $error;
}
}
/**
* Return user to starting point on template multi-form.
*/
function uif_import_form_back($form, &$form_state) {
$form_state['storage']['step'] = 1;
}
/**
* Theme preview of all users.
*/
function theme_uif_preview_users($variables) {
$data = $variables['data'];
$limit = $variables['limit'];
$current = 0;
$output = '';
foreach ($data['user'] as $user_data) {
$current++;
if ($current > $limit) {
break;
}
$output .= theme('uif_preview_one_user', array(
'data' => $user_data,
));
}
if (!$output) {
$output = t('There are no users to import.');
}
return $output;
}
/**
* Theme preview of a single user.
*/
function theme_uif_preview_one_user($variables) {
$user_data = $variables['data'];
$rows = array();
foreach ($user_data as $field => $value) {
$rows[] = array(
$field,
$value,
);
}
$args = array(
':mail' => db_like($user_data['mail']),
);
$user_exists = db_query('SELECT COUNT(*) FROM {users} WHERE mail LIKE :mail', $args)
->fetchField();
$annotation = $user_exists ? t('update') : t('create');
$heading = $user_data['mail'] . ' (' . $annotation . ')';
return '<h3>' . $heading . '</h3>' . theme('table', array(
'rows' => $rows,
));
}
/**
* Batch import all users.
*/
function uif_batch_import_users($form_state) {
$batch = array(
'title' => t('Importing users'),
'operations' => array(
array(
'uif_batch_import_users_process',
array(
$form_state,
),
),
),
'progress_message' => '',
// uses count(operations) which is irrelevant in this case
'finished' => 'uif_batch_import_users_finished',
'file' => drupal_get_path('module', 'uif') . '/uif.admin.inc',
);
batch_set($batch);
}
/**
* User import batch processing.
*/
function uif_batch_import_users_process($form_state, &$context) {
// Initialize
if (empty($context['sandbox']['progress'])) {
$context['sandbox']['progress'] = 0;
$context['sandbox']['max'] = count($form_state['storage']['data']['user']);
$context['results']['created'] = 0;
$context['results']['updated'] = 0;
}
// Process max 20 users at a time
$processed = 0;
$notify = $form_state['storage']['notify'];
while ($context['sandbox']['progress'] < $context['sandbox']['max'] && $processed < 20) {
$index = $context['sandbox']['progress'];
uif_import_user($form_state['storage']['data']['user'][$index], $notify, $context['results'], $form_state);
$context['sandbox']['progress']++;
$processed++;
}
// Finished yet?
if ($context['sandbox']['progress'] != $context['sandbox']['max']) {
$context['finished'] = $context['sandbox']['progress'] / $context['sandbox']['max'];
}
}
/**
* User import batch completion.
*/
function uif_batch_import_users_finished($success, $results, $operations) {
if ($success) {
global $user;
if (isset($results['self'])) {
uif_update_user($results['self'], $user->uid);
$results['updated']++;
unset($results['self']);
}
$done = t('User import complete.');
$created = $results['created'] ? ' ' . format_plural($results['created'], 'One user was created.', '@count users were created.') . ' ' : '';
$updated = $results['updated'] ? ' ' . format_plural($results['updated'], 'One user was updated.', '@count users were updated.') . ' ' : '';
$more = t('View the <a href="@url">user list</a>.', array(
'@url' => url('admin/people'),
));
drupal_set_message($done . $created . $updated . $more);
}
else {
drupal_set_message(t('An error occurred and processing did not complete.'), 'error');
}
}
/**
* Import one user.
*/
function uif_import_user($user_data, $notify, &$results, $form_state) {
$args = array(
':mail' => db_like($user_data['mail']),
);
if ($uid = db_query('SELECT uid FROM {users} WHERE mail LIKE :mail', $args)
->fetchField()) {
global $user;
if ($uid === $user->uid) {
$results['self'] = $user_data;
return;
}
$account = uif_update_user($user_data, $uid, $form_state);
$results['updated']++;
}
else {
$account = uif_create_user($user_data, $notify, $form_state);
$results['created']++;
}
}
/**
* Create a new user.
*/
function uif_create_user($user_data, $notify, $form_state) {
$account = array();
$account['mail'] = $user_data['mail'];
$account['init'] = $user_data['mail'];
$account['status'] = 1;
// Use the provided username if any, or derive it from the email
$username = empty($user_data['name']) ? preg_replace('/@.*$/', '', $user_data['mail']) : $user_data['name'];
$account['name'] = uif_unique_username($username);
// Use the provided password if any, otherwise a random one
$pass = empty($user_data['pass']) ? user_password() : $user_data['pass'];
$account['pass'] = $pass;
// Add roles if present
if (isset($user_data['roles'])) {
$account['roles'] = uif_parse_roles($user_data['roles']);
}
$account = array_merge($account, module_invoke_all('uif_pre_create', $account, $user_data, $form_state));
$account = user_save('', $account);
module_invoke_all('uif_post_create', $account, $user_data, $form_state);
if ($notify) {
$account->password = $pass;
// For mail token; _user_mail_notify() expects this
_user_mail_notify('register_admin_created', $account);
}
return $account;
}
/**
* Update an existing user.
*/
function uif_update_user($user_data, $uid, $form_state) {
$account = user_load($uid);
// todo: Support update of user mail. This requires optional inclusion of uid column,
// which would override use of email column as uid lookup method.
$changes = module_invoke_all('uif_pre_update', $account, $user_data, $form_state);
// Update the username if it has changed
if (!empty($user_data['name'])) {
$username = uif_unique_username($user_data['name'], $uid);
if ($username != $account->name) {
$changes['name'] = $username;
}
}
// Update the password if one is provided
if (!empty($user_data['pass'])) {
$changes['pass'] = $user_data['pass'];
}
// Update roles if present
if (isset($user_data['roles'])) {
$changes['roles'] = uif_parse_roles($user_data['roles']);
}
$account = user_save($account, $changes);
module_invoke_all('uif_post_update', $account, $user_data, $form_state);
return $account;
}
/**
* Implements hook_uif_pre_create().
*/
function uif_uif_pre_create($account, $user_data, $form_state) {
return uif_assign_presave_fields($account, $user_data, $form_state);
}
/**
* Implements hook_uif_pre_update().
*/
function uif_uif_pre_update($account, $user_data, $form_state) {
return uif_assign_presave_fields($account, $user_data, $form_state);
}
/**
* Given a starting point for a Drupal username (e.g. the name portion of an email address) return
* a legal, unique Drupal username.
*
* @param $name
* A name from which to base the final user name. May contain illegal characters; these will be stripped.
*
* @param $uid
* (optional) Uid to ignore when searching for unique user (e.g. if we update the username after the
* {users} row is inserted)
*
* @return
* A unique user name based on $name.
*
*/
function uif_unique_username($name, $uid = 0) {
// Strip illegal characters
$name = preg_replace('/[^\\x{80}-\\x{F7} a-zA-Z0-9@_.\'-]/', '', $name);
// Strip leading and trailing whitespace
$name = trim($name);
// Convert any other series of spaces to a single space
$name = preg_replace('/ +/', ' ', $name);
// If there's nothing left use a default
$name = '' === $name ? t('user') : $name;
// Truncate to reasonable size
$name = drupal_strlen($name) > USERNAME_MAX_LENGTH - 10 ? drupal_substr($name, 0, USERNAME_MAX_LENGTH - 11) : $name;
// Iterate until we find a unique name
$i = 0;
do {
$newname = empty($i) ? $name : $name . '_' . $i;
$args = array(
':uid' => $uid,
':name' => $newname,
);
$found = db_query_range('SELECT uid from {users} WHERE uid <> :uid AND name = :name', 0, 1, $args)
->fetchField();
$i++;
} while ($found);
return $newname;
}
/**
* Theme function for import form help.
*/
function theme_uif_form_help() {
$basic_help = '<p>' . t('Choose an import file. You\'ll have a chance to preview the data before doing the import. The import file must have a header row with a name in each column for the value you are importing. Importable fields include the following:') . '</p>';
$items = array();
// Core user table fields
$supported_fields = uif_get_supported_fields();
foreach ($supported_fields as $name => $data) {
if ($data['type'] == 'core') {
$required = uif_isset_or($data['required']) ? t('required') : t('optional');
$subs = array(
'@name' => $name,
'@required' => $required,
'!description' => $data['description'],
);
$items[] = t('@name (@required) - !description', $subs);
}
}
// Entity fields
foreach (uif_field_info_instances('user', 'user') as $name => $data) {
$field_type = uif_lookup_field_type($name);
if (uif_is_supported_field($field_type)) {
$subs = array(
'@name' => $name,
'@required' => $data['required'] ? t('required') : t('optional'),
'%label' => $data['label'],
'%type' => $field_type,
'@description' => $data['description'] ? $data['description'] : uif_isset_or($supported_fields[$field_type]['description']),
);
$items[] = t('@name (@required) - @description (type is %type, human name is %label)', $subs);
}
}
$basic_help .= theme('item_list', array(
'items' => $items,
));
if (!module_exists('uif_plus')) {
$basic_help .= '<p>' . t('If you need support for entity reference, file, or image fields, or support for modules such profile2 and organic groups, try adding and enabling the <a href="http://drupal.org/project/uif_plus">User Import Framework Plus</a> module.') . '</p>';
}
// Add other modules' help
$helps = module_invoke_all('uif_help');
array_unshift($helps, $basic_help);
$output = '';
foreach ($helps as $help) {
$output .= '<div class="uif_help_section">' . $help . '</div>';
}
return $output;
}
/**
* Field delimiter options.
*/
function uif_field_delimiters() {
return array(
',' => ',',
';' => ';',
'|' => '|',
);
}
/**
* Value delimiter options.
*/
function uif_value_delimiters() {
return array(
'|' => '|',
':' => ':',
'_:_' => '_:_',
'-*-' => '-*-',
);
}
/**
* Users to preview options.
* @return array
*/
function uif_options_users_to_preview() {
$preview_count = drupal_map_assoc(array(
0,
1,
10,
100,
1000,
10000,
9999999,
));
$preview_count[0] = t('None - just do it');
$preview_count[9999999] = t('Preview all');
return $preview_count;
}
/**
* Parse input roles if any.
*/
function uif_parse_roles($roles_string, &$errors = array()) {
$roles = array();
$errors = array();
if ($roles_string) {
$role_names = explode(variable_get('uif_value_delimiter', '|'), $roles_string);
foreach ($role_names as $name) {
$rid = db_query('SELECT rid FROM {role} WHERE name = :name', array(
':name' => $name,
))
->fetchField();
if (is_numeric($rid) && $rid < 2) {
$errors[] = t('System-managed roles are not allowed: %name', array(
'%name' => $name,
));
}
elseif ($rid) {
$roles[$rid] = $name;
}
else {
$errors[] = t('Unrecognized role: %name', array(
'%name' => $name,
));
}
}
}
return $roles;
}
/**
* Perform header adjustments.
*/
function uif_adjust_header_values(&$header_row) {
foreach ($header_row as &$label) {
if ('email' == $label) {
$label = 'mail';
drupal_set_message(t('Header label <em>mail</em> substituted for deprecated label <em>email</em>.'), 'warning');
}
if ('username' == $label) {
$label = 'name';
drupal_set_message(t('Header label <em>name</em> substituted for deprecated label <em>username</em>.'), 'warning');
}
if ('password' == $label) {
$label = 'pass';
drupal_set_message(t('Header label <em>pass</em> substituted for deprecated label <em>password</em>.'), 'warning');
}
}
}
/**
* Prepare core and entity user fields for user_save().
*/
function uif_assign_presave_fields($account, $user_data, $form_state) {
$value_delimiter = $form_state['storage']['value_delimiter'];
$timestamp_fields = array(
'created',
'access',
'login',
);
$user_fields = array();
foreach ($form_state['storage']['data']['fields'] as $label => $info) {
if (!$info['supported']) {
continue;
}
$parser = uif_isset_or($info['import']['parser']) ? $info['import']['parser'] : 'uif_get_raw_value';
if ($info['type'] == 'core') {
$user_fields[$label] = $parser($account, $info['data'], $user_data[$label]);
}
elseif ($info['type'] == 'entity') {
$field_values = array();
$values = explode($value_delimiter, $user_data[$label]);
$key = uif_isset_or($info['import']['key']) ? $info['import']['key'] : 'value';
foreach ($values as $value) {
$value = trim($value);
if (drupal_strlen($value)) {
$parsed_value = $parser($account, $info['data'], $value);
if (!is_null($parsed_value)) {
$field_values[] = $parsed_value;
}
}
}
for ($delta = 0; $delta < count($field_values); $delta++) {
if ($info['data']['cardinality'] == 1 && $delta > 0) {
break;
}
if (drupal_strlen($field_values[$delta])) {
$user_fields[$label][LANGUAGE_NONE][$delta][$key] = $field_values[$delta];
}
}
}
}
return $user_fields;
}
/**
* Read and store field info relevant to the import.
*/
function uif_get_field_info($header) {
$field_info = array();
$users_table = drupal_get_schema('users');
$instance_fields = uif_field_info_instances('user', 'user');
$supported_fields = uif_get_supported_fields();
foreach ($header as $label) {
if (isset($users_table['fields'][$label])) {
$supported = isset($supported_fields[$label]);
$field_info[$label] = array(
'type' => 'core',
'supported' => $supported,
'data' => $users_table['fields'][$label],
);
if ($supported) {
$field_info[$label]['import'] = $supported_fields[$label];
}
}
elseif (isset($instance_fields[$label])) {
$data = uif_field_info_field($label);
$supported = isset($supported_fields[$data['type']]);
$field_info[$label] = array(
'type' => 'entity',
'supported' => $supported,
'data' => $data,
);
if ($supported) {
$field_info[$label]['import'] = $supported_fields[$data['type']];
}
}
else {
// Contrib module handling?
$supported = isset($supported_fields[$label]);
if (!$supported) {
$field_info[$label] = array(
'type' => 'unknown',
'supported' => FALSE,
);
}
}
if (!$supported) {
drupal_set_message(t('Unknown column @field in the import file. Data in this column will be ignored.', array(
'@field' => $label,
)), 'warning');
}
}
return $field_info;
}
/**
* Given a field's machine name look up the field type.
*/
function uif_lookup_field_type($field_name) {
if ($info = uif_field_info_field($field_name)) {
return $info['type'];
}
}
/**
* Return TRUE if a module supports import of the passed field type.
*/
function uif_is_supported_field($field_type) {
$supported_fields = uif_get_supported_fields();
return isset($supported_fields[$field_type]);
}
/**
* Return list of supported fields.
*/
function uif_get_supported_fields() {
$supported_fields =& drupal_static(__FUNCTION__);
if (!isset($supported_fields)) {
$supported_fields = module_invoke_all('uif_supported_fields');
drupal_alter('uif_supported_fields', $supported_fields);
}
return $supported_fields;
}
/**
* Implementation of hook_uif_supported_fields().
*
* Provide out-of-box supported fields.
*/
function uif_uif_supported_fields() {
$subs = array(
'@strtotime_url' => 'http://php.net/manual/en/function.strtotime.php',
'@tz_url' => url('admin/config/regional/settings'),
'@mods_url' => url('admin/modules'),
'@flds_url' => url('admin/config/people/accounts/fields'),
);
return array(
'mail' => array(
'type' => 'core',
'required' => TRUE,
'description' => t('the user\'s email address'),
),
'name' => array(
'type' => 'core',
'description' => t('a name for the user. If not provided, a name is created based on the email.'),
),
'pass' => array(
'type' => 'core',
'description' => t('a password for the user. If not provided, a password is generated.'),
),
'roles' => array(
'type' => 'core',
'description' => t('roles for the user as delimited text, e.g. "admin|editor" (without quotes).'),
),
'created' => array(
'type' => 'core',
'description' => t('the creation date for the user in <a href="@strtotime_url">strtotime()</a> format.', $subs),
'parser' => 'uif_get_strtotime_value',
),
'access' => array(
'type' => 'core',
'description' => t('the last access date for the user in <a href="@strtotime_url">strtotime()</a> format.', $subs),
'parser' => 'uif_get_strtotime_value',
),
'login' => array(
'type' => 'core',
'description' => t('the last login date for the user in <a href="@strtotime_url">strtotime()</a> format.', $subs),
'parser' => 'uif_get_strtotime_value',
),
'status' => array(
'type' => 'core',
'description' => t('the account status (1 = active (default) 0 = blocked).'),
),
'timezone' => array(
'type' => 'core',
'description' => t('the time zone to use for this user. You should <a href="@tz_url">let users set their time zone</a> if you import this.', $subs),
),
'language' => array(
'type' => 'core',
'description' => t('the language to use for this user. You should <a href="@mods_url">enable the locale module</a> if you import this.', $subs),
),
'uid' => array(
'type' => 'core',
'description' => t('the uid of the user (experts only; use mail as unique key, not uid)'),
),
'list_boolean' => array(
'type' => 'entity',
'label' => t('Boolean'),
'description' => t('true/false. Use 0 for false, 1 for true.'),
),
'number_float' => array(
'type' => 'entity',
'label' => t('Float'),
'description' => t('floating point number'),
),
'number_decimal' => array(
'type' => 'entity',
'label' => t('Decimal'),
'description' => t('decimal number'),
),
'number_integer' => array(
'type' => 'entity',
'label' => t('Integer'),
'description' => t('integer number'),
),
'list_float' => array(
'type' => 'entity',
'label' => t('List (float)'),
'description' => t('list of floating point values'),
),
'list_integer' => array(
'type' => 'entity',
'label' => t('List (integer)'),
'description' => t('list of integers'),
),
'list_text' => array(
'type' => 'entity',
'label' => t('List (text)'),
'description' => t('list of text values'),
),
'text' => array(
'type' => 'entity',
'label' => t('Text'),
'description' => t('text'),
),
'text_long' => array(
'type' => 'entity',
'label' => t('Long text'),
'description' => t('long text'),
),
'text_with_summary' => array(
'type' => 'entity',
'label' => t('Long text and summary'),
'description' => t('long text and summary'),
),
'taxonomy_term_reference' => array(
'type' => 'entity',
'label' => t('Taxonomy term reference'),
'parser' => 'uif_get_taxonomy_value',
'key' => 'tid',
'description' => t('taxonomy term ID or name'),
),
);
}
/**
* Helper function to process import data for core supported fields.
*/
function uif_get_raw_value($account, $field_info, $value) {
return $value;
}
/**
* Helper function to process import data for core supported fields.
*/
function uif_get_taxonomy_value($account, $field_info, $value) {
if (uif_is_natural($value)) {
return $value;
}
if (drupal_strlen($field_info['settings']['allowed_values'][0]['vocabulary'])) {
$terms = taxonomy_get_term_by_name($value, $field_info['settings']['allowed_values'][0]['vocabulary']);
if (count($terms)) {
$tids = array_keys($terms);
return $tids[0];
}
}
}
/**
* Helper function to convert date string to timestamp.
*/
function uif_get_strtotime_value($account, $field_info, $value) {
// BUG: do strtotime() check in validation?
$timestamp = strtotime($value);
return $timestamp < 1 ? strtotime('now') : $timestamp;
}
/**
* Return TRUE if a $val is a natural number (integer 1, 2, 3, ...). Base can
* be changed to zero if desired.
*/
function uif_is_natural($val, $base = 1) {
if (!isset($val)) {
return FALSE;
}
$return = (string) $val === (string) (int) $val;
if ($return && intval($val) < $base) {
$return = FALSE;
}
return $return;
}
/**
* Check if a variable is set and return it if so, otherwise the alternative.
*/
function uif_isset_or(&$val, $alternate = NULL) {
return isset($val) ? $val : $alternate;
}
/**
* Wrapper for field_info_instances() to avoid module dependency.
*/
function uif_field_info_instances($entity_type = NULL, $bundle_name = NULL) {
return function_exists('field_info_instances') ? field_info_instances($entity_type, $bundle_name) : array();
}
/**
* Wrapper for field_info_field() to avoid module dependency.
*/
function uif_field_info_field($field_name) {
return function_exists('field_info_field') ? field_info_field($field_name) : array();
}
/**
* User Import Framework configuration page.
*/
function uif_configuration_page() {
$form = array(
'uif_field_delimiter' => array(
'#type' => 'select',
'#title' => t('Field delimiter'),
'#default_value' => variable_get('uif_field_delimiter', ','),
'#options' => uif_field_delimiters(),
'#description' => t('Select default field delimiter. Comma is typical for CSV export files.'),
),
'uif_value_delimiter' => array(
'#type' => 'select',
'#title' => t('Value delimiter'),
'#default_value' => variable_get('uif_value_delimiter', '|'),
'#options' => uif_value_delimiters(),
'#description' => t('Select default value delimiter for fields receiving multiple values.'),
),
'uif_users_to_preview' => array(
'#type' => 'select',
'#title' => t('Users to preview'),
'#default_value' => variable_get('uif_users_to_preview', 10),
'#options' => uif_options_users_to_preview(),
'#description' => t('Default value for number of users to preview before importing. Note: If you run out of memory set this lower or increase your memory.'),
),
'uif_notify' => array(
'#type' => 'checkbox',
'#title' => t('Notify new users of account'),
'#default_value' => variable_get('uif_notify', FALSE),
'#description' => t('If checked, each newly created user will receive the <em>Welcome, new user created by administrator</em> email using the template on the <a href="@url1">user settings page</a>. This is the same email sent for <a href="@url2">admin-created accounts</a>.', array(
'@url1' => url('admin/user/settings'),
'@url2' => url('admin/user/user/create'),
)),
),
);
return system_settings_form($form);
}
Functions
Name | Description |
---|---|
theme_uif_form_help | Theme function for import form help. |
theme_uif_preview_one_user | Theme preview of a single user. |
theme_uif_preview_users | Theme preview of all users. |
uif_add_line_number | Prepend the line number on the error. |
uif_adjust_header_values | Perform header adjustments. |
uif_assign_presave_fields | Prepare core and entity user fields for user_save(). |
uif_batch_import_users | Batch import all users. |
uif_batch_import_users_finished | User import batch completion. |
uif_batch_import_users_process | User import batch processing. |
uif_clean_and_key_row | Trim all elements of $row, and pad $row out to the number of columns in the $header. Then replace keys in $row with $header values. |
uif_clean_value | Check that input is UTF-8. |
uif_configuration_page | User Import Framework configuration page. |
uif_create_user | Create a new user. |
uif_field_delimiters | Field delimiter options. |
uif_field_info_field | Wrapper for field_info_field() to avoid module dependency. |
uif_field_info_instances | Wrapper for field_info_instances() to avoid module dependency. |
uif_get_field_info | Read and store field info relevant to the import. |
uif_get_raw_value | Helper function to process import data for core supported fields. |
uif_get_strtotime_value | Helper function to convert date string to timestamp. |
uif_get_supported_fields | Return list of supported fields. |
uif_get_taxonomy_value | Helper function to process import data for core supported fields. |
uif_import_form | User import multi-part form. |
uif_import_form_back | Return user to starting point on template multi-form. |
uif_import_form_submit | Form submission handler. |
uif_import_form_validate | Validate the import data. |
uif_import_user | Import one user. |
uif_isset_or | Check if a variable is set and return it if so, otherwise the alternative. |
uif_is_natural | Return TRUE if a $val is a natural number (integer 1, 2, 3, ...). Base can be changed to zero if desired. |
uif_is_supported_field | Return TRUE if a module supports import of the passed field type. |
uif_lookup_field_type | Given a field's machine name look up the field type. |
uif_normalize_header | Normalize the header columns. |
uif_options_users_to_preview | Users to preview options. |
uif_parse_roles | Parse input roles if any. |
uif_row_has_data | Is there data in the row? |
uif_uif_pre_create | Implements hook_uif_pre_create(). |
uif_uif_pre_update | Implements hook_uif_pre_update(). |
uif_uif_supported_fields | Implementation of hook_uif_supported_fields(). |
uif_uif_validate_header | Implementation of hook_uif_validate_header(). |
uif_uif_validate_user | Implementation of hook_uif_validate_user(). |
uif_unique_username | Given a starting point for a Drupal username (e.g. the name portion of an email address) return a legal, unique Drupal username. |
uif_update_user | Update an existing user. |
uif_validate_user_file | Read the user import file and validate on the way. |
uif_value_delimiters | Value delimiter options. |