BasicDiffView::generateChangeOpHtml()   A
last analyzed

Complexity

Conditions 4
Paths 6

Size

Total Lines 20

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 20
rs 9.6
c 0
b 0
f 0
cc 4
nc 6
nop 3
1
<?php
2
3
namespace Wikibase\Repo\Diff;
4
5
use Diff\DiffOp\Diff\Diff;
6
use Diff\DiffOp\DiffOp;
7
use Diff\DiffOp\DiffOpAdd;
8
use Diff\DiffOp\DiffOpChange;
9
use Diff\DiffOp\DiffOpRemove;
10
use Html;
11
use MWException;
12
13
/**
14
 * Class for generating views of DiffOp objects.
15
 *
16
 * @license GPL-2.0-or-later
17
 */
18
class BasicDiffView implements DiffView {
19
20
	/**
21
	 * @var string[]
22
	 */
23
	private $path;
24
25
	/**
26
	 * @var Diff
27
	 */
28
	private $diff;
29
30
	/**
31
	 * @param string[] $path
32
	 * @param Diff $diff
33
	 */
34
	public function __construct( array $path, Diff $diff ) {
35
		$this->path = $path;
36
		$this->diff = $diff;
37
	}
38
39
	/**
40
	 * Builds and returns the HTML to represent the Diff.
41
	 *
42
	 * @return string
43
	 */
44
	public function getHtml() {
45
		return $this->generateOpHtml( $this->path, $this->diff );
46
	}
47
48
	/**
49
	 * Does the actual work.
50
	 *
51
	 * @param string[] $path
52
	 * @param DiffOp $op
53
	 *
54
	 * @return string
55
	 * @throws MWException
56
	 */
57
	protected function generateOpHtml( array $path, DiffOp $op ) {
58
		if ( $op->isAtomic() ) {
59
			$localizedPath = $path;
60
61
			$html = $this->generateDiffHeaderHtml( implode( ' / ', $localizedPath ) );
62
63
			//TODO: no path, but localized section title
64
65
			//FIXME: complex objects as values?
66
			if ( $op->getType() === 'add' ) {
67
				/** @var DiffOpAdd $op */
68
				'@phan-var DiffOpAdd $op';
69
				$html .= $this->generateChangeOpHtml( null, $op->getNewValue(), $path );
70
			} elseif ( $op->getType() === 'remove' ) {
71
				/** @var DiffOpRemove $op */
72
				'@phan-var DiffOpRemove $op';
73
				$html .= $this->generateChangeOpHtml( $op->getOldValue(), null, $path );
74
			} elseif ( $op->getType() === 'change' ) {
75
				/** @var DiffOpChange $op */
76
				'@phan-var DiffOpChange $op';
77
				$html .= $this->generateChangeOpHtml( $op->getOldValue(), $op->getNewValue(), $path );
78
			} else {
79
				throw new MWException( 'Invalid diffOp type' );
80
			}
81
		} else {
82
			$html = '';
83
			// @phan-suppress-next-line PhanTypeNoPropertiesForeach
84
			foreach ( $op as $key => $subOp ) {
0 ignored issues
show
Bug introduced by
The expression $op of type object<Diff\DiffOp\DiffOp> is not traversable.
Loading history...
85
				$html .= $this->generateOpHtml(
86
					array_merge( $path, [ $key ] ),
87
					$subOp
88
				);
89
			}
90
		}
91
92
		return $html;
93
	}
94
95
	/**
96
	 * Generates HTML for an change diffOp
97
	 *
98
	 * @param string|null $oldValue
99
	 * @param string|null $newValue
100
	 * @param string[] $path
101
	 *
102
	 * @return string
103
	 */
104
	protected function generateChangeOpHtml( $oldValue, $newValue, array $path ) {
105
		//TODO: use WordLevelDiff!
106
		$html = Html::openElement( 'tr' );
107
		if ( $oldValue !== null ) {
108
			$html .= Html::rawElement( 'td', [ 'class' => 'diff-marker' ], '-' );
109
			$html .= Html::rawElement( 'td', [ 'class' => 'diff-deletedline' ],
110
				Html::rawElement( 'div', [], $this->getDeletedLine( $oldValue, $path ) ) );
111
		}
112
		if ( $newValue !== null ) {
113
			if ( $oldValue === null ) {
114
				$html .= Html::rawElement( 'td', [ 'colspan' => '2' ], '&nbsp;' );
115
			}
116
			$html .= Html::rawElement( 'td', [ 'class' => 'diff-marker' ], '+' );
117
			$html .= Html::rawElement( 'td', [ 'class' => 'diff-addedline' ],
118
				Html::rawElement( 'div', [], $this->getAddedLine( $newValue, $path ) ) );
119
		}
120
		$html .= Html::closeElement( 'tr' );
121
122
		return $html;
123
	}
124
125
	/**
126
	 * @param string $value
127
	 * @param string[] $path
128
	 *
129
	 * @return string
130
	 */
131
	private function getDeletedLine( $value, array $path ) {
132
		return $this->getChangedLine( 'del', $value, $path );
133
	}
134
135
	/**
136
	 * @param string $value
137
	 * @param string[] $path
138
	 *
139
	 * @return string
140
	 */
141
	private function getAddedLine( $value, array $path ) {
142
		return $this->getChangedLine( 'ins', $value, $path );
143
	}
144
145
	/**
146
	 * @param string $tag
147
	 * @param string $value
148
	 * @param string[] $path
149
	 *
150
	 * @return string
151
	 */
152
	private function getChangedLine( $tag, $value, array $path ) {
0 ignored issues
show
Unused Code introduced by
The parameter $path is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
153
		return Html::element( $tag, [ 'class' => 'diffchange diffchange-inline' ], $value );
154
	}
155
156
	/**
157
	 * Generates HTML for the header of the diff operation
158
	 *
159
	 * @param string $name
160
	 *
161
	 * @return string
162
	 */
163
	protected function generateDiffHeaderHtml( $name ) {
164
		$html = Html::openElement( 'tr' );
165
		$html .= Html::element( 'td', [ 'colspan' => '2', 'class' => 'diff-lineno' ], $name );
166
		$html .= Html::element( 'td', [ 'colspan' => '2', 'class' => 'diff-lineno' ], $name );
167
		$html .= Html::closeElement( 'tr' );
168
169
		return $html;
170
	}
171
172
}
173