SnakDeserializer   A
last analyzed

Complexity

Total Complexity 27

Size/Duplication

Total Lines 164
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 11

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
wmc 27
lcom 1
cbo 11
dl 0
loc 164
ccs 67
cts 67
cp 1
rs 10
c 0
b 0
f 0

13 Methods

Rating   Name   Duplication   Size   Complexity  
A newNoValueSnak() 0 3 1
A __construct() 0 7 1
A isDeserializerFor() 0 5 3
A hasSnakType() 0 3 1
A hasCorrectSnakType() 0 3 1
A deserialize() 0 6 1
A getDeserialized() 0 10 3
A newSomeValueSnak() 0 3 1
A newValueSnak() 0 8 1
A deserializeDataValue() 0 15 5
A deserializePropertyId() 0 21 3
A assertCanDeserialize() 0 13 4
A requireAttribute() 0 7 2
1
<?php
2
3
namespace Wikibase\DataModel\Deserializers;
4
5
use DataValues\DataValue;
6
use DataValues\Deserializers\DataValueDeserializer;
7
use DataValues\UnDeserializableValue;
8
use Deserializers\Deserializer;
9
use Deserializers\DispatchableDeserializer;
10
use Deserializers\Exceptions\DeserializationException;
11
use Deserializers\Exceptions\InvalidAttributeException;
12
use Deserializers\Exceptions\MissingAttributeException;
13
use Deserializers\Exceptions\MissingTypeException;
14
use Deserializers\Exceptions\UnsupportedTypeException;
15
use Wikibase\DataModel\Entity\EntityIdParser;
16
use Wikibase\DataModel\Entity\EntityIdParsingException;
17
use Wikibase\DataModel\Entity\PropertyId;
18
use Wikibase\DataModel\Snak\PropertyNoValueSnak;
19
use Wikibase\DataModel\Snak\PropertySomeValueSnak;
20
use Wikibase\DataModel\Snak\PropertyValueSnak;
21
22
/**
23
 * Package private
24
 *
25
 * @license GPL-2.0-or-later
26
 * @author Jeroen De Dauw < [email protected] >
27
 * @author Thomas Pellissier Tanon
28
 */
29
class SnakDeserializer implements DispatchableDeserializer {
30
31
	/**
32
	 * @var Deserializer
33
	 */
34
	private $dataValueDeserializer;
35
36
	/**
37
	 * @var EntityIdParser
38
	 */
39
	private $propertyIdParser;
40
41 69
	public function __construct(
42
		EntityIdParser $propertyIdParser,
43
		Deserializer $dataValueDeserializer
44
	) {
45 69
		$this->dataValueDeserializer = $dataValueDeserializer;
46 69
		$this->propertyIdParser = $propertyIdParser;
47 69
	}
48
49
	/**
50
	 * @see Deserializer::isDeserializerFor
51
	 *
52
	 * @param mixed $serialization
53
	 *
54
	 * @return bool
55
	 */
56 7
	public function isDeserializerFor( $serialization ) {
57 7
		return is_array( $serialization )
58 7
			&& $this->hasSnakType( $serialization )
59 7
			&& $this->hasCorrectSnakType( $serialization );
60
	}
61
62 44
	private function hasSnakType( $serialization ) {
63 44
		return array_key_exists( 'snaktype', $serialization );
64
	}
65
66 40
	private function hasCorrectSnakType( $serialization ) {
67 40
		return in_array( $serialization['snaktype'], [ 'novalue', 'somevalue', 'value' ] );
68
	}
69
70
	/**
71
	 * @see Deserializer::deserialize
72
	 *
73
	 * @param array $serialization
74
	 *
75
	 * @throws DeserializationException
76
	 * @return PropertyNoValueSnak|PropertySomeValueSnak|PropertyValueSnak
77
	 */
78 39
	public function deserialize( $serialization ) {
79 39
		$this->assertCanDeserialize( $serialization );
80 35
		$this->requireAttribute( $serialization, 'property' );
81
82 34
		return $this->getDeserialized( $serialization );
83
	}
84
85
	/**
86
	 * @see SnakDeserializer::hasCorrectSnakType
87
	 *
88
	 * @param array $serialization
89
	 *
90
	 * @throws InvalidAttributeException
91
	 * @return PropertyNoValueSnak|PropertySomeValueSnak|PropertyValueSnak
92
	 */
93 34
	private function getDeserialized( array $serialization ) {
94 34
		switch ( $serialization['snaktype'] ) {
95 34
			case 'novalue':
96 21
				return $this->newNoValueSnak( $serialization );
97 18
			case 'somevalue':
98 8
				return $this->newSomeValueSnak( $serialization );
99
			default:
100 10
				return $this->newValueSnak( $serialization );
101
		}
102
	}
103
104 21
	private function newNoValueSnak( array $serialization ) {
105 21
		return new PropertyNoValueSnak( $this->deserializePropertyId( $serialization['property'] ) );
106
	}
107
108 8
	private function newSomeValueSnak( array $serialization ) {
109 8
		return new PropertySomeValueSnak( $this->deserializePropertyId( $serialization['property'] ) );
110
	}
111
112 10
	private function newValueSnak( array $serialization ) {
113 10
		$this->requireAttribute( $serialization, 'datavalue' );
114
115 9
		return new PropertyValueSnak(
116 9
			$this->deserializePropertyId( $serialization['property'] ),
117 9
			$this->deserializeDataValue( $serialization['datavalue'] )
118
		);
119
	}
120
121
	/**
122
	 * @param array $serialization
123
	 *
124
	 * @return DataValue
125
	 */
126 9
	private function deserializeDataValue( $serialization ) {
127
		try {
128 9
			return $this->dataValueDeserializer->deserialize( $serialization );
129 3
		} catch ( DeserializationException $ex ) {
130 3
			$value = isset( $serialization[DataValueDeserializer::VALUE_KEY] )
131 3
				? $serialization[DataValueDeserializer::VALUE_KEY]
132 3
				: null;
133 3
			$type = isset( $serialization[DataValueDeserializer::TYPE_KEY] )
134 3
				? $serialization[DataValueDeserializer::TYPE_KEY]
135 3
				: null;
136 3
			$error = isset( $serialization['error'] ) ? $serialization['error'] : $ex->getMessage();
137
138 3
			return new UnDeserializableValue( $value, $type, $error );
139
		}
140
	}
141
142
	/**
143
	 * @param string $serialization
144
	 *
145
	 * @throws InvalidAttributeException
146
	 * @return PropertyId
147
	 */
148 33
	private function deserializePropertyId( $serialization ) {
149
		try {
150 33
			$id = $this->propertyIdParser->parse( $serialization );
151 1
		} catch ( EntityIdParsingException $ex ) {
152 1
			throw new InvalidAttributeException(
153 1
				'property',
154
				$serialization,
155 1
				"'$serialization' is not a valid property ID"
156
			);
157
		}
158
159 32
		if ( $id instanceof PropertyId ) {
160 31
			return $id;
161
		}
162
163 1
		throw new InvalidAttributeException(
164 1
			'property',
165
			$serialization,
166 1
			"'$serialization' is not a property ID"
167
		);
168
	}
169
170 39
	private function assertCanDeserialize( $serialization ) {
171 39
		if ( !is_array( $serialization ) ) {
172 1
			throw new DeserializationException( 'The snak serialization should be an array' );
173
		}
174
175 38
		if ( !$this->hasSnakType( $serialization ) ) {
176 2
			throw new MissingTypeException();
177
		}
178
179 36
		if ( !$this->hasCorrectSnakType( $serialization ) ) {
180 1
			throw new UnsupportedTypeException( $serialization['snaktype'] );
181
		}
182 35
	}
183
184 35
	private function requireAttribute( array $array, $attributeName ) {
185 35
		if ( !array_key_exists( $attributeName, $array ) ) {
186 2
			throw new MissingAttributeException(
187 2
				$attributeName
188
			);
189
		}
190 34
	}
191
192
}
193