Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
55 / 55
100.00% covered (success)
100.00%
13 / 13
CRAP
100.00% covered (success)
100.00%
1 / 1
ViolationMessageDeserializer
100.00% covered (success)
100.00%
55 / 55
100.00% covered (success)
100.00%
13 / 13
22
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 unabbreviateViolationMessageKey
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 deserialize
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
2
 deserializeArgument
100.00% covered (success)
100.00%
26 / 26
100.00% covered (success)
100.00%
1 / 1
2
 deserializeStringByIdentity
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 deserializeEntityId
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 deserializeEntityIdList
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 deserializeItemIdSnakValue
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
4
 deserializeItemIdSnakValueList
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 deserializeDataValue
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 deserializeContextType
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
5
 deserializeContextTypeList
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 deserializeMultilingualText
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2
3namespace WikibaseQuality\ConstraintReport\ConstraintCheck\Message;
4
5use DataValues\DataValue;
6use DataValues\MultilingualTextValue;
7use Deserializers\Deserializer;
8use InvalidArgumentException;
9use LogicException;
10use Wikibase\DataModel\Entity\EntityId;
11use Wikibase\DataModel\Entity\EntityIdParser;
12use Wikibase\Lib\DataValueFactory;
13use WikibaseQuality\ConstraintReport\ConstraintCheck\Context\Context;
14use WikibaseQuality\ConstraintReport\ConstraintCheck\ItemIdSnakValue;
15use Wikimedia\Assert\Assert;
16
17/**
18 * A deserializer for {@link ViolationMessage}s.
19 *
20 * @license GPL-2.0-or-later
21 */
22class ViolationMessageDeserializer implements Deserializer {
23
24    /**
25     * @var EntityIdParser
26     */
27    private $entityIdParser;
28
29    /**
30     * @var DataValueFactory
31     */
32    private $dataValueFactory;
33
34    public function __construct(
35        EntityIdParser $entityIdParser,
36        DataValueFactory $dataValueFactory
37    ) {
38        $this->entityIdParser = $entityIdParser;
39        $this->dataValueFactory = $dataValueFactory;
40    }
41
42    public function unabbreviateViolationMessageKey( $messageKeySuffix ) {
43        return ViolationMessage::MESSAGE_KEY_PREFIX . $messageKeySuffix;
44    }
45
46    /**
47     * @param array $serialization
48     * @return ViolationMessage
49     */
50    public function deserialize( $serialization ) {
51        Assert::parameterType( 'array', $serialization, '$serialization' );
52
53        $message = new ViolationMessage(
54            $this->unabbreviateViolationMessageKey( $serialization['k'] )
55        );
56
57        foreach ( $serialization['a'] as $serializedArgument ) {
58            $message = $this->deserializeArgument( $message, $serializedArgument );
59        }
60
61        return $message;
62    }
63
64    /**
65     * @param ViolationMessage $message
66     * @param array $serializedArgument [ 't' => ViolationMessage::TYPE_*, 'v' => serialized value, 'r' => $role ]
67     * @return ViolationMessage $message with the deserialized argument appended
68     */
69    private function deserializeArgument( ViolationMessage $message, array $serializedArgument ) {
70        $methods = [
71            ViolationMessage::TYPE_ENTITY_ID => 'deserializeEntityId',
72            ViolationMessage::TYPE_ENTITY_ID_LIST => 'deserializeEntityIdList',
73            ViolationMessage::TYPE_ITEM_ID_SNAK_VALUE => 'deserializeItemIdSnakValue',
74            ViolationMessage::TYPE_ITEM_ID_SNAK_VALUE_LIST => 'deserializeItemIdSnakValueList',
75            ViolationMessage::TYPE_DATA_VALUE => 'deserializeDataValue',
76            ViolationMessage::TYPE_DATA_VALUE_TYPE => 'deserializeStringByIdentity',
77            ViolationMessage::TYPE_INLINE_CODE => 'deserializeStringByIdentity',
78            ViolationMessage::TYPE_CONSTRAINT_SCOPE => 'deserializeContextType',
79            ViolationMessage::TYPE_CONSTRAINT_SCOPE_LIST => 'deserializeContextTypeList',
80            ViolationMessage::TYPE_PROPERTY_SCOPE => 'deserializeContextType',
81            ViolationMessage::TYPE_PROPERTY_SCOPE_LIST => 'deserializeContextTypeList',
82            ViolationMessage::TYPE_LANGUAGE => 'deserializeStringByIdentity',
83            ViolationMessage::TYPE_LANGUAGE_LIST => 'deserializeStringByIdentity',
84            ViolationMessage::TYPE_MULTILINGUAL_TEXT => 'deserializeMultilingualText',
85        ];
86
87        $type = $serializedArgument['t'];
88        $serializedValue = $serializedArgument['v'];
89        $role = $serializedArgument['r'];
90
91        if ( array_key_exists( $type, $methods ) ) {
92            $method = $methods[$type];
93            $value = $this->$method( $serializedValue );
94        } else {
95            throw new InvalidArgumentException(
96                'Unknown ViolationMessage argument type ' . $type . '!'
97            );
98        }
99
100        return $message->withArgument( $type, $role, $value );
101    }
102
103    /**
104     * @param string $string any value that shall simply be deserialized into itself
105     * @return string that same value, unchanged
106     */
107    private function deserializeStringByIdentity( $string ) {
108        return $string;
109    }
110
111    /**
112     * @param string $entityIdSerialization entity ID serialization
113     * @return EntityId
114     */
115    private function deserializeEntityId( $entityIdSerialization ) {
116        return $this->entityIdParser->parse( $entityIdSerialization );
117    }
118
119    /**
120     * @param string[] $entityIdSerializations entity ID serializations
121     * @return EntityId[]
122     */
123    private function deserializeEntityIdList( array $entityIdSerializations ) {
124        return array_map( [ $this, 'deserializeEntityId' ], $entityIdSerializations );
125    }
126
127    /**
128     * @param string $valueSerialization entity ID serialization, '::somevalue' or '::novalue'
129     * @return ItemIdSnakValue
130     */
131    private function deserializeItemIdSnakValue( $valueSerialization ) {
132        switch ( $valueSerialization ) {
133            case '::somevalue':
134                return ItemIdSnakValue::someValue();
135            case '::novalue':
136                return ItemIdSnakValue::noValue();
137            default:
138                $itemId = $this->deserializeEntityId( $valueSerialization );
139                '@phan-var \Wikibase\DataModel\Entity\ItemId $itemId';
140                return ItemIdSnakValue::fromItemId( $itemId );
141        }
142    }
143
144    /**
145     * @param string[] $valueSerializations entity ID serializations, '::somevalue's or '::novalue's
146     * @return ItemIdSnakValue[]
147     */
148    private function deserializeItemIdSnakValueList( $valueSerializations ) {
149        return array_map( [ $this, 'deserializeItemIdSnakValue' ], $valueSerializations );
150    }
151
152    /**
153     * @param array $dataValueSerialization the data value in array form
154     * @return DataValue
155     */
156    private function deserializeDataValue( array $dataValueSerialization ) {
157        return $this->dataValueFactory->newFromArray( $dataValueSerialization );
158    }
159
160    /**
161     * @param string $contextTypeAbbreviation
162     * @return string one of the Context::TYPE_* constants
163     */
164    private function deserializeContextType( $contextTypeAbbreviation ) {
165        switch ( $contextTypeAbbreviation ) {
166            case 's':
167                return Context::TYPE_STATEMENT;
168            case 'q':
169                return Context::TYPE_QUALIFIER;
170            case 'r':
171                return Context::TYPE_REFERENCE;
172            default:
173                // @codeCoverageIgnoreStart
174                throw new LogicException(
175                    'Unknown context type abbreviation ' . $contextTypeAbbreviation
176                );
177                // @codeCoverageIgnoreEnd
178        }
179    }
180
181    /**
182     * @param string[] $contextTypeAbbreviations
183     * @return string[] Context::TYPE_* constants
184     */
185    private function deserializeContextTypeList( array $contextTypeAbbreviations ) {
186        return array_map( [ $this, 'deserializeContextType' ], $contextTypeAbbreviations );
187    }
188
189    /**
190     * @param mixed $textSerialization {@see MultilingualTextValue::getArrayValue}
191     * @return MultilingualTextValue
192     */
193    private function deserializeMultilingualText( $textSerialization ) {
194        return MultilingualTextValue::newFromArray( $textSerialization );
195    }
196
197}