ILIAS  trunk Revision v12.0_alpha-377-g3641b37b9db
Title.php
Go to the documentation of this file.
1<?php
2
19// patched: alex, 30.4.2019: Added missing defines
20define('NS_MAIN', "nsmain");
21define('NS_SPECIAL', "nsspecial");
22
23define('GAID_FOR_UPDATE', 1);
24
25# Title::newFromTitle maintains a cache to avoid
26# expensive re-normalization of commonly used titles.
27# On a batch operation this can become a memory leak
28# if not bounded. After hitting this many titles,
29# reset the cache.
30define('MW_TITLECACHE_MAX', 1000);
31
32# Constants for pr_cascade bitfield
33define('CASCADE', 1);
34
41class Title
42{
43 private static array $titleCache = array();
44 private static array $interwikiCache = array();
45 protected bool $mOldRestrictions;
46
56 public $mTextform; # Text form (spaces not underscores) of the main part
57 public $mUrlform; # URL-encoded form of the main part
58 public $mDbkeyform; # Main part with underscores
59 public $mNamespace; # Namespace index, i.e. one of the NS_xxxx constants
60 public $mInterwiki; # Interwiki prefix (or null string)
61 public $mFragment; # Title fragment (i.e. the bit after the #)
62 public $mArticleID; # Article ID, fetched from the link cache on demand
63 public $mLatestID; # ID of most recent revision
64 public $mRestrictions; # Array of groups allowed to edit this article
65 public $mCascadeRestriction; # Cascade restrictions on this page to included templates and images?
66 public $mRestrictionsExpiry; # When do the restrictions on this page expire?
67 public $mHasCascadingRestrictions; # Are cascading restrictions in effect on this page?
68 public $mCascadeRestrictionSources;# Where are the cascading restrictions coming from on this page?
69 public $mRestrictionsLoaded; # Boolean for initialisation on demand
70 public $mPrefixedText; # Text form including namespace/interwiki, initialised on demand
71 public $mDefaultNamespace; # Namespace index when there is no namespace
72 # Zero except in {{transclusion}} tags
73 public $mWatched; # Is $wgUser watching this page? NULL if unfilled, accessed through userIsWatching()
81 /* private */ public function __construct()
82 {
83 $this->mInterwiki = $this->mUrlform =
84 $this->mTextform = $this->mDbkeyform = '';
85 $this->mArticleID = -1;
86 $this->mNamespace = NS_MAIN;
87 $this->mRestrictionsLoaded = false;
88 $this->mRestrictions = array();
89 # Dont change the following, NS_MAIN is hardcoded in several place
90 # See bug #696
91 $this->mDefaultNamespace = NS_MAIN;
92 $this->mWatched = null;
93 $this->mLatestID = false;
94 $this->mOldRestrictions = false;
95 }
96
97
109 public static function newFromText($text, $defaultNamespace = NS_MAIN)
110 {
119 if ($defaultNamespace == NS_MAIN && isset(Title::$titleCache[$text])) {
121 }
122
126 $filteredText = Sanitizer::decodeCharReferences($text);
127
128 $t = new Title();
129 $t->mDbkeyform = str_replace(' ', '_', $filteredText);
130 $t->mDefaultNamespace = $defaultNamespace;
131
132 static $cachedcount = 0 ;
133 if ($t->secureAndSplit()) {
134 if ($defaultNamespace == NS_MAIN) {
135 if ($cachedcount >= MW_TITLECACHE_MAX) {
136 # Avoid memory leaks on mass operations...
137 Title::$titleCache = array();
138 $cachedcount = 0;
139 }
140 $cachedcount++;
142 }
143 return $t;
144 } else {
145 $ret = null;
146 return $ret;
147 }
148 }
149
150
151 #----------------------------------------------------------------------------
152 # Static functions
153 #----------------------------------------------------------------------------
154
155
160 public static function legalChars()
161 {
162 global $wgLegalTitleChars;
163
164 $wgLegalTitleChars = " %!\"$&'()*,\\-.\\/0-9:;=?@A-Z\\\\^_`a-z~\\x80-\\xFF+";
165
166 return $wgLegalTitleChars;
167 }
168
169
177 public function getInterwikiLink($key)
178 {
179 return "";
180 }
181
182 #----------------------------------------------------------------------------
183 # Other stuff
184 #----------------------------------------------------------------------------
185
191 public function getText()
192 {
193 return $this->mTextform;
194 }
195
200 public function getDBkey()
201 {
202 return $this->mDbkeyform;
203 }
208 public function getNamespace()
209 {
210 return $this->mNamespace;
211 }
216 public function getNsText()
217 {
218 global $wgContLang, $wgCanonicalNamespaceNames;
219
220 if ('' != $this->mInterwiki) {
221 // This probably shouldn't even happen. ohh man, oh yuck.
222 // But for interwiki transclusion it sometimes does.
223 // Shit. Shit shit shit.
224 //
225 // Use the canonical namespaces if possible to try to
226 // resolve a foreign namespace.
227 if (isset($wgCanonicalNamespaceNames[$this->mNamespace])) {
228 return $wgCanonicalNamespaceNames[$this->mNamespace];
229 }
230 }
231 return $wgContLang->getNsText($this->mNamespace);
232 }
237 public function getInterwiki()
238 {
239 return $this->mInterwiki;
240 }
245 public function getFragment()
246 {
247 return $this->mFragment;
248 }
249
258 /* private */ public function prefix($name)
259 {
260 $p = '';
261 if ('' != $this->mInterwiki) {
262 $p = $this->mInterwiki . ':';
263 }
264 if (0 != $this->mNamespace) {
265 $p .= $this->getNsText() . ':';
266 }
267 return $p . $name;
268 }
269
280 private function secureAndSplit()
281 {
282 global $wgContLang, $wgLocalInterwiki, $wgCapitalLinks;
283
284 # Initialisation
285 static $rxTc = false;
286 if (!$rxTc) {
287 # % is needed as well
288 $rxTc = '/[^' . Title::legalChars() . ']|%[0-9A-Fa-f]{2}/S';
289 }
290
291 $this->mInterwiki = $this->mFragment = '';
292 $this->mNamespace = $this->mDefaultNamespace; # Usually NS_MAIN
293
294 $dbkey = $this->mDbkeyform;
295
296 # Strip Unicode bidi override characters.
297 # Sometimes they slip into cut-n-pasted page titles, where the
298 # override chars get included in list displays.
299 $dbkey = str_replace("\xE2\x80\x8E", '', $dbkey); // 200E LEFT-TO-RIGHT MARK
300 $dbkey = str_replace("\xE2\x80\x8F", '', $dbkey); // 200F RIGHT-TO-LEFT MARK
301
302 # Clean up whitespace
303 #
304 $dbkey = preg_replace('/[ _]+/', '_', $dbkey);
305 $dbkey = trim($dbkey, '_');
306
307 if ('' == $dbkey) {
308 return false;
309 }
310
311 if (false !== strpos($dbkey, UTF8_REPLACEMENT)) {
312 # Contained illegal UTF-8 sequences or forbidden Unicode chars.
313 return false;
314 }
315
316 $this->mDbkeyform = $dbkey;
317
318 # Initial colon indicates main namespace rather than specified default
319 # but should not create invalid {ns,title} pairs such as {0,Project:Foo}
320 if (':' == $dbkey[0]) {
321 $this->mNamespace = NS_MAIN;
322 $dbkey = substr($dbkey, 1); # remove the colon but continue processing
323 $dbkey = trim($dbkey, '_'); # remove any subsequent whitespace
324 }
325
326 # Namespace or interwiki prefix
327 $firstPass = true;
328 do {
329 $m = array();
330 if (preg_match("/^(.+?)_*:_*(.*)$/S", $dbkey, $m)) {
331 $p = $m[1];
332 if ($ns = $wgContLang->getNsIndex($p)) {
333 # Ordinary namespace
334 $dbkey = $m[2];
335 $this->mNamespace = $ns;
336 } elseif ($this->getInterwikiLink($p)) {
337 if (!$firstPass) {
338 # Can't make a local interwiki link to an interwiki link.
339 # That's just crazy!
340 return false;
341 }
342
343 # Interwiki link
344 $dbkey = $m[2];
345 $this->mInterwiki = $wgContLang->lc($p);
346
347 # Redundant interwiki prefix to the local wiki
348 if (0 == strcasecmp($this->mInterwiki, $wgLocalInterwiki)) {
349 if ($dbkey == '') {
350 # Can't have an empty self-link
351 return false;
352 }
353 $this->mInterwiki = '';
354 $firstPass = false;
355 # Do another namespace split...
356 continue;
357 }
358
359 # If there's an initial colon after the interwiki, that also
360 # resets the default namespace
361 if ($dbkey !== '' && $dbkey[0] == ':') {
362 $this->mNamespace = NS_MAIN;
363 $dbkey = substr($dbkey, 1);
364 }
365 }
366 # If there's no recognized interwiki or namespace,
367 # then let the colon expression be part of the title.
368 }
369 break;
370 } while (true);
371
372 # We already know that some pages won't be in the database!
373 #
374 if ('' != $this->mInterwiki || NS_SPECIAL == $this->mNamespace) {
375 $this->mArticleID = 0;
376 }
377 $fragment = strstr($dbkey, '#');
378 if (false !== $fragment) {
379 $this->setFragment($fragment);
380 $dbkey = substr($dbkey, 0, strlen($dbkey) - strlen($fragment));
381 # remove whitespace again: prevents "Foo_bar_#"
382 # becoming "Foo_bar_"
383 $dbkey = preg_replace('/_*$/', '', $dbkey);
384 }
385
386 # Reject illegal characters.
387 #
388 if (preg_match($rxTc, $dbkey)) {
389 return false;
390 }
391
397 if (strpos($dbkey, '.') !== false &&
398 ($dbkey === '.' || $dbkey === '..' ||
399 strpos($dbkey, './') === 0 ||
400 strpos($dbkey, '../') === 0 ||
401 strpos($dbkey, '/./') !== false ||
402 strpos($dbkey, '/../') !== false)) {
403 return false;
404 }
405
409 if (strpos($dbkey, '~~~') !== false) {
410 return false;
411 }
412
420 if (($this->mNamespace != NS_SPECIAL && strlen($dbkey) > 255) ||
421 strlen($dbkey) > 512) {
422 return false;
423 }
424
433 if ($wgCapitalLinks && $this->mInterwiki == '') {
434 $dbkey = $wgContLang->ucfirst($dbkey);
435 }
436
442 if ($dbkey == '' &&
443 $this->mInterwiki == '' &&
444 $this->mNamespace != NS_MAIN) {
445 return false;
446 }
447
448 // Any remaining initial :s are illegal.
449 if ($dbkey !== '' && ':' == $dbkey[0]) {
450 return false;
451 }
452
453 # Fill fields
454 $this->mDbkeyform = $dbkey;
455 $this->mUrlform = ilWikiUtil::wfUrlencode($dbkey);
456
457 $this->mTextform = str_replace('_', ' ', $dbkey);
458
459 return true;
460 }
461
471 public function setFragment($fragment)
472 {
473 $this->mFragment = str_replace('_', ' ', substr($fragment, 1));
474 }
475
482 public function equals($title)
483 {
484 // Note: === is necessary for proper matching of number-like titles.
485 return $this->getInterwiki() === $title->getInterwiki()
486 && $this->getNamespace() == $title->getNamespace()
487 && $this->getDBkey() === $title->getDBkey();
488 }
489}
const NS_MAIN
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
Definition: Title.php:20
const MW_TITLECACHE_MAX
Definition: Title.php:30
const NS_SPECIAL
Definition: Title.php:21
static decodeCharReferences($text)
Decode any character references, numeric or named entities, in the text and return a UTF-8 string.
Definition: Sanitizer.php:374
Title class.
Definition: Title.php:42
getNamespace()
Get the namespace index, i.e.
Definition: Title.php:208
$mHasCascadingRestrictions
Definition: Title.php:67
$mInterwiki
Definition: Title.php:60
$mTextform
All member variables should be considered private Please use the accessor functions.
Definition: Title.php:56
secureAndSplit()
Secure and split - main initialisation function for this object.
Definition: Title.php:280
$mArticleID
Definition: Title.php:62
$mNamespace
Definition: Title.php:59
getFragment()
Get the Title fragment (i.e.
Definition: Title.php:245
$mWatched
Definition: Title.php:73
prefix($name)
Prefix some arbitrary text with the namespace or interwiki prefix of this object.
Definition: Title.php:258
static newFromText($text, $defaultNamespace=NS_MAIN)
Create a new Title from text, such as what one would find in a link.
Definition: Title.php:109
$mDbkeyform
Definition: Title.php:58
$mRestrictionsLoaded
Definition: Title.php:69
$mCascadeRestrictionSources
Definition: Title.php:68
static legalChars()
Get a regex character class describing the legal characters in a link.
Definition: Title.php:160
getNsText()
Get the namespace text.
Definition: Title.php:216
equals($title)
Compare with another title.
Definition: Title.php:482
static array $interwikiCache
Definition: Title.php:44
$mRestrictionsExpiry
Definition: Title.php:66
getDBkey()
Get the main part with underscores.
Definition: Title.php:200
$mRestrictions
Definition: Title.php:64
getText()
Simple accessors.
Definition: Title.php:191
$mUrlform
Definition: Title.php:57
__construct()
#-
Definition: Title.php:81
$mLatestID
Definition: Title.php:63
static array $titleCache
Definition: Title.php:43
setFragment($fragment)
Set the fragment for this title This is kind of bad, since except for this rarely-used function,...
Definition: Title.php:471
$mFragment
Definition: Title.php:61
bool $mOldRestrictions
Definition: Title.php:45
$mCascadeRestriction
Definition: Title.php:65
getInterwikiLink($key)
Returns the URL associated with an interwiki prefix.
Definition: Title.php:177
$mPrefixedText
Definition: Title.php:70
getInterwiki()
Get the interwiki prefix (or null string)
Definition: Title.php:237
$mDefaultNamespace
Definition: Title.php:71
static wfUrlencode(string $s)
form(?array $class_path, string $cmd, string $submit_caption="")
link(string $caption, string $href, bool $new_viewport=false)
to(\GdImage $image, ?int $quality=null)
Currently this is the only way to make a FileStream from a GD image resource.
$text
Definition: xapiexit.php:21