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

EntityId::joinSerialization()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 12
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
dl 0
loc 12
ccs 0
cts 0
cp 0
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 7
nc 2
nop 1
crap 6
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
	 * @param string $serialization
25
	 */
26
	public function __construct( $serialization ) {
27
		self::assertValidSerialization( $serialization );
28 31
		$this->serialization = self::normalizeIdSerialization( $serialization );
29 31
	}
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 5
40 5
		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 5
	 */
53 5
	public function getSerialization() {
54 5
		return $this->serialization;
55
	}
56
57
	/**
58 5
	 * 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
	 * @param string $serialization
64
	 * @return string[] Array containing the serialization split into 3 parts.
65
	 */
66
	public static function splitSerialization( $serialization ) {
67
		self::assertValidSerialization( $serialization );
68
69
		$parts = explode( ':', self::normalizeIdSerialization( $serialization ) );
70
		$localPart = array_pop( $parts );
71
		$repoName = array_shift( $parts );
72
		$prefixRemainder = implode( ':', $parts );
73
74
		return array(
75
			is_string( $repoName ) ? $repoName : '',
76
			$prefixRemainder,
77
			$localPart
78
		);
79
	}
80
81
	/**
82
	 * Builds an ID serialization from the parts returned by EntityId::splitSerialization.
83
	 *
84
	 * @param string[] $parts
85
	 * @return string
86
	 *
87
	 * @throws InvalidArgumentException
88
	 */
89
	public static function joinSerialization( array $parts ) {
90
		if ( end( $parts ) === '' ) {
91
			throw new InvalidArgumentException( 'The last element of $parts must not be empty.' );
92
		}
93
94
		return implode(
95
			':',
96
			array_filter( $parts, function( $part ) {
97
				return $part !== '';
98
			} )
99
		);
100
	}
101
102
	/**
103
	 * Returns '' for local IDs and the foreign repository name for foreign IDs. For chained IDs (e.g. foo:bar:Q42) it
104
	 * will return only the first part.
105
	 *
106
	 * @return string
107
	 */
108
	public function getRepoName() {
109
		$parts = self::splitSerialization( $this->serialization );
110
111
		return $parts[0];
112
	}
113
114
	/**
115
	 * Returns the serialization without the first repository prefix.
116
	 *
117
	 * @return string
118
	 */
119
	public function getLocalPart() {
120
		$parts = self::splitSerialization( $this->serialization );
121
122
		return self::joinSerialization( array( $parts[1], $parts[2] ) );
123
	}
124
125
	/**
126
	 * Returns true iff EntityId::getRepoName returns a non-empty string.
127
	 *
128
	 * @return bool
129
	 */
130
	public function isForeign() {
131
		// not actually using EntityId::getRepoName for performance reasons
132
		return strpos( $this->serialization, ':' ) > 0;
133
	}
134
135
	/**
136
	 * @param string $id
137
	 * @return string
138
	 */
139
	private static function normalizeIdSerialization( $id ) {
140
		return ltrim( $id, ':' );
141
	}
142
143
	/**
144
	 * This is a human readable representation of the EntityId.
145
	 * This format is allowed to change and should therefore not
146
	 * be relied upon to be stable.
147
	 *
148
	 * @return string
149
	 */
150
	public function __toString() {
151
		return $this->serialization;
152
	}
153
154
	/**
155
	 * @see Comparable::equals
156
	 *
157
	 * @since 0.5
158
	 *
159
	 * @param mixed $target
160
	 *
161
	 * @return bool
162
	 */
163
	public function equals( $target ) {
164
		if ( $this === $target ) {
165
			return true;
166
		}
167
168
		return $target instanceof self
169
			&& $target->serialization === $this->serialization;
170
	}
171
172
}
173