source: sipes/modules_contrib/editablefields/editablefields.module @ 663b989

stableversion-3.0
Last change on this file since 663b989 was 177a560, checked in by José Gregorio Puentes <jpuentes@…>, 8 años ago

se agrego el directorio de modulos contribuidos de drupal

  • Propiedad mode establecida a 100755
File size: 22.1 KB
Línea 
1<?php
2
3/**
4 * @file
5 * Editable fields module.
6 */
7
8/**
9 * Implementation of hook_perm.
10 *
11 * @return array
12 * An array of permissions that this module provides.
13 */
14function editablefields_perm() {
15  return array('administer editablefields');
16}
17
18/**
19 * Implementation of hook_ctools_plugin_directory().
20 *
21 * @param $module
22 * @param $plugin_type
23 * @return string
24 */
25function editablefields_ctools_plugin_directory($module, $plugin_type) {
26
27  if ($plugin_type == 'export_ui') {
28    return "plugins/export_ui";
29  }
30
31  if ($module == 'editablefields' && !empty($plugin_type)) {
32    return "plugins/$plugin_type";
33  }
34}
35
36
37/**
38 * Implementation of hook_ctools_plugin_api().
39 *
40 * Tell Ctools that we support the default_editablefields_presets API.
41 */
42function editablefields_ctools_plugin_api($owner, $api) {
43  if ($owner == 'editablefields' && $api == 'default_editablefields_presets') {
44    return array('version' => 1);
45  }
46}
47
48/**
49 * Implementation of hook_default_editablefields_preset().
50 *
51 * Provide a couple of default presets.
52 */
53function editablefields_default_editablefields_preset() {
54  $export = array();
55
56  $export['modal'] = (object) array(
57    'api_version' => 1,
58    'name' => 'modal',
59    'description' => 'Display the field form in a Modal Dialog',
60    'config' => array(
61      'editable_type' => 'modal',
62    ),
63  );
64
65  $export['html'] = (object) array(
66    'api_version' => 1,
67    'name' => 'html',
68    'description' => 'Display the field form inline',
69    'config' => array(
70      'editable_type' => 'html',
71    )
72  );
73
74  return $export;
75}
76
77/**
78 * Implementation of hook_menu_alter().
79 */
80function editablefields_menu_alter(&$items) {
81  // takeover the filefield ahah callback. This is a temporary hackish solution.
82  if (isset($items['filefield/ahah/%/%/%'])) {
83    $items['filefield/ahah/%/%/%'] = array(
84      'page callback' => 'editablefields_filefield_js',
85    ) + $items['filefield/ahah/%/%/%'];
86  }
87}
88
89/**
90 * Implementation of hook_menu().
91 */
92function editablefields_menu() {
93  $items = array();
94
95  // Admin pages:
96  $items['editablefields_view'] = array(
97    'page callback' => 'editablefields_view',
98    'access arguments' => array('access content'),
99    'type' => MENU_CALLBACK,
100    'title' => 'ajax view',
101  );
102  $items['editablefields_html'] = array(
103    'page callback' => 'editablefields_html',
104    'access arguments' => array('access content'),
105    'type' => MENU_CALLBACK,
106    'title' => 'ajax form',
107  );
108  $items['editablefields_submit'] = array(
109    'page callback' => 'editablefields_submit',
110    'access arguments' => array('access content'),
111    'type' => MENU_CALLBACK,
112    'title' => 'ajax submit',
113  );
114
115  $plugins = editablefields_get_responders();
116  foreach($plugins as $plugin_name => $plugin) {
117    foreach($plugin['hook_menu'] as $plugin_item_path => $plugin_item) {
118      $items[$plugin_item_path] = $plugin_item + array(
119        'title' => $plugin['title'],
120        'file' => $plugin['file'],
121        'file path' => $plugin['path'],
122        'type' => MENU_CALLBACK,
123      );
124    }
125  }
126
127  return $items;
128}
129
130/**
131 * Implementation of hook_theme().
132 */
133function editablefields_theme() {
134 
135  $items = array();
136 
137  $plugins = editablefields_get_editables();
138  foreach($plugins as $plugin_name => $plugin) {
139    if (!empty($plugin['theme'])) {
140      $items = array_merge($items, $plugin['theme']);
141    }
142  }
143
144  return $items;
145}
146
147/*
148function editablefields_theme_registry_alter(&$items) {
149  $items['views_view_field']['function'] = 'editablefields_views_view_field';
150}
151*/
152
153/**
154 * Implementation of hook_field_formatter_info().
155 */
156function editablefields_field_formatter_info() {
157  $items = array();
158 
159  $plugins = editablefields_get_editables();
160  foreach($plugins as $plugin_name => $plugin) {
161    if (!empty($plugin['formatter_info'])) {
162      $items = array_merge($items, $plugin['formatter_info']);
163    }
164  }
165 
166  return $items;
167}
168
169/**
170 * Implementation of hook_content_build_modes().
171 *
172 * @return array
173 */
174//agrega los widgets en editable(node type)
175function editablefields_content_build_modes() {
176  // Tell CCK about our "build" modes so that users can specify
177  // how they want the text in their modal/other link to be formatted
178  // on the Display Fields tab of the CCK admin.
179  $build_modes = array();
180  $plugins = editablefields_get_responders();
181  if (!empty($plugins)) {
182    $build_modes = array(
183      'editablefields' => array(
184        'title' => t('Editable mode'),
185        'build modes' => array(),
186      ),
187    );
188    foreach($plugins as $plugin_name => $plugin) {
189      foreach($plugin['build modes'] as $mode_name => $mode_info) {
190        $build_modes['editablefields']['build modes'][$mode_name] = $mode_info;   
191      }
192    }
193  }
194  return $build_modes;
195}
196
197/**
198 * Implementation of hook_form_alter().
199 */
200//elimina los widgets editables
201function editablefields_form_alter(&$form, &$form_state, $form_id) {
202  if ($form_id == 'content_display_overview_form') {
203    // Remove editable field formatters from the options.
204    if ($form['#contexts'] == 'editablefields') {
205      $formatters = editablefields_field_formatter_info();
206      foreach($form as $key => &$element) {
207        if (substr($key, 0, 6) == 'field_') {
208          foreach($element as $setting_name => &$setting) {
209            if (!empty($setting['format'])) {
210              foreach($formatters as $formatter_name => $formatter) {
211                unset($setting['format']['#options'][$formatter_name]);
212                unset($setting['format']['base']['#options'][$formatter_name]);
213              }
214            }
215          }
216        }
217      }
218    }
219  }
220 
221}
222
223
224
225/**
226 * Editablefields version of replace CTools command.
227 * It uses the
228 *
229 * The replace command will replace a portion of the current document
230 * with the specified HTML.
231 *
232 * @param $html
233 *   The data to use with the jquery replace() function.
234 *
235 * @return array
236 */
237function ctools_ajax_command_replace_active_element($index, $html) {
238  return array(
239    'command' => 'replace_active_element',
240    'active_elem_index' => $index,
241    'data' => $html,
242  );
243}
244
245
246/**
247 * Theme the editable field.
248 */
249/*
250function theme_editablefields_formatter_editable($element) {
251
252  static $js_ready;
253
254  $field_name = $element['#field_name'];
255  $field = content_fields($field_name);
256
257  $revision = !empty($element['#node']->vid) ? $element['#node']->vid : NULL;
258  $node = node_load($element['#node']->nid, $revision);
259  $delta = $element['#item']['#delta'];
260
261  // to disable overriding textareas just set this variable to 0
262  if (variable_get('editablefields_textareas_resizable_threshold', 25)) {
263    static $textareas_count = 0;
264    if (
265      $field['type'] == 'text' && $field['widget']['type'] == 'text_textarea') {
266      if ($textareas_count++
267        >= variable_get('editablefields_textareas_resizable_threshold', 25)) {
268        drupal_add_js(drupal_get_path('module', 'editablefields')
269                        . '/editablefields_overrides.js');
270      }
271    }
272  }
273
274  // See if access to this form element is restricted,
275  // if so, skip widget processing and just set the value.
276  if (!node_access('update', $node) || !content_access('edit', $field)) {
277    // can't edit
278    $formatter_name = 'default';
279    if ($formatter = _content_get_formatter($formatter_name, $field['type'])) {
280      $theme = $formatter['module'] . '_formatter_' . $formatter_name;
281      return theme($theme, $element);
282    }
283  }
284  else {
285    $formatter_name = 'default';
286    if ($formatter = _content_get_formatter($formatter_name, $field['type'])) {
287      if (!isset($js_ready)) {
288        $js_ready = TRUE;
289        drupal_add_js('misc/jquery.form.js');
290        drupal_add_js(
291          drupal_get_path('module', 'editablefields') . '/editablefields.js');
292        drupal_add_css(
293          drupal_get_path('module', 'editablefields') . '/editablefields.css');
294
295        $settings = array(
296          'url_html' => url('editablefields_html', array('absolute' => TRUE)),
297          'url_submit' => url('editablefields_submit',
298                              array('absolute' => TRUE)),
299          'url_view' => url('editablefields_view', array('absolute' => TRUE)),
300          'clicktoedit_message' => theme('editablefields_clicktoedit_message'),
301          'clicktoedit_message_empty' => theme('editablefields_clicktoedit_message_empty'),
302        );
303        drupal_add_js(array('editablefields' => $settings), 'setting');
304      }
305
306      // [andreiashu] not sure how this works exactly but it does...
307      if (content_handle('widget', 'multiple values', $field)
308        != CONTENT_HANDLE_CORE) {
309        if ($delta != 0) {
310          return;
311        }
312      }
313
314      $theme = $formatter['module'] . '_formatter_' . $formatter_name;
315      $class = "editablefields";
316      if ($element['#formatter'] == 'editable') {
317        $class .= " ajax-editable";
318      }
319      elseif ($element['#formatter'] == 'clicktoedit') {
320        $class .= " clicktoedit";
321      }
322      elseif ($element['#formatter'] == 'editable_html') {
323        $class .= " editablefields-html-load";
324      }
325
326      $pre = '<div class="' . $class . '" nid="' . $node->nid . '" field="'
327        . $field_name . '" delta="' . $delta . '">';
328      $post = '</div>';
329
330      if ($element['#formatter'] != 'editable_html') {
331        $themed_element = theme($theme, $element);
332
333        // add the edit link for clicktoedit formatters
334        if ($element['#formatter'] == 'clicktoedit') {
335          if (!empty($themed_element)) {
336            $pre .= theme('editablefields_clicktoedit_message');
337          }
338          else {
339            $pre .= theme('editablefields_clicktoedit_message_empty');
340          }
341        }
342        return $pre . $themed_element . $post;
343      }
344      else {
345        // $node seems to be incomplete, so we reload it
346        $node = node_load($node->nid, $revision);
347        return $pre
348          . drupal_get_form('editablefields_form', $node, $field_name, $delta)
349          . $post;
350      }
351    }
352  }
353}
354*/
355
356function theme_editablefields_clicktoedit_message() {
357  return '<span class="editablefields_clicktoedit_message editablefields-hide">'
358    . t('[edit]') . '</span>';
359}
360
361function theme_editablefields_clicktoedit_message_empty() {
362  return '<span class="editablefields_clicktoedit_message">' . t('[edit]')
363    . '</span>';
364}
365
366/**
367 * Implementation of hook_forms().
368 */
369function editablefields_forms($form_id) {
370  $forms = array();
371  $forms['editablefields_form'] = array(
372    'callback' => 'editablefields_form_builder',
373//    'callback arguments' => array('node', 'field_name'),
374  );
375  return $forms;
376}
377
378/**
379 * Form builder callback.
380 */
381function editablefields_form_builder(&$form_state, $node, $field_name, $delta) {
382  $field = content_fields($field_name);
383  $form = array('#node' => $node);
384  //  $form_state = array('values' => array($field['field_name'] => $default_value));
385  module_load_include('inc', 'content', 'includes/content.node_form');
386  $form['#field_info'] = array($field['field_name'] => $field);
387  $form = content_field_form($form, $form_state, $field, $delta);
388
389  unset($form[$field_name]['#title']);
390  if (is_array($form[$field_name][0]) && !is_array($form[$field_name][1])) {
391    unset($form[$field_name][0]['#title']);
392  }
393
394  $form['editablefields_node_nid'] = array(
395    '#type' => 'hidden',
396    '#value' => $node->nid,
397  );
398
399  $form['#field_info'] = array($field['field_name'] => $field);
400  $form['#pre_render'] = array('_editablefields_pre_render');
401
402  return $form;
403}
404
405/**
406 * Resizable Textarea has an issue with setting focus.
407 * To circumvent this we have to set the forms fields #resizable field to FALSE.
408 * We have to use pre_render because the here the field's #type is still textarea.
409 * TODO Keep editable_HTML and editable_JAVA fields resizable, they don't have the focus issue.
410 */
411function _editablefields_pre_render(&$form) {
412  if ($form['field_name'][0]['value']['#type'] == 'textarea') {
413    $form['field_name'][0]['value']['#resizable'] = FALSE;
414  }
415  return $form;
416}
417
418/**
419 * Menu callback: ajax view.
420 */
421function editablefields_view() {
422  $output = '';
423  $nid = arg(1);
424  $field_name = arg(2);
425  $delta = arg(3);
426  $node = node_load($nid);
427  drupal_set_header('Content-Type: text; charset=utf-8');
428  //  $html = node_view($node, FALSE, FALSE, FALSE);
429  // this required traversing the entire node to get the field (and doesn't work
430  // for checkboxes anyway)
431
432  $field = content_fields($field_name, $node->type);
433
434  $field['display_settings']['label']['format'] = 'hidden';
435  // We have 2 reasonable choices here. We COULD use 'clicktoedit' and end up
436  // with the same HTML - then we could strip that HTML down to remove the
437  // surrounding 'click to edit' div (which we dont want, as we'll be replacing
438  // the html inside one of those div's)
439  // or we can simply use the 'defualt' formatter - which wont have the click to
440  // edit inside it  - and is hard coded into this module (for now) anyway!
441  $field['display_settings']['full']['format'] = 'default';
442  $html = content_view_field($field, $node);
443
444  $messages = drupal_get_messages('status', TRUE);
445  if (count($messages) > 0) {
446    foreach ($messages as $type => $messages) {
447      foreach ($messages as $message) {
448        $output .= '<div class="messages ' . $type . '">' . $message . "</div>";
449      }
450    }
451  }
452
453  $object = new stdClass();
454  $object->content =
455    $output . $html . drupal_render($node->content[$field_name]);
456  drupal_json($object);
457  exit();
458}
459
460/**
461 * Menu callback: ajax form.
462 */
463function editablefields_html() {
464  $nid = arg(1);
465  $field_name = arg(2);
466  $delta = arg(3);
467  $node = node_load($nid);
468
469  if (node_access('update', $node)) {
470    //  $html = _editablefields_create_form($node, $field_name);
471    $html = drupal_get_form('editablefields_form', $node, $field_name, $delta);
472    $object = new stdClass();
473    $object->content = $html;
474    // Register the JavaScript callback for this module.
475    $object->__callbacks = array();
476    // Allow other modules to extend the data returned.
477    drupal_alter('ajax_data', $object, 'editablefields', $html);
478    drupal_json($object);
479  }
480  else {
481    drupal_not_found();
482  }
483  exit();
484}
485
486/**
487 * Menu callback: ajax submit.
488 */
489function editablefields_submit() {
490  $nid = $_POST['nid'];
491  $field_name = $_POST['field'];
492  $delta = $_POST['delta'];
493
494  $node = node_load($nid);
495
496  $node_options = variable_get(
497    'node_options_' . $node->type, array('status', 'promote'));
498  $node->revision = in_array('revision', $node_options);
499  if ($node->revision) {
500    $node->log = t(
501      '%field_name updated by editablefields.',
502      array('%field_name' => $field_name)
503    );
504  }
505
506  if (node_access('update', $node)) {
507
508    if (!isset($_POST[$field_name])) {
509      $_POST[$field_name] = array();
510    }
511
512    $form_state = array('values' => $_POST);
513
514    /* it seems that the serializer does not serialize e.g. un-checked
515     * checkboxes. Leaving them as empty arrays. This FILTHY hack fills in the
516     * array with 'something' so that when the form is executed, it fills in the
517     * right value - I dislike this code - JMB */
518    if (is_array($node->{$field_name})) {
519      $field = content_fields($field_name, $node->type);
520
521      $items = &$form_state['values'][$field_name];
522
523      if (empty($items)) {
524        foreach (array_keys($field['columns']) as $column) {
525          if ($field['multiple']) {
526            $items[$delta][$column][] = NULL;
527          }
528          else {
529            $items[$column] = NULL;
530          }
531        }
532      }
533
534      if (isset($items['value'])) {
535        if (!($field['widget']['type'] == 'optionwidgets_buttons' &&
536          $field['multiple'])) {
537          $items = array($items);
538        }
539      }
540
541      // go through content_set_empty if this is NOT a checkbox multi valued element
542      if (!($field['widget']['type'] == 'optionwidgets_buttons' &&
543        $field['multiple'])) {
544        $items = content_set_empty($field, $items);
545      }
546
547      switch ($field['type']) {
548        case 'nodereference':
549        case 'userreference':
550          if ($field['multiple']) {
551            reset($field['columns']);
552            $items[key($field['columns'])] = array_pop($items);
553          }
554          break;
555      }
556
557      drupal_execute('editablefields_form', $form_state, $node, $field_name,
558        $delta
559      );
560
561      $err = drupal_get_messages();
562
563      if (count($err) > 0) {
564        drupal_set_header('HTTP/1.1 404 Not Found');
565        // format the error message suitable for a popup window in simple text.
566        foreach ($err as $type => $messages) {
567          foreach ($messages as $message) {
568            print $type . ' : ' . $message . "\n";
569          }
570        }
571        exit();
572      }
573
574      // the matrix field identifies itself as being multivalue, but in fact, it is not.
575      if ((content_handle('widget', 'multiple values', $field)
576        == CONTENT_HANDLE_CORE) && ($field['type'] != matrix)) {
577        if ($node->{$field_name}[$delta] !=
578          $form_state['values'][$field_name][0]) {
579          $node->{$field_name}[$delta] = $form_state['values'][$field_name][0];
580          node_save($node);
581        }
582      }
583      else {
584        if ($node->{$field_name} != $form_state['values'][$field_name]) {
585          $node->{$field_name} = $form_state['values'][$field_name];
586          node_save($node);
587        }
588      }
589      // make sure sensible headers etc are sent...
590      drupal_set_header('Content-Type: text; charset=utf-8');
591    }
592    else {
593      drupal_set_header('HTTP/1.1 404 Not Found');
594      print t('No field found, of name: %field',
595              array('%field' => $field_name));
596    }
597  }
598  else {
599    drupal_set_header('HTTP/1.1 404 Not Found');
600    print t('No write permissions for %field', array('%field' => $field_name));
601  }
602  exit();
603}
604
605
606/**
607 * If the Remove button was clicked remove the file from the node.
608 */
609function editablefields_filefield_js($type_name, $field_name, $delta) {
610  if (!empty($_POST['editablefields_node_nid']) &&
611    $node = node_load($_POST['editablefields_node_nid'])) {
612    $remove_button_clicked = FALSE;
613    foreach ($_POST as $key => $value) {
614      // check if the remove button was clicked
615      if (stripos($key, $field_name) === 0 &&
616        stripos($key, '_filefield_remove') !== FALSE) {
617        $remove_button_clicked = TRUE;
618        break;
619      }
620    }
621
622    if ($remove_button_clicked) {
623      $field = $_POST[$field_name];
624      $field = array_pop($field);
625      $file = (object)field_file_load($field['fid']);
626
627      // respect revision settings
628      $node_options = variable_get(
629        'node_options_' . $node->type, array('status', 'promote'));
630      $node->revision = in_array('revision', $node_options);
631      if ($node->revision) {
632        $node->log = t('%field_name updated by editablefields.',
633          array('%field_name' => $field_name));
634      }
635
636      $file->field_name = $field_name;
637      $references = field_file_delete($file);
638
639      $node->{$field_name}[$delta] = array();
640      node_save($node);
641
642      drupal_set_message(t('File %filename was removed from node.',
643        array('%filename' => $file->filename)));
644    }
645  }
646
647  filefield_js($type_name, $field_name, $delta);
648}
649
650/**
651 * Implementation of hook_file_insert().
652 */
653function editablefields_file_insert($file) {
654  if (stripos($_GET['q'], 'filefield/ahah/') === 0 && !empty(
655  $_POST['editablefields_node_nid']) &&
656    $node = node_load($_POST['editablefields_node_nid'])) {
657    $file_clone = (array)$file;
658    field_file_save($node, $file_clone);
659
660    $q_arr = explode('/', $_GET['q']);
661    $field_name = $q_arr[3];
662    $delta = $q_arr[4];
663
664    $node->{$field_name}[$delta] = array(
665      'fid' => $file->fid
666    );
667
668    // respect revision settings
669    $node_options = variable_get(
670      'node_options_' . $node->type, array('status', 'promote'));
671    $node->revision = in_array('revision', $node_options);
672    if ($node->revision) {
673      $node->log = t('%field_name updated by editablefields.',
674        array('%field_name' => $field_name));
675    }
676
677    node_save($node);
678  }
679}
680
681
682function editablefields_formatter_get_settings($field_name, $type_name, $context) {
683  $options = array();
684  $value = 'editablefields:'. $type_name .':'. $context .':'. $field_name;
685  $options['editablefields'] = variable_get($value . '_text_formatter', 'default');
686  /*
687  $options['repeat']['show_repeat_rule'] = variable_get($value .'_show_repeat_rule', 'show');
688  $options['multiple']['multiple_number'] = variable_get($value .'_multiple_number', '');
689  $options['multiple']['multiple_from'] = variable_get($value .'_multiple_from', '');
690  $options['multiple']['multiple_to'] = variable_get($value .'_multiple_to', '');
691  $options['fromto']['fromto'] = variable_get($value .'_fromto', 'both')
692  */
693  return $options;
694}
695
696/**
697 * Returns all 'editables' plugins.
698 *
699 * @return array
700 */
701function editablefields_get_responders() {
702  ctools_include('plugins');
703  $plugins = ctools_get_plugins('editablefields', 'responders');
704  foreach($plugins as &$plugin) {
705    // add defaults
706    $plugin += array(
707      'hook_menu' => array(),
708      'formatter_info' => array(),
709    );
710  }
711  return $plugins;
712}
713
714function editablefields_get_editables() {
715  ctools_include('plugins');
716  $plugins = ctools_get_plugins('editablefields', 'editables');
717  return $plugins;
718}
719/**
720 * Menu wildcard argument callback.
721 */
722function editablefields_object_load($object_id, $editable) {
723  $editables = editablefields_get_editables();
724  $function = $editables[$editable]['entity callback'];
725  return $function($object_id);
726}
727
728/**
729 * Implementation of hook_views_api().
730 */
731function editablefields_views_api() {
732  return array(
733    'api' => 2,
734    'path' => drupal_get_path('module', 'editablefields') . '/includes/views',
735  );
736}
737
738function editablefields_views_option_form(&$form, &$form_state, $editable) {
739  $form['editablefields_allowed'] = array(
740    '#title' => t('Make field editable'),
741    '#description' => t('This will override any other link you have set.'),
742    '#type' => 'checkbox',
743    '#default_value' => '',
744  );
745  $responders = editablefields_get_responders();
746  $options = array();
747
748  foreach($responders as $responder) {
749    $options[$responder['name']] = $responder['title'];
750  }
751 
752  $form['editablefields_responder'] = array(
753    '#title' => t('Editable Behavior'),
754    '#description' => t('How would you like to edit this field?'),
755    '#type' => 'select',
756    '#options' => $options,
757    '#dependency' => array('edit-options-editablefields-allowed' =>  array('1')),
758    '#process' => array('views_process_dependency')
759  );
760 
761  $form['editablefields_editable'] = array(
762    '#type' => 'hidden',
763    '#value' => $editable,
764  );
765}
Nota: Vea TracBrowser para ayuda de uso del navegador del repositorio.