Completed
Pull Request — master (#713)
by Bekh-Ivanov
33:57 queued 30:36
created

SnakList::equals()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 8
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 3

Importance

Changes 0
Metric Value
dl 0
loc 8
ccs 4
cts 4
cp 1
rs 9.4285
c 0
b 0
f 0
cc 3
eloc 5
nc 3
nop 1
crap 3
1
<?php
2
3
namespace Wikibase\DataModel\Snak;
4
5
use Comparable;
6
use InvalidArgumentException;
7
use Traversable;
8
use Wikibase\DataModel\HashArray;
9
use Wikibase\DataModel\Internal\MapValueHasher;
10
11
/**
12
 * List of Snak objects.
13
 * Indexes the snaks by hash and ensures no more the one snak with the same hash are in the list.
14
 *
15
 * @since 0.1
16
 *
17
 * @license GPL-2.0+
18
 * @author Jeroen De Dauw < [email protected] >
19
 * @author Addshore
20
 */
21
class SnakList extends HashArray implements Comparable {
22
23
	/**
24
	 * @param Snak[]|Traversable $snaks
25
	 *
26
	 * @throws InvalidArgumentException
27 7
	 */
28 7
	public function __construct( $snaks = [] ) {
29
		if ( !is_array( $snaks ) && !( $snaks instanceof Traversable ) ) {
30
			throw new InvalidArgumentException( '$snaks must be an array or an instance of Traversable' );
31
		}
32
33
		foreach ( $snaks as $index => $snak ) {
34
			$this->setElement( $index, $snak );
35
		}
36
	}
37
38
	/**
39
	 * @see GenericArrayObject::getObjectType
40 3
	 *
41 3
	 * @since 0.1
42
	 *
43
	 * @return string
44
	 */
45
	public function getObjectType() {
46
		return 'Wikibase\DataModel\Snak\Snak';
47
	}
48
49
	/**
50
	 * @since 0.1
51 5
	 *
52 5
	 * @param string $snakHash
53 5
	 *
54
	 * @return boolean
55
	 */
56
	public function hasSnakHash( $snakHash ) {
57
		return $this->hasElementHash( $snakHash );
58
	}
59
60
	/**
61
	 * @since 0.1
62
	 *
63
	 * @param string $snakHash
64 10
	 */
65 10
	public function removeSnakHash( $snakHash ) {
66
		$this->removeByElementHash( $snakHash );
67
	}
68
69
	/**
70
	 * @since 0.1
71
	 *
72
	 * @param Snak $snak
73
	 *
74
	 * @return boolean Indicates if the snak was added or not.
75
	 */
76
	public function addSnak( Snak $snak ) {
77 11
		return $this->addElement( $snak );
78 11
	}
79
80
	/**
81
	 * @since 0.1
82
	 *
83
	 * @param Snak $snak
84
	 *
85
	 * @return boolean
86
	 */
87
	public function hasSnak( Snak $snak ) {
88 13
		return $this->hasElementHash( $snak->getHash() );
89 13
	}
90 13
91
	/**
92
	 * @since 0.1
93
	 *
94
	 * @param Snak $snak
95
	 */
96
	public function removeSnak( Snak $snak ) {
97
		$this->removeByElementHash( $snak->getHash() );
98
	}
99
100
	/**
101
	 * @since 0.1
102
	 *
103
	 * @param string $snakHash
104
	 *
105
	 * @return Snak|bool
106
	 */
107
	public function getSnak( $snakHash ) {
108
		return $this->getByElementHash( $snakHash );
109
	}
110
111
	/**
112 7
	 * @see HashArray::getHash
113 7
	 *
114 7
	 * @since 0.5
115
	 *
116
	 * @return string
117
	 */
118
	public function getHash() {
119
		$hasher = new MapValueHasher();
120
		return $hasher->hash( $this );
121
	}
122
123
	/**
124 7
	 * @see Comparable::equals
125 7
	 *
126 7
	 * The comparison is done purely value based, ignoring the order of the elements in the array.
127
	 *
128 7
	 * @since 0.3
129 6
	 *
130 5
	 * @param mixed $target
131 5
	 *
132 5
	 * @return bool
133 7
	 */
134 7
	public function equals( $target ) {
135
		if ( $this === $target ) {
136
			return true;
137
		}
138
139 5
		return $target instanceof self
140 5
			&& $this->getHash() === $target->getHash();
141 5
	}
142 5
143 5
	/**
144 5
	 * Orders the snaks in the list grouping them by property.
145
	 *
146
	 * @param string[] $order List of serliazed property ids to order by.
147
	 *
148
	 * @since 0.5
149
	 */
150
	public function orderByProperty( array $order = [] ) {
151
		$snaksByProperty = $this->getSnaksByProperty();
152 7
		$orderedProperties = array_unique( array_merge( $order, array_keys( $snaksByProperty ) ) );
153 7
154
		foreach ( $orderedProperties as $property ) {
155 7
			if ( array_key_exists( $property, $snaksByProperty ) ) {
156
				$snaks = $snaksByProperty[$property];
157 5
				$this->moveSnaksToBottom( $snaks );
158 5
			}
159 5
		}
160 5
	}
161 5
162 7
	/**
163
	 * @param Snak[] $snaks to remove and re add
164 7
	 */
165
	private function moveSnaksToBottom( array $snaks ) {
166
		foreach ( $snaks as $snak ) {
167
			$this->removeSnak( $snak );
168
			$this->addSnak( $snak );
169
		}
170
	}
171
172
	/**
173
	 * Gets the snaks in the current object in an array
174
	 * grouped by property id
175
	 *
176
	 * @return array[]
177
	 */
178
	private function getSnaksByProperty() {
179
		$snaksByProperty = [];
180
181
		foreach ( $this as $snak ) {
182
			/** @var Snak $snak */
183
			$propertyId = $snak->getPropertyId()->getSerialization();
184
			if ( !isset( $snaksByProperty[$propertyId] ) ) {
185
				$snaksByProperty[$propertyId] = [];
186
			}
187
			$snaksByProperty[$propertyId][] = $snak;
188
		}
189
190
		return $snaksByProperty;
191
	}
192
193
}
194