View source
<?php
function editablefields_field_formatter_info() {
$all_types = array_keys(field_info_field_types());
return array(
'editable' => array(
'label' => t('Editable'),
'field types' => $all_types,
'settings' => array(
'fallback_format' => NULL,
'fallback_settings' => array(),
'click_to_edit' => FALSE,
'click_to_edit_style' => 'button',
'empty_text' => '',
),
),
);
}
function editablefields_library() {
$path = drupal_get_path('module', 'editablefields');
$libraries['editablefields'] = array(
'title' => 'Editable Fields',
'version' => '1.x',
'js' => array(
$path . '/editablefields.js' => array(
'group' => JS_DEFAULT + 1,
),
),
'css' => array(
$path . '/editablefields.css' => array(
'group' => CSS_DEFAULT + 1,
),
),
'dependencies' => array(
array(
'system',
'drupal.form',
),
array(
'system',
'drupal.autocomplete',
),
),
);
return $libraries;
}
function editablefields_permission() {
return array(
'use editablefields' => array(
'title' => t('Use editablefields'),
'description' => t('Use editable fields'),
),
);
}
function editablefields_field_formatter_settings_form($field, $instance, $view_mode, $form, &$form_state) {
$display = $instance['display'][$view_mode];
$settings = editablefields_field_formatter_default_settings($display['settings'], $field);
module_load_include('inc', 'field_ui', 'field_ui.admin');
$formatters = field_ui_formatter_options($field['type']);
unset($formatters['editable']);
$element['click_to_edit'] = array(
'#type' => 'checkbox',
'#title' => t('Click to edit'),
'#default_value' => $settings['click_to_edit'],
);
$element['click_to_edit_style'] = array(
'#type' => 'select',
'#title' => t('Click to edit style'),
'#options' => array(
'button' => t('Button'),
'hover' => t('Hover'),
),
'#default_value' => $settings['click_to_edit_style'],
);
$element['empty_text'] = array(
'#type' => 'textarea',
'#rows' => 3,
'#title' => t('Empty text'),
'#description' => t('Text to show when the field is empty.'),
'#default_value' => $settings['empty_text'],
);
$element['fallback_format'] = array(
'#type' => 'select',
'#title' => t('Fallback formatter'),
'#options' => $formatters,
'#default_value' => $settings['fallback_format'],
);
if (isset($form_state['complete form']) && $form_state['complete form']['#form_id'] == 'field_ui_display_overview_form') {
$element['fallback_format'] += array(
'#field_name' => $field['field_name'],
'#op' => 'edit',
'#executes_submit_callback' => TRUE,
'#submit' => array(
'editablefields_field_ui_display_overview_multistep_submit',
),
'#ajax' => array(
'callback' => 'field_ui_display_overview_multistep_js',
'wrapper' => 'field-display-overview-wrapper',
'effect' => 'fade',
),
);
$field_name = $form_state['triggering_element']['#field_name'];
$element['click_to_edit_style'] += array(
'#states' => array(
'visible' => array(
':input[name="fields[' . $field_name . '][settings_edit_form][settings][click_to_edit]"]' => array(
'checked' => TRUE,
),
),
),
);
}
else {
if (isset($form_state['form_id']) && $form_state['form_id'] == 'views_ui_config_item_form') {
$element['fallback_format'] += array(
'#ajax' => array(
'path' => views_ui_build_form_url($form_state),
),
'#submit' => array(
'views_ui_config_item_form_submit_temporary',
),
'#executes_submit_callback' => TRUE,
);
$element['click_to_edit_style'] += array(
'#dependency' => array(
'edit-options-settings-click-to-edit' => array(
1,
),
),
);
}
}
$fallback_formatter = field_info_formatter_types($settings['fallback_format']);
$fallback_settings = $settings['fallback_settings'] + field_info_formatter_settings($settings['fallback_format']);
$instance['display']['_dummy'] = array(
'type' => $settings['fallback_format'],
'settings' => $fallback_settings,
);
$settings_form = array(
'#value' => array(),
);
$function = $fallback_formatter['module'] . '_field_formatter_settings_form';
if (function_exists($function)) {
$settings_form = $function($field, $instance, '_dummy', $form, $form_state);
}
$element['fallback_settings'] = $settings_form;
return $element;
}
function editablefields_field_ui_display_overview_multistep_submit($form, &$form_state) {
$trigger = $form_state['triggering_element'];
$op = $trigger['#op'];
$field_name = $trigger['#field_name'];
$values = $form_state['values']['fields'][$field_name]['settings_edit_form']['settings'];
$form_state['formatter_settings'][$field_name] = $values;
$form_state['rebuild'] = TRUE;
}
function editablefields_field_formatter_settings_summary($field, $instance, $view_mode) {
$display = $instance['display'][$view_mode];
$settings = editablefields_field_formatter_default_settings($display['settings'], $field);
return t('Fallback formatter: @formatter', array(
'@formatter' => $settings['fallback_format'],
));
}
function editablefields_field_formatter_default_settings($settings, $field) {
if (empty($settings['fallback_format'])) {
$field_type = field_info_field_types($field['type']);
$settings['fallback_format'] = $field_type['default_formatter'];
}
$settings += array(
'fallback_settings' => array(),
);
return $settings;
}
function editablefields_fallback_formatter($entity_type, $entity, $field, $instance, $langcode, $items, $display) {
$display['type'] = $display['settings']['fallback_format'];
$display['settings'] = $display['settings']['fallback_settings'];
$formatter_type = field_info_formatter_types($display['type']);
if (isset($formatter_type['module'])) {
$display['module'] = $formatter_type['module'];
}
else {
return;
}
$cloned_entity = clone $entity;
return field_view_field($entity_type, $cloned_entity, $field['field_name'], $display, $langcode);
}
function editablefields_field_formatter_view($entity_type, $entity, $field, $instance, $langcode, &$items, $display) {
if (!$display['type'] == 'editable') {
return;
}
$field_name = $field['field_name'];
list($id, $vid, $bundle) = entity_extract_ids($entity_type, $entity);
if (!entity_access('update', $entity_type, $entity) || !field_access('edit', $field, $entity_type, $entity) || !user_access('use editablefields')) {
return editablefields_fallback_formatter($entity_type, $entity, $field, $instance, $langcode, $items, $display);
}
if (isset($display['views_view'])) {
$view = $display['views_view'];
$views_field = $display['views_field'];
$row_id = $display['views_row_id'];
unset($display['views_view']);
unset($display['views_field']);
unset($display['views_row_id']);
$views_field->views_form_callback = 'editablefields_views_form';
$entity = $view->result[$row_id]->_field_data[$views_field->field_alias]['entity'];
$views_field->editablefield_data[$row_id] = compact('entity_type', 'entity', 'langcode', 'display');
$views_field->editablefield_field = $field;
$views_field->editablefield_instance = $instance;
if (empty($views_field->seen_by_editable_fields)) {
$views_field->options['element_class'] .= ' views-field-editablefield';
$views_field->seen_by_editable_fields = TRUE;
}
$field_id = array_search($views_field, $view->field, TRUE);
$items = array(
0 => array(),
);
return array(
0 => array(
'#markup' => '<!--form-item-' . $field_id . '--' . $row_id . '-->',
),
);
}
else {
$display['label'] = 'hidden';
$items = array(
0 => array(),
);
return array(
0 => drupal_get_form('editablefields_form__' . $entity_type . '__' . $id . '__' . $vid . '__' . $field['field_name'], $entity_type, $entity, $field, $instance, $langcode, $display),
);
}
}
function editablefields_forms($form_id) {
$forms = array();
if (preg_match('/^editablefields_form_/', $form_id)) {
$forms[$form_id] = array(
'callback' => 'editablefields_form',
);
}
return $forms;
}
function editablefields_form($form, &$form_state, $entity_type, $entity, $field, $instance, $langcode, $display) {
$form += array(
'#parents' => array(),
);
$form['#attached']['library'][] = array(
'editablefields',
'editablefields',
);
$form['#attributes'] = array(
'class' => array(
'editable-field',
),
);
list($id, $vid, $bundle) = entity_extract_ids($entity_type, $entity);
$form['#entity_type'] = $entity_type;
$form['#bundle'] = $bundle;
$form['#langcode'] = $langcode;
list($id, $vid, $bundle) = entity_extract_ids($entity_type, $entity);
$form['#entity_id'] = $id;
if (!isset($form_state['editablefields_entities'][$entity_type][$id])) {
$form_state['editablefields_entities'][$entity_type][$id] = $entity;
}
else {
$entity = $form_state['editablefields_entities'][$entity_type][$id];
}
$info = entity_get_info($entity_type);
foreach (array(
'id',
'revision',
'bundle',
) as $key) {
$id = isset($entity->{$info['entity keys']['id']}) ? $entity->{$info['entity keys']['id']} : NULL;
if (isset($info['entity keys'][$key]) && isset($entity->{$info['entity keys'][$key]})) {
$form[$info['entity keys'][$key]] = array(
'#type' => 'value',
'#value' => $entity->{$info['entity keys'][$key]},
);
}
}
$wrapper_id = drupal_html_id('editablefields-' . $field['field_name']);
$form['#prefix'] = '<div id="' . $wrapper_id . '" class="editablefield-item">';
$form['#suffix'] = '</div>';
$ajax = array(
'callback' => 'editablefields_form_update',
'wrapper' => $wrapper_id,
'effect' => 'fade',
'event' => 'click',
'progress' => array(
'type' => 'throbber',
'message' => t('Please wait'),
),
);
$instance['label'] = '';
$edit_mode_state = _editablefields_get_edit_mode($form_state, $form['#parents']);
$edit_mode = empty($display['settings']['click_to_edit']) || $edit_mode_state;
if ($edit_mode) {
$items = $entity->{$field['field_name']};
$items = isset($items[$langcode]) ? $items[$langcode] : array();
$form += field_default_form($entity_type, $entity, $field, $instance, $langcode, $items, $form, $form_state);
$form['actions'] = array(
'#type' => 'actions',
);
$form['actions']['submit'] = array(
'#name' => 'submit-' . implode('-', $form['#parents']),
'#type' => 'submit',
'#value' => t('Save'),
'#ajax' => $ajax,
'#submit' => array(
'editablefields_form_submit',
),
'#limit_validation_errors' => array(
$form['#parents'],
),
);
}
else {
$edit_style = isset($display['settings']['click_to_edit_style']) ? $display['settings']['click_to_edit_style'] : 'button';
$items = $entity->{$field['field_name']};
$items = isset($items[$langcode]) ? $items[$langcode] : array();
$shield = new EditableFieldsShield();
$shield->arguments = array(
$entity_type,
$entity,
$field,
$instance,
$langcode,
$items,
$display,
);
$form['field'] = array(
'#pre_render' => array(
'editablefields_lazy_render_fields',
),
'#arguments' => $shield,
);
$form['actions']['edit'] = array(
'#name' => 'edit-' . implode('-', $form['#parents']),
'#type' => 'submit',
'#value' => t('Edit this field'),
'#submit' => array(
'editablefields_form_submit_edit_mode',
),
'#ajax' => $ajax,
'#limit_validation_errors' => array(
$form['#parents'],
),
'#attributes' => array(
'class' => array(
'editablefield-edit',
'editablefield-edit-' . $edit_style,
),
),
);
}
$form['#build_id'] = 'editablefields_form__' . $entity_type . '__' . $id . '__' . $vid . '__' . $field['field_name'];
return $form;
}
class EditableFieldsShield {
function __sleep() {
return array();
}
}
function editablefields_lazy_render_fields($element) {
$element['field'] = call_user_func_array('editablefields_fallback_formatter', $element['#arguments']->arguments);
if (empty($element['field']) && isset($element['#arguments']->arguments[6]['settings']['empty_text'])) {
if ($element['#arguments']->arguments[6]['settings']['empty_text'] !== '') {
$element['field'] = array(
'#markup' => $element['#arguments']->arguments[6]['settings']['empty_text'],
);
}
}
return $element;
}
function editablefields_views_form($view, $views_field, &$form, &$form_state) {
$field_id = array_search($views_field, $view->field, TRUE);
if (!isset($form_state['editablefields'][$field_id])) {
$form_state['editablefields'][$field_id] = array(
'rows' => $views_field->editablefield_data,
'field' => $views_field->editablefield_field,
'instance' => $views_field->editablefield_instance,
);
}
$field = $form_state['editablefields'][$field_id]['field'];
$instance = $form_state['editablefields'][$field_id]['instance'];
foreach ($form_state['editablefields'][$field_id]['rows'] as $row_id => $row) {
extract($row);
if (isset($row['entity'])) {
list($entity_id, ) = entity_extract_ids($entity_type, $row['entity']);
if (!isset($form_state['editablefields_entities'][$entity_type][$entity_id])) {
$form_state['editablefields_entities'][$entity_type][$entity_id] = $entity;
}
else {
$entity = $form_state['editablefields_entities'][$entity_type][$entity_id];
}
$form_state['editablefields'][$field_id][$row_id]['entity_id'] = $entity_id;
unset($form_state['editablefields'][$field_id][$row_id]['entity']);
}
else {
$entity = $form_state['editablefields_entities'][$entity_type][$row['entity_id']];
}
$temp_form = array(
'#parents' => array(
$field_id,
$row_id,
),
'#tree' => TRUE,
);
$form[$field_id][$row_id] = editablefields_form($temp_form, $form_state, $entity_type, $entity, $field, $instance, $langcode, $display);
}
unset($views_field->editablefield_data);
}
function editablefields_form_update($form, $form_state) {
$parents = $form_state['triggering_element']['#array_parents'];
array_pop($parents);
array_pop($parents);
$element =& $form;
foreach ($parents as $parent) {
$element =& $element[$parent];
}
return $element;
}
function editablefields_form_validate(&$form, &$form_state) {
entity_form_field_validate($form['#entity_type'], $form, $form_state);
}
function editablefields_form_submit_edit_mode(&$form, &$form_state) {
$parents = $form_state['triggering_element']['#array_parents'];
array_pop($parents);
array_pop($parents);
_editablefields_set_edit_mode($form_state, TRUE, $parents);
$form_state['rebuild'] = TRUE;
}
function editablefields_form_submit(&$form, &$form_state) {
$parents = $form_state['triggering_element']['#array_parents'];
array_pop($parents);
array_pop($parents);
$element =& $form;
foreach ($parents as $parent) {
$element =& $element[$parent];
}
_editablefields_set_edit_mode($form_state, FALSE, $parents);
$entity_type = $element['#entity_type'];
$entity_id = $element['#entity_id'];
$entity = entity_load_single($entity_type, $entity_id);
if ($entity_type == 'node') {
node_object_prepare($entity);
}
entity_form_submit_build_entity($entity_type, $entity, $element, $form_state);
entity_save($entity_type, $entity);
$form_state['rebuild'] = TRUE;
$form_state['editablefields_entities'][$entity_type][$entity_id] = $entity;
}
function _editablefields_get_edit_mode($form_state, $parents = array()) {
if (!isset($form_state['edit_mode'])) {
return FALSE;
}
if (!empty($parents) && is_array($form_state['edit_mode'])) {
return drupal_array_get_nested_value($form_state['edit_mode'], $parents);
}
return (bool) $form_state['edit_mode'];
}
function _editablefields_set_edit_mode(&$form_state, $value, $parents = array()) {
if (!empty($parents)) {
if (!isset($form_state['edit_mode']) || !is_array($form_state['edit_mode'])) {
$form_state['edit_mode'] = array();
}
drupal_array_set_nested_value($form_state['edit_mode'], $parents, $value);
}
else {
$form_state['edit_mode'] = $value;
}
}