source: sipes/modules_contrib/diff/diff.module @ c43ea01

stableversion-3.0
Last change on this file since c43ea01 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 100644
File size: 11.9 KB
Línea 
1<?php
2
3/**
4 * @file
5 * Provides functionality to show a diff between two node revisions.
6 */
7
8/**
9 * Number of items on one page of the revision list.
10 */
11define('REVISION_LIST_SIZE', 50);
12
13/**
14 * Implementation of hook_help().
15 */
16function diff_help($path, $arg) {
17  switch ($path) {
18    case 'admin/help#diff':
19      $output = '<p>'. t('The diff module overwrites the normal revisions view. The revisions table is enhanced with a possibility to view the difference between two node revisions. Users with the %view_revisions permission will also be able to view the changes between any two selected revisions. You may disable this for individual content types on the content type configuration page. This module also provides a nifty %preview_changes button while editing a post.', array('%preview_changes' => t('View changes'), '%view_revisions' => t('view revisions'))) .'</p>';
20      return $output;
21    case 'node/%/revisions/%/view':
22      // the following string is copied from string copied from node_help('node/%/revisions')
23      return '<p>'. t('The revisions let you track differences between multiple versions of a post.') .'</p>';
24    case 'node/%/revisions/view/%/%':
25      return '<p>'. t('Comparing two revisions:') .'</p>';
26  }
27}
28
29/**
30 * Implementation of hook_menu().
31 */
32function diff_menu() {
33  $items = array();
34
35  /**
36   * By using MENU_LOCAL_TASK (and 'tab_parent') we can get the various revision-views to
37   * show the View|Edit|Revision-tabs of the node on top, and have the Revisions-tab open.
38   * To avoid creating/showing any extra tabs or sub-tabs (tasks below top level) for the
39   * various paths (i.e. "Diff", "Show latest" and "Show a specific revision") that need
40   * a revision-id (vid) parameter, we make sure to set 'tab_parent' a bit odd.
41   * This solution may not be sthe prettiest one, but by avoiding having two _LOCAL_TASKs
42   * sharing a parent that can be accessed by its full path, it seems to work as desired.
43   * Breadcrumbs work decently, at least the node link is among the crumbs. For some reason
44   * any breadcrumbs "before/above" the node is only seen at 'node/%node/revisions/%/view'.
45   */
46  $items['node/%node/revisions/list'] = array(
47    // Not used directly, but was created to get the other menu items to work well
48    'title' => 'List revisions',
49    'page callback' => 'diff_diffs_overview',
50    'type' => MENU_DEFAULT_LOCAL_TASK,
51    'access callback' => 'diff_node_revision_access',
52    'access arguments' => array(1),
53    'file' => 'diff.pages.inc',
54  );
55  $items['node/%node/revisions/view/%/%'] = array(
56    'title' => 'Diff',
57    'page callback' => 'diff_diffs_show',
58    'page arguments' => array(1, 4, 5),
59    'type' => MENU_LOCAL_TASK,
60    'access callback' => 'diff_node_revision_access',
61    'access arguments' => array(1),
62    'tab_parent' => 'node/%/revisions/list',
63    'file' => 'diff.pages.inc',
64  );
65  $items['node/%node/revisions/view/latest'] = array(
66    'title' => 'Show latest diff',
67    'page callback' => 'diff_latest',
68    'page arguments' => array(1),
69    'type' => MENU_LOCAL_TASK,
70    'access callback' => '_node_revision_access',
71    'access arguments' => array(1),
72    'tab_parent' => 'node/%/revisions/view',
73    'file' => 'diff.pages.inc',
74  );
75  $items['node/%node/revisions/diff-inline'] = array(
76    'page callback' => 'diff_inline_ahah',
77    'page arguments' => array(1),
78    'type' => MENU_CALLBACK,
79    'access callback' => 'diff_node_revision_access',
80    'access arguments' => array(1),
81    'file' => 'diff.pages.inc',
82  );
83  return $items;
84}
85
86/**
87 * Implementation of hook_menu_alter().
88 */
89function diff_menu_alter(&$callbacks) {
90  // Overwrite the default 'Revisions' page
91  $callbacks['node/%node/revisions']['page callback'] = 'diff_diffs_overview';
92  $callbacks['node/%node/revisions']['module'] = 'diff';
93  $callbacks['node/%node/revisions']['file'] = 'diff.pages.inc';
94
95  $callbacks['node/%node/revisions/%/view']['tab_parent'] = 'node/%/revisions/list';
96  $callbacks['node/%node/revisions/%/revert']['tab_parent'] = 'node/%/revisions/%/view';
97  $callbacks['node/%node/revisions/%/delete']['tab_parent'] = 'node/%/revisions/%/view';
98
99  return;
100}
101
102/**
103 * Access callback for the node revisions page.
104 */
105function diff_node_revision_access($node, $op = 'view') {
106  $may_revision_this_type = variable_get('enable_revisions_page_'. $node->type, TRUE) || user_access('administer nodes');
107  return $may_revision_this_type && _node_revision_access($node, $op);
108}
109
110/**
111 * Implementation of hook_block().
112 */
113function diff_block($op = 'list', $delta = 0, $edit = array()) {
114  if ($op === 'list') {
115    return array('inline' => array('info' => t('Inline diff')));
116  }
117  elseif ($op === 'view' && $delta === 'inline' && user_access('view revisions') && $node = menu_get_object()) {
118    $block = array();
119    $revisions = node_revision_list($node);
120    if (count($revisions) > 1) {
121      $block['subject'] = t('Highlight changes');
122      $block['content'] = drupal_get_form('diff_inline_form', $node, $revisions);
123    }
124    return $block;
125  }
126}
127
128/**
129 * Implementation of hook_nodeapi().
130 */
131function diff_nodeapi(&$node, $op, $teaser, $page) {
132  if ($page && $op == 'view' && user_access('view revisions') && variable_get('show_diff_inline_'. $node->type, FALSE)) {
133    // Ugly but cheap way to check that we are viewing a node's revision page.
134    if (arg(2) === 'revisions' && arg(3) === $node->vid) {
135      module_load_include('inc', 'diff', 'diff.pages');
136      $node->content = array('#value' => diff_inline_show($node, $node->vid));
137    }
138    $node->content['#prefix'] = isset($node->content['#prefix']) ? "<div id='diff-inline-{$node->nid}'>" . $node->content['#prefix'] : "<div id='diff-inline-{$node->nid}'>";
139    $node->content['#suffix'] = isset($node->content['#suffix']) ? $node->content['#suffix'] . "</div>" : "</div>";
140  }
141}
142
143/**
144 * Implementation of hook_form_alter().
145 */
146function diff_form_alter(&$form, $form_state, $form_id) {
147  if (isset($form['type']['#value']) && $form['type']['#value'] .'_node_form' == $form_id) {
148    // Add a 'View changes' button on the node edit form.
149    if (variable_get('show_preview_changes_'. $form['type']['#value'], TRUE) && $form['nid']['#value'] > 0) {
150      $form['buttons']['preview_changes'] = array(
151        '#type' => 'submit',
152        '#value' => t('View changes'),
153        '#weight' => 12,
154        '#submit' => array('diff_node_form_build_preview_changes')
155      );
156    }
157  }
158  elseif ($form_id == 'node_type_form' && isset($form['identity']['type'])) {
159    // Node type edit form.
160    // Add checkbox to activate 'View changes' button per node type.
161    $form['workflow']['diff'] = array(
162      '#title' => t('Diff'),
163      '#type' => 'item',
164      '#tree' => FALSE,
165    );
166    $form['workflow']['diff']['show_preview_changes'] = array(
167      '#type' => 'checkbox',
168      '#title' => t('Show %preview_changes button on node edit form', array('%preview_changes' => t('View changes'))),
169      '#weight' => 10,
170      '#default_value' => variable_get('show_preview_changes_'. $form['#node_type']->type, TRUE),
171    );
172    $form['workflow']['diff']['show_diff_inline'] = array(
173      '#type' => 'checkbox',
174      '#title' => t('Show diffs inline for this content type'),
175      '#description' => t("You must enable the 'Inline diff' block to use this feature"),
176      '#weight' => 10,
177      '#default_value' => variable_get('show_diff_inline_'. $form['#node_type']->type, FALSE),
178    );
179    $form['workflow']['diff']['enable_revisions_page'] = array(
180      '#type' => 'checkbox',
181      '#title' => t('Enable the %revisions page for this content type', array('%revisions' => t('Revisions'))),
182      '#weight' => 11,
183      '#default_value' => variable_get('enable_revisions_page_'. $form['#node_type']->type, TRUE),
184    );
185  }
186}
187
188/**
189 * Callback if 'View changes' is pressed.
190 */
191function diff_node_form_build_preview_changes($form, &$form_state) {
192  module_load_include('inc', 'diff', 'diff.pages');
193  $node = node_form_submit_build_node($form, $form_state);
194
195  // Create diff of old node and edited node
196  $rows = _diff_body_rows(node_load($form_state['values']['nid']), $node);
197  $cols = _diff_default_cols();
198  $header = _diff_default_header();
199  $changes = theme('diff_table', $header, $rows, array('class' => 'diff'), NULL, $cols);
200
201  // Prepend diff to edit form
202  $form_state['node_preview'] = isset($form_state['node_preview']) ? $changes . $form_state['node_preview'] : $changes;
203}
204
205/**
206 * Implementation of hook_theme().
207 */
208function diff_theme() {
209  return array(
210    'diff_node_revisions' => array(
211      'arguments' => array('form' => NULL),
212      'file' => 'diff.theme.inc',
213    ),
214    'diff_table' => array(
215      'arguments' => array('header' => NULL, 'rows' => NULL, 'attributes' => array(), 'caption' => NULL, 'cols' => array()),
216      'file' => 'diff.theme.inc',
217    ),
218    'diff_header_line' => array(
219      'arguments' => array('lineno' => NULL),
220      'file' => 'diff.theme.inc',
221    ),
222    'diff_content_line' => array(
223      'arguments' => array('line' => NULL),
224      'file' => 'diff.theme.inc',
225    ),
226    'diff_empty_line' => array(
227      'arguments' => array('line' => NULL),
228      'file' => 'diff.theme.inc',
229    ),
230    'diff_inline_form' => array(
231      'arguments' => array('form' => array()),
232      'file' => 'diff.theme.inc',
233    ),
234    'diff_inline_metadata' => array(
235      'arguments' => array('node' => NULL),
236      'file' => 'diff.theme.inc',
237    ),
238    'diff_inline_chunk' => array(
239      'arguments' => array('text' => '', 'type' => NULL),
240      'file' => 'diff.theme.inc',
241    ),
242  );
243}
244
245/**
246 * Render a diff of two strings to a $rows array suitable for use with
247 * theme('table') or theme('diff_table').
248 *
249 * @param string $a
250 *   The source string to compare from.
251 * @param string $b
252 *   The target string to compare to.
253 * @param boolean $show_header
254 *   Display diff context headers, e.g. "Line x".
255 * @return
256 *   Array of rows usable with theme('table').
257 */
258function diff_get_rows($a, $b, $show_header = FALSE) {
259  $a = is_array($a) ? $a : explode("\n", $a);
260  $b = is_array($b) ? $b : explode("\n", $b);
261
262  module_load_include('php', 'diff', 'DiffEngine');
263  $formatter = new DrupalDiffFormatter();
264  $formatter->show_header = $show_header;
265  $diff = new Diff($a, $b);
266  return $formatter->format($diff);
267}
268
269/**
270 * Render a diff of two strings into HTML markup indicating additions, changes
271 * and deletions.
272 *
273 * @param string $a
274 *   The source string to compare from.
275 * @param string $b
276 *   The target string to compare to.
277 * @return
278 *   String containing HTML markup.
279 */
280function diff_get_inline($a, $b) {
281  module_load_include('php', 'diff', 'DiffEngine');
282  $diff = new DrupalDiffInline($a, $b);
283  return $diff->render();
284}
285
286/**
287 * Form builder: Inline diff controls.
288 */
289function diff_inline_form($form_state, $node, $revisions) {
290  $form = array();
291  $form['node'] = array(
292    '#type' => 'value',
293    '#value' => $node
294  );
295  $form['revision'] = array(
296    '#type' => 'select',
297    '#options' => array(0 => '< '. t('No highlighting') . ' >'),
298    '#default_value' => (arg(2) === 'revisions' && arg(3) === $node->vid) ? $node->vid : 0,
299    '#ahah' => array(
300      'path' => "node/{$node->nid}/revisions/diff-inline",
301      'wrapper' => "diff-inline-{$node->nid}",
302      'method' => 'replace',
303    ),
304  );
305  foreach ($revisions as $revision) {
306    $form['revision']['#options'][$revision->vid] = t('@revision by @name', array(
307      '@revision' => format_date($revision->timestamp, 'small'),
308      '@name' => $revision->name,
309    ));
310  }
311  $form['submit'] = array(
312    '#type' => 'submit',
313    '#value' => t('View'),
314    '#submit' => array('diff_inline_form_submit'),
315    '#attributes' => array('class' => 'diff-js-hidden'),
316  );
317  return $form;
318}
319
320/**
321 * Form submission handler for diff_inline_form() for JS-disabled clients.
322 */
323function diff_inline_form_submit(&$form, &$form_state) {
324  if (isset($form_state['values']['revision'], $form_state['values']['node'])) {
325    $node = $form_state['values']['node'];
326    $vid = $form_state['values']['revision'];
327    $form_state['redirect'] = "node/{$node->nid}/revisions/{$vid}/view";
328  }
329}
Nota: Vea TracBrowser para ayuda de uso del navegador del repositorio.