Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
83.33% |
45 / 54 |
|
91.67% |
11 / 12 |
CRAP | |
0.00% |
0 / 1 |
TitleValue | |
84.91% |
45 / 53 |
|
91.67% |
11 / 12 |
25.98 | |
0.00% |
0 / 1 |
tryNew | |
100.00% |
5 / 5 |
|
100.00% |
1 / 1 |
3 | |||
newFromPage | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
newFromLinkTarget | |
0.00% |
0 / 8 |
|
0.00% |
0 / 1 |
6 | |||
castPageToLinkTarget | |
100.00% |
3 / 3 |
|
100.00% |
1 / 1 |
3 | |||
__construct | |
100.00% |
5 / 5 |
|
100.00% |
1 / 1 |
1 | |||
assertValidSpec | |
100.00% |
15 / 15 |
|
100.00% |
1 / 1 |
6 | |||
getNamespace | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
getFragment | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
getDBkey | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
createFragmentTarget | |
100.00% |
6 / 6 |
|
100.00% |
1 / 1 |
1 | |||
getInterwiki | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
__toString | |
100.00% |
6 / 6 |
|
100.00% |
1 / 1 |
3 |
1 | <?php |
2 | /** |
3 | * Representation of a page title within MediaWiki. |
4 | * |
5 | * This program is free software; you can redistribute it and/or modify |
6 | * it under the terms of the GNU General Public License as published by |
7 | * the Free Software Foundation; either version 2 of the License, or |
8 | * (at your option) any later version. |
9 | * |
10 | * This program is distributed in the hope that it will be useful, |
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
13 | * GNU General Public License for more details. |
14 | * |
15 | * You should have received a copy of the GNU General Public License along |
16 | * with this program; if not, write to the Free Software Foundation, Inc., |
17 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
18 | * http://www.gnu.org/copyleft/gpl.html |
19 | * |
20 | * @file |
21 | * @author Daniel Kinzler |
22 | */ |
23 | |
24 | namespace MediaWiki\Title; |
25 | |
26 | use InvalidArgumentException; |
27 | use MediaWiki\Linker\LinkTarget; |
28 | use MediaWiki\Page\PageReference; |
29 | use Stringable; |
30 | use Wikimedia\Assert\Assert; |
31 | use Wikimedia\Assert\ParameterAssertionException; |
32 | use Wikimedia\Assert\ParameterTypeException; |
33 | use Wikimedia\Parsoid\Core\LinkTarget as ParsoidLinkTarget; |
34 | use Wikimedia\Parsoid\Core\LinkTargetTrait; |
35 | |
36 | /** |
37 | * Represents the target of a wiki link. |
38 | * |
39 | * @note In contrast to Title, this is designed to be a plain value object. That is, |
40 | * it is immutable, does not use global state, and causes no side effects. |
41 | * |
42 | * @newable |
43 | * |
44 | * @see https://www.mediawiki.org/wiki/Manual:Modeling_pages |
45 | * @since 1.23 |
46 | */ |
47 | class TitleValue implements Stringable, LinkTarget { |
48 | use LinkTargetTrait; |
49 | |
50 | /** @var int */ |
51 | private $namespace; |
52 | |
53 | /** @var string */ |
54 | private $dbkey; |
55 | |
56 | /** @var string */ |
57 | private $fragment; |
58 | |
59 | /** @var string */ |
60 | private $interwiki; |
61 | |
62 | /** |
63 | * Text form including namespace/interwiki, initialised on demand |
64 | * |
65 | * Only public to share cache with TitleFormatter |
66 | * |
67 | * @internal |
68 | * @var string |
69 | */ |
70 | public $prefixedText = null; |
71 | |
72 | /** |
73 | * Constructs a TitleValue, or returns null if the parameters are not valid. |
74 | * |
75 | * @note This does not perform any normalization, and only basic validation. |
76 | * For full normalization and validation, use TitleParser::makeTitleValueSafe(). |
77 | * |
78 | * @param int $namespace The namespace ID. This is not validated. |
79 | * @param string $title The page title in either DBkey or text form. No normalization is applied |
80 | * beyond underscore/space conversion. |
81 | * @param string $fragment The fragment title. Use '' to represent the whole page. |
82 | * No validation or normalization is applied. |
83 | * @param string $interwiki The interwiki component. |
84 | * No validation or normalization is applied. |
85 | * @return TitleValue|null |
86 | */ |
87 | public static function tryNew( $namespace, $title, $fragment = '', $interwiki = '' ) { |
88 | if ( !is_int( $namespace ) ) { |
89 | throw new ParameterTypeException( '$namespace', 'int' ); |
90 | } |
91 | |
92 | try { |
93 | return new static( $namespace, $title, $fragment, $interwiki ); |
94 | } catch ( ParameterAssertionException $ex ) { |
95 | return null; |
96 | } |
97 | } |
98 | |
99 | /** |
100 | * Create a TitleValue from a local PageReference. |
101 | * |
102 | * @note The PageReference may belong to another wiki. In that case, the resulting TitleValue |
103 | * is also logically bound to that other wiki. No attempt is made to map the |
104 | * PageReference wiki ID to an interwiki prefix for the TitleValue. |
105 | * |
106 | * @since 1.36 |
107 | * @param PageReference $page |
108 | * @return TitleValue |
109 | */ |
110 | public static function newFromPage( PageReference $page ): TitleValue { |
111 | return new TitleValue( $page->getNamespace(), $page->getDBkey() ); |
112 | } |
113 | |
114 | /** |
115 | * Create a TitleValue from a LinkTarget |
116 | * @param ParsoidLinkTarget $linkTarget |
117 | * @return TitleValue |
118 | * @since 1.42 |
119 | */ |
120 | public static function newFromLinkTarget( ParsoidLinkTarget $linkTarget ): TitleValue { |
121 | if ( $linkTarget instanceof TitleValue ) { |
122 | return $linkTarget; |
123 | } |
124 | return new TitleValue( |
125 | $linkTarget->getNamespace(), |
126 | $linkTarget->getDBkey(), |
127 | $linkTarget->getFragment(), |
128 | $linkTarget->getInterwiki() |
129 | ); |
130 | } |
131 | |
132 | /** |
133 | * Casts a PageReference to a LinkTarget. |
134 | * |
135 | * If $page is null, null is returned. |
136 | * If $page is also an instance of LinkTarget, $page is returned unchanged. |
137 | * |
138 | * @see newFromPage() |
139 | * @since 1.37 |
140 | * @param PageReference|null $page |
141 | * @return LinkTarget|null |
142 | */ |
143 | public static function castPageToLinkTarget( ?PageReference $page ): ?LinkTarget { |
144 | if ( !$page || $page instanceof LinkTarget ) { |
145 | return $page; |
146 | } |
147 | |
148 | return self::newFromPage( $page ); |
149 | } |
150 | |
151 | /** |
152 | * Construct a TitleValue. |
153 | * |
154 | * @note TitleValue expects a valid namespace and name; typically, a TitleValue is constructed |
155 | * either from a database entry, or by a TitleParser. For constructing a TitleValue from user |
156 | * input or external sources, use a TitleParser. |
157 | * |
158 | * @stable to call |
159 | * @param int $namespace The namespace ID. This is not validated. |
160 | * @param string $title The page title in either DBkey or text form. No normalization is applied |
161 | * beyond underscore/space conversion. |
162 | * @param string $fragment The fragment title. Use '' to represent the whole page. |
163 | * No validation or normalization is applied. |
164 | * @param string $interwiki The interwiki component. |
165 | * No validation or normalization is applied. |
166 | */ |
167 | public function __construct( $namespace, $title, $fragment = '', $interwiki = '' ) { |
168 | self::assertValidSpec( $namespace, $title, $fragment, $interwiki ); |
169 | |
170 | $this->namespace = $namespace; |
171 | $this->dbkey = strtr( $title, ' ', '_' ); |
172 | $this->fragment = $fragment; |
173 | $this->interwiki = $interwiki; |
174 | } |
175 | |
176 | /** |
177 | * Assert that the given parameters could be used to construct a TitleValue object. |
178 | * |
179 | * Performs basic syntax and consistency checks. Does not perform full validation, |
180 | * use TitleParser::makeTitleValueSafe() for that. |
181 | * |
182 | * @param int $namespace |
183 | * @param string $title |
184 | * @param string $fragment |
185 | * @param string $interwiki |
186 | * @throws InvalidArgumentException if the combination of parameters is not valid for |
187 | * constructing a TitleValue. |
188 | */ |
189 | public static function assertValidSpec( $namespace, $title, $fragment = '', $interwiki = '' ) { |
190 | if ( !is_int( $namespace ) ) { |
191 | throw new ParameterTypeException( '$namespace', 'int' ); |
192 | } |
193 | if ( !is_string( $title ) ) { |
194 | throw new ParameterTypeException( '$title', 'string' ); |
195 | } |
196 | if ( !is_string( $fragment ) ) { |
197 | throw new ParameterTypeException( '$fragment', 'string' ); |
198 | } |
199 | if ( !is_string( $interwiki ) ) { |
200 | throw new ParameterTypeException( '$interwiki', 'string' ); |
201 | } |
202 | |
203 | Assert::parameter( !preg_match( '/^[_ ]|[\r\n\t]|[_ ]$/', $title ), '$title', |
204 | "invalid name '$title'" ); |
205 | |
206 | // NOTE: As of MW 1.34, [[#]] is rendered as a valid link, pointing to the empty |
207 | // page title, effectively leading to the wiki's main page. This means that a completely |
208 | // empty TitleValue has to be considered valid, for consistency with Title. |
209 | // Also note that [[#foo]] is a valid on-page section links, and that [[acme:#foo]] is |
210 | // a valid interwiki link. |
211 | Assert::parameter( |
212 | $title !== '' || $namespace === NS_MAIN, |
213 | '$title', |
214 | 'should not be empty unless namespace is main' |
215 | ); |
216 | } |
217 | |
218 | public function getNamespace(): int { |
219 | return $this->namespace; |
220 | } |
221 | |
222 | public function getFragment(): string { |
223 | return $this->fragment; |
224 | } |
225 | |
226 | public function getDBkey(): string { |
227 | return $this->dbkey; |
228 | } |
229 | |
230 | public function createFragmentTarget( string $fragment ): self { |
231 | return new TitleValue( |
232 | $this->namespace, |
233 | $this->dbkey, |
234 | $fragment, |
235 | $this->interwiki |
236 | ); |
237 | } |
238 | |
239 | public function getInterwiki(): string { |
240 | return $this->interwiki; |
241 | } |
242 | |
243 | /** |
244 | * Returns a string representation of the title, for logging. This is purely informative |
245 | * and must not be used programmatically. Use the appropriate TitleFormatter to generate |
246 | * the correct string representation for a given use. |
247 | * |
248 | * @since 1.23 |
249 | * @return string |
250 | */ |
251 | public function __toString(): string { |
252 | $name = $this->namespace . ':' . $this->dbkey; |
253 | |
254 | if ( $this->fragment !== '' ) { |
255 | $name .= '#' . $this->fragment; |
256 | } |
257 | |
258 | if ( $this->interwiki !== '' ) { |
259 | $name = $this->interwiki . ':' . $name; |
260 | } |
261 | |
262 | return $name; |
263 | } |
264 | } |
265 | |
266 | /** @deprecated class alias since 1.41 */ |
267 | class_alias( TitleValue::class, 'TitleValue' ); |