Passed
Pull Request — master (#416)
by no
02:43
created

SnakList::getHash()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

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