Completed
Push — master ( c0676d...e5a675 )
by
unknown
24s
created

StatementListPatcher::changeStatement()   D

Complexity

Conditions 9
Paths 24

Size

Total Lines 27
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

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