MediaWiki  master
TableDiffFormatter.php
Go to the documentation of this file.
1 <?php
34 
38  private const SIDE_DELETED = 'deleted';
39  private const SIDE_ADDED = 'added';
40  private const SIDE_CLASSES = [
41  self::SIDE_DELETED => 'diff-side-deleted',
42  self::SIDE_ADDED => 'diff-side-added'
43  ];
44 
45  public function __construct() {
46  $this->leadingContextLines = 2;
47  $this->trailingContextLines = 2;
48  }
49 
55  public static function escapeWhiteSpace( $msg ) {
56  $msg = preg_replace( '/^ /m', "\u{00A0} ", $msg );
57  $msg = preg_replace( '/ $/m', " \u{00A0}", $msg );
58  $msg = preg_replace( '/ /', "\u{00A0} ", $msg );
59 
60  return $msg;
61  }
62 
71  protected function blockHeader( $xbeg, $xlen, $ybeg, $ylen ) {
72  // '<!--LINE \d+ -->' get replaced by a localised line number
73  // in DifferenceEngine::localiseLineNumbers
74  return Html::rawElement(
75  'tr',
76  [],
78  'td',
79  [ 'colspan' => '2', 'class' => 'diff-lineno', 'id' => 'mw-diff-left-l' . $xbeg ],
80  '<!--LINE ' . $xbeg . '-->'
81  ) .
82  "\n" .
84  'td',
85  [ 'colspan' => '2', 'class' => 'diff-lineno' ],
86  '<!--LINE ' . $ybeg . '-->'
87  )
88  ) . "\n";
89  }
90 
92  protected function startBlock( $header ) {
93  $this->writeOutput( $header );
94  }
95 
97  protected function endBlock() {
98  }
99 
105  protected function lines( $lines, $prefix = ' ', $color = 'white' ) {
106  }
107 
115  protected function addedLine( $line ) {
116  return $this->wrapLine( '+', [ 'diff-addedline', $this->getClassForSide( self::SIDE_ADDED ) ], $line );
117  }
118 
126  protected function deletedLine( $line ) {
127  return $this->wrapLine( '−', [ 'diff-deletedline', $this->getClassForSide( self::SIDE_DELETED ) ], $line );
128  }
129 
138  protected function contextLine( $line, string $side ) {
139  return $this->wrapLine( '', [ 'diff-context', $this->getClassForSide( $side ) ], $line );
140  }
141 
149  protected function wrapLine( $marker, $class, $line ) {
150  if ( $line !== '' ) {
151  // The <div> wrapper is needed for 'overflow: auto' style to scroll properly
152  $line = Html::rawElement( 'div', [], $this->escapeWhiteSpace( $line ) );
153  } else {
154  $line = Html::element( 'br' );
155  }
156 
157  $markerAttrs = [ 'class' => 'diff-marker' ];
158  if ( $marker ) {
159  $markerAttrs['data-marker'] = $marker;
160  }
161 
162  return Html::element( 'td', $markerAttrs ) .
163  Html::rawElement( 'td', [ 'class' => $class ], $line );
164  }
165 
170  protected function emptyLine( string $side ) {
171  return Html::element( 'td', [ 'colspan' => '2', 'class' => $this->getClassForSide( $side ) ] );
172  }
173 
179  protected function added( $lines ) {
180  foreach ( $lines as $line ) {
181  $this->writeOutput(
183  'tr',
184  [],
185  $this->emptyLine( self::SIDE_DELETED ) .
186  $this->addedLine(
188  'ins',
189  [ 'class' => 'diffchange' ],
190  $line
191  )
192  )
193  ) .
194  "\n"
195  );
196  }
197  }
198 
204  protected function deleted( $lines ) {
205  foreach ( $lines as $line ) {
206  $this->writeOutput(
208  'tr',
209  [],
210  $this->deletedLine(
212  'del',
213  [ 'class' => 'diffchange' ],
214  $line
215  )
216  ) .
217  $this->emptyLine( self::SIDE_ADDED )
218  ) .
219  "\n"
220  );
221  }
222  }
223 
229  protected function context( $lines ) {
230  foreach ( $lines as $line ) {
231  $this->writeOutput(
233  'tr',
234  [],
235  $this->contextLine( htmlspecialchars( $line ), self::SIDE_DELETED ) .
236  $this->contextLine( htmlspecialchars( $line ), self::SIDE_ADDED )
237  ) .
238  "\n"
239  );
240  }
241  }
242 
249  protected function changed( $orig, $closing ) {
250  $diff = new WordLevelDiff( $orig, $closing );
251  $del = $diff->orig();
252  $add = $diff->closing();
253 
254  # Notice that WordLevelDiff returns HTML-escaped output.
255  # Hence, we will be calling addedLine/deletedLine without HTML-escaping.
256 
257  $ndel = count( $del );
258  $nadd = count( $add );
259  $n = max( $ndel, $nadd );
260  for ( $i = 0; $i < $n; $i++ ) {
261  $delLine = $i < $ndel ? $this->deletedLine( $del[$i] ) : $this->emptyLine( self::SIDE_DELETED );
262  $addLine = $i < $nadd ? $this->addedLine( $add[$i] ) : $this->emptyLine( self::SIDE_ADDED );
263  $this->writeOutput(
265  'tr',
266  [],
267  $delLine . $addLine
268  ) .
269  "\n"
270  );
271  }
272  }
273 
281  private function getClassForSide( string $side ): string {
282  if ( !isset( self::SIDE_CLASSES[$side] ) ) {
283  throw new InvalidArgumentException( "Invalid diff side: $side" );
284  }
285  return self::SIDE_CLASSES[$side];
286  }
287 }
TableDiffFormatter\wrapLine
wrapLine( $marker, $class, $line)
Definition: TableDiffFormatter.php:149
TableDiffFormatter\deleted
deleted( $lines)
Writes all lines to the output buffer, each enclosed in .
Definition: TableDiffFormatter.php:204
TableDiffFormatter\escapeWhiteSpace
static escapeWhiteSpace( $msg)
Definition: TableDiffFormatter.php:55
TableDiffFormatter\blockHeader
blockHeader( $xbeg, $xlen, $ybeg, $ylen)
Definition: TableDiffFormatter.php:71
DiffFormatter
Base class for diff formatters.
Definition: DiffFormatter.php:36
TableDiffFormatter\getClassForSide
getClassForSide(string $side)
Get a class for the given diff side, or throw if the side is invalid.
Definition: TableDiffFormatter.php:281
WordLevelDiff
Performs a word-level diff on several lines.
Definition: WordLevelDiff.php:34
DiffFormatter\writeOutput
writeOutput( $text)
Writes a string to the output buffer.
Definition: DiffFormatter.php:159
TableDiffFormatter
MediaWiki default table style diff formatter.
Definition: TableDiffFormatter.php:33
TableDiffFormatter\contextLine
contextLine( $line, string $side)
HTML-escape parameter before calling this.
Definition: TableDiffFormatter.php:138
TableDiffFormatter\__construct
__construct()
Definition: TableDiffFormatter.php:45
TableDiffFormatter\addedLine
addedLine( $line)
HTML-escape parameter before calling this.
Definition: TableDiffFormatter.php:115
TableDiffFormatter\emptyLine
emptyLine(string $side)
Definition: TableDiffFormatter.php:170
TableDiffFormatter\SIDE_DELETED
const SIDE_DELETED
Constants for diff sides.
Definition: TableDiffFormatter.php:38
TableDiffFormatter\changed
changed( $orig, $closing)
Writes the two sets of lines to the output buffer, each enclosed in .
Definition: TableDiffFormatter.php:249
TableDiffFormatter\endBlock
endBlock()
Called at the end of a block of connected edits.This default implementation does nothing.
Definition: TableDiffFormatter.php:97
TableDiffFormatter\SIDE_CLASSES
const SIDE_CLASSES
Definition: TableDiffFormatter.php:40
TableDiffFormatter\deletedLine
deletedLine( $line)
HTML-escape parameter before calling this.
Definition: TableDiffFormatter.php:126
TableDiffFormatter\added
added( $lines)
Writes all lines to the output buffer, each enclosed in .
Definition: TableDiffFormatter.php:179
TableDiffFormatter\startBlock
startBlock( $header)
Called at the start of a block of connected edits.This default implementation writes the header and a...
Definition: TableDiffFormatter.php:92
$header
$header
Definition: updateCredits.php:37
$line
$line
Definition: mcc.php:119
TableDiffFormatter\SIDE_ADDED
const SIDE_ADDED
Definition: TableDiffFormatter.php:39
TableDiffFormatter\context
context( $lines)
Writes all lines to the output buffer, each enclosed in .
Definition: TableDiffFormatter.php:229
$lines
if(!file_exists( $CREDITS)) $lines
Definition: updateCredits.php:45
Html\rawElement
static rawElement( $element, $attribs=[], $contents='')
Returns an HTML element in a string.
Definition: Html.php:210
TableDiffFormatter\lines
lines( $lines, $prefix=' ', $color='white')
Definition: TableDiffFormatter.php:105
Html\element
static element( $element, $attribs=[], $contents='')
Identical to rawElement(), but HTML-escapes $contents (like Xml::element()).
Definition: Html.php:232