Passed
Push — unDocs ( 1b36dd )
by no
04:21
created

SnakDeserializer::deserializePropertyId()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 13
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 2

Importance

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