1); } } /** * Implementation of hook_default_editablefields_preset(). * * Provide a couple of default presets. */ function editablefields_default_editablefields_preset() { $export = array(); $export['modal'] = (object) array( 'api_version' => 1, 'name' => 'modal', 'description' => 'Display the field form in a Modal Dialog', 'config' => array( 'editable_type' => 'modal', ), ); $export['html'] = (object) array( 'api_version' => 1, 'name' => 'html', 'description' => 'Display the field form inline', 'config' => array( 'editable_type' => 'html', ) ); return $export; } /** * Implementation of hook_menu_alter(). */ function editablefields_menu_alter(&$items) { // takeover the filefield ahah callback. This is a temporary hackish solution. if (isset($items['filefield/ahah/%/%/%'])) { $items['filefield/ahah/%/%/%'] = array( 'page callback' => 'editablefields_filefield_js', ) + $items['filefield/ahah/%/%/%']; } } /** * Implementation of hook_menu(). */ function editablefields_menu() { $items = array(); // Admin pages: $items['editablefields_view'] = array( 'page callback' => 'editablefields_view', 'access arguments' => array('access content'), 'type' => MENU_CALLBACK, 'title' => 'ajax view', ); $items['editablefields_html'] = array( 'page callback' => 'editablefields_html', 'access arguments' => array('access content'), 'type' => MENU_CALLBACK, 'title' => 'ajax form', ); $items['editablefields_submit'] = array( 'page callback' => 'editablefields_submit', 'access arguments' => array('access content'), 'type' => MENU_CALLBACK, 'title' => 'ajax submit', ); $plugins = editablefields_get_responders(); foreach($plugins as $plugin_name => $plugin) { foreach($plugin['hook_menu'] as $plugin_item_path => $plugin_item) { $items[$plugin_item_path] = $plugin_item + array( 'title' => $plugin['title'], 'file' => $plugin['file'], 'file path' => $plugin['path'], 'type' => MENU_CALLBACK, ); } } return $items; } /** * Implementation of hook_theme(). */ function editablefields_theme() { $items = array(); $plugins = editablefields_get_editables(); foreach($plugins as $plugin_name => $plugin) { if (!empty($plugin['theme'])) { $items = array_merge($items, $plugin['theme']); } } return $items; } /* function editablefields_theme_registry_alter(&$items) { $items['views_view_field']['function'] = 'editablefields_views_view_field'; } */ /** * Implementation of hook_field_formatter_info(). */ function editablefields_field_formatter_info() { $items = array(); $plugins = editablefields_get_editables(); foreach($plugins as $plugin_name => $plugin) { if (!empty($plugin['formatter_info'])) { $items = array_merge($items, $plugin['formatter_info']); } } return $items; } /** * Implementation of hook_content_build_modes(). * * @return array */ //agrega los widgets en editable(node type) function editablefields_content_build_modes() { // Tell CCK about our "build" modes so that users can specify // how they want the text in their modal/other link to be formatted // on the Display Fields tab of the CCK admin. $build_modes = array(); $plugins = editablefields_get_responders(); if (!empty($plugins)) { $build_modes = array( 'editablefields' => array( 'title' => t('Editable mode'), 'build modes' => array(), ), ); foreach($plugins as $plugin_name => $plugin) { foreach($plugin['build modes'] as $mode_name => $mode_info) { $build_modes['editablefields']['build modes'][$mode_name] = $mode_info; } } } return $build_modes; } /** * Implementation of hook_form_alter(). */ //elimina los widgets editables function editablefields_form_alter(&$form, &$form_state, $form_id) { if ($form_id == 'content_display_overview_form') { // Remove editable field formatters from the options. if ($form['#contexts'] == 'editablefields') { $formatters = editablefields_field_formatter_info(); foreach($form as $key => &$element) { if (substr($key, 0, 6) == 'field_') { foreach($element as $setting_name => &$setting) { if (!empty($setting['format'])) { foreach($formatters as $formatter_name => $formatter) { unset($setting['format']['#options'][$formatter_name]); unset($setting['format']['base']['#options'][$formatter_name]); } } } } } } } } /** * Editablefields version of replace CTools command. * It uses the * * The replace command will replace a portion of the current document * with the specified HTML. * * @param $html * The data to use with the jquery replace() function. * * @return array */ function ctools_ajax_command_replace_active_element($index, $html) { return array( 'command' => 'replace_active_element', 'active_elem_index' => $index, 'data' => $html, ); } /** * Theme the editable field. */ /* function theme_editablefields_formatter_editable($element) { static $js_ready; $field_name = $element['#field_name']; $field = content_fields($field_name); $revision = !empty($element['#node']->vid) ? $element['#node']->vid : NULL; $node = node_load($element['#node']->nid, $revision); $delta = $element['#item']['#delta']; // to disable overriding textareas just set this variable to 0 if (variable_get('editablefields_textareas_resizable_threshold', 25)) { static $textareas_count = 0; if ( $field['type'] == 'text' && $field['widget']['type'] == 'text_textarea') { if ($textareas_count++ >= variable_get('editablefields_textareas_resizable_threshold', 25)) { drupal_add_js(drupal_get_path('module', 'editablefields') . '/editablefields_overrides.js'); } } } // See if access to this form element is restricted, // if so, skip widget processing and just set the value. if (!node_access('update', $node) || !content_access('edit', $field)) { // can't edit $formatter_name = 'default'; if ($formatter = _content_get_formatter($formatter_name, $field['type'])) { $theme = $formatter['module'] . '_formatter_' . $formatter_name; return theme($theme, $element); } } else { $formatter_name = 'default'; if ($formatter = _content_get_formatter($formatter_name, $field['type'])) { if (!isset($js_ready)) { $js_ready = TRUE; drupal_add_js('misc/jquery.form.js'); drupal_add_js( drupal_get_path('module', 'editablefields') . '/editablefields.js'); drupal_add_css( drupal_get_path('module', 'editablefields') . '/editablefields.css'); $settings = array( 'url_html' => url('editablefields_html', array('absolute' => TRUE)), 'url_submit' => url('editablefields_submit', array('absolute' => TRUE)), 'url_view' => url('editablefields_view', array('absolute' => TRUE)), 'clicktoedit_message' => theme('editablefields_clicktoedit_message'), 'clicktoedit_message_empty' => theme('editablefields_clicktoedit_message_empty'), ); drupal_add_js(array('editablefields' => $settings), 'setting'); } // [andreiashu] not sure how this works exactly but it does... if (content_handle('widget', 'multiple values', $field) != CONTENT_HANDLE_CORE) { if ($delta != 0) { return; } } $theme = $formatter['module'] . '_formatter_' . $formatter_name; $class = "editablefields"; if ($element['#formatter'] == 'editable') { $class .= " ajax-editable"; } elseif ($element['#formatter'] == 'clicktoedit') { $class .= " clicktoedit"; } elseif ($element['#formatter'] == 'editable_html') { $class .= " editablefields-html-load"; } $pre = '
'; $post = '
'; if ($element['#formatter'] != 'editable_html') { $themed_element = theme($theme, $element); // add the edit link for clicktoedit formatters if ($element['#formatter'] == 'clicktoedit') { if (!empty($themed_element)) { $pre .= theme('editablefields_clicktoedit_message'); } else { $pre .= theme('editablefields_clicktoedit_message_empty'); } } return $pre . $themed_element . $post; } else { // $node seems to be incomplete, so we reload it $node = node_load($node->nid, $revision); return $pre . drupal_get_form('editablefields_form', $node, $field_name, $delta) . $post; } } } } */ function theme_editablefields_clicktoedit_message() { return '' . t('[edit]') . ''; } function theme_editablefields_clicktoedit_message_empty() { return '' . t('[edit]') . ''; } /** * Implementation of hook_forms(). */ function editablefields_forms($form_id) { $forms = array(); $forms['editablefields_form'] = array( 'callback' => 'editablefields_form_builder', // 'callback arguments' => array('node', 'field_name'), ); return $forms; } /** * Form builder callback. */ function editablefields_form_builder(&$form_state, $node, $field_name, $delta) { $field = content_fields($field_name); $form = array('#node' => $node); // $form_state = array('values' => array($field['field_name'] => $default_value)); module_load_include('inc', 'content', 'includes/content.node_form'); $form['#field_info'] = array($field['field_name'] => $field); $form = content_field_form($form, $form_state, $field, $delta); unset($form[$field_name]['#title']); if (is_array($form[$field_name][0]) && !is_array($form[$field_name][1])) { unset($form[$field_name][0]['#title']); } $form['editablefields_node_nid'] = array( '#type' => 'hidden', '#value' => $node->nid, ); $form['#field_info'] = array($field['field_name'] => $field); $form['#pre_render'] = array('_editablefields_pre_render'); return $form; } /** * Resizable Textarea has an issue with setting focus. * To circumvent this we have to set the forms fields #resizable field to FALSE. * We have to use pre_render because the here the field's #type is still textarea. * TODO Keep editable_HTML and editable_JAVA fields resizable, they don't have the focus issue. */ function _editablefields_pre_render(&$form) { if ($form['field_name'][0]['value']['#type'] == 'textarea') { $form['field_name'][0]['value']['#resizable'] = FALSE; } return $form; } /** * Menu callback: ajax view. */ function editablefields_view() { $output = ''; $nid = arg(1); $field_name = arg(2); $delta = arg(3); $node = node_load($nid); drupal_set_header('Content-Type: text; charset=utf-8'); // $html = node_view($node, FALSE, FALSE, FALSE); // this required traversing the entire node to get the field (and doesn't work // for checkboxes anyway) $field = content_fields($field_name, $node->type); $field['display_settings']['label']['format'] = 'hidden'; // We have 2 reasonable choices here. We COULD use 'clicktoedit' and end up // with the same HTML - then we could strip that HTML down to remove the // surrounding 'click to edit' div (which we dont want, as we'll be replacing // the html inside one of those div's) // or we can simply use the 'defualt' formatter - which wont have the click to // edit inside it - and is hard coded into this module (for now) anyway! $field['display_settings']['full']['format'] = 'default'; $html = content_view_field($field, $node); $messages = drupal_get_messages('status', TRUE); if (count($messages) > 0) { foreach ($messages as $type => $messages) { foreach ($messages as $message) { $output .= '
' . $message . "
"; } } } $object = new stdClass(); $object->content = $output . $html . drupal_render($node->content[$field_name]); drupal_json($object); exit(); } /** * Menu callback: ajax form. */ function editablefields_html() { $nid = arg(1); $field_name = arg(2); $delta = arg(3); $node = node_load($nid); if (node_access('update', $node)) { // $html = _editablefields_create_form($node, $field_name); $html = drupal_get_form('editablefields_form', $node, $field_name, $delta); $object = new stdClass(); $object->content = $html; // Register the JavaScript callback for this module. $object->__callbacks = array(); // Allow other modules to extend the data returned. drupal_alter('ajax_data', $object, 'editablefields', $html); drupal_json($object); } else { drupal_not_found(); } exit(); } /** * Menu callback: ajax submit. */ function editablefields_submit() { $nid = $_POST['nid']; $field_name = $_POST['field']; $delta = $_POST['delta']; $node = node_load($nid); $node_options = variable_get( 'node_options_' . $node->type, array('status', 'promote')); $node->revision = in_array('revision', $node_options); if ($node->revision) { $node->log = t( '%field_name updated by editablefields.', array('%field_name' => $field_name) ); } if (node_access('update', $node)) { if (!isset($_POST[$field_name])) { $_POST[$field_name] = array(); } $form_state = array('values' => $_POST); /* it seems that the serializer does not serialize e.g. un-checked * checkboxes. Leaving them as empty arrays. This FILTHY hack fills in the * array with 'something' so that when the form is executed, it fills in the * right value - I dislike this code - JMB */ if (is_array($node->{$field_name})) { $field = content_fields($field_name, $node->type); $items = &$form_state['values'][$field_name]; if (empty($items)) { foreach (array_keys($field['columns']) as $column) { if ($field['multiple']) { $items[$delta][$column][] = NULL; } else { $items[$column] = NULL; } } } if (isset($items['value'])) { if (!($field['widget']['type'] == 'optionwidgets_buttons' && $field['multiple'])) { $items = array($items); } } // go through content_set_empty if this is NOT a checkbox multi valued element if (!($field['widget']['type'] == 'optionwidgets_buttons' && $field['multiple'])) { $items = content_set_empty($field, $items); } switch ($field['type']) { case 'nodereference': case 'userreference': if ($field['multiple']) { reset($field['columns']); $items[key($field['columns'])] = array_pop($items); } break; } drupal_execute('editablefields_form', $form_state, $node, $field_name, $delta ); $err = drupal_get_messages(); if (count($err) > 0) { drupal_set_header('HTTP/1.1 404 Not Found'); // format the error message suitable for a popup window in simple text. foreach ($err as $type => $messages) { foreach ($messages as $message) { print $type . ' : ' . $message . "\n"; } } exit(); } // the matrix field identifies itself as being multivalue, but in fact, it is not. if ((content_handle('widget', 'multiple values', $field) == CONTENT_HANDLE_CORE) && ($field['type'] != matrix)) { if ($node->{$field_name}[$delta] != $form_state['values'][$field_name][0]) { $node->{$field_name}[$delta] = $form_state['values'][$field_name][0]; node_save($node); } } else { if ($node->{$field_name} != $form_state['values'][$field_name]) { $node->{$field_name} = $form_state['values'][$field_name]; node_save($node); } } // make sure sensible headers etc are sent... drupal_set_header('Content-Type: text; charset=utf-8'); } else { drupal_set_header('HTTP/1.1 404 Not Found'); print t('No field found, of name: %field', array('%field' => $field_name)); } } else { drupal_set_header('HTTP/1.1 404 Not Found'); print t('No write permissions for %field', array('%field' => $field_name)); } exit(); } /** * If the Remove button was clicked remove the file from the node. */ function editablefields_filefield_js($type_name, $field_name, $delta) { if (!empty($_POST['editablefields_node_nid']) && $node = node_load($_POST['editablefields_node_nid'])) { $remove_button_clicked = FALSE; foreach ($_POST as $key => $value) { // check if the remove button was clicked if (stripos($key, $field_name) === 0 && stripos($key, '_filefield_remove') !== FALSE) { $remove_button_clicked = TRUE; break; } } if ($remove_button_clicked) { $field = $_POST[$field_name]; $field = array_pop($field); $file = (object)field_file_load($field['fid']); // respect revision settings $node_options = variable_get( 'node_options_' . $node->type, array('status', 'promote')); $node->revision = in_array('revision', $node_options); if ($node->revision) { $node->log = t('%field_name updated by editablefields.', array('%field_name' => $field_name)); } $file->field_name = $field_name; $references = field_file_delete($file); $node->{$field_name}[$delta] = array(); node_save($node); drupal_set_message(t('File %filename was removed from node.', array('%filename' => $file->filename))); } } filefield_js($type_name, $field_name, $delta); } /** * Implementation of hook_file_insert(). */ function editablefields_file_insert($file) { if (stripos($_GET['q'], 'filefield/ahah/') === 0 && !empty( $_POST['editablefields_node_nid']) && $node = node_load($_POST['editablefields_node_nid'])) { $file_clone = (array)$file; field_file_save($node, $file_clone); $q_arr = explode('/', $_GET['q']); $field_name = $q_arr[3]; $delta = $q_arr[4]; $node->{$field_name}[$delta] = array( 'fid' => $file->fid ); // respect revision settings $node_options = variable_get( 'node_options_' . $node->type, array('status', 'promote')); $node->revision = in_array('revision', $node_options); if ($node->revision) { $node->log = t('%field_name updated by editablefields.', array('%field_name' => $field_name)); } node_save($node); } } function editablefields_formatter_get_settings($field_name, $type_name, $context) { $options = array(); $value = 'editablefields:'. $type_name .':'. $context .':'. $field_name; $options['editablefields'] = variable_get($value . '_text_formatter', 'default'); /* $options['repeat']['show_repeat_rule'] = variable_get($value .'_show_repeat_rule', 'show'); $options['multiple']['multiple_number'] = variable_get($value .'_multiple_number', ''); $options['multiple']['multiple_from'] = variable_get($value .'_multiple_from', ''); $options['multiple']['multiple_to'] = variable_get($value .'_multiple_to', ''); $options['fromto']['fromto'] = variable_get($value .'_fromto', 'both') */ return $options; } /** * Returns all 'editables' plugins. * * @return array */ function editablefields_get_responders() { ctools_include('plugins'); $plugins = ctools_get_plugins('editablefields', 'responders'); foreach($plugins as &$plugin) { // add defaults $plugin += array( 'hook_menu' => array(), 'formatter_info' => array(), ); } return $plugins; } function editablefields_get_editables() { ctools_include('plugins'); $plugins = ctools_get_plugins('editablefields', 'editables'); return $plugins; } /** * Menu wildcard argument callback. */ function editablefields_object_load($object_id, $editable) { $editables = editablefields_get_editables(); $function = $editables[$editable]['entity callback']; return $function($object_id); } /** * Implementation of hook_views_api(). */ function editablefields_views_api() { return array( 'api' => 2, 'path' => drupal_get_path('module', 'editablefields') . '/includes/views', ); } function editablefields_views_option_form(&$form, &$form_state, $editable) { $form['editablefields_allowed'] = array( '#title' => t('Make field editable'), '#description' => t('This will override any other link you have set.'), '#type' => 'checkbox', '#default_value' => '', ); $responders = editablefields_get_responders(); $options = array(); foreach($responders as $responder) { $options[$responder['name']] = $responder['title']; } $form['editablefields_responder'] = array( '#title' => t('Editable Behavior'), '#description' => t('How would you like to edit this field?'), '#type' => 'select', '#options' => $options, '#dependency' => array('edit-options-editablefields-allowed' => array('1')), '#process' => array('views_process_dependency') ); $form['editablefields_editable'] = array( '#type' => 'hidden', '#value' => $editable, ); }