Completed
Push — master ( db833a...340657 )
by
unknown
04:20
created

serializePropertyScope()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 16

Duplication

Lines 16
Ratio 100 %

Importance

Changes 0
Metric Value
dl 16
loc 16
rs 9.7333
c 0
b 0
f 0
cc 4
nc 4
nop 1
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 ) ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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.

Loading history...
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() );
0 ignored issues
show
Bug introduced by
It seems like $value->getItemId() can be null; however, serializeEntityId() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
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 ) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
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 ) {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

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.

Loading history...
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