Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
96.67% covered (success)
96.67%
58 / 60
92.31% covered (success)
92.31%
12 / 13
CRAP
0.00% covered (danger)
0.00%
0 / 1
ViolationMessageSerializer
96.67% covered (success)
96.67%
58 / 60
92.31% covered (success)
92.31%
12 / 13
23
0.00% covered (danger)
0.00%
0 / 1
 abbreviateViolationMessageKey
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 serialize
100.00% covered (success)
100.00%
9 / 9
100.00% covered (success)
100.00%
1 / 1
2
 serializeArgument
100.00% covered (success)
100.00%
31 / 31
100.00% covered (success)
100.00%
1 / 1
2
 serializeStringByIdentity
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 serializeStringListByIdentity
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 serializeEntityId
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 serializeEntityIdList
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 serializeItemIdSnakValue
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
5
 serializeItemIdSnakValueList
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 serializeDataValue
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 serializeContextType
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
5
 serializeContextTypeList
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 serializeMultilingualText
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 InvalidArgumentException;
8use LogicException;
9use Serializers\Serializer;
10use Wikibase\DataModel\Entity\EntityId;
11use WikibaseQuality\ConstraintReport\ConstraintCheck\Context\Context;
12use WikibaseQuality\ConstraintReport\ConstraintCheck\ItemIdSnakValue;
13use Wikimedia\Assert\Assert;
14
15/**
16 * A serializer for {@link ViolationMessage}s.
17 *
18 * @license GPL-2.0-or-later
19 */
20class ViolationMessageSerializer implements Serializer {
21
22    private function abbreviateViolationMessageKey( $fullMessageKey ) {
23        return substr( $fullMessageKey, strlen( ViolationMessage::MESSAGE_KEY_PREFIX ) );
24    }
25
26    /**
27     * @param ViolationMessage $object
28     * @return array
29     */
30    public function serialize( $object ) {
31        /** @var ViolationMessage $object */
32        Assert::parameterType( ViolationMessage::class, $object, '$object' );
33
34        $arguments = $object->getArguments();
35        $serializedArguments = [];
36        foreach ( $arguments as $argument ) {
37            $serializedArguments[] = $this->serializeArgument( $argument );
38        }
39
40        return [
41            'k' => $this->abbreviateViolationMessageKey( $object->getMessageKey() ),
42            'a' => $serializedArguments,
43        ];
44    }
45
46    /**
47     * @param array $argument element of ViolationMessage::getArguments()
48     * @return array [ 't' => ViolationMessage::TYPE_*, 'v' => serialized value, 'r' => $role ]
49     */
50    private function serializeArgument( array $argument ) {
51        $methods = [
52            ViolationMessage::TYPE_ENTITY_ID => 'serializeEntityId',
53            ViolationMessage::TYPE_ENTITY_ID_LIST => 'serializeEntityIdList',
54            ViolationMessage::TYPE_ITEM_ID_SNAK_VALUE => 'serializeItemIdSnakValue',
55            ViolationMessage::TYPE_ITEM_ID_SNAK_VALUE_LIST => 'serializeItemIdSnakValueList',
56            ViolationMessage::TYPE_DATA_VALUE => 'serializeDataValue',
57            ViolationMessage::TYPE_DATA_VALUE_TYPE => 'serializeStringByIdentity',
58            ViolationMessage::TYPE_INLINE_CODE => 'serializeStringByIdentity',
59            ViolationMessage::TYPE_CONSTRAINT_SCOPE => 'serializeContextType',
60            ViolationMessage::TYPE_CONSTRAINT_SCOPE_LIST => 'serializeContextTypeList',
61            ViolationMessage::TYPE_PROPERTY_SCOPE => 'serializeContextType',
62            ViolationMessage::TYPE_PROPERTY_SCOPE_LIST => 'serializeContextTypeList',
63            ViolationMessage::TYPE_LANGUAGE => 'serializeStringByIdentity',
64            ViolationMessage::TYPE_LANGUAGE_LIST => 'serializeStringListByIdentity',
65            ViolationMessage::TYPE_MULTILINGUAL_TEXT => 'serializeMultilingualText',
66        ];
67
68        $type = $argument['type'];
69        $value = $argument['value'];
70        $role = $argument['role'];
71
72        if ( array_key_exists( $type, $methods ) ) {
73            $method = $methods[$type];
74            $serializedValue = $this->$method( $value );
75        } else {
76            throw new InvalidArgumentException(
77                'Unknown ViolationMessage argument type ' . $type . '!'
78            );
79        }
80
81        $serialized = [
82            't' => $type,
83            'v' => $serializedValue,
84            'r' => $role,
85        ];
86
87        return $serialized;
88    }
89
90    /**
91     * @param string $string any value that shall simply be serialized to itself
92     * @return string that same value, unchanged
93     */
94    private function serializeStringByIdentity( $string ) {
95        Assert::parameterType( 'string', $string, '$string' );
96        return $string;
97    }
98
99    /**
100     * @param string[] $strings
101     * @return string[]
102     */
103    private function serializeStringListByIdentity( $strings ) {
104        Assert::parameterElementType( 'string', $strings, '$strings' );
105        return $strings;
106    }
107
108    /**
109     * @param EntityId $entityId
110     * @return string entity ID serialization
111     */
112    private function serializeEntityId( EntityId $entityId ) {
113        return $entityId->getSerialization();
114    }
115
116    /**
117     * @param EntityId[] $entityIdList
118     * @return string[] entity ID serializations
119     */
120    private function serializeEntityIdList( array $entityIdList ) {
121        return array_map( [ $this, 'serializeEntityId' ], $entityIdList );
122    }
123
124    /**
125     * @param ItemIdSnakValue $value
126     * @return string entity ID serialization, '::somevalue', or '::novalue'
127     * (according to EntityId::PATTERN, entity ID serializations can never begin with two colons)
128     */
129    private function serializeItemIdSnakValue( ItemIdSnakValue $value ) {
130        switch ( true ) {
131            case $value->isValue():
132                return $this->serializeEntityId( $value->getItemId() );
133            case $value->isSomeValue():
134                return '::somevalue';
135            case $value->isNoValue():
136                return '::novalue';
137            default:
138                // @codeCoverageIgnoreStart
139                throw new LogicException(
140                    'ItemIdSnakValue should guarantee that one of is{,Some,No}Value() is true'
141                );
142                // @codeCoverageIgnoreEnd
143        }
144    }
145
146    /**
147     * @param ItemIdSnakValue[] $valueList
148     * @return string[] array of entity ID serializations, '::somevalue's or '::novalue's
149     */
150    private function serializeItemIdSnakValueList( array $valueList ) {
151        return array_map( [ $this, 'serializeItemIdSnakValue' ], $valueList );
152    }
153
154    /**
155     * @param DataValue $dataValue
156     * @return array the data value in array form
157     */
158    private function serializeDataValue( DataValue $dataValue ) {
159        return $dataValue->toArray();
160    }
161
162    /**
163     * @param string $contextType one of the Context::TYPE_* constants
164     * @return string the abbreviated context type
165     */
166    private function serializeContextType( $contextType ) {
167        switch ( $contextType ) {
168            case Context::TYPE_STATEMENT:
169                return 's';
170            case Context::TYPE_QUALIFIER:
171                return 'q';
172            case Context::TYPE_REFERENCE:
173                return 'r';
174            default:
175                // @codeCoverageIgnoreStart
176                throw new LogicException(
177                    'Unknown context type ' . $contextType
178                );
179                // @codeCoverageIgnoreEnd
180        }
181    }
182
183    /**
184     * @param string[] $contextTypeList Context::TYPE_* constants
185     * @return string[] abbreviated context types
186     */
187    private function serializeContextTypeList( array $contextTypeList ) {
188        return array_map( [ $this, 'serializeContextType' ], $contextTypeList );
189    }
190
191    /**
192     * @param MultilingualTextValue $text
193     * @return mixed {@see MultilingualTextValue::getArrayValue}
194     */
195    private function serializeMultilingualText( MultilingualTextValue $text ) {
196        return $text->getArrayValue();
197    }
198
199}