'node_type_get_type',
'bundle_save_callback' => 'node_type_save',
'export_menu' => array(
'path' => 'admin/structure/types/export',
'access arguments' => 'administer content types',
),
'import_menu' => array(
'path' => 'admin/structure/types/import',
'access arguments' => 'administer content types',
),
);
$info['user'] = array(
'bundle_export_callback' => '_bc_bundle_export_ignore',
'bundle_save_callback' => '_bc_bundle_save_ignore',
'export_menu' => array(
'path' => 'admin/config/people/accounts/export',
'access arguments' => 'administer users',
),
'import_menu' => array(
'path' => 'admin/config/people/accounts/import',
'access arguments' => 'administer users',
),
);
if (module_exists('taxonomy')) {
$info['taxonomy_term'] = array(
'bundle_export_callback' => '_bc_copy_taxonomy_load',
'bundle_save_callback' => '_bc_copy_taxonomy_save',
'export_menu' => array(
'path' => 'admin/structure/taxonomy/export',
'access arguments' => 'administer taxonomy',
),
'import_menu' => array(
'path' => 'admin/structure/taxonomy/import',
'access arguments' => 'administer taxonomy',
),
);
}
return $info;
}
/**
* Implements hook_menu().
*/
function bundle_copy_menu() {
$items = array();
$bc_info = bundle_copy_get_info();
foreach ($bc_info as $entity_type => $info) {
$items[$info['export_menu']['path']] = array(
'title' => 'Export',
'page callback' => 'drupal_get_form',
'page arguments' => array('bundle_copy_export', $entity_type),
'access arguments' => array($info['export_menu']['access arguments']),
'type' => MENU_LOCAL_TASK
);
$items[$info['import_menu']['path']] = array(
'title' => 'Import',
'page callback' => 'drupal_get_form',
'page arguments' => array('bundle_copy_import', $entity_type),
'access callback' => 'bundle_copy_import_access',
'access arguments' => array($info['import_menu']['access arguments']),
'type' => MENU_LOCAL_TASK
);
}
return $items;
}
/**
* Bundle copy import access callback.
*
* Bundle copy imports require an additional access check because they are PHP
* code and PHP is more locked down than the general permission.
*/
function bundle_copy_import_access($permission) {
return user_access($permission) && user_access('use PHP for settings');
}
/**
* Menu callback: present the export page.
*/
function bundle_copy_export($form, &$form_state, $entity_type = 'node') {
if (isset($form_state['step'])) {
$step = $form_state['step'];
}
else {
$step = 1;
$form_state['step'] = $step;
}
switch ($step) {
// Select the bundles.
case 1:
$bundles = _bundle_copy_bundle_info($entity_type, TRUE);
$form['bundle-info'] = array(
'#markup' => t('Select bundles you want to export.'),
);
$form['bundles'] = array(
'#type' => 'tableselect',
'#header' => array('label' => t('Bundle')),
'#options' => $bundles,
'#required' => TRUE,
'#empty' => t('No bundles found.'),
);
$form['next'] = array(
'#type' => 'submit',
'#value' => t('Next'),
);
break;
// List the fields / field groups.
case 2:
// Field group.
$all_groups = function_exists('field_group_info_groups') ? field_group_info_groups() : array();
// Fields.
$field_options = $instances = array();
$selected_bundles = $form_state['page_values'][1]['bundles'];
foreach ($selected_bundles as $key => $bundle) {
if ($key === $bundle) {
$instances += field_info_instances($entity_type, $bundle);
}
}
ksort($instances);
foreach ($instances as $key => $info) {
$field_options[$key]['field'] = $info['field_name']; // Same as $key.
$field_options[$key]['label'] = $info['label'];
}
$form['fields-info'] = array(
'#markup' => t('Select fields you want to export.'),
);
$form['fields'] = array(
'#type' => 'tableselect',
'#header' => array('field' => t('Field name'), 'label' => t('Label')),
'#options' => $field_options,
'#empty' => t('No fields found.'),
);
// Field group support.
if (!empty($all_groups)) {
$group_options = $fieldgroups = array();
if (isset($all_groups[$entity_type])) {
foreach ($selected_bundles as $key => $bundle) {
if ($key === $bundle) {
if (!isset($all_groups[$entity_type][$key])) {
continue;
}
foreach ($all_groups[$entity_type][$key] as $view_mode => $groups) {
foreach ($groups as $field_group) {
$group_options[$field_group->id]['fieldgroup'] = $field_group->label . ' (' . $field_group->bundle . ' - ' . $field_group->mode .')';
$fieldgroups[$field_group->id] = $field_group;
}
}
}
}
}
if (!empty($group_options)) {
$form['fieldgroups-info'] = array(
'#markup' => t('Select field groups you want to export.'),
);
$form['fieldgroups'] = array(
'#type' => 'tableselect',
'#header' => array('fieldgroup' => t('Field group name')),
'#options' => $group_options,
);
$form['fieldgroups-full'] = array(
'#type' => 'value',
'#value' => $fieldgroups,
);
}
}
$form['actions'] = array('#type' => 'actions');
$form['actions']['next'] = array(
'#type' => 'submit',
'#value' => t('Export'),
);
$bc_info = bundle_copy_get_info();
$form['actions']['cancel'] = array(
'#markup' => l(t('Cancel'), $bc_info[$entity_type]['export_menu']['path']),
);
break;
// Export data.
case 3:
$data = _bundle_copy_export_data($entity_type, $form_state['page_values']);
$form['export'] = array(
'#title' => t('Export data'),
'#type' => 'textarea',
'#cols' => 60,
'#value' => $data,
'#rows' => 40,
'#description' => t('Copy the export text and paste it into another bundle using the import function.'),
);
break;
}
return $form;
}
/**
* Submit callback: export data.
*/
function bundle_copy_export_submit($form, &$form_state) {
// Save the form state values.
$step = $form_state['step'];
$form_state['page_values'][$step] = $form_state['values'];
// Add step and rebuild.
$form_state['step'] = $form_state['step'] + 1;
$form_state['rebuild'] = TRUE;
}
/**
* Menu callback: present the import page.
*/
function bundle_copy_import($form, $form_state, $entity_type = 'node') {
$form['entity_type'] = array('#type' => 'value', '#value' => $entity_type);
$form['info'] = array(
'#markup' => t('This form will import bundle and field definitions.'),
);
//$form['type_name'] = array(
// '#title' => t('Bundle'),
// '#description' => t('Select the bundle to import these fields into.
Select <Create> to create a new bundle to contain the fields.'),
// '#type' => 'select',
// '#options' => array('' => t('')) + _bundle_copy_bundle_info($entity_type),
//);
$form['macro'] = array(
'#type' => 'textarea',
'#rows' => 10,
'#title' => t('Import data'),
'#required' => TRUE,
'#description' => t('Paste the text created by a bundle export into this field.'),
);
$form['submit'] = array(
'#type' => 'submit',
'#value' => t('Import'),
);
return $form;
}
/**
* Submit callback: import data.
*/
function bundle_copy_import_submit($form, &$form_state) {
// Evaluate data.
eval($form_state['values']['macro']);
if (isset($data) && is_array($data)) {
$modules = module_list();
$bc_info = bundle_copy_get_info();
// Create bundles.
foreach ($data['bundles'] as $key => $bundle) {
$entity_type = '';
if (is_object($bundle)) {
$entity_type = $bundle->bc_entity_type;
}
elseif (is_array($bundle)) {
$entity_type = $bundle['bc_entity_type'];
}
if (!empty($entity_type)) {
$existing_bundles = _bundle_copy_bundle_info($entity_type);
$bundle_save_callback = $bc_info[$entity_type]['bundle_save_callback'];
$bundle_info = $bundle_save_callback($bundle);
if (!isset($existing_bundles[$key])) {
drupal_set_message(t('%bundle bundle has been created.', array('%bundle' => $bundle->name)));
}
else {
drupal_set_message(t('%bundle bundle has been updated.', array('%bundle' => $bundle->name)));
}
}
}
// Create or update fields and their instances
if (isset($data['fields'])) {
foreach ($data['fields'] as $key => $field) {
// Check if the field module exists.
$module = $field['module'];
if (!isset($modules[$module])) {
drupal_set_message(t('%field_name field could not be created because the module %module is disabled or missing.', array('%field_name' => $key, '%module' => $module)), 'error');
continue;
}
if (isset($data['instances'][$key])) {
// Create or update field.
$prior_field = field_read_field($field['field_name'], array('include_inactive' => TRUE));
if (!$prior_field) {
field_create_field($field);
drupal_set_message(t('%field_name field has been created.', array('%field_name' => $key)));
}
else {
$field['id'] = $prior_field['id'];
field_update_field($field);
drupal_set_message(t('%field_name field has been updated.', array('%field_name' => $key)));
}
// Create or update field instances.
foreach ($data['instances'][$key] as $ikey => $instance) {
// Make sure the needed key exists.
if (!isset($instance['field_name'])) {
continue;
}
$prior_instance = field_read_instance($instance['entity_type'], $instance['field_name'], $instance['bundle']);
if (!$prior_instance) {
field_create_instance($instance);
drupal_set_message(t('%field_name instance has been created for @bundle in @entity_type.', array('%field_name' => $key, '@bundle' => $instance['bundle'], '@entity_type' => $instance['entity_type'])));
}
else {
$instance['id'] = $prior_instance['id'];
$instance['field_id'] = $prior_instance['field_id'];
field_update_instance($instance);
drupal_set_message(t('%field_name instance has been updated for @bundle in @entity_type.', array('%field_name' => $key, '@bundle' => $instance['bundle'], '@entity_type' => $instance['entity_type'])));
}
}
}
}
}
// Create / update fieldgroups.
if (isset($data['fieldgroups'])) {
if (module_exists('field_group')) {
ctools_include('export');
$existing_field_groups = field_group_info_groups();
foreach ($data['fieldgroups'] as $identifier => $fieldgroup) {
if (isset($existing_field_groups[$fieldgroup->entity_type][$fieldgroup->bundle][$fieldgroup->mode][$fieldgroup->group_name])) {
$existing = $existing_field_groups[$fieldgroup->entity_type][$fieldgroup->bundle][$fieldgroup->mode][$fieldgroup->group_name];
$fieldgroup->id = $existing->id;
if (!isset($fieldgroup->disabled)) {
$fieldgroup->disabled = FALSE;
}
ctools_export_crud_save('field_group', $fieldgroup);
ctools_export_crud_set_status('field_group', $fieldgroup, $fieldgroup->disabled);
drupal_set_message(t('%fieldgroup fieldgroup has been updated for @bundle in @entity_type.', array('%fieldgroup' => $fieldgroup->label, '@bundle' => $fieldgroup->bundle, '@entity_type' => $fieldgroup->entity_type)));
}
else {
unset($fieldgroup->id);
unset($fieldgroup->export_type);
if (!isset($fieldgroup->disabled)) {
$fieldgroup->disabled = FALSE;
}
ctools_export_crud_save('field_group', $fieldgroup);
$fieldgroup->export_type = 1;
ctools_export_crud_set_status('field_group', $fieldgroup, $fieldgroup->disabled);
drupal_set_message(t('%fieldgroup fieldgroup has been saved for @bundle in @entity_type.', array('%fieldgroup' => $fieldgroup->label, '@bundle' => $fieldgroup->bundle, '@entity_type' => $fieldgroup->entity_type)));
}
}
}
else {
drupal_set_message(t('The fieldgroups could not be saved because the Field group module is disabled or missing.'), 'error');
}
}
// Clear caches.
field_info_cache_clear();
if (module_exists('field_group')) {
cache_clear_all('field_groups', 'cache_field');
}
}
else {
drupal_set_message(t('The pasted text did not contain any valid export data.'), 'error');
}
}
/**
* Return bundles for a certain entity type.
*
* @param $entity_type
* The name of the entity type.
* @param $table_select
* Whether we're returning for the table select or not.
*/
function _bundle_copy_bundle_info($entity_type, $table_select = FALSE) {
static $bundles = array();
if (!isset($bundles[$entity_type])) {
$bundles[$entity_type] = array();
$entity_info = entity_get_info($entity_type);
$entity_bundles = $entity_info['bundles'];
ksort($entity_bundles);
foreach ($entity_bundles as $key => $info) {
$label = isset($info['label']) ? $info['label'] : drupal_ucfirst(str_replace('_', ' ', $key));
if ($table_select) {
$bundles[$entity_type][$key]['label'] = $label;
}
else {
$bundles[$entity_type][$key] = $label;
}
}
}
return $bundles[$entity_type];
}
/**
* Creates export data
*
* @param $entity_type
* The name of the entity_type
* @param $selected_data
* The selected data.
*/
function _bundle_copy_export_data($entity_type, $selected_data) {
ctools_include('export');
$bc_info = bundle_copy_get_info();
$selected_bundles = $selected_data[1]['bundles'];
$selected_fields = $selected_data[2]['fields'];
$selected_fieldgroups = isset($selected_data[2]['fieldgroups']) ? $selected_data[2]['fieldgroups'] : array();
$full_fieldgroups = isset($selected_data[2]['fieldgroups-full']) ? $selected_data[2]['fieldgroups-full'] : array();
$data = $instances = array();
$fields = field_info_fields();
foreach ($selected_bundles as $bkey => $binfo) {
if ($bkey !== $binfo) {
continue;
}
$field_instances = field_info_instances($entity_type, $bkey);
ksort($field_instances);
// Bundles export data.
$bundle_info_callback = $bc_info[$entity_type]['bundle_export_callback'];
$bundle_info = $bundle_info_callback($bkey, $entity_type);
if (is_object($bundle_info)) {
$bundle_info->bc_entity_type = $entity_type;
}
elseif (is_array($bundle_info)) {
$bundle_info['bc_entity_type'] = $entity_type;
}
$data['bundles'][$bkey] = $bundle_info;
// Fields export data.
foreach ($selected_fields as $fkey => $finfo) {
if ($fkey === $finfo) {
if (!isset($data['fields'][$fkey])) {
unset($fields[$fkey]['id']);
$data['fields'][$fkey] = $fields[$fkey];
}
if (isset($field_instances[$fkey])) {
unset($field_instances[$fkey]['id']);
unset($field_instances[$fkey]['field_id']);
$instances[$fkey][] = $field_instances[$fkey];
}
}
}
}
ksort($instances);
$data['instances'] = $instances;
// Field group export data.
if (!empty($selected_fieldgroups)) {
foreach ($selected_fieldgroups as $key => $value) {
if ($value !== 0) {
$data['fieldgroups'][$full_fieldgroups[$key]->identifier] = $full_fieldgroups[$key];
}
}
}
return '$data = ' . ctools_var_export($data) . ';';
}
/**
* Helper function to load the taxonomy, but remove the vid on the object.
*
* @param $name
* The name of the bundle.
*/
function _bc_copy_taxonomy_load($name) {
$bundle = taxonomy_vocabulary_machine_name_load($name);
return $bundle;
}
/**
* Helper function to save the taxonomy.
*/
function _bc_copy_taxonomy_save($bundle) {
if ($bundle->vid) {
unset($bundle->vid);
}
$vid = db_query('SELECT vid FROM {taxonomy_vocabulary} WHERE machine_name = :machine_name', array(':machine_name' => $bundle->machine_name))->fetchField();
if ($vid) {
$bundle->vid = $vid;
}
taxonomy_vocabulary_save($bundle);
}
/**
* Helper function to ignore a bundle on export.
*/
function _bc_bundle_export_ignore($name) {
}
/**
* Helper function to ignore a bundle save.
*/
function _bc_bundle_save_ignore($bundle) {
}