')) + node_get_types('names'),
'#default_value' => $type_name,
'#title' => t('Content type'),
'#description' => t('Select the content type to import these fields into.
Select <Create> to create a new content type to contain the fields.'),
);
$form['macro'] = array(
'#type' => 'textarea',
'#rows' => 40,
'#title' => t('Import data'),
'#required' => TRUE,
'#description' => t('Paste the text created by a content export into this field.'),
);
$form['submit'] = array(
'#type' => 'submit',
'#value' => t('Submit'),
);
// Read in a file if there is one and set it as the default macro value.
if (isset($_REQUEST['macro_file']) && $file = file_get_contents($_REQUEST['macro_file'])) {
$form['macro']['#default_value'] = $file;
if (isset($_REQUEST['type_name'])) {
$form['type_name']['#default_value'] = $_REQUEST['type_name'];
}
$form['#prefix'] .= ''. t('A file has been pre-loaded for import.') .'
';
}
return $form;
}
/**
* Submit handler for import form.
* For each submitted field:
* 1) add new field to the database
* 2) execute the imported field macro to update the settings to the imported values
*/
function content_copy_import_form_submit($form_id, $form_values) {
// Get the content type we are importing into.
$type_name = $form_values['type_name'];
$type_label = node_get_types('name', $type_name);
$content = NULL;
// Convert the import formatted text back into a $content array.
// Return if errors generated or not an array.
eval($form_values['macro']);
// Preliminary error trapping, must have valid arrays to work with.
if (!is_array($content) || !is_array($content['type'])) {
form_set_error('macro', t('The import data is not valid import text.'));
return;
}
// Get all type and field info for this database.
$content_info = _content_type_info();
$imported_type = $content['type'];
$imported_type_name = $imported_type['type'];
$imported_type_label = $imported_type['name'];
// It is allowed to import a type with no fields,
// so the fields array could be empty and must be cast as an array.
$imported_fields = (array) $content['fields'];
// Perform more pre-import error trapping.
// If there are potential problems, exit without doing the import.
$not_enabled = array();
// The groups array could be empty and still valid, make sure to cast it as an array.
// If there are groups in the import, make sure the fieldgroup module is enabled.
if (module_exists('fieldgroup')) {
$imported_groups = (array) $content['groups'];
}
elseif (is_array($content['groups'])) {
$not_enabled[] = 'fieldgroup';
}
// Make sure that all the field and widget modules in the import are enabled in this database.
foreach ($imported_fields as $field) {
if (empty($field['module'])) {
$not_enabled[] = $field['field_name'];
}
else {
$modules = explode(', ', $field['module']);
foreach ($modules as $module) {
if (!module_exists($module)) {
$not_enabled[] = $module;
}
}
}
}
// If any required module is not enabled, set an error message and exit.
if ($not_enabled) {
form_set_error('macro', t('The following modules must be enabled for this import to work: %modules.', array(
'%modules' => implode(', ', array_unique($not_enabled))
)));
}
// Make sure the imported content type doesn't already exist in the database.
if ($form_values['type_name'] == '') {
if (in_array($imported_type_name, array_keys($content_info['content types']))) {
form_set_error('macro', t('The content type %type already exists in this database.', array(
'%type' => $imported_type_name
)));
}
}
if (form_get_errors()) {
drupal_set_message(t('Exiting. No import performed.'), 'error');
return;
}
// Create the content type, if requested.
if ($form_values['type_name'] == '') {
$node = (object) $imported_type;
$values = $imported_type;
drupal_execute('node_type_form', $values, $node);
// Reset type and database values once new type has been added.
$type_name = $imported_type_name;
$type_label = node_get_types('name', $type_name);
$content_info = _content_type_info();
if (form_get_errors() || !is_array($content_info['content types'][$type_name])) {
drupal_set_message(t("An error has occured adding the content type %type.
Please check the errors displayed for more details.", array(
'%type' => $imported_type_name
)));
return;
}
}
// Create the groups for this type, if they don't already exist.
if (module_exists('fieldgroup')) {
$groups = fieldgroup_groups($type_name);
$content_type = content_types($type_name);
$errors = FALSE;
foreach ($imported_groups as $group) {
$group_name = $group['group_name'];
if (!is_array($groups[$group_name])) {
$values = (array) $group;
drupal_execute('fieldgroup_edit_group_form', $values, $content_type, $group_name, 'add');
}
}
cache_clear_all('fieldgroup_data', 'cache_content');
// Reset the static variable in fieldgroup_groups() with new data.
fieldgroup_groups('', FALSE, TRUE);
}
$should_clear_type_cache = 0;
// Iterate through the field forms in the import and execute each.
foreach ($imported_fields as $field) {
// Make sure the field doesn't already exist in the type.
// If so, do nothing, fields can't be duplicated within a content type.
$field_name = $field['field_name'];
$field_values = $field;
$field_label = $field_values['label'];
if (!empty($field['field_name']) && is_array($content_info['content types'][$type_name]['fields'][$field_name])) {
drupal_set_message(t("The imported field %field_label (%field_name) was not added to %type because that field already exists in %type.", array(
'%field_label' => $field_label,
'%field_name' => $field_name,
'%type' => $type_name
)));
}
else {
$values = array();
$errors = FALSE;
// Check if field already exists in the database.
// If not, add new, otherwise, add existing.
if (!array_key_exists($field_name, $content_info['fields'])) {
$values['field_name'] = $field_values['field_name'];
$values['label'] = $field_values['label'];
$values['field_widget_type'] = $field_values['field_type'] .'-'. $field_values['widget_type'];
$values['type_name'] = $type_name;
$field_url = drupal_execute('_content_admin_field_add_new', $values, $type_name, $field_name);
if (form_get_errors()) {
drupal_set_message(t("An error has occured adding the field %field_label (%field_name).
Please check the errors displayed for more details.", array(
'%field_label' => $field_label,
'%field_name' => $field_name
)));
$errors = TRUE;
}
else {
// Retrieve the new field name by picking out the arg from the url returned by
// _content_admin_field_add_new(), needed so the right field can be updated in the next step.
$args = explode('/', $field_url);
$field_name = array_pop($args);
$field_values['field_name'] = $field_name;
}
}
else {
$values['field_name'] = $field_values['field_name'];
$values['type_name'] = $type_name;
drupal_execute('_content_admin_field_add_existing', $values, $type_name);
if (form_get_errors()) {
drupal_set_message(t("An error has occured adding the field %field_label (%field_name).
Please check the errors displayed for more details.", array(
'%field_label' => $field_label,
'%field_name' => $field_name
)));
$errors = TRUE;
}
}
// Once the field has been added, update the settings with the macro values.
// Replace the export type name with the import type name.
if (!$errors) {
$field_values['type_name'] = $type_name;
drupal_execute('_content_admin_field', $field_values, $type_name, $field_name);
if (form_get_errors()) {
drupal_set_message(t("The field %field_label (%field_name) was added to the content type %type, but an error has occured updating the field settings.
Please check the errors displayed for more details.", array(
'%field_label' => $field_label,
'%field_name' => $field_name,
'%type' => $type_label
)));
}
else {
// If we successfully updated the form, serialize the display_settings info
// and insert the display_settings (if it exists) into the database.
if (array_key_exists('display_settings', $field)) {
$query = 'UPDATE {node_field_instance} SET display_settings = \'%s\' WHERE field_name = \'%s\'';
db_query($query, serialize($field['display_settings']), $field['field_name']);
if ($db_err = db_error()) {
drupal_set_message(t("The field %field_label (%field_name) was added to the content type %type, but an error has occured updating the field's 'display_settings'.
The db error is: '%db_err'.", array(
'%field_label' => $field_label,
'%field_name' => $field_name,
'%type' => $type_label,
'%db_err' => $db_err
)));
}
else {
// If any data was successfully inserted into the DB,
// we make sure the cache is cleared.
$should_clear_type_cache = 1;
}
}
}
}
}
}
// If no errors occured when inserting field data directly into the DB,
// clear the type cache.
if ($should_clear_type_cache) {
content_clear_type_cache();
}
if (!form_get_errors()) {
if (sizeof($imported_fields) > 0 || sizeof($imported_groups) > 0) {
return 'admin/content/types/'. $content_info['content types'][$type_name]['url_str'] .'/fields';
}
else {
return 'admin/content/types';
}
}
}
/**
* Implementation of hook_form_alter().
* Intervene to run form through macro when doing export
*/
function content_copy_form_alter($form_id, &$form) {
$alter_forms = array('node_type_form', '_content_admin_field', 'fieldgroup_edit_group_form');
if ($GLOBALS['content_copy']['status'] == 'export' && in_array($form_id, $alter_forms)) {
$form['#submit'] = array('content_copy_record_macro' => array($form));
}
}
/**
* Get all the fields for a content type.
*/
function content_copy_fields($type_name) {
$fields = array();
if (!$type_name) {
return $fields;
}
$content_info = _content_type_info();
foreach ($content_info['content types'][$type_name]['fields'] as $field_name => $field) {
// Omit fields from the export if their module is not currently installed
// otherwise the system will generate errors when the macro tries to execute their forms.
$field_types = _content_field_types();
$field_module = $field_types[$field['type']]['module'];
$widget_types = _content_widget_types();
$widget_module = $widget_types[$field['widget']['type']]['module'];
if (!empty($field_module) && module_exists($field_module) && !empty($widget_module) && module_exists($widget_module)) {
$fields[$field_name] = $field['widget']['label'] .' ('. $field['field_name'] .')';
}
}
return $fields;
}
/**
* Get all the groups for a content type.
*/
function content_copy_groups($type_name = '') {
$groups = array();
if (!$type_name || !module_exists('fieldgroup')) {
return $groups;
}
$data = fieldgroup_groups($type_name);
foreach ($data as $group_name => $group) {
$groups[$group_name] = $group['label'] .' ('. $group['group_name'] .')';
}
return $groups;
}
/**
* Get all content types.
*/
function content_copy_types() {
$types = array();
$content_info = _content_type_info();
foreach ($content_info['content types'] as $type_name => $val) {
$types[$type_name] = $val['name'] .' ('. $type_name .')';
}
return $types;
}
/**
* A handler that stores the form submissions into a $GLOBALS array
*/
function content_copy_record_macro($form_id, $edit, $form) {
$subs = $GLOBALS['content_copy']['submissions'];
// Get the form values and store them in a $GLOBALS['content_copy']['submissions'] array.
// Update $GLOBALS['content_copy']['count'] with an approximation of the number of rows in this item.
// Count is used to approximate necessary size of textarea in form.
unset($edit['type_name'], $edit['submit'], $edit['delete'], $edit['form_id']);
switch ($form_id) {
case 'node_type_form':
$subs['type'] = $edit;
$GLOBALS['content_copy']['count'] += sizeof($edit) + 5;
break;
case 'fieldgroup_edit_group_form':
$subs['groups'][] = $edit;
$GLOBALS['content_copy']['count'] += sizeof($edit) + 5;
break;
default:
if ($edit['field_widget_type']) {
$tmp = explode('-', $edit['field_widget_type']);
$field_name = $tmp[0];
}
else {
$field_name = $edit['field_name'];
}
// The display settings are being fetched directly from the DB. During import,
// we'll re-insert the data directly as well.
//
$query = 'SELECT display_settings FROM {node_field_instance} WHERE field_name = \'%s\'';
$row_info = db_fetch_array(db_query($query, $field_name));
// If an error occurs, notify the user.
if ($db_err = db_error()) {
drupal_set_message(t("An error occurred when exporting the 'display settings' data for the field %field_name.
The db error is: '%db_err'.", array(
'%field_name' => $field_name,
'%db_err' => $db_err
)));
}
else {
// The db fetch occurred successfully, unserialize the data blob and
// insert it into a new "display_settings" field of the data.
if ($display_settings = unserialize($row_info['display_settings'])) {
$edit['display_settings'] = $display_settings;
}
}
$subs['fields'][] = $edit;
$GLOBALS['content_copy']['count'] += sizeof($edit) + 5;
break;
}
$GLOBALS['content_copy']['submissions'] = $subs;
}
/**
* @return a code representation of the recorded macro.
*/
function content_copy_get_macro() {
foreach ($GLOBALS['content_copy']['submissions'] as $form_type => $form) {
$string .= "\$content[$form_type] = ". var_export((array) $form, TRUE) .";\n";
}
return $string;
}