Completed
Pull Request — master (#713)
by Bekh-Ivanov
09:50
created

SnakList::hasSnakHash()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

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