Completed
Pull Request — master (#678)
by Jakob
03:27
created

EntityId::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

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