Passed
Push — master ( 269d57...37045e )
by Marius
07:04
created

SnakDeserializer::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 1
CRAP Score 1

Importance

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