[ Index ]

PHP Cross Reference of Drupal 6 (gatewave)

title

Body

[close]

/sites/all/modules/diff/ -> diff.pages.inc (source)

   1  <?php
   2  // $Id: diff.pages.inc,v 1.1.2.9 2010/08/12 16:34:08 yhahn Exp $
   3  
   4  /**
   5   * @file
   6   * Menu callbacks for hook_menu().
   7   */
   8  
   9  /**
  10   * Menu callback - show latest diff for a given node.
  11   */
  12  function diff_latest($node) {
  13    $revisions = node_revision_list($node);
  14    $new = array_shift($revisions);
  15    $old = array_shift($revisions);
  16    drupal_goto("node/{$node->nid}/revisions/view/{$old->vid}/{$new->vid}");
  17  }
  18  
  19  /**
  20   * Generate an overview table of older revisions of a node and provide
  21   * an input form to select two revisions for a comparison.
  22   */
  23  function diff_diffs_overview($node) {
  24    drupal_set_title(t('Revisions for %title', array('%title' => $node->title)));
  25    return drupal_get_form('diff_node_revisions', $node);
  26  }
  27  
  28  /**
  29   * Input form to select two revisions.
  30   *
  31   * @param $node
  32   *   Node whose revisions are displayed for selection.
  33   */
  34  function diff_node_revisions($form_state, $node) {
  35    global $form_values;
  36    $form = array();
  37  
  38    $form['nid'] = array(
  39      '#type' => 'hidden',
  40      '#value' => $node->nid,
  41    );
  42  
  43    $revision_list = node_revision_list($node);
  44  
  45    if (count($revision_list) > REVISION_LIST_SIZE) {
  46      // If the list of revisions is longer than the number shown on one page split the array.
  47      $page = isset($_GET['page']) ? $_GET['page'] : '0';
  48      $revision_chunks = array_chunk(node_revision_list($node), REVISION_LIST_SIZE);
  49      $revisions = $revision_chunks[$page];
  50      // Set up global pager variables as would 'pager_query' do.
  51      // These variables are then used in the theme('pager') call later.
  52      global $pager_page_array, $pager_total, $pager_total_items;
  53      $pager_total_items[0] = count($revision_list);
  54      $pager_total[0] = ceil(count($revision_list) / REVISION_LIST_SIZE);
  55      $pager_page_array[0] = max(0, min($page, ((int)$pager_total[0]) - 1));
  56    }
  57    else {
  58      $revisions = $revision_list;
  59    }
  60  
  61    $revert_permission = FALSE;
  62    if ((user_access('revert revisions') || user_access('administer nodes')) && node_access('update', $node)) {
  63      $revert_permission = TRUE;
  64    }
  65    $delete_permission = FALSE;
  66    if ((user_access('delete revisions') || user_access('administer nodes')) && node_access('delete', $node)) {
  67      $delete_permission = TRUE;
  68    }
  69  
  70    foreach ($revisions as $revision) {
  71      $operations = array();
  72      $revision_ids[$revision->vid] = '';
  73  
  74      if ($revision->current_vid > 0) {
  75        $form['info'][$revision->vid] = array(
  76          '#value' => t('!date by !username', array(
  77            '!date' => l(format_date($revision->timestamp, 'small'), "node/$node->nid"),
  78            '!username' => theme('username', $revision)))
  79          . (($revision->log != '') ? '<p class="revision-log">'. filter_xss($revision->log) .'</p>' : ''),
  80        );
  81      }
  82      else {
  83        $form['info'][$revision->vid] = array(
  84          '#value' => t('!date by !username', array(
  85            '!date' => l(format_date($revision->timestamp, 'small'), "node/$node->nid/revisions/$revision->vid/view"),
  86            '!username' => theme('username', $revision)))
  87          . (($revision->log != '') ? '<p class="revision-log">'. filter_xss($revision->log) .'</p>' : '')
  88        );
  89        if ($revert_permission) {
  90          $operations[] = array('#value' => l(t('revert'), "node/$node->nid/revisions/$revision->vid/revert"));
  91        }
  92        if ($delete_permission) {
  93          $operations[] = array('#value' => l(t('delete'), "node/$node->nid/revisions/$revision->vid/delete"));
  94        }
  95        // Set a dummy, even if the user has no permission for the other
  96        // operations, so that we can check if the operations array is
  97        // empty to know if the row denotes the current revision.
  98        $operations[] = array();
  99      }
 100      $form['operations'][$revision->vid] = $operations;
 101  
 102    }
 103    $new_vid = key($revision_ids);
 104    next($revision_ids);
 105    $old_vid = key($revision_ids);
 106    $form['diff']['old'] = array(
 107      '#type' => 'radios',
 108      '#options' => $revision_ids,
 109      '#default_value' => $old_vid
 110    );
 111    $form['diff']['new'] = array(
 112      '#type' => 'radios',
 113      '#options' => $revision_ids,
 114      '#default_value' => $new_vid
 115    );
 116    $form['submit'] = array('#type' => 'submit', '#value' => t('Show diff'));
 117  
 118    if (count($revision_list) > REVISION_LIST_SIZE) {
 119      $form['#suffix'] = theme('pager', NULL, REVISION_LIST_SIZE, 0);
 120    }
 121  
 122    return $form;
 123  }
 124  
 125  /**
 126   * Submit code for input form to select two revisions.
 127   */
 128  function diff_node_revisions_submit($form, &$form_state) {
 129    // the ids are ordered so the old revision is always on the left
 130    $old_vid = min($form_state['values']['old'], $form_state['values']['new']);
 131    $new_vid = max($form_state['values']['old'], $form_state['values']['new']);
 132    $form_state['redirect'] =  'node/'. $form_state['values']['nid'] .'/revisions/view/'. $old_vid .'/'. $new_vid;
 133  }
 134  
 135  /**
 136   * Validation for input form to select two revisions.
 137   */
 138  function diff_node_revisions_validate($form, &$form_state) {
 139    $old_vid = $form_state['values']['old'];
 140    $new_vid = $form_state['values']['new'];
 141    if ($old_vid==$new_vid || !$old_vid || !$new_vid) {
 142      form_set_error('diff', t('Select different revisions to compare.'));
 143    }
 144  }
 145  
 146  /**
 147   * Create output string for a comparison of 'node' between
 148   * versions 'old_vid' and 'new_vid'.
 149   *
 150   * @param $node
 151   *   Node on which to perform comparison
 152   * @param $old_vid
 153   *   Version ID of the old revision.
 154   * @param $new_vid
 155   *   Version ID of the new revision.
 156   */
 157  function diff_diffs_show($node, $old_vid, $new_vid) {
 158  
 159    // Set same title as on the 'Revisions' tab for consistency
 160    drupal_set_title(t('Revisions for %title', array('%title' => $node->title)));
 161  
 162    $node_revisions = node_revision_list($node);
 163  
 164    $old_node = node_load($node->nid, $old_vid);
 165    $new_node = node_load($node->nid, $new_vid);
 166  
 167    // Generate table header (date, username, logmessage).
 168    $old_header = t('!date by !username', array(
 169      '!date' => l(format_date($old_node->revision_timestamp), "node/$node->nid/revisions/$old_node->vid/view"),
 170      '!username' => theme('username', $node_revisions[$old_vid]),
 171    ));
 172    $new_header = t('!date by !username', array(
 173      '!date' => l(format_date($new_node->revision_timestamp), "node/$node->nid/revisions/$new_node->vid/view"),
 174      '!username' => theme('username', $node_revisions[$new_vid]),
 175    ));
 176  
 177    $old_log = $old_node->log != '' ? '<p class="revision-log">'. filter_xss($old_node->log) .'</p>' : '';
 178    $new_log = $new_node->log != '' ? '<p class="revision-log">'. filter_xss($new_node->log) .'</p>' : '';
 179  
 180    // Generate previous diff/next diff links.
 181    $next_vid = _diff_get_next_vid($node_revisions, $new_vid);
 182    if ($next_vid) {
 183      $next_link = l(t('next diff >'), 'node/'. $node->nid .'/revisions/view/'. $new_vid .'/'. $next_vid);
 184    }
 185    else {
 186      $next_link = '';
 187    }
 188    $prev_vid = _diff_get_previous_vid($node_revisions, $old_vid);
 189    if ($prev_vid) {
 190      $prev_link = l(t('< previous diff'), 'node/'. $node->nid .'/revisions/view/'. $prev_vid .'/'. $old_vid);
 191    }
 192    else {
 193      $prev_link = '';
 194    }
 195  
 196    $cols = _diff_default_cols();
 197    $header = _diff_default_header($old_header, $new_header);
 198    $rows = array();
 199    if ($old_log || $new_log) {
 200      $rows[] = array(
 201        array(
 202          'data' => $old_log,
 203          'colspan' => 2
 204        ),
 205        array(
 206          'data' => $new_log,
 207          'colspan' => 2
 208        )
 209      );
 210    }
 211    $rows[] = array(
 212      array(
 213        'data' => $prev_link,
 214        'class' => 'diff-prevlink',
 215        'colspan' => 2
 216      ),
 217      array(
 218        'data' => $next_link,
 219        'class' => 'diff-nextlink',
 220        'colspan' => 2
 221      )
 222    );
 223    $rows = array_merge($rows, _diff_body_rows($old_node, $new_node));
 224    $output = theme('diff_table', $header, $rows, array('class' => 'diff'), NULL, $cols);
 225  
 226    if ($node->vid == $new_vid) {
 227      $output .= '<div class="diff-section-title">'. t('Current revision:') .'</div>';
 228    }
 229    else {
 230      $output .= '<div class="diff-section-title">'. t('Revision of !new_date:', array('!new_date' => format_date($new_node->revision_timestamp))) .'</div>';
 231    }
 232    // Don't include node links (final argument) when viewing the diff.
 233    $output .= node_view($new_node, FALSE, FALSE, FALSE);
 234    return $output;
 235  }
 236  
 237  /**
 238   * Creates an array of rows which represent a diff between $old_node and $new_node.
 239   * The rows can be used via theme('diff_table') to be displayed.
 240   *
 241   * @param $old_node
 242   *   Node for comparison which will be displayed on the left side.
 243   * @param $new_node
 244   *   Node for comparison which will be displayed on the right side.
 245   */
 246  function _diff_body_rows($old_node, $new_node) {
 247    drupal_add_css(drupal_get_path('module', 'diff') .'/diff.css', 'module', 'all', FALSE);
 248    module_load_include('inc', 'diff', 'includes/node');
 249    if (module_exists('taxonomy')) {
 250      module_load_include('inc', 'diff', 'includes/taxonomy');
 251    }
 252    if (module_exists('upload')) {
 253      module_load_include('inc', 'diff', 'includes/upload');
 254    }
 255  
 256    $rows = array();
 257    $any_visible_change = FALSE;
 258    // @todo quick workaround for PHP >= 5.3.0 date_diff() conflict.
 259    $node_diffs = _diff_module_invoke_all($old_node, $new_node);
 260  
 261    // We start off assuming all form elements are in the correct order.
 262    $node_diffs['#sorted'] = TRUE;
 263  
 264    // Recurse through all child elements.
 265    $count = 0;
 266    foreach (element_children($node_diffs) as $key) {
 267      // Assign a decimal placeholder weight to preserve original array order.
 268      if (!isset($node_diffs[$key]['#weight'])) {
 269        $node_diffs[$key]['#weight'] = $count/1000;
 270      }
 271      else {
 272        // If one of the child elements has a weight then we will need to sort
 273        // later.
 274        unset($node_diffs['#sorted']);
 275      }
 276      $count++;
 277    }
 278  
 279    // One of the children has a #weight.
 280    if (!isset($node_diffs['#sorted'])) {
 281      uasort($node_diffs, "element_sort");
 282    }
 283  
 284    // Render diffs for each.
 285    foreach ($node_diffs as $node_diff) {
 286      $show_header = isset($node_diff['#format']['show_header']) ? $node_diff['#format']['show_header'] : FALSE;
 287      if ($node_diff_rows = diff_get_rows($node_diff['#old'], $node_diff['#new'], $show_header)) {
 288        $rows[] = array(array(
 289          'data' => t('Changes to %name', array('%name' => $node_diff['#name'])),
 290          'class' => 'diff-section-title',
 291          'colspan' => 4
 292        ));
 293        $rows = array_merge($rows, $node_diff_rows);
 294        $any_visible_change = TRUE;
 295      }
 296    }
 297    if (!$any_visible_change) {
 298      $rows[] = array(array(
 299        'data' => t('No visible changes'),
 300        'class' => 'diff-section-title',
 301        'colspan' => 4
 302      ));
 303      // Needed to keep safari happy
 304      $rows[] = array(
 305        array('data' => ''),
 306        array('data' => ''),
 307        array('data' => ''),
 308        array('data' => ''),
 309      );
 310    }
 311    return $rows;
 312  }
 313  
 314  /**
 315   * Helper function to invoke hook_diff in all enabled modules that implement it.
 316   *
 317   * Don't use module_invoke_all() since if date.module is enabled will clash with
 318   * PHP 5.3's date_diff() function.
 319   *
 320   * @todo figure out any else possible solution but not workaround.
 321   * @link http://drupal.org/node/639320
 322   * @see module_invoke_all()
 323   */
 324  function _diff_module_invoke_all($old_node, $new_node) {
 325    $return = array();
 326    foreach (module_implements('diff') as $module) {
 327      if ($module == 'date') {
 328        continue; // Avoid function name collision with date_diff().
 329      }
 330      $result = module_invoke($module, 'diff', $old_node, $new_node);
 331      if (isset($result) && is_array($result)) {
 332        $return = array_merge_recursive($return, $result);
 333      }
 334      elseif (isset($result)) {
 335        $return[] = $result;
 336      }
 337    }
 338    return $return;
 339  }
 340  
 341  /**
 342   * Get the entry in the revisions list after $vid.
 343   * Returns FALSE if $vid is the last entry.
 344   *
 345   * @param $node_revisions
 346   *   Array of node revision IDs in descending order.
 347   * @param $vid
 348   *   Version ID to look for.
 349   */
 350  function _diff_get_next_vid($node_revisions, $vid) {
 351    $previous = NULL;
 352    foreach ($node_revisions as $revision) {
 353      if ($revision->vid == $vid) {
 354        return ($previous ? $previous->vid : FALSE);
 355      }
 356      $previous = $revision;
 357    }
 358    return FALSE;
 359  }
 360  
 361  /**
 362   * Get the entry in the revision list before $vid.
 363   * Returns FALSE if $vid is the first entry.
 364   *
 365   * @param $node_revisions
 366   *   Array of node revision IDs in descending order.
 367   * @param $vid
 368   *   Version ID to look for.
 369   */
 370  function _diff_get_previous_vid($node_revisions, $vid) {
 371    $previous = NULL;
 372    foreach ($node_revisions as $revision) {
 373      if ($previous && $previous->vid == $vid) {
 374        return $revision->vid;
 375      }
 376      $previous = $revision;
 377    }
 378    return FALSE;
 379  }
 380  
 381  /**
 382   * Helper function to create default 'cols' array for diff table.
 383   */
 384  function _diff_default_cols() {
 385    return array(
 386      array(
 387        array(
 388          'class' => 'diff-marker',
 389        ),
 390        array(
 391          'class' => 'diff-content',
 392        ),
 393        array(
 394          'class' => 'diff-marker',
 395        ),
 396        array(
 397          'class' => 'diff-content',
 398        ),
 399      ),
 400    );
 401  }
 402  
 403  /**
 404   * Helper function to create default 'header' array for diff table.
 405   */
 406  function _diff_default_header($old_header = '', $new_header = '') {
 407    return array(
 408      array(
 409        'data' => $old_header,
 410        'colspan' => 2
 411      ),
 412      array(
 413        'data' => $new_header,
 414        'colspan' => 2
 415      )
 416    );
 417  }
 418  
 419  /**
 420   * AHAH callback for rendering the inline diff of a node.
 421   */
 422  function diff_inline_ahah($node) {
 423    $form_state = array('values' => $_POST);
 424    if ($form = form_get_cache($form_state['values']['form_build_id'], $form_state)) {
 425      if (!empty($form_state['values']['revision']) && is_numeric($form_state['values']['revision'])) {
 426        $vid = $form_state['values']['revision'];
 427      }
 428      else {
 429        $vid = 0;
 430      }
 431      drupal_json(array('status' => TRUE, 'data' => diff_inline_show($node, $vid)));
 432      exit;
 433    }
 434    drupal_json(array('status' => FALSE, 'data' => ''));
 435    exit;
 436  }
 437  
 438  /**
 439   * Show the inline diff for a given node, vid. If vid = 0 or no previous vid
 440   * exists for the given revision returns the normally rendered content of the
 441   * specified revision.
 442   */
 443  function diff_inline_show($node, $vid = 0, $metadata = TRUE) {
 444    $new_node = $vid ? node_load($node->nid, $vid, TRUE) : drupal_clone($node);
 445    $new = node_build_content($new_node);
 446    $new = drupal_render($new->content);
 447  
 448    $old = $vid ? _diff_get_previous_vid(node_revision_list($node), $vid) : 0;
 449    if ($old) {
 450      $old = node_build_content(node_load($node->nid, $old, TRUE));
 451      $old = drupal_render($old->content);
 452      $output = $metadata ? theme('diff_inline_metadata', $new_node) : '';
 453      $output .= diff_get_inline($old, $new);
 454      return $output;
 455    }
 456    return $new;
 457  }


Generated: Thu Mar 24 11:18:33 2011 Cross-referenced by PHPXref 0.7