MediaWiki REL1_37
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 [],
77 Html::rawElement(
78 'td',
79 [ 'colspan' => '2', 'class' => 'diff-lineno', 'id' => 'mw-diff-left-l' . $xbeg ],
80 '<!--LINE ' . $xbeg . '-->'
81 ) .
82 "\n" .
83 Html::rawElement(
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(
182 Html::rawElement(
183 'tr',
184 [],
185 $this->emptyLine( self::SIDE_DELETED ) .
186 $this->addedLine(
187 Html::element(
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(
207 Html::rawElement(
208 'tr',
209 [],
210 $this->deletedLine(
211 Html::element(
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(
232 Html::rawElement(
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(
264 Html::rawElement(
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}
if(ini_get('mbstring.func_overload')) if(!defined('MW_ENTRY_POINT'))
Pre-config setup: Before loading LocalSettings.php.
Definition Setup.php:88
Base class for diff formatters.
writeOutput( $text)
Writes a string to the output buffer.
MediaWiki default table style diff formatter.
deletedLine( $line)
HTML-escape parameter before calling this.
startBlock( $header)
Called at the start of a block of connected edits.This default implementation writes the header and a...
wrapLine( $marker, $class, $line)
const SIDE_DELETED
Constants for diff sides.
added( $lines)
Writes all lines to the output buffer, each enclosed in .
changed( $orig, $closing)
Writes the two sets of lines to the output buffer, each enclosed in .
lines( $lines, $prefix=' ', $color='white')
blockHeader( $xbeg, $xlen, $ybeg, $ylen)
endBlock()
Called at the end of a block of connected edits.This default implementation does nothing.
static escapeWhiteSpace( $msg)
addedLine( $line)
HTML-escape parameter before calling this.
contextLine( $line, string $side)
HTML-escape parameter before calling this.
context( $lines)
Writes all lines to the output buffer, each enclosed in .
deleted( $lines)
Writes all lines to the output buffer, each enclosed in .
getClassForSide(string $side)
Get a class for the given diff side, or throw if the side is invalid.
Performs a word-level diff on several lines.
$line
Definition mcc.php:119
if(!file_exists( $CREDITS)) $lines
$header