field_defaults.module in Field Defaults 7.2
Same filename and directory in other branches
Allows updating existing content with default values
File
field_defaults.moduleView source
<?php
/**
* @file field_defaults.module
*
* Allows updating existing content with default values
*/
/**
* Implements hook_menu().
*/
function field_defaults_menu() {
$items = array();
$items['admin/config/content/field_defaults'] = [
'title' => 'Field Default Settings',
'description' => t('Administer Field Defaults settings.'),
'page callback' => 'drupal_get_form',
'page arguments' => array(
'field_defaults_admin_settings_form',
),
'access arguments' => array(
'administer field defaults',
),
'file' => 'field_defaults.admin.inc',
'type' => MENU_NORMAL_ITEM,
];
return $items;
}
/**
* Implements hook_permission().
*/
function field_defaults_permission() {
return array(
'administer field defaults' => array(
'title' => t('Administer Field Defaults'),
'description' => t('Perform administrative actions with Field Defaults.'),
),
);
}
/**
* Implements hook_entity_presave().
*/
function field_defaults_entity_presave($entity, $type) {
if (variable_get('field_defaults_retain_updated', 1) && isset($entity->original->changed)) {
$entity->changed = $entity->original->changed;
}
}
/**
* Implements hook_form_FORM_ID_alter().
*/
function field_defaults_form_field_ui_field_edit_form_alter(&$form, &$form_state) {
if (isset($form['instance']['default_value_widget'])) {
// Check for field translations
$field_translatable = !empty($form['#field']['translatable']);
$form['instance']['default_value_widget']['update_defaults'] = array(
'#type' => 'fieldset',
'#title' => t('Update existing content'),
'#weight' => 100,
);
$form['instance']['default_value_widget']['update_defaults']['field_defaults_update'] = array(
'#type' => 'checkbox',
'#title' => t('Update existing content with the default value(s)'),
'#description' => t('Note: Translatable <strong>fields</strong> will need to be updated per language on the translate tab'),
);
$form['instance']['default_value_widget']['update_defaults']['field_defaults_no_overwrite'] = array(
'#type' => 'checkbox',
'#title' => t('Keep existing values'),
'#description' => t('This option will prevent overwriting fields with existing values.'),
);
// If field translation off, then we need to select what ENTITY LANGUAGE
// content to update, otherwise we can
if ($field_translatable) {
$form['instance']['default_value_widget']['update_defaults']['field_defaults_lang'] = array(
'#type' => 'value',
'#value' => 'field_translation',
);
}
else {
$options = array(
LANGUAGE_NONE => t('Language neutral'),
);
// Only give other options if i18n enabled
if (module_exists('i18n')) {
$language_list = language_list();
foreach ($language_list as $language) {
$options[$language->language] = $language->name;
}
$default_language = language_default();
$form['instance']['default_value_widget']['update_defaults']['field_defaults_lang'] = array(
'#type' => 'checkboxes',
'#title' => t('Update entities of the following languages'),
'#default_value' => array(
$default_language->language,
),
'#options' => $options,
);
}
else {
$form['instance']['default_value_widget']['update_defaults']['field_defaults_lang'] = array(
'#type' => 'value',
'#value' => $options,
);
}
}
$form['#submit'][] = '_field_defaults_ui_submit';
}
}
/**
* Submit handler for field ui form
*/
function _field_defaults_ui_submit($form, &$form_state) {
$update_defaults = $form_state['values']['update_defaults']['field_defaults_update'];
$field = $form_state['values']['instance']['field_name'];
if ($update_defaults && isset($form_state['values'][$field])) {
$field_translate = FALSE;
$languages = $form_state['values']['update_defaults']['field_defaults_lang'];
if ($languages == 'field_translation') {
$default_language = language_default();
$languages = array(
$default_language->language => $default_language->name,
);
$field_translate = TRUE;
}
$batch = array(
'entity_type' => $form_state['values']['instance']['entity_type'],
'bundle' => $form_state['values']['instance']['bundle'],
'field' => $field,
'default_value' => $form_state['values'][$field][LANGUAGE_NONE],
'languages' => $languages,
'field_translation' => $field_translate,
'redirect' => $form_state['redirect'],
'no_overwrite' => $form_state['values']['update_defaults']['field_defaults_no_overwrite'],
);
// update the defaults
field_defaults_batch_run($batch);
}
}
/**
* Implements hook_form_FORM_ID_alter().
*
* @TODO: Need to find out how to actually get some details here... might have
* to build a new form as this one is not bound to the entity so doing some
* pretty hack-ish works here...
*
*/
function field_defaults_form_i18n_string_translate_page_form_alter(&$form, &$form_state) {
$disabled = TRUE;
foreach ($form['strings']['instance'] as $key => $field) {
if (strpos($key, 'default_value') !== FALSE) {
$disabled = $form['strings']['instance'][$key]['#disabled'];
$parts = explode(':', $key);
}
}
if (!$disabled) {
// See if we can narrow this field down to its entity type
$entity_type = FALSE;
$field = $parts[1];
$bundle = $parts[2];
$field_info = field_info_field($field);
// If only one entity we're golden
if (count($field_info['entity_types']) == 1) {
$entity_type = $field_info['entity_types'][0];
}
else {
foreach ($field_info['bundles'] as $type => $bundles) {
if (in_array($bundle, $bundles)) {
$entity_type = $type;
}
}
}
if ($entity_type) {
$form['field_defaults_batch'] = array(
'#type' => 'value',
'#value' => array(
'entity_type' => $entity_type,
'bundle' => $bundle,
'field' => $field,
),
);
$form['strings']['instance']['update_defaults'] = array(
'#type' => 'checkbox',
'#title' => t('Update existing content with the default value'),
'#weight' => 100,
);
$form['strings']['instance']['update_defaults_no_overwrite'] = array(
'#type' => 'checkbox',
'#title' => t('Keep existing values'),
'#description' => t('This option will prevent overwriting fields with existing values.'),
'#weight' => 101,
);
$form['#submit'][] = '_field_defaults_translation_submit';
}
}
}
/**
* Submit handler for field ui translation form
*/
function _field_defaults_translation_submit($form, &$form_state) {
$update_defaults = $form_state['values']['update_defaults'];
// @TODO: Again, some pretty hacky ways to get at this data
if ($update_defaults) {
// Setup batch
$batch = $form_state['values']['field_defaults_batch'];
$batch['languages'] = array(
$form_state['values']['langcode'] => $form_state['values']['langcode'],
);
$batch['field_translation'] = TRUE;
$batch['no_overwrite'] = $form_state['values']['update_defaults_no_overwrite'];
$key = 'field:' . $batch['field'] . ':' . $batch['bundle'] . ':default_value';
if (isset($form_state['values']['strings'][$key])) {
$batch['default_value'] = array(
array(
'value' => $form_state['values']['strings'][$key],
),
);
field_defaults_batch_run($batch);
}
}
}
/**
* The batch callback.
*/
function field_defaults_batch_run($variables) {
$batch = array(
'operations' => array(),
'finished' => 'field_defaults_batch_finished',
'title' => t('Update field defaults'),
'init_message' => t('Grabbing entities'),
'progress_message' => t('Processed @current out of @total.'),
'error_message' => t('updated has encountered an error.'),
);
$redirect = isset($variables['redirect']) ? $variables['redirect'] : NULL;
// Run each language separate
foreach ($variables['languages'] as $langcode => $value) {
// unchecked have no values but still have keys
if ($value) {
$batch['operations'][] = array(
'field_defaults_batch_process',
array(
$variables,
$langcode,
),
);
}
}
batch_set($batch);
batch_process($redirect);
}
/**
* The batch processor.
*
* @TODO: There is a chance of someone using LANGUAGE_NONE for the entity, but
* still having field translation. This still should work but is leaving erroneous
* records in the field I believe
*
*/
function field_defaults_batch_process($variables, $langcode, &$context) {
$entity_type = $variables['entity_type'];
$bundle = $variables['bundle'];
$field = $variables['field'];
if (!isset($context['sandbox']['current'])) {
$context['sandbox']['count'] = 0;
$context['sandbox']['current'] = 0;
}
$entity_info = entity_get_info($entity_type);
$entity_keys = $entity_info['entity keys'];
// Get all entities to update
$query = new EntityFieldQuery();
$query
->entityCondition('entity_type', $entity_type)
->propertyCondition($entity_info['entity keys']['id'], $context['sandbox']['current'], '>')
->propertyOrderBy($entity_info['entity keys']['id']);
if (!empty($entity_keys['bundle'])) {
$query
->propertyCondition($entity_keys['bundle'], $bundle);
}
if (!$variables['field_translation'] && !empty($entity_keys['language'])) {
$query
->propertyCondition($entity_keys['language'], $langcode);
// Set language for fields as LANGUAGE_NONE since we are updating based on
// content and not field
$langcode = LANGUAGE_NONE;
}
// Get the total amount of entities to process.
if (!isset($context['sandbox']['total'])) {
$context['sandbox']['total'] = $query
->count()
->execute();
$query->count = FALSE;
// If there are no entities, stop now
if (!$context['sandbox']['total']) {
$context['finished'] = 1;
return;
}
}
// Process 25 entities per iteration.
$query
->range(0, 25);
$result = $query
->execute();
if (isset($result[$entity_type])) {
$update_ids = array_keys($result[$entity_type]);
$entities = entity_load($entity_type, $update_ids);
foreach ($entities as $entity_id => $entity) {
// Check for existing data.
if ($variables['no_overwrite'] && !empty($entity->{$field}[$langcode][0])) {
continue;
}
// Need to account for Deltas
foreach ($variables['default_value'] as $delta => $value) {
// Values can be multiple columns as well depending on widget
foreach ($value as $key => $data) {
// support tokens.
if (module_exists('token')) {
$data = token_replace($data, [
$entity_type => $entity,
]);
}
$entity->{$field}[$langcode][$delta][$key] = $data;
}
// @TODO: Need to Catch?
entity_save($entity_type, $entity);
}
$context['results'][] = t('Field defaults for field @field on @bundle @id updated.', [
'@field' => $field,
'@bundle' => $entity_type . ': ' . $bundle,
'@id' => $entity_id,
]);
}
}
// Track progress.
$context['sandbox']['count'] += count($update_ids);
$context['sandbox']['current'] = max($update_ids);
if ($context['sandbox']['count'] != $context['sandbox']['total']) {
$context['finished'] = $context['sandbox']['count'] / $context['sandbox']['total'];
}
}
/**
* The batch finish handler.
*/
function field_defaults_batch_finished($success, $results, $operations) {
if ($success) {
drupal_set_message(t('Default values updated on existing content'));
}
else {
$error_operation = reset($operations);
$message = t('An error occurred while processing %error_operation with arguments: @arguments', array(
'%error_operation' => $error_operation[0],
'@arguments' => print_r($error_operation[1], TRUE),
));
drupal_set_message($message, 'error');
}
}
Functions
Name | Description |
---|---|
field_defaults_batch_finished | The batch finish handler. |
field_defaults_batch_process | The batch processor. |
field_defaults_batch_run | The batch callback. |
field_defaults_entity_presave | Implements hook_entity_presave(). |
field_defaults_form_field_ui_field_edit_form_alter | Implements hook_form_FORM_ID_alter(). |
field_defaults_form_i18n_string_translate_page_form_alter | Implements hook_form_FORM_ID_alter(). |
field_defaults_menu | Implements hook_menu(). |
field_defaults_permission | Implements hook_permission(). |
_field_defaults_translation_submit | Submit handler for field ui translation form |
_field_defaults_ui_submit | Submit handler for field ui form |