uif_plus.module in User Import Framework Plus 7
Advanced user import from a CSV file.
File
uif_plus.moduleView source
<?php
/**
* @file
* Advanced user import from a CSV file.
*/
/**
* Implements hook_uif_help().
*/
function uif_plus_uif_help() {
$uif_plus_help = '<p><strong>' . t('User Import Framework Plus adds support for the following:') . '</strong></p>';
$items[] = t('picture (optional) - the user\'s picture.');
if (module_exists('og')) {
$items[] = t('groups (optional) - groups user is a member of as delimited text, e.g. "group1|group2" or group ids e.g. "23|427" (without quotes)');
}
$supported_fields = uif_get_supported_fields();
foreach (uif_plus_profile2_fields() 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);
}
}
$uif_plus_help .= theme('item_list', array(
'items' => $items,
));
return $uif_plus_help;
}
/**
* Implements hook_form_FORM_ID_alter().
*
* Add delimiters for multiple values and move the "Next" button to the bottom
* of the form.
*/
function uif_plus_form_uif_import_form_alter(&$form, &$form_state, $form_id) {
$step = empty($form_state['storage']['step']) ? 1 : $form_state['storage']['step'];
$form_state['storage']['step'] = $step;
switch ($step) {
case 1:
$form['image_path'] = array(
'#type' => 'textfield',
'#title' => t('Images path'),
'#default_value' => '',
'#size' => 25,
'#maxlength' => 255,
'#description' => t("For images, enter the full path to the directory. Default: files/uif_plus (leave blank)."),
'#weight' => 90,
);
if (module_exists('addressfield')) {
$form['addressfield_part_delimiter'] = array(
'#type' => 'select',
'#title' => t('Addressfield part delimiter'),
'#default_value' => variable_get('uif_plus_addressfield_part_delimiter', '|'),
'#options' => uif_plus_addressfield_part_delimiters(),
'#description' => t('Select delimiter for addressfield parts or fragments e.g. "locality:Swindon" is a part. Must be different from the field delimiter above.'),
'#weight' => 91,
);
$form['addressfield_field_delimiter'] = array(
'#type' => 'select',
'#title' => t('Addressfield field delimiter'),
'#default_value' => variable_get('uif_plus_addressfield_field_delimiter', ':'),
'#options' => uif_plus_addressfield_field_delimiters(),
'#description' => t('Select delimiter for addressfield fields e.g. "locality" is a field. eg. To specify the value for locality, "locality:Swindon'),
'#weight' => 92,
);
}
$form['#validate'][] = 'uif_plus_uif_import_form_validate';
$form['#submit'][] = 'uif_plus_form_uif_import_form_submit';
$form['next']['#weight'] = 100;
break;
}
}
/**
* Custom submit function for the uif import settings form.
*
* @param $form
* @param $form_state
*/
function uif_plus_form_uif_import_form_submit($form, &$form_state) {
$form_state['storage']['image_path'] = isset($form_state['values']['image_path']) ? $form_state['values']['image_path'] : '';
$form_state['storage']['addressfield_part_delimiter'] = isset($form_state['values']['addressfield_part_delimiter']) ? $form_state['values']['addressfield_part_delimiter'] : '';
$form_state['storage']['addressfield_field_delimiter'] = isset($form_state['values']['addressfield_field_delimiter']) ? $form_state['values']['addressfield_field_delimiter'] : '';
variable_set('uif_plus_image_path', $form_state['storage']['image_path']);
variable_set('uif_plus_addressfield_part_delimiter', $form_state['storage']['addressfield_part_delimiter']);
variable_set('uif_plus_addressfield_field_delimiter', $form_state['storage']['addressfield_field_delimiter']);
}
/**
* Implementats hook_uif_post_create().
*
*/
function uif_plus_uif_post_create($account, $user_data, $form_state) {
uif_plus_update_user($account, $user_data, $form_state);
}
/**
* Implements hook_uif_post_update().
*
*/
function uif_plus_uif_post_update($account, $user_data, $form_state) {
uif_plus_update_user($account, $user_data, $form_state);
}
/**
* Common function for updating users based on types of fields as provided by
* contrib modules.
*
* @param object $account - User account to be updated
* @param array $user_data
*/
function uif_plus_update_user($account, $user_data, $form_state) {
$fields = uif_plus_get_field_info(array_keys($user_data));
$value_delimiter = $form_state['storage']['value_delimiter'];
$user_fields = $profile_fields = array();
foreach ($fields as $label => $info) {
if (!$info['supported']) {
continue;
}
$parser = uif_isset_or($info['import']['parser']) ? $info['import']['parser'] : 'uif_get_raw_value';
if ($label == 'picture') {
if (drupal_strlen($user_data[$label])) {
$user_fields[$label] = $parser($account, $info['data'], $user_data[$label]);
user_save($account, $user_fields);
}
}
elseif ($label == 'groups') {
if (isset($user_data[$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;
}
}
}
if (isset($info['data']) && array_key_exists('bundles', $info['data']) && count($info['data']['bundles']['profile2'])) {
foreach ($info['data']['bundles']['profile2'] as $profile_type) {
for ($delta = 0; $delta < count($field_values); $delta++) {
if ($info['data']['cardinality'] == 1 && $delta > 0) {
break;
}
if (drupal_strlen($field_values[$delta] || count($field_values[$delta]))) {
switch ($info['data']['type']) {
case 'addressfield':
foreach ($field_values[$delta] as $field_value) {
foreach ($field_value as $key => $value) {
$profile_fields[$profile_type][$label][LANGUAGE_NONE][$delta][$key] = $value;
}
}
break;
case 'file':
$profile_fields[$profile_type][$label][LANGUAGE_NONE][$delta] = $field_values[$delta];
break;
default:
$profile_fields[$profile_type][$label][LANGUAGE_NONE][$delta][$key] = $field_values[$delta];
break;
}
}
}
}
}
}
}
if (count($profile_fields)) {
uif_plus_save_profile2_fields($account, $profile_fields);
}
}
/**
* Helper function to remove a slash from the back of a filename
*
* @param string $filename
* @return string
*/
function uif_plus_normalise_filename($filename) {
if ($filename[0] == DIRECTORY_SEPARATOR) {
$filename = drupal_substr($filename, 1);
}
return $filename;
}
/**
* Helper function to remove trailing slashes from file paths
*
* @param string $filepath
* @return string
*/
function uif_plus_normalise_filepath($filepath) {
if (drupal_substr($filepath, -1) == DIRECTORY_SEPARATOR) {
$filepath = drupal_substr($filepath, 0, -1);
}
return $filepath;
}
/**
* Implements hook_uif_supported_fields().
*/
function uif_plus_uif_supported_fields() {
$supported_fields = array(
'entityreference' => array(
'type' => 'entity',
'label' => t('Entity reference'),
'parser' => 'uif_plus_get_entityreference_value',
'key' => 'target_id',
'description' => t('entity reference (node only currently)'),
),
'image' => array(
'type' => 'entity',
'label' => t('Image field'),
'parser' => 'uif_plus_process_image_field',
'key' => 'fid',
'description' => t('image field added to a user'),
),
'file' => array(
'type' => 'entity',
'label' => t('File field'),
'parser' => 'uif_plus_process_file_field',
'key' => 'fid',
'description' => t('file field added to a user'),
),
'picture' => array(
'type' => 'core',
'label' => t('User picture'),
'description' => t('the user picture'),
'parser' => 'uif_plus_process_user_picture',
),
'groups' => array(
'type' => 'og',
'label' => t('Organic groups'),
'description' => t('the og memberships of user'),
'parser' => 'uif_plus_process_user_groups',
),
'addressfield' => array(
'type' => 'addressfield',
'label' => t('Address field'),
'description' => t('the postal address of user'),
'parser' => 'uif_plus_process_addressfield',
),
);
$instance_fields = uif_plus_profile2_fields();
if (count($instance_fields)) {
foreach ($instance_fields as $field) {
$supported_fields[$field['field_name']] = array(
'type' => $field['entity_type'],
'label' => $field['label'],
'description' => $field['description'],
);
}
}
return $supported_fields;
}
/**
* Process import of user pictures
*
* @param object $account
* @param array $field_info
* @param string $value
* @return object $picture - File object of uploaded picture
*/
function uif_plus_process_user_picture($account, $field_info, $value = '') {
if (drupal_strlen($value)) {
$file = uif_plus_upload_file($account, $field_info, $value);
return $file;
}
}
/**
* Process import of image fields.
*
* @param object $account
* @param array $field_info
* @param string $value
* @return int - File ID of uploaded file
*/
function uif_plus_process_image_field($account, $field_info, $value) {
if (drupal_strlen($value)) {
$file = uif_plus_upload_file($account, $field_info, $value);
return $file->fid;
}
}
/**
* Process import of file fields.
*
* @param object $account
* @param array $field_info
* @param string $value
* @return $file - Array of uploaded file data
*/
function uif_plus_process_file_field($account, $field_info, $value) {
if (drupal_strlen($value)) {
$file = uif_plus_upload_file($account, $field_info, $value);
return (array) $file;
}
}
/**
* Process import of users into groups.
*
* @param object $account
* @param array $field_info
* @param string $value
*/
function uif_plus_process_user_groups($account, $field_info, $value) {
if (drupal_strlen($value) && module_exists('og')) {
$delimiter = variable_get('uif_value_delimiter', '|');
$groups = explode($delimiter, $value);
$og_version_1 = uif_plus_check_og_version_1();
foreach ($groups as $og) {
$gid = uif_is_natural($og) ? $og : uif_plus_get_og_group($og, $og_version_1);
if ($gid) {
// As of og 2.x-beta2 the signature for og_group() is different from 1.x
if ($og_version_1) {
og_group($gid, array(
'entity' => $account,
));
}
else {
og_group('node', $gid, array(
'entity' => $account,
));
}
}
}
}
}
/**
* Helper function to process data for fields provided by the entityreference module.
*/
function uif_plus_get_entityreference_value($account, $field_info, $value) {
if (uif_is_natural($value)) {
return $value;
}
switch ($field_info['settings']['target_type']) {
case 'node':
$table = $field_info['foreign keys'][$field_info['settings']['target_type']]['table'];
$column = $field_info['foreign keys'][$field_info['settings']['target_type']]['columns']['target_id'];
$types = array_keys($field_info['settings']['handler_settings']['target_bundles']);
$entity_id = db_select($table, 'n')
->extend('PagerDefault')
->fields('n', array(
$column,
))
->condition('n.type', $types, 'IN')
->condition('n.title', $value)
->limit(1)
->execute()
->fetchField();
return $entity_id;
case 'user':
// TODO: email or username
return $value;
}
return $value;
}
/**
* Create array of field info of supported fields and uif plus data for the
* later process of import
*
* @param type $header
* @return boolean
*/
function uif_plus_get_field_info($header) {
$field_info = array();
$instance_fields = uif_plus_profile2_fields();
$supported_fields = uif_get_supported_fields();
foreach ($header as $label) {
switch (TRUE) {
case count($instance_fields) && isset($instance_fields[$label]):
$data = uif_field_info_field($label);
$supported = uif_is_supported_field($data['type']);
$field_info[$label] = array(
'type' => 'entity',
'supported' => $supported,
'data' => $data,
);
if ($supported) {
$field_info[$label]['import'] = $supported_fields[$data['type']];
}
break;
case $label == 'picture':
$supported = uif_is_supported_field($label);
$users_table = drupal_get_schema('users');
$field_info[$label] = array(
'type' => 'core',
'supported' => $supported,
'data' => $users_table['fields'][$label],
);
if ($supported) {
$field_info[$label]['import'] = $supported_fields[$label];
}
break;
case in_array($label, array(
'groups',
'addressfield',
)):
$supported = uif_is_supported_field($label);
$field_info[$label] = array(
'type' => 'custom',
'supported' => $supported,
'data' => $label,
);
if ($supported) {
$field_info[$label]['import'] = $supported_fields[$label];
}
break;
default:
$field_info[$label] = array(
'type' => 'unknown',
'supported' => FALSE,
);
break;
}
}
return $field_info;
}
/**
* Get all fields provided by profile2 types
*
* @return array $instance_fields
*/
function uif_plus_profile2_fields() {
$instance_fields = array();
if (module_exists('profile2')) {
foreach (profile2_get_types() as $type) {
$instance_fields = array_merge($instance_fields, uif_field_info_instances('profile2', $type->type));
}
}
return $instance_fields;
}
/**
* Save fields of profile2 types
*
* @param object $account
* @param array $profile_fields
*/
function uif_plus_save_profile2_fields($account, $profile_fields) {
foreach ($profile_fields as $type_name => $fields) {
$profile = profile2_load_by_user($account, $type_name);
if (empty($profile)) {
$profile = profile2_create(array(
'user' => $account,
'type' => $type_name,
));
}
foreach ($fields as $field_name => $field) {
$profile->{$field_name} = $field;
}
profile2_save($profile);
}
}
/**
* Handle file uploads for image and file fields
*
* @param array $account
* @param array $field_info
* @param string $value
* @return object $file
*/
function uif_plus_upload_file($account, $field_info, $value) {
// prepare file paths
$uif_plus_image_path = variable_get('uif_plus_image_path', '');
if (!strlen($uif_plus_image_path)) {
$uif_plus_image_path = file_default_scheme() . '://uif_plus';
}
$image_path = uif_plus_normalise_filepath($uif_plus_image_path) . DIRECTORY_SEPARATOR . uif_plus_normalise_filename($value);
// get file URI
if ($field_info['type'] == 'int') {
$picture_directory = file_default_scheme() . '://' . variable_get('user_picture_path', 'pictures');
file_prepare_directory($picture_directory, FILE_CREATE_DIRECTORY);
$pathinfo = pathinfo($image_path);
$uri = $picture_directory . '/picture-' . $account->uid . '-' . REQUEST_TIME . '.' . $pathinfo['extension'];
}
else {
$picture_directory = file_default_scheme() . '://';
file_prepare_directory($picture_directory, FILE_CREATE_DIRECTORY);
$pathinfo = pathinfo($image_path);
$uri = $picture_directory . '/' . $pathinfo['basename'];
}
// prepare for file upload
$info = image_get_info($image_path);
$destination = file_stream_wrapper_uri_normalize($uri);
// create file
$file = new stdClass();
$file->uid = 1;
$file->uri = $image_path;
$file->filemime = $info['mime_type'];
$file->status = 1;
$file->filesize = $info['file_size'];
$file->id = 1;
$file->display = 1;
// Move the temporary file into the final location.
if ($file = file_move($file, $destination, FILE_EXISTS_RENAME)) {
$file->status = FILE_STATUS_PERMANENT;
$file = file_save($file);
file_usage_add($file, $field_info['type'] == 'int' ? 'user' : $field_info['module'], 'user', 1);
}
return $file;
}
/**
* Helper function to get a group ID from the og table.
*
* http://drupal.org/node/1615542#3 - "The og table is deprecated in the 2.x version, so it should stay empty"
*
* @param mixed $group
* @param boolean $og_version_1 - Is the version of the og module 1.x?
* @return int $gid
*/
function uif_plus_get_og_group($group, $og_version_1) {
$gid = 0;
if ($og_version_1) {
$column = intval($group) > 0 ? 'g.gid' : 'g.label';
$gid = db_select('og', 'g')
->extend('PagerDefault')
->fields('g', array(
'gid',
))
->condition($column, $group)
->condition('g.state', 1)
->limit(1)
->execute()
->fetchField();
}
else {
$column = intval($group) > 0 ? 'n.nid' : 'n.title';
$gid = db_select('node', 'n')
->extend('PagerDefault')
->fields('n', array(
'nid',
))
->condition($column, $group)
->condition('n.status', 1)
->limit(1)
->execute()
->fetchField();
}
return $gid;
}
/**
* Helper function to check the version of og, if available. We are interested in
* whether the available version of og is 1.x
*
* @return boolean - If true, og is 1.x else if og is enabled, it's >= 2.0
*/
function uif_plus_check_og_version_1() {
$module_info = system_get_info('module', 'og');
$og_version_1 = isset($module_info['version']) && strpos($module_info['version'], '7.x-1.') !== FALSE ? TRUE : FALSE;
return $og_version_1;
}
/**
* Process import of address field values.
*
* @param $account
* @param $field_info
* @param $value
*/
function uif_plus_process_addressfield($account, $field_info, $value) {
$addresses = explode(variable_get('uif_value_delimiter', '_*_'), $value);
$values = array();
foreach ($addresses as $address_string) {
$address = array();
$parts = explode(variable_get('uif_plus_addressfield_part_delimiter', '|'), $address_string);
foreach ($parts as $part) {
$field = explode(variable_get('uif_plus_addressfield_field_delimiter', ':'), $part);
list($key, $val) = $field;
$address[$key] = $val;
}
$values[] = $address;
}
return $values;
}
/**
* Addressfield part delimiter options.
*/
function uif_plus_addressfield_part_delimiters() {
//array('|', '', '')
return array(
'|' => '|',
'__:__' => '__:__',
'__*__' => '__*__',
);
}
/**
* Addressfield field delimiter options.
*/
function uif_plus_addressfield_field_delimiters() {
return array(
':' => ':',
'_' => '_',
'+' => '+',
);
}
/**
* Validate delimiters on the import form.
*/
function uif_plus_uif_import_form_validate($form, &$form_state) {
$step = empty($form_state['storage']['step']) ? 1 : $form_state['storage']['step'];
switch ($step) {
case 1:
if ($form_state['values']['value_delimiter'] == $form_state['values']['addressfield_part_delimiter'] || $form_state['values']['value_delimiter'] == $form_state['values']['addressfield_field_delimiter']) {
$msg = t('Value and addressfield delimiters must be different.');
form_set_error('value_delimiter', $msg);
form_set_error('addressfield_part_delimiter', $msg);
form_set_error('addressfield_field_delimiter', $msg);
return;
}
break;
}
}
Functions
Name | Description |
---|---|
uif_plus_addressfield_field_delimiters | Addressfield field delimiter options. |
uif_plus_addressfield_part_delimiters | Addressfield part delimiter options. |
uif_plus_check_og_version_1 | Helper function to check the version of og, if available. We are interested in whether the available version of og is 1.x |
uif_plus_form_uif_import_form_alter | Implements hook_form_FORM_ID_alter(). |
uif_plus_form_uif_import_form_submit | Custom submit function for the uif import settings form. |
uif_plus_get_entityreference_value | Helper function to process data for fields provided by the entityreference module. |
uif_plus_get_field_info | Create array of field info of supported fields and uif plus data for the later process of import |
uif_plus_get_og_group | Helper function to get a group ID from the og table. |
uif_plus_normalise_filename | Helper function to remove a slash from the back of a filename |
uif_plus_normalise_filepath | Helper function to remove trailing slashes from file paths |
uif_plus_process_addressfield | Process import of address field values. |
uif_plus_process_file_field | Process import of file fields. |
uif_plus_process_image_field | Process import of image fields. |
uif_plus_process_user_groups | Process import of users into groups. |
uif_plus_process_user_picture | Process import of user pictures |
uif_plus_profile2_fields | Get all fields provided by profile2 types |
uif_plus_save_profile2_fields | Save fields of profile2 types |
uif_plus_uif_help | Implements hook_uif_help(). |
uif_plus_uif_import_form_validate | Validate delimiters on the import form. |
uif_plus_uif_post_create | Implementats hook_uif_post_create(). |
uif_plus_uif_post_update | Implements hook_uif_post_update(). |
uif_plus_uif_supported_fields | Implements hook_uif_supported_fields(). |
uif_plus_update_user | Common function for updating users based on types of fields as provided by contrib modules. |
uif_plus_upload_file | Handle file uploads for image and file fields |