Completed
Push — master ( 7247aa...c0676d )
by
unknown
03:08
created

StatementListPatcher::changeStatement()   D

Complexity

Conditions 9
Paths 24

Size

Total Lines 27
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 90

Importance

Changes 1
Bugs 1 Features 0
Metric Value
c 1
b 1
f 0
dl 0
loc 27
ccs 0
cts 0
cp 0
rs 4.909
cc 9
eloc 16
nc 24
nop 3
crap 90
1
<?php
2
3
namespace Wikibase\DataModel\Services\Diff\Internal;
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 Diff\Patcher\PatcherException;
11
use InvalidArgumentException;
12
use Wikibase\DataModel\Statement\Statement;
13
use Wikibase\DataModel\Statement\StatementList;
14
15
/**
16
 * TODO: Class must be public.
17
 * TODO: Should this support actual edit conflict detection?
18
 *
19
 * Package private.
20
 *
21
 * @since 1.0
22
 *
23
 * @license GPL-2.0+
24
 * @author Jeroen De Dauw < [email protected] >
25
 * @author Thiemo Mättig
26
 */
27 2
class StatementListPatcher {
28 2
29
	/**
30 2
	 * @since 3.6
31 1
	 *
32 1
	 * @param StatementList $statements
33
	 * @param Diff $patch
34 2
	 *
35 2
	 * @throws PatcherException
36
	 */
37
	public function patchStatementList( StatementList $statements, Diff $patch ) {
38
		/** @var DiffOp $diffOp */
39
		foreach ( $patch as $diffOp ) {
40
			switch ( true ) {
41
				case $diffOp instanceof DiffOpAdd:
42
					/** @var DiffOpAdd $diffOp */
43
					/** @var Statement $statement */
44 2
					$statement = $diffOp->getNewValue();
45 2
					$guid = $statement->getGuid();
46
					if ( $statements->getFirstStatementWithGuid( $guid ) === null ) {
47
						$statements->addStatement( $statement );
48
					}
49
					break;
50 2
51 1
				case $diffOp instanceof DiffOpChange:
52 2
					/** @var DiffOpChange $diffOp */
53
					/** @var Statement $oldStatement */
54 2
					/** @var Statement $newStatement */
55
					$oldStatement = $diffOp->getOldValue();
56 2
					$newStatement = $diffOp->getNewValue();
57 1
					$this->changeStatement( $statements, $oldStatement->getGuid(), $newStatement );
58 2
					break;
59
60 2
				case $diffOp instanceof DiffOpRemove:
61
					/** @var DiffOpRemove $diffOp */
62
					/** @var Statement $statement */
63
					$statement = $diffOp->getOldValue();
64
					$statements->removeStatementsWithGuid( $statement->getGuid() );
65
					break;
66
67
				default:
68
					throw new PatcherException( 'Invalid statement list diff' );
69
			}
70
		}
71
	}
72
73
	/**
74
	 * @param StatementList $statements
75
	 * @param string|null $oldGuid
76
	 * @param Statement $newStatement
77
	 */
78
	private function changeStatement( StatementList $statements, $oldGuid, Statement $newStatement ) {
79
		$replacements = array();
80
81
		foreach ( $statements->toArray() as $statement ) {
82
			$guid = $statement->getGuid();
83
84
			// Collect all elements starting from the first with the same GUID
85
			if ( $replacements !== array() ) {
86
				$guid === null
87
					? $replacements[] = $statement
88
					: $replacements[$guid] = $statement;
89
			} elseif ( $guid === $oldGuid ) {
90
				$guid === null
91
					? $replacements[] = $newStatement
92
					: $replacements[$guid] = $newStatement;
93
			}
94
		}
95
96
		// Remove all starting from the one that should be replaced
97
		foreach ( $replacements as $guid => $statement ) {
98
			$statements->removeStatementsWithGuid( is_int( $guid ) ? null : $guid );
99
		}
100
		// Re-add all starting from the new one
101
		foreach ( $replacements as $statement ) {
102
			$statements->addStatement( $statement );
103
		}
104
	}
105
106
	/**
107
	 * @deprecated since 3.6, use patchStatementList instead
108
	 *
109
	 * @param StatementList $statements
110
	 * @param Diff $patch
111
	 *
112
	 * @throws InvalidArgumentException
113
	 * @return StatementList
114
	 */
115
	public function getPatchedStatementList( StatementList $statements, Diff $patch ) {
116
		$patched = clone $statements;
117
		$this->patchStatementList( $patched, $patch );
118
		return $patched;
119
	}
120
121
}
122