Index: DiffEngine.php
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/diff/DiffEngine.php,v
retrieving revision 1.1.4.2
diff -U3 -r1.1.4.2 DiffEngine.php
--- DiffEngine.php 13 Dec 2007 02:41:24 -0000 1.1.4.2
+++ DiffEngine.php 17 Dec 2007 17:18:59 -0000
@@ -1029,93 +1029,147 @@
}
/**
- * Wikipedia Table style diff formatter.
- * @todo document
+ * Diff formatter which uses Drupal theme functions.
* @private
* @subpackage DifferenceEngine
*/
-class TableDiffFormatter extends DiffFormatter
+class DrupalDiffFormatter extends DiffFormatter
{
- function TableDiffFormatter() {
- $this->leading_context_lines = 2;
- $this->trailing_context_lines = 2;
- }
-
- function _block_header( $xbeg, $xlen, $ybeg, $ylen ) {
- $r = '
| '.t('Line @line', array('@line' => $xbeg))." | \n" .
- ''.t('Line @line', array('@line' => $ybeg))." |
\n";
- return $r;
- }
-
- function _start_block( $header ) {
- if ($this->show_header)
- echo $header;
- }
-
- function _end_block() {
- }
-
- function _lines( $lines, $prefix=' ', $color='white' ) {
- }
-
- # HTML-escape parameter before calling this
- function addedLine( $line ) {
- return "+ | {$line} | ";
- }
-
- # HTML-escape parameter before calling this
- function deletedLine( $line ) {
- return "- | {$line} | ";
- }
-
- # HTML-escape parameter before calling this
- function contextLine( $line ) {
- return " | {$line} | ";
- }
-
- function emptyLine() {
- return ' | ';
- }
-
- function _added( $lines ) {
- foreach ($lines as $line) {
- echo '' . $this->emptyLine() .
- $this->addedLine( check_plain ( $line ) ) . "
\n";
- }
- }
-
- function _deleted($lines) {
- foreach ($lines as $line) {
- echo '' . $this->deletedLine( check_plain ( $line ) ) .
- $this->emptyLine() . "
\n";
- }
- }
-
- function _context( $lines ) {
- foreach ($lines as $line) {
- echo '' .
- $this->contextLine( check_plain ( $line ) ) .
- $this->contextLine( check_plain ( $line ) ) . "
\n";
- }
- }
-
- function _changed( $orig, $closing ) {
-
- $diff = new WordLevelDiff( $orig, $closing );
- $del = $diff->orig();
- $add = $diff->closing();
-
- # Notice that WordLevelDiff returns HTML-escaped output.
- # Hence, we will be calling addedLine/deletedLine without HTML-escaping.
-
- while ( $line = array_shift( $del ) ) {
- $aline = array_shift( $add );
- echo '' . $this->deletedLine( $line ) .
- $this->addedLine( $aline ) . "
\n";
- }
- foreach ($add as $line) { # If any leftovers
- echo '' . $this->emptyLine() .
- $this->addedLine( $line ) . "
\n";
- }
- }
+
+ var $rows;
+
+ function DrupalDiffFormatter() {
+ $this->leading_context_lines = 2;
+ $this->trailing_context_lines = 2;
+ }
+
+ function _start_diff() {
+ $this->rows = array();
+ }
+
+ function _end_diff() {
+ return $this->rows;
+ }
+
+ function _block_header($xbeg, $xlen, $ybeg, $ylen) {
+ return array(
+ array(
+ 'data' => theme('diff_header_line', $xbeg),
+ 'colspan' => 2
+ ),
+ array(
+ 'data' => theme('diff_header_line', $ybeg),
+ 'colspan' => 2
+ )
+ );
+ }
+
+ function _start_block($header) {
+ if ($this->show_header) {
+ $this->rows[] = $header;
+ }
+ }
+
+ function _end_block() {
+ }
+
+ function _lines($lines, $prefix=' ', $color='white') {
+ }
+
+ /**
+ * Note: you should HTML-escape parameter before calling this.
+ */
+ function addedLine($line) {
+ return array(
+ array(
+ 'data' => '+',
+ ),
+ array(
+ 'data' => theme('diff_content_line', $line),
+ 'class' => 'diff-addedline',
+ )
+ );
+ }
+
+ /**
+ * Note: you should HTML-escape parameter before calling this.
+ */
+ function deletedLine($line) {
+ return array(
+ array(
+ 'data' => '-',
+ ),
+ array(
+ 'data' => theme('diff_content_line', $line),
+ 'class' => 'diff-deletedline',
+ )
+ );
+ }
+
+ /**
+ * Note: you should HTML-escape parameter before calling this.
+ */
+ function contextLine($line) {
+ return array(
+ ' ',
+ array(
+ 'data' => theme('diff_content_line', $line),
+ 'class' => 'diff-context',
+ )
+ );
+ }
+
+ function emptyLine() {
+ return array(
+ ' ',
+ theme('diff_empty_line', ' '),
+ );
+ }
+
+ function _added($lines) {
+ foreach($lines as $line) {
+ $this->rows[] = array_merge($this->emptyLine(), $this->addedLine(check_plain($line)));
+ }
+ }
+
+ function _deleted($lines) {
+ foreach($lines as $line) {
+ $this->rows[] = array_merge($this->deletedLine(check_plain($line)), $this->emptyLine());
+ }
+ }
+
+ function _context($lines) {
+ foreach($lines as $line) {
+ $this->rows[] = array_merge($this->contextLine(check_plain($line)), $this->contextLine(check_plain($line)));
+ }
+ }
+
+ function _changed($orig, $closing) {
+ $diff = new WordLevelDiff($orig, $closing);
+ $del = $diff->orig();
+ $add = $diff->closing();
+
+ // Notice that WordLevelDiff returns HTML-escaped output.
+ // Hence, we will be calling addedLine/deletedLine without HTML-escaping.
+
+ while ($line = array_shift($del)) {
+ $aline = array_shift( $add );
+ $this->rows[] = array_merge($this->deletedLine($line), $this->addedLine($aline));
+ }
+ foreach ($add as $line) { // If any leftovers
+ $this->rows[] = array_merge($this->emptyLine(), $this->addedLine($line));
+ }
+ }
+}
+
+function theme_diff_header_line($lineno) {
+ return ''. t('Line %lineno', array('%lineno' => $lineno)) .'';
+}
+
+function theme_diff_content_line($line) {
+ return ''. $line .'
';
+}
+
+function theme_diff_empty_line($line) {
+ return $line;
}
Index: diff.css
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/diff/diff.css,v
retrieving revision 1.2.2.4
diff -U3 -r1.2.2.4 diff.css
--- diff.css 13 Dec 2007 02:41:24 -0000 1.2.2.4
+++ diff.css 17 Dec 2007 17:18:59 -0000
@@ -6,6 +6,10 @@
table-layout: fixed;
width: 100%;
}
+table.diff tr.even, table.diff tr.odd {
+ background-color: inherit;
+ border: none;
+}
td.diff-prevlink {
text-align: left;
}
Index: diff.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/diff/diff.module,v
retrieving revision 1.8.2.14
diff -U3 -r1.8.2.14 diff.module
--- diff.module 13 Dec 2007 19:08:25 -0000 1.8.2.14
+++ diff.module 17 Dec 2007 17:18:59 -0000
@@ -330,17 +330,59 @@
$prev_link = '';
}
- // display table
- $output .= '';
- $output .= '';
- $output .= ' | '. $old_header .' | | '. $new_header .' |
';
- if ($new_log || $old_log) {
- $output .= ' | '. $old_log .' | | '. $new_log .' |
';
- }
- $output .= ' | '. $prev_link .' | | '. $next_link .' |
';
- $output .= _diff_table_body($old_node, $new_node);
- $output .= '
';
- $output .= '
';
+ $cols = array(
+ array(
+ array(
+ 'class' => 'diff-marker',
+ ),
+ array(
+ 'class' => 'diff-content',
+ ),
+ array(
+ 'class' => 'diff-marker',
+ ),
+ array(
+ 'class' => 'diff-content',
+ ),
+ ),
+ );
+ $header = array(
+ array(
+ 'data' => $old_header,
+ 'colspan' => 2
+ ),
+ array(
+ 'data' => $new_header,
+ 'colspan' => 2
+ )
+ );
+ $rows = array();
+ if ($old_log || $new_log) {
+ $rows[] = array(
+ array(
+ 'data' => $old_log,
+ 'colspan' => 2
+ ),
+ array(
+ 'data' => $new_log,
+ 'colspan' => 2
+ )
+ );
+ }
+ $rows[] = array(
+ array(
+ 'data' => $prev_link,
+ 'class' => 'diff-prevlink',
+ 'colspan' => 2
+ ),
+ array(
+ 'data' => $next_link,
+ 'class' => 'diff-nextlink',
+ 'colspan' => 2
+ )
+ );
+ $rows = array_merge($rows, _diff_body_rows($old_node, $new_node));
+ $output = theme('diff_table', $header, $rows, array('class' => 'diff'), NULL, $cols);
if ($node->vid == $new_vid) {
$output .= ''. t('Current revision:') .'
';
@@ -354,18 +396,21 @@
}
/**
- * Create the table body of the diff between $old_node and $new_node.
- * The result is a html table part enclosed in tags.
+ * Creates an array of rows which represent a diff between $old_node and $new_node.
+ * The rows can be used via theme('diff_table') to be displayed.
*
* @param $old_node
* Node for comparison which will be displayed on the left side.
* @param $new_node
* Node for comparison which will be displayed on the right side.
*/
-function _diff_table_body(&$old_node, &$new_node) {
+function _diff_body_rows(&$old_node, &$new_node) {
drupal_add_css(drupal_get_path('module', 'diff') .'/diff.css', 'module', 'all', FALSE);
include_once('DiffEngine.php');
include_once('node.inc');
+ if (module_exists('taxonomy')) {
+ include_once('taxonomy.inc');
+ }
if (module_exists('upload')) {
include_once('upload.inc');
}
@@ -373,27 +418,38 @@
include_once('cck.inc');
}
- $output = '';
+ $rows = array();
$any_visible_change = false;
$node_diffs = module_invoke_all('diff', $old_node, $new_node);
foreach($node_diffs as $node_diff) {
$diff = new Diff($node_diff['old'], $node_diff['new']);
- $formatter = new TableDiffFormatter();
+ $formatter = new DrupalDiffFormatter();
if (isset($node_diff['format'])) {
$formatter->show_header = $node_diff['format']['show_header'];
}
- $formatter_output = $formatter->format($diff);
- if ($formatter_output) {
- $output .= '| '. t('Changes to %name', array('%name' => $node_diff['name'])) .' |
';
- $output .= $formatter_output;
+ $diff_rows = $formatter->format($diff);
+ if (count($diff_rows)) {
+ $rows[] = array(
+ array(
+ 'data' => t('Changes to %name', array('%name' => $node_diff['name'])),
+ 'class' => 'diff-section-title',
+ 'colspan' => 4
+ )
+ );
+ $rows = array_merge($rows, $diff_rows);
$any_visible_change = true;
}
}
if (!$any_visible_change) {
- $output .= '| ' .t('No visible changes') .' |
';
+ $rows[] = array(
+ array(
+ 'data' => t('No visible changes'),
+ 'class' => 'diff-section-title',
+ 'colspan' => 4
+ )
+ );
}
- $output .= '';
- return $output;
+ return $rows;
}
/**
@@ -482,11 +538,12 @@
$op = isset($form_values['op']) ? $form_values['op'] : '';
if ($op == t('Preview changes')) {
+ // Diff module expects node as object, thus $form_values is cast to an object.
$node = (object)$form_values;
- $changes = '';
- $changes .= '';
- $changes .= _diff_table_body(node_load($form_values['nid']), $node);
- $changes .= '
';
+ // Create diff of old node and edited node
+ $rows = _diff_body_rows(node_load($form_values['nid']), $node);
+ $changes = theme('table', array(), $rows, array('class' => 'diff'));
+ // Prepend diff to edit form
$form['#prefix'] = isset($form['#prefix']) ? $changes . $form['#prefix'] : $changes;
}
return $form;
@@ -538,3 +595,199 @@
return $output;
}
+
+/**
+ * Return a themed table. This is a modified version of theme_table, adding
+ * colgroup tag and col tag options.
+ *
+ * @param $header
+ * An array containing the table headers. Each element of the array can be
+ * either a localized string or an associative array with the following keys:
+ * - "data": The localized title of the table column.
+ * - "field": The database field represented in the table column (required if
+ * user is to be able to sort on this column).
+ * - "sort": A default sort order for this column ("asc" or "desc").
+ * - Any HTML attributes, such as "colspan", to apply to the column header cell.
+ * @param $rows
+ * An array of table rows. Every row is an array of cells, or an associative
+ * array with the following keys:
+ * - "data": an array of cells
+ * - Any HTML attributes, such as "class", to apply to the table row.
+ *
+ * Each cell can be either a string or an associative array with the following keys:
+ * - "data": The string to display in the table cell.
+ * - "header": Indicates this cell is a header.
+ * - Any HTML attributes, such as "colspan", to apply to the table cell.
+ *
+ * Here's an example for $rows:
+ * @verbatim
+ * $rows = array(
+ * // Simple row
+ * array(
+ * 'Cell 1', 'Cell 2', 'Cell 3'
+ * ),
+ * // Row with attributes on the row and some of its cells.
+ * array(
+ * 'data' => array('Cell 1', array('data' => 'Cell 2', 'colspan' => 2)), 'class' => 'funky'
+ * )
+ * );
+ * @endverbatim
+ *
+ * @param $attributes
+ * An array of HTML attributes to apply to the table tag.
+ * @param $caption
+ * A localized string to use for the tag.
+ * @param $cols
+ * An array of table colum groups. Every column group is an array of columns,
+ * or an associative array with the following keys:
+ * - "data": an array of cells
+ * - Any HTML attributes, such as "class", to apply to the table column group.
+ *
+ * Each column can be either an empty array or associative array with the following keys:
+ * - Any HTML attributes, such as "class", to apply to the table column group.
+ *
+ * Here's an example for $cols:
+ * @verbatim
+ * $cols = array(
+ * // Simple colgroup.
+ * array(),
+ * // Simple colgroup with attributes.
+ * array(
+ * 'data' => array(), 'colspan' => 2, 'style' => 'color: green;',
+ * ),
+ * // Simple colgroup with one col.
+ * array(
+ * array(),
+ * ),
+ * // Colgroup with attributes on the colgroup and some of its cols.
+ * array(
+ * 'data' => array(array('class' => 'diff-marker'), array('colspan' => 2)), 'class' => 'funky',
+ * ),
+ * );
+ * @endverbatim
+ *
+ * The HTML will look as follows:
+ * @verbatim
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ *
+ * ...
+ *
+ * @endverbatim
+ *
+ * @return
+ * An HTML string representing the table.
+ */
+function theme_diff_table($header, $rows, $attributes = array(), $caption = NULL, $cols = array()) {
+ $output = '\n";
+
+ if (isset($caption)) {
+ $output .= ''. $caption ."\n";
+ }
+
+ // Format the table columns:
+ if (count($cols)) {
+ foreach ($cols as $number => $col) {
+ $attributes = array();
+
+ // Check if we're dealing with a simple or complex column
+ if (isset($col['data'])) {
+ foreach ($col as $key => $value) {
+ if ($key == 'data') {
+ $cells = $value;
+ }
+ else {
+ $attributes[$key] = $value;
+ }
+ }
+ }
+ else {
+ $cells = $col;
+ }
+
+ // Build colgroup
+ if (is_array($cells) && count($cells)) {
+ $output .= ' ';
+ $i = 0;
+ foreach ($cells as $cell) {
+ $output .= ' ';
+ }
+ $output .= " \n";
+ }
+ else {
+ $output .= ' \n";
+ }
+ }
+ }
+
+ // Format the table header:
+ if (count($header)) {
+ $ts = tablesort_init($header);
+ $output .= ' ';
+ foreach ($header as $cell) {
+ $cell = tablesort_header($cell, $header, $ts);
+ $output .= _theme_table_cell($cell, TRUE);
+ }
+ $output .= "
\n";
+ }
+
+ // Format the table rows:
+ $output .= "\n";
+ if (count($rows)) {
+ $flip = array('even' => 'odd', 'odd' => 'even');
+ $class = 'even';
+ foreach ($rows as $number => $row) {
+ $attributes = array();
+
+ // Check if we're dealing with a simple or complex row
+ if (isset($row['data'])) {
+ foreach ($row as $key => $value) {
+ if ($key == 'data') {
+ $cells = $value;
+ }
+ else {
+ $attributes[$key] = $value;
+ }
+ }
+ }
+ else {
+ $cells = $row;
+ }
+
+ // Add odd/even class
+ $class = $flip[$class];
+ if (isset($attributes['class'])) {
+ $attributes['class'] .= ' '. $class;
+ }
+ else {
+ $attributes['class'] = $class;
+ }
+
+ // Build row
+ $output .= ' ';
+ $i = 0;
+ foreach ($cells as $cell) {
+ $cell = tablesort_cell($cell, $header, $ts, $i++);
+ $output .= _theme_table_cell($cell);
+ }
+ $output .= "
\n";
+ }
+ }
+
+ $output .= "
\n";
+ return $output;
+}