Passed
Push — aliasGroupTest ( 84a0d7...e654f3 )
by no
02:52
created

EntityId::getLocalPart()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 5
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 3
nc 1
nop 0
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
	const PATTERN = '/^:?(\w+:)*[^:]+\z/';
20
21
	/**
22
	 * @since 6.2
23
	 *
24
	 * @param string $serialization
25
	 */
26
	public function __construct( $serialization ) {
27
		self::assertValidSerialization( $serialization );
28
		$this->serialization = self::normalizeIdSerialization( $serialization );
29
	}
30
31
	private static function assertValidSerialization( $serialization ) {
32
		if ( !is_string( $serialization ) ) {
33
			throw new InvalidArgumentException( '$serialization must be a string' );
34
		}
35
36
		if ( $serialization === '' ) {
37
			throw new InvalidArgumentException( '$serialization must not be an empty string' );
38
		}
39
40
		if ( !preg_match( self::PATTERN, $serialization ) ) {
41
			throw new InvalidArgumentException( '$serialization must match ' . self::PATTERN );
42
		}
43
	}
44
45
	/**
46
	 * @return string
47
	 */
48
	public abstract function getEntityType();
49
50
	/**
51
	 * @return string
52
	 */
53
	public function getSerialization() {
54
		return $this->serialization;
55
	}
56
57
	/**
58
	 * Returns an array with 3 elements: the foreign repository name as the first element, the local ID as the last
59
	 * element and everything that is in between as the second element.
60
	 *
61
	 * EntityId::joinSerialization can be used to restore the original serialization from the parts returned.
62
	 *
63
	 * @since 6.2
64
	 *
65
	 * @param string $serialization
66
	 * @return string[] Array containing the serialization split into 3 parts.
67
	 */
68
	public static function splitSerialization( $serialization ) {
69
		self::assertValidSerialization( $serialization );
70
71
		$parts = explode( ':', self::normalizeIdSerialization( $serialization ) );
72
		$localPart = array_pop( $parts );
73
		$repoName = array_shift( $parts );
74
		$prefixRemainder = implode( ':', $parts );
75
76
		return [
77
			is_string( $repoName ) ? $repoName : '',
78
			$prefixRemainder,
79
			$localPart
80
		];
81
	}
82
83
	/**
84
	 * Builds an ID serialization from the parts returned by EntityId::splitSerialization.
85
	 *
86
	 * @since 6.2
87
	 *
88
	 * @param string[] $parts
89
	 * @return string
90
	 *
91
	 * @throws InvalidArgumentException
92
	 */
93
	public static function joinSerialization( array $parts ) {
94
		if ( end( $parts ) === '' ) {
95
			throw new InvalidArgumentException( 'The last element of $parts must not be empty.' );
96
		}
97
98
		return implode(
99
			':',
100
			array_filter( $parts, function( $part ) {
101
				return $part !== '';
102
			} )
103
		);
104
	}
105
106
	/**
107
	 * Returns '' for local IDs and the foreign repository name for foreign IDs. For chained IDs (e.g. foo:bar:Q42) it
108
	 * will return only the first part.
109
	 *
110
	 * @since 6.2
111
	 *
112
	 * @return string
113
	 */
114
	public function getRepositoryName() {
115
		$parts = self::splitSerialization( $this->serialization );
116
117
		return $parts[0];
118
	}
119
120
	/**
121
	 * Returns the serialization without the first repository prefix.
122
	 *
123
	 * @since 6.2
124
	 *
125
	 * @return string
126
	 */
127
	public function getLocalPart() {
128
		$parts = self::splitSerialization( $this->serialization );
129
130
		return self::joinSerialization( [ '', $parts[1], $parts[2] ] );
131
	}
132
133
	/**
134
	 * Returns true iff EntityId::getRepoName returns a non-empty string.
135
	 *
136
	 * @since 6.2
137
	 *
138
	 * @return bool
139
	 */
140
	public function isForeign() {
141
		// not actually using EntityId::getRepoName for performance reasons
142
		return strpos( $this->serialization, ':' ) > 0;
143
	}
144
145
	/**
146
	 * @param string $id
147
	 * @return string
148
	 */
149
	private static function normalizeIdSerialization( $id ) {
150
		return ltrim( $id, ':' );
151
	}
152
153
	/**
154
	 * This is a human readable representation of the EntityId.
155
	 * This format is allowed to change and should therefore not
156
	 * be relied upon to be stable.
157
	 *
158
	 * @return string
159
	 */
160
	public function __toString() {
161
		return $this->serialization;
162
	}
163
164
	/**
165
	 * @see Comparable::equals
166
	 *
167
	 * @since 0.5
168
	 *
169
	 * @param mixed $target
170
	 *
171
	 * @return bool
172
	 */
173
	public function equals( $target ) {
174
		if ( $this === $target ) {
175
			return true;
176
		}
177
178
		return $target instanceof self
179
			&& $target->serialization === $this->serialization;
180
	}
181
182
}
183