Completed
Pull Request — master (#439)
by no
14:39 queued 11:28
created

SnakList::__construct()   B

Complexity

Conditions 5
Paths 4

Size

Total Lines 13
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 5

Importance

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