Passed
Push — T178651 ( ff36ef )
by no
02:55
created

SnakDeserializer::hasSnakType()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

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