Completed
Pull Request — master (#439)
by no
03:24
created

SnakList::__construct()   A

Complexity

Conditions 4
Paths 3

Size

Total Lines 9
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 4

Importance

Changes 1
Bugs 0 Features 1
Metric Value
c 1
b 0
f 1
dl 0
loc 9
ccs 2
cts 2
cp 1
rs 9.2
cc 4
eloc 5
nc 3
nop 1
crap 4
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 $index => $snak ) {
33
			$this->setElement( $index, $snak );
34
		}
35
	}
36
37
	/**
38
	 * @see GenericArrayObject::getObjectType
39
	 *
40 3
	 * @since 0.1
41 3
	 *
42
	 * @return string
43
	 */
44
	public function getObjectType() {
45
		return 'Wikibase\DataModel\Snak\Snak';
46
	}
47
48
	/**
49
	 * @see Snaks::hasSnakHash
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
	 * @see Snaks::removeSnakHash
63
	 *
64 10
	 * @since 0.1
65 10
	 *
66
	 * @param string $snakHash
67
	 */
68
	public function removeSnakHash( $snakHash ) {
69
		$this->removeByElementHash( $snakHash );
70
	}
71
72
	/**
73
	 * @see Snaks::addSnak
74
	 *
75
	 * @since 0.1
76
	 *
77 11
	 * @param Snak $snak
78 11
	 *
79
	 * @return boolean Indicates if the snak was added or not.
80
	 */
81
	public function addSnak( Snak $snak ) {
82
		return $this->addElement( $snak );
83
	}
84
85
	/**
86
	 * @see Snaks::hasSnak
87
	 *
88 13
	 * @since 0.1
89 13
	 *
90 13
	 * @param Snak $snak
91
	 *
92
	 * @return boolean
93
	 */
94
	public function hasSnak( Snak $snak ) {
95
		return $this->hasElementHash( $snak->getHash() );
96
	}
97
98
	/**
99
	 * @see Snaks::removeSnak
100
	 *
101
	 * @since 0.1
102
	 *
103
	 * @param Snak $snak
104
	 */
105
	public function removeSnak( Snak $snak ) {
106
		$this->removeByElementHash( $snak->getHash() );
107
	}
108
109
	/**
110
	 * @see Snaks::getSnak
111
	 *
112 7
	 * @since 0.1
113 7
	 *
114 7
	 * @param string $snakHash
115
	 *
116
	 * @return Snak|bool
117
	 */
118
	public function getSnak( $snakHash ) {
119
		return $this->getByElementHash( $snakHash );
120
	}
121
122
	/**
123
	 * @see HashArray::getHash
124 7
	 *
125 7
	 * @since 0.5
126 7
	 *
127
	 * @return string
128 7
	 */
129 6
	public function getHash() {
130 5
		$hasher = new MapValueHasher();
131 5
		return $hasher->hash( $this );
132 5
	}
133 7
134 7
	/**
135
	 * Orders the snaks in the list grouping them by property.
136
	 *
137
	 * @param string[] $order List of serliazed property ids to order by.
138
	 *
139 5
	 * @since 0.5
140 5
	 */
141 5
	public function orderByProperty( $order = array() ) {
142 5
		$snaksByProperty = $this->getSnaksByProperty();
143 5
		$orderedProperties = array_unique( array_merge( $order, array_keys( $snaksByProperty ) ) );
144 5
145
		foreach ( $orderedProperties as $property ) {
146
			if ( array_key_exists( $property, $snaksByProperty ) ) {
147
				$snaks = $snaksByProperty[$property];
148
				$this->moveSnaksToBottom( $snaks );
149
			}
150
		}
151
	}
152 7
153 7
	/**
154
	 * @param Snak[] $snaks to remove and re add
155 7
	 */
156
	private function moveSnaksToBottom( array $snaks ) {
157 5
		foreach ( $snaks as $snak ) {
158 5
			$this->removeSnak( $snak );
159 5
			$this->addSnak( $snak );
160 5
		}
161 5
	}
162 7
163
	/**
164 7
	 * Gets the snaks in the current object in an array
165
	 * grouped by property id
166
	 *
167
	 * @return array[]
168
	 */
169
	private function getSnaksByProperty() {
170
		$snaksByProperty = array();
171
172
		foreach ( $this as $snak ) {
173
			/** @var Snak $snak */
174
			$propertyId = $snak->getPropertyId()->getSerialization();
175
			if ( !isset( $snaksByProperty[$propertyId] ) ) {
176
				$snaksByProperty[$propertyId] = array();
177
			}
178
			$snaksByProperty[$propertyId][] = $snak;
179
		}
180
181
		return $snaksByProperty;
182
	}
183
184
}
185