MediaWiki REL1_34
AbstractContent.php
Go to the documentation of this file.
1<?php
34abstract class AbstractContent implements Content {
43 protected $model_id;
44
50 public function __construct( $modelId = null ) {
51 $this->model_id = $modelId;
52 }
53
60 public function getModel() {
61 return $this->model_id;
62 }
63
72 protected function checkModelID( $modelId ) {
73 if ( $modelId !== $this->model_id ) {
74 throw new MWException(
75 "Bad content model: " .
76 "expected {$this->model_id} " .
77 "but got $modelId."
78 );
79 }
80 }
81
88 public function getContentHandler() {
89 return ContentHandler::getForContent( $this );
90 }
91
98 public function getDefaultFormat() {
99 return $this->getContentHandler()->getDefaultFormat();
100 }
101
108 public function getSupportedFormats() {
109 return $this->getContentHandler()->getSupportedFormats();
110 }
111
121 public function isSupportedFormat( $format ) {
122 if ( !$format ) {
123 return true; // this means "use the default"
124 }
125
126 return $this->getContentHandler()->isSupportedFormat( $format );
127 }
128
136 protected function checkFormat( $format ) {
137 if ( !$this->isSupportedFormat( $format ) ) {
138 throw new MWException(
139 "Format $format is not supported for content model " .
140 $this->getModel()
141 );
142 }
143 }
144
154 public function serialize( $format = null ) {
155 return $this->getContentHandler()->serializeContent( $this, $format );
156 }
157
165 public function isEmpty() {
166 return $this->getSize() === 0;
167 }
168
178 public function isValid() {
179 return true;
180 }
181
202 public function equals( Content $that = null ) {
203 if ( is_null( $that ) ) {
204 return false;
205 }
206
207 if ( $that === $this ) {
208 return true;
209 }
210
211 if ( $that->getModel() !== $this->getModel() ) {
212 return false;
213 }
214
215 // For type safety. Needed for odd cases like MessageContent using CONTENT_MODEL_WIKITEXT
216 if ( get_class( $that ) !== get_class( $this ) ) {
217 return false;
218 }
219
220 return $this->equalsInternal( $that );
221 }
222
241 protected function equalsInternal( Content $that ) {
242 return $this->serialize() === $that->serialize();
243 }
244
268 public function getSecondaryDataUpdates( Title $title, Content $old = null,
269 $recursive = true, ParserOutput $parserOutput = null
270 ) {
271 if ( $parserOutput === null ) {
272 $parserOutput = $this->getParserOutput( $title, null, null, false );
273 }
274
275 $updates = [
276 new LinksUpdate( $title, $parserOutput, $recursive )
277 ];
278
279 Hooks::run( 'SecondaryDataUpdates', [ $title, $old, $recursive, $parserOutput, &$updates ] );
280
281 return $updates;
282 }
283
291 public function getRedirectChain() {
292 global $wgMaxRedirects;
293 $title = $this->getRedirectTarget();
294 if ( is_null( $title ) ) {
295 return null;
296 }
297 // recursive check to follow double redirects
298 $recurse = $wgMaxRedirects;
299 $titles = [ $title ];
300 while ( --$recurse > 0 ) {
301 if ( $title->isRedirect() ) {
302 $page = WikiPage::factory( $title );
303 $newtitle = $page->getRedirectTarget();
304 } else {
305 break;
306 }
307 // Redirects to some special pages are not permitted
308 if ( $newtitle instanceof Title && $newtitle->isValidRedirectTarget() ) {
309 // The new title passes the checks, so make that our current
310 // title so that further recursion can be checked
311 $title = $newtitle;
312 $titles[] = $newtitle;
313 } else {
314 break;
315 }
316 }
317
318 return $titles;
319 }
320
330 public function getRedirectTarget() {
331 return null;
332 }
333
343 public function getUltimateRedirectTarget() {
344 $titles = $this->getRedirectChain();
345
346 return $titles ? array_pop( $titles ) : null;
347 }
348
356 public function isRedirect() {
357 return $this->getRedirectTarget() !== null;
358 }
359
372 public function updateRedirect( Title $target ) {
373 return $this;
374 }
375
384 public function getSection( $sectionId ) {
385 return null;
386 }
387
398 public function replaceSection( $sectionId, Content $with, $sectionTitle = '' ) {
399 return null;
400 }
401
412 public function preSaveTransform( Title $title, User $user, ParserOptions $popts ) {
413 return $this;
414 }
415
424 public function addSectionHeader( $header ) {
425 return $this;
426 }
427
438 public function preloadTransform( Title $title, ParserOptions $popts, $params = [] ) {
439 return $this;
440 }
441
453 public function prepareSave( WikiPage $page, $flags, $parentRevId, User $user ) {
454 if ( $this->isValid() ) {
455 return Status::newGood();
456 } else {
457 return Status::newFatal( "invalid-content-data" );
458 }
459 }
460
471 public function getDeletionUpdates( WikiPage $page, ParserOutput $parserOutput = null ) {
472 return [
473 new LinksDeletionUpdate( $page ),
474 ];
475 }
476
489 public function matchMagicWord( MagicWord $word ) {
490 return false;
491 }
492
504 public function convert( $toModel, $lossy = '' ) {
505 if ( $this->getModel() === $toModel ) {
506 // nothing to do, shorten out.
507 return $this;
508 }
509
510 $lossy = ( $lossy === 'lossy' ); // string flag, convert to boolean for convenience
511 $result = false;
512
513 Hooks::run( 'ConvertContent', [ $this, $toModel, $lossy, &$result ] );
514
515 return $result;
516 }
517
538 public function getParserOutput( Title $title, $revId = null,
539 ParserOptions $options = null, $generateHtml = true
540 ) {
541 if ( $options === null ) {
542 $options = ParserOptions::newCanonical( 'canonical' );
543 }
544
545 $po = new ParserOutput();
546 $options->registerWatcher( [ $po, 'recordOption' ] );
547
548 if ( Hooks::run( 'ContentGetParserOutput',
549 [ $this, $title, $revId, $options, $generateHtml, &$po ] )
550 ) {
551 // Save and restore the old value, just in case something is reusing
552 // the ParserOptions object in some weird way.
553 $oldRedir = $options->getRedirectTarget();
554 $options->setRedirectTarget( $this->getRedirectTarget() );
555 $this->fillParserOutput( $title, $revId, $options, $generateHtml, $po );
556 $options->setRedirectTarget( $oldRedir );
557 }
558
559 Hooks::run( 'ContentAlterParserOutput', [ $this, $title, $po ] );
560 $options->registerWatcher( null );
561
562 return $po;
563 }
564
586 protected function fillParserOutput( Title $title, $revId,
587 ParserOptions $options, $generateHtml, ParserOutput &$output
588 ) {
589 // Don't make abstract, so subclasses that override getParserOutput() directly don't fail.
590 throw new MWException( 'Subclasses of AbstractContent must override fillParserOutput!' );
591 }
592}
serialize()
$wgMaxRedirects
Max number of redirects to follow when resolving redirects.
Base implementation for content objects.
checkModelID( $modelId)
getParserOutput(Title $title, $revId=null, ParserOptions $options=null, $generateHtml=true)
Returns a ParserOutput object containing information derived from this content.
equals(Content $that=null)
Decides whether two Content objects are equal.
getSection( $sectionId)
__construct( $modelId=null)
preSaveTransform(Title $title, User $user, ParserOptions $popts)
convert( $toModel, $lossy='')
This base implementation calls the hook ConvertContent to enable custom conversions.
updateRedirect(Title $target)
This default implementation always returns $this.
isSupportedFormat( $format)
fillParserOutput(Title $title, $revId, ParserOptions $options, $generateHtml, ParserOutput &$output)
Fills the provided ParserOutput with information derived from the content.
prepareSave(WikiPage $page, $flags, $parentRevId, User $user)
isValid()
Subclasses may override this to implement (light weight) validation.
serialize( $format=null)
addSectionHeader( $header)
matchMagicWord(MagicWord $word)
This default implementation always returns false.
getDeletionUpdates(WikiPage $page, ParserOutput $parserOutput=null)
$model_id
Name of the content model this Content object represents.
getSecondaryDataUpdates(Title $title, Content $old=null, $recursive=true, ParserOutput $parserOutput=null)
Returns a list of DataUpdate objects for recording information about this Content in some secondary d...
preloadTransform(Title $title, ParserOptions $popts, $params=[])
equalsInternal(Content $that)
Checks whether $that is logically equal to this Content object.
replaceSection( $sectionId, Content $with, $sectionTitle='')
getRedirectTarget()
Subclasses that implement redirects should override this.
Update object handling the cleanup of links tables after a page was deleted.
Class the manages updates of *_link tables as well as similar extension-managed tables.
MediaWiki exception.
This class encapsulates "magic words" such as "#redirect", NOTOC, etc.
Definition MagicWord.php:57
Set options of the Parser.
Represents a title within MediaWiki.
Definition Title.php:42
isValidRedirectTarget()
Check if this Title is a valid redirect target.
Definition Title.php:4492
The User object encapsulates all of the user-specific settings (user_id, name, rights,...
Definition User.php:51
Class representing a MediaWiki article and history.
Definition WikiPage.php:47
Base interface for content objects.
Definition Content.php:34
getSize()
Returns the content's nominal size in "bogo-bytes".
serialize( $format=null)
Convenience method for serializing this Content object.
$header