1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace WikibaseQuality\ConstraintReport\ConstraintCheck\Message; |
4
|
|
|
|
5
|
|
|
use DataValues\DataValue; |
6
|
|
|
use DataValues\MultilingualTextValue; |
7
|
|
|
use InvalidArgumentException; |
8
|
|
|
use LogicException; |
9
|
|
|
use Serializers\Serializer; |
10
|
|
|
use Wikibase\DataModel\Entity\EntityId; |
11
|
|
|
use WikibaseQuality\ConstraintReport\ConstraintCheck\Context\Context; |
12
|
|
|
use WikibaseQuality\ConstraintReport\ConstraintCheck\ItemIdSnakValue; |
13
|
|
|
use Wikimedia\Assert\Assert; |
14
|
|
|
|
15
|
|
|
/** |
16
|
|
|
* A serializer for {@link ViolationMessage}s. |
17
|
|
|
* |
18
|
|
|
* @license GPL-2.0-or-later |
19
|
|
|
*/ |
20
|
|
|
class 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 => 'serializeConstraintScope', |
60
|
|
|
ViolationMessage::TYPE_CONSTRAINT_SCOPE_LIST => 'serializeConstraintScopeList', |
61
|
|
|
ViolationMessage::TYPE_PROPERTY_SCOPE => 'serializePropertyScope', |
62
|
|
|
ViolationMessage::TYPE_PROPERTY_SCOPE_LIST => 'serializePropertyScopeList', |
63
|
|
|
ViolationMessage::TYPE_LANGUAGE => 'serializeStringByIdentity', |
64
|
|
|
ViolationMessage::TYPE_MULTILINGUAL_TEXT => 'serializeMultilingualText', |
65
|
|
|
]; |
66
|
|
|
|
67
|
|
|
$type = $argument['type']; |
68
|
|
|
$value = $argument['value']; |
69
|
|
|
$role = $argument['role']; |
70
|
|
|
|
71
|
|
View Code Duplication |
if ( array_key_exists( $type, $methods ) ) { |
|
|
|
|
72
|
|
|
$method = $methods[$type]; |
73
|
|
|
$serializedValue = $this->$method( $value ); |
74
|
|
|
} else { |
75
|
|
|
throw new InvalidArgumentException( |
76
|
|
|
'Unknown ViolationMessage argument type ' . $type . '!' |
77
|
|
|
); |
78
|
|
|
} |
79
|
|
|
|
80
|
|
|
$serialized = [ |
81
|
|
|
't' => $type, |
82
|
|
|
'v' => $serializedValue, |
83
|
|
|
'r' => $role, |
84
|
|
|
]; |
85
|
|
|
|
86
|
|
|
return $serialized; |
87
|
|
|
} |
88
|
|
|
|
89
|
|
|
/** |
90
|
|
|
* @param string $string any value that shall simply be serialized to itself |
91
|
|
|
* @return string that same value, unchanged |
92
|
|
|
*/ |
93
|
|
|
private function serializeStringByIdentity( $string ) { |
94
|
|
|
Assert::parameterType( 'string', $string, '$string' ); |
95
|
|
|
return $string; |
96
|
|
|
} |
97
|
|
|
|
98
|
|
|
/** |
99
|
|
|
* @param EntityId $entityId |
100
|
|
|
* @return string entity ID serialization |
101
|
|
|
*/ |
102
|
|
|
private function serializeEntityId( EntityId $entityId ) { |
103
|
|
|
return $entityId->getSerialization(); |
104
|
|
|
} |
105
|
|
|
|
106
|
|
|
/** |
107
|
|
|
* @param EntityId[] $entityIdList |
108
|
|
|
* @return string[] entity ID serializations |
109
|
|
|
*/ |
110
|
|
|
private function serializeEntityIdList( array $entityIdList ) { |
111
|
|
|
return array_map( [ $this, 'serializeEntityId' ], $entityIdList ); |
112
|
|
|
} |
113
|
|
|
|
114
|
|
|
/** |
115
|
|
|
* @param ItemIdSnakValue $value |
116
|
|
|
* @return string entity ID serialization, '::somevalue', or '::novalue' |
117
|
|
|
* (according to EntityId::PATTERN, entity ID serializations can never begin with two colons) |
118
|
|
|
*/ |
119
|
|
|
private function serializeItemIdSnakValue( ItemIdSnakValue $value ) { |
120
|
|
|
switch ( true ) { |
121
|
|
|
case $value->isValue(): |
122
|
|
|
return $this->serializeEntityId( $value->getItemId() ); |
|
|
|
|
123
|
|
|
case $value->isSomeValue(): |
124
|
|
|
return '::somevalue'; |
125
|
|
|
case $value->isNoValue(): |
126
|
|
|
return '::novalue'; |
127
|
|
|
default: |
128
|
|
|
// @codeCoverageIgnoreStart |
129
|
|
|
throw new LogicException( |
130
|
|
|
'ItemIdSnakValue should guarantee that one of is{,Some,No}Value() is true' |
131
|
|
|
); |
132
|
|
|
// @codeCoverageIgnoreEnd |
133
|
|
|
} |
134
|
|
|
} |
135
|
|
|
|
136
|
|
|
/** |
137
|
|
|
* @param ItemIdSnakValue[] $valueList |
138
|
|
|
* @return string[] array of entity ID serializations, '::somevalue's or '::novalue's |
139
|
|
|
*/ |
140
|
|
|
private function serializeItemIdSnakValueList( array $valueList ) { |
141
|
|
|
return array_map( [ $this, 'serializeItemIdSnakValue' ], $valueList ); |
142
|
|
|
} |
143
|
|
|
|
144
|
|
|
/** |
145
|
|
|
* @param DataValue $dataValue |
146
|
|
|
* @return array the data value in array form |
147
|
|
|
*/ |
148
|
|
|
private function serializeDataValue( DataValue $dataValue ) { |
149
|
|
|
return $dataValue->toArray(); |
150
|
|
|
} |
151
|
|
|
|
152
|
|
|
/** |
153
|
|
|
* @param string $scope one of the Context::TYPE_* constants |
154
|
|
|
* @return string the abbreviated scope |
155
|
|
|
*/ |
156
|
|
View Code Duplication |
private function serializeConstraintScope( $scope ) { |
|
|
|
|
157
|
|
|
switch ( $scope ) { |
158
|
|
|
case Context::TYPE_STATEMENT: |
159
|
|
|
return 's'; |
160
|
|
|
case Context::TYPE_QUALIFIER: |
161
|
|
|
return 'q'; |
162
|
|
|
case Context::TYPE_REFERENCE: |
163
|
|
|
return 'r'; |
164
|
|
|
default: |
165
|
|
|
// @codeCoverageIgnoreStart |
166
|
|
|
throw new LogicException( |
167
|
|
|
'Unknown constraint scope ' . $scope |
168
|
|
|
); |
169
|
|
|
// @codeCoverageIgnoreEnd |
170
|
|
|
} |
171
|
|
|
} |
172
|
|
|
|
173
|
|
|
/** |
174
|
|
|
* @param string[] $scopeList Context::TYPE_* constants |
175
|
|
|
* @return string[] abbreviated scopes |
176
|
|
|
*/ |
177
|
|
|
private function serializeConstraintScopeList( array $scopeList ) { |
178
|
|
|
return array_map( [ $this, 'serializeConstraintScope' ], $scopeList ); |
179
|
|
|
} |
180
|
|
|
|
181
|
|
|
/** |
182
|
|
|
* @param string $scope one of the Context::TYPE_* constants |
183
|
|
|
* @return string the abbreviated scope |
184
|
|
|
*/ |
185
|
|
View Code Duplication |
private function serializePropertyScope( $scope ) { |
|
|
|
|
186
|
|
|
switch ( $scope ) { |
187
|
|
|
case Context::TYPE_STATEMENT: |
188
|
|
|
return 's'; |
189
|
|
|
case Context::TYPE_QUALIFIER: |
190
|
|
|
return 'q'; |
191
|
|
|
case Context::TYPE_REFERENCE: |
192
|
|
|
return 'r'; |
193
|
|
|
default: |
194
|
|
|
// @codeCoverageIgnoreStart |
195
|
|
|
throw new LogicException( |
196
|
|
|
'Unknown property scope ' . $scope |
197
|
|
|
); |
198
|
|
|
// @codeCoverageIgnoreEnd |
199
|
|
|
} |
200
|
|
|
} |
201
|
|
|
|
202
|
|
|
/** |
203
|
|
|
* @param string[] $scopeList Context::TYPE_* constants |
204
|
|
|
* @return string[] abbreviated scopes |
205
|
|
|
*/ |
206
|
|
|
private function serializePropertyScopeList( array $scopeList ) { |
207
|
|
|
return array_map( [ $this, 'serializePropertyScope' ], $scopeList ); |
208
|
|
|
} |
209
|
|
|
|
210
|
|
|
/** |
211
|
|
|
* @param MultilingualTextValue $text |
212
|
|
|
* @return mixed {@see MultilingualTextValue::getArrayValue} |
213
|
|
|
*/ |
214
|
|
|
private function serializeMultilingualText( MultilingualTextValue $text ) { |
215
|
|
|
return $text->getArrayValue(); |
216
|
|
|
} |
217
|
|
|
|
218
|
|
|
} |
219
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.