Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
90.48% covered (success)
90.48%
38 / 42
69.23% covered (warning)
69.23%
9 / 13
CRAP
0.00% covered (danger)
0.00%
0 / 1
BaseTextDiffer
90.48% covered (success)
90.48%
38 / 42
69.23% covered (warning)
69.23%
9 / 13
23.46
0.00% covered (danger)
0.00%
0 / 1
 setLocalizer
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getLocalizer
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 hasFormat
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 addRowWrapper
87.50% covered (warning)
87.50%
7 / 8
0.00% covered (danger)
0.00%
0 / 1
3.02
 validateFormats
66.67% covered (warning)
66.67%
2 / 3
0.00% covered (danger)
0.00%
0 / 1
2.15
 render
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 renderBatch
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
2
 doRenderBatch
n/a
0 / 0
n/a
0 / 0
0
 addModules
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getCacheKeys
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 localize
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getTablePrefixes
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getPreferredFormatBatch
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 localizeLineNumbers
94.12% covered (success)
94.12%
16 / 17
0.00% covered (danger)
0.00%
0 / 1
7.01
1<?php
2
3namespace MediaWiki\Diff\TextDiffer;
4
5use MediaWiki\Html\Html;
6use MediaWiki\Output\OutputPage;
7use MessageLocalizer;
8
9/**
10 * The base class for specific implementations of TextDiffer, apart from
11 * ManifoldTextDiffer.
12 *
13 * A place for protected utility functions.
14 *
15 * @since 1.41
16 */
17abstract class BaseTextDiffer implements TextDiffer {
18    /** @var MessageLocalizer */
19    private $localizer;
20
21    /**
22     * @param MessageLocalizer $localizer
23     */
24    public function setLocalizer(
25        MessageLocalizer $localizer
26    ) {
27        $this->localizer = $localizer;
28    }
29
30    /**
31     * Provide a MessageLocalizer, or throw if setLocalizer() has not been called.
32     *
33     * @return MessageLocalizer
34     */
35    protected function getLocalizer(): MessageLocalizer {
36        return $this->localizer;
37    }
38
39    public function hasFormat( string $format ): bool {
40        return in_array( $format, $this->getFormats(), true );
41    }
42
43    public function addRowWrapper( string $format, string $diffText ): string {
44        $context = $this->getFormatContext( $format );
45        if ( $context === self::CONTEXT_PLAIN ) {
46            return "<tr><td colspan=\"4\">$diffText</td></tr>";
47        } elseif ( $context === self::CONTEXT_PRE ) {
48            return '<tr><td colspan="4">' .
49                Html::element( 'pre', [], $diffText ) .
50                '</td></tr>';
51        } else {
52            return $diffText;
53        }
54    }
55
56    /**
57     * Throw an exception if any of the formats in the array is not supported.
58     *
59     * @param string[] $formats
60     */
61    protected function validateFormats( $formats ) {
62        $badFormats = array_diff( $formats, $this->getFormats() );
63        if ( $badFormats ) {
64            throw new \InvalidArgumentException( 'The requested format is not supported by this engine' );
65        }
66    }
67
68    public function render( string $oldText, string $newText, string $format ): string {
69        $result = $this->renderBatch( $oldText, $newText, [ $format ] );
70        return reset( $result );
71    }
72
73    public function renderBatch( string $oldText, string $newText, array $formats ): array {
74        $this->validateFormats( $formats );
75        if ( !count( $formats ) ) {
76            return [];
77        }
78        return $this->doRenderBatch( $oldText, $newText, $formats );
79    }
80
81    /**
82     * Subclasses should override this to render diffs in the specified formats.
83     * The $formats array is guaranteed to not be empty and to contain only
84     * formats supported by the subclass.
85     *
86     * @param string $oldText
87     * @param string $newText
88     * @param array $formats
89     * @return array
90     */
91    abstract protected function doRenderBatch( string $oldText, string $newText, array $formats ): array;
92
93    public function addModules( OutputPage $out, string $format ): void {
94    }
95
96    public function getCacheKeys( array $formats ): array {
97        return [];
98    }
99
100    public function localize( string $format, string $diff, array $options = [] ): string {
101        return $diff;
102    }
103
104    public function getTablePrefixes( string $format ): array {
105        return [];
106    }
107
108    public function getPreferredFormatBatch( string $format ): array {
109        return [ $format ];
110    }
111
112    /**
113     * Replace a common convention for language-independent line numbers with
114     * the text in the language of the current localizer.
115     *
116     * @param string $text
117     * @param bool $reducedLineNumbers
118     *
119     * @return string
120     */
121    protected function localizeLineNumbers(
122        $text, $reducedLineNumbers
123    ) {
124        // Inline diffs.
125        $text = preg_replace_callback( '/<!-- LINES (\d+),(\d+) -->/',
126            function ( array $matches ) use ( $reducedLineNumbers ) {
127                if ( $matches[1] === '1' && $matches[2] === '1' && $reducedLineNumbers ) {
128                    return '';
129                }
130                $msg = $matches[1] === $matches[2]
131                    ? 'lineno'
132                    : 'lineno-inline';
133                return $this->getLocalizer()->msg( $msg )
134                    ->numParams( $matches[1], $matches[2] )
135                    ->escaped();
136            }, $text );
137
138        // Table diffs.
139        return preg_replace_callback( '/<!--LINE (\d+)-->/',
140            function ( array $matches ) use ( $reducedLineNumbers ) {
141                if ( $matches[1] === '1' && $reducedLineNumbers ) {
142                    return '';
143                }
144                return $this->getLocalizer()->msg( 'lineno' )->numParams( $matches[1] )->escaped();
145            }, $text );
146    }
147
148}