Passed
Pull Request — 7.x (#767)
by Leszek
04:48 queued 02:14
created

EntityId::extractSerializationParts()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 12
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 12
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 9
nc 2
nop 1
1
<?php
2
3
namespace Wikibase\DataModel\Entity;
4
5
use Comparable;
6
use InvalidArgumentException;
7
use Serializable;
8
9
/**
10
 * @since 0.5
11
 * Abstract since 2.0
12
 *
13
 * @license GPL-2.0+
14
 */
15
abstract class EntityId implements Comparable, Serializable {
16
17
	protected $serialization;
18
19
	/**
20
	 * @var string
21
	 */
22
	protected $repositoryName;
23
24
	/**
25
	 * @var string
26
	 */
27
	protected $localPart;
28
29
	const PATTERN = '/^:?(\w+:)*[^:]+\z/';
30
31
	/**
32
	 * @since 6.2
33
	 *
34
	 * @param string $serialization
35
	 */
36
	public function __construct( $serialization ) {
37
		self::assertValidSerialization( $serialization );
38
		$this->serialization = self::normalizeIdSerialization( $serialization );
39
40
		list ( $this->repositoryName, $this->localPart ) = self::extractRepositoryNameAndLocalPart( $serialization );
41
	}
42
43
	private static function assertValidSerialization( $serialization ) {
44
		if ( !is_string( $serialization ) ) {
45
			throw new InvalidArgumentException( '$serialization must be a string' );
46
		}
47
48
		if ( $serialization === '' ) {
49
			throw new InvalidArgumentException( '$serialization must not be an empty string' );
50
		}
51
52
		if ( !preg_match( self::PATTERN, $serialization ) ) {
53
			throw new InvalidArgumentException( '$serialization must match ' . self::PATTERN );
54
		}
55
	}
56
57
	/**
58
	 * @return string
59
	 */
60
	public abstract function getEntityType();
61
62
	/**
63
	 * @return string
64
	 */
65
	public function getSerialization() {
66
		return $this->serialization;
67
	}
68
69
	/**
70
	 * Returns an array with 3 elements: the foreign repository name as the first element, the local ID as the last
71
	 * element and everything that is in between as the second element.
72
	 *
73
	 * EntityId::joinSerialization can be used to restore the original serialization from the parts returned.
74
	 *
75
	 * @since 6.2
76
	 *
77
	 * @param string $serialization
78
	 * @return string[] Array containing the serialization split into 3 parts.
79
	 */
80
	public static function splitSerialization( $serialization ) {
81
		self::assertValidSerialization( $serialization );
82
83
		return self::extractSerializationParts( self::normalizeIdSerialization( $serialization ) );
84
	}
85
86
	/**
87
	 * Splits the given ID serialization into an array with the following three elements:
88
	 *  - the repository name as the first element (empty string for local repository)
89
	 *  - any parts of the ID serialization but the repository name and the local ID (if any, empty string
90
	 *    if nothing else present)
91
	 *  - the local ID
92
	 * Note: this method does not perform any validation of the given input. Calling code should take
93
	 * care of this!
94
	 *
95
	 * @param $serialization
96
	 * @return array
97
	 */
98
	private static function extractSerializationParts( $serialization ) {
99
		$parts = explode( ':', $serialization );
100
		$localPart = array_pop( $parts );
101
		$repoName = array_shift( $parts );
102
		$prefixRemainder = implode( ':', $parts );
103
104
		return [
105
			is_string( $repoName ) ? $repoName : '',
106
			$prefixRemainder,
107
			$localPart
108
		];
109
	}
110
111
	/**
112
	 * Builds an ID serialization from the parts returned by EntityId::splitSerialization.
113
	 *
114
	 * @since 6.2
115
	 *
116
	 * @param string[] $parts
117
	 * @return string
118
	 *
119
	 * @throws InvalidArgumentException
120
	 */
121
	public static function joinSerialization( array $parts ) {
122
		if ( end( $parts ) === '' ) {
123
			throw new InvalidArgumentException( 'The last element of $parts must not be empty.' );
124
		}
125
126
		return implode(
127
			':',
128
			array_filter( $parts, function( $part ) {
129
				return $part !== '';
130
			} )
131
		);
132
	}
133
134
	/**
135
	 * Returns '' for local IDs and the foreign repository name for foreign IDs. For chained IDs (e.g. foo:bar:Q42) it
136
	 * will return only the first part.
137
	 *
138
	 * @since 6.2
139
	 *
140
	 * @return string
141
	 */
142
	public function getRepositoryName() {
143
		return $this->repositoryName;
144
	}
145
146
	/**
147
	 * Returns the serialization without the first repository prefix.
148
	 *
149
	 * @since 6.2
150
	 *
151
	 * @return string
152
	 */
153
	public function getLocalPart() {
154
		return $this->localPart;
155
	}
156
157
	/**
158
	 * Returns true iff EntityId::getRepoName returns a non-empty string.
159
	 *
160
	 * @since 6.2
161
	 *
162
	 * @return bool
163
	 */
164
	public function isForeign() {
165
		// not actually using EntityId::getRepoName for performance reasons
166
		return strpos( $this->serialization, ':' ) > 0;
167
	}
168
169
	/**
170
	 * @param string $id
171
	 * @return string
172
	 */
173
	private static function normalizeIdSerialization( $id ) {
174
		return ltrim( $id, ':' );
175
	}
176
177
	/**
178
	 * This is a human readable representation of the EntityId.
179
	 * This format is allowed to change and should therefore not
180
	 * be relied upon to be stable.
181
	 *
182
	 * @return string
183
	 */
184
	public function __toString() {
185
		return $this->serialization;
186
	}
187
188
	/**
189
	 * @see Comparable::equals
190
	 *
191
	 * @since 0.5
192
	 *
193
	 * @param mixed $target
194
	 *
195
	 * @return bool
196
	 */
197
	public function equals( $target ) {
198
		if ( $this === $target ) {
199
			return true;
200
		}
201
202
		return $target instanceof self
203
			&& $target->serialization === $this->serialization;
204
	}
205
206
	/**
207
	 * Returns a pair (repository name, local part of ID) from the given ID serialization.
208
	 * Note: this does not perform any validation of the given input. Calling code should take
209
	 * care of this!
210
	 *
211
	 * @param string $serialization
212
	 * @return string[] Array of form [ string $repositoryName, string $localPart ]
213
	 */
214
	protected static function extractRepositoryNameAndLocalPart( $serialization ) {
215
		$parts = explode( ':', $serialization, 2 );
216
		return count( $parts ) > 1 ? [ $parts[0], $parts[1] ] : [ '', $parts[0] ];
217
		return [ $repoName, $localPart ];
0 ignored issues
show
Unused Code introduced by
return array($repoName, $localPart); does not seem to be reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
218
	}
219
220
}
221