[ Index ]

PHP Cross Reference of MediaWiki-1.24.0

title

Body

[close]

/includes/content/ -> AbstractContent.php (source)

   1  <?php
   2  /**
   3   * A content object represents page content, e.g. the text to show on a page.
   4   * Content objects have no knowledge about how they relate to Wiki pages.
   5   *
   6   * This program is free software; you can redistribute it and/or modify
   7   * it under the terms of the GNU General Public License as published by
   8   * the Free Software Foundation; either version 2 of the License, or
   9   * (at your option) any later version.
  10   *
  11   * This program is distributed in the hope that it will be useful,
  12   * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14   * GNU General Public License for more details.
  15   *
  16   * You should have received a copy of the GNU General Public License along
  17   * with this program; if not, write to the Free Software Foundation, Inc.,
  18   * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  19   * http://www.gnu.org/copyleft/gpl.html
  20   *
  21   * @since 1.21
  22   *
  23   * @file
  24   * @ingroup Content
  25   *
  26   * @author Daniel Kinzler
  27   */
  28  
  29  /**
  30   * Base implementation for content objects.
  31   *
  32   * @ingroup Content
  33   */
  34  abstract class AbstractContent implements Content {
  35      /**
  36       * Name of the content model this Content object represents.
  37       * Use with CONTENT_MODEL_XXX constants
  38       *
  39       * @since 1.21
  40       *
  41       * @var string $model_id
  42       */
  43      protected $model_id;
  44  
  45      /**
  46       * @param string $modelId
  47       *
  48       * @since 1.21
  49       */
  50  	public function __construct( $modelId = null ) {
  51          $this->model_id = $modelId;
  52      }
  53  
  54      /**
  55       * @since 1.21
  56       *
  57       * @see Content::getModel
  58       */
  59  	public function getModel() {
  60          return $this->model_id;
  61      }
  62  
  63      /**
  64       * @since 1.21
  65       *
  66       * @param string $modelId The model to check
  67       *
  68       * @throws MWException If the provided ID is not the ID of the content model supported by this
  69       * Content object.
  70       */
  71  	protected function checkModelID( $modelId ) {
  72          if ( $modelId !== $this->model_id ) {
  73              throw new MWException(
  74                  "Bad content model: " .
  75                  "expected {$this->model_id} " .
  76                  "but got $modelId."
  77              );
  78          }
  79      }
  80  
  81      /**
  82       * @since 1.21
  83       *
  84       * @see Content::getContentHandler
  85       */
  86  	public function getContentHandler() {
  87          return ContentHandler::getForContent( $this );
  88      }
  89  
  90      /**
  91       * @since 1.21
  92       *
  93       * @see Content::getDefaultFormat
  94       */
  95  	public function getDefaultFormat() {
  96          return $this->getContentHandler()->getDefaultFormat();
  97      }
  98  
  99      /**
 100       * @since 1.21
 101       *
 102       * @see Content::getSupportedFormats
 103       */
 104  	public function getSupportedFormats() {
 105          return $this->getContentHandler()->getSupportedFormats();
 106      }
 107  
 108      /**
 109       * @since 1.21
 110       *
 111       * @param string $format
 112       *
 113       * @return bool
 114       *
 115       * @see Content::isSupportedFormat
 116       */
 117  	public function isSupportedFormat( $format ) {
 118          if ( !$format ) {
 119              return true; // this means "use the default"
 120          }
 121  
 122          return $this->getContentHandler()->isSupportedFormat( $format );
 123      }
 124  
 125      /**
 126       * @since 1.21
 127       *
 128       * @param string $format The serialization format to check.
 129       *
 130       * @throws MWException If the format is not supported by this content handler.
 131       */
 132  	protected function checkFormat( $format ) {
 133          if ( !$this->isSupportedFormat( $format ) ) {
 134              throw new MWException(
 135                  "Format $format is not supported for content model " .
 136                  $this->getModel()
 137              );
 138          }
 139      }
 140  
 141      /**
 142       * @since 1.21
 143       *
 144       * @param string $format
 145       *
 146       * @return string
 147       *
 148       * @see Content::serialize
 149       */
 150  	public function serialize( $format = null ) {
 151          return $this->getContentHandler()->serializeContent( $this, $format );
 152      }
 153  
 154      /**
 155       * @since 1.21
 156       *
 157       * @return bool
 158       *
 159       * @see Content::isEmpty
 160       */
 161  	public function isEmpty() {
 162          return $this->getSize() === 0;
 163      }
 164  
 165      /**
 166       * Subclasses may override this to implement (light weight) validation.
 167       *
 168       * @since 1.21
 169       *
 170       * @return bool Always true.
 171       *
 172       * @see Content::isValid
 173       */
 174  	public function isValid() {
 175          return true;
 176      }
 177  
 178      /**
 179       * @since 1.21
 180       *
 181       * @param Content $that
 182       *
 183       * @return bool
 184       *
 185       * @see Content::equals
 186       */
 187  	public function equals( Content $that = null ) {
 188          if ( is_null( $that ) ) {
 189              return false;
 190          }
 191  
 192          if ( $that === $this ) {
 193              return true;
 194          }
 195  
 196          if ( $that->getModel() !== $this->getModel() ) {
 197              return false;
 198          }
 199  
 200          return $this->getNativeData() === $that->getNativeData();
 201      }
 202  
 203      /**
 204       * Returns a list of DataUpdate objects for recording information about this
 205       * Content in some secondary data store.
 206       *
 207       * This default implementation calls
 208       * $this->getParserOutput( $content, $title, null, null, false ),
 209       * and then calls getSecondaryDataUpdates( $title, $recursive ) on the
 210       * resulting ParserOutput object.
 211       *
 212       * Subclasses may override this to determine the secondary data updates more
 213       * efficiently, preferably without the need to generate a parser output object.
 214       *
 215       * @since 1.21
 216       *
 217       * @param Title $title
 218       * @param Content $old
 219       * @param bool $recursive
 220       * @param ParserOutput $parserOutput
 221       *
 222       * @return DataUpdate[]
 223       *
 224       * @see Content::getSecondaryDataUpdates()
 225       */
 226  	public function getSecondaryDataUpdates( Title $title, Content $old = null,
 227          $recursive = true, ParserOutput $parserOutput = null ) {
 228          if ( $parserOutput === null ) {
 229              $parserOutput = $this->getParserOutput( $title, null, null, false );
 230          }
 231  
 232          return $parserOutput->getSecondaryDataUpdates( $title, $recursive );
 233      }
 234  
 235      /**
 236       * @since 1.21
 237       *
 238       * @return Title[]|null
 239       *
 240       * @see Content::getRedirectChain
 241       */
 242  	public function getRedirectChain() {
 243          global $wgMaxRedirects;
 244          $title = $this->getRedirectTarget();
 245          if ( is_null( $title ) ) {
 246              return null;
 247          }
 248          // recursive check to follow double redirects
 249          $recurse = $wgMaxRedirects;
 250          $titles = array( $title );
 251          while ( --$recurse > 0 ) {
 252              if ( $title->isRedirect() ) {
 253                  $page = WikiPage::factory( $title );
 254                  $newtitle = $page->getRedirectTarget();
 255              } else {
 256                  break;
 257              }
 258              // Redirects to some special pages are not permitted
 259              if ( $newtitle instanceof Title && $newtitle->isValidRedirectTarget() ) {
 260                  // The new title passes the checks, so make that our current
 261                  // title so that further recursion can be checked
 262                  $title = $newtitle;
 263                  $titles[] = $newtitle;
 264              } else {
 265                  break;
 266              }
 267          }
 268  
 269          return $titles;
 270      }
 271  
 272      /**
 273       * Subclasses that implement redirects should override this.
 274       *
 275       * @since 1.21
 276       *
 277       * @return null
 278       *
 279       * @see Content::getRedirectTarget
 280       */
 281  	public function getRedirectTarget() {
 282          return null;
 283      }
 284  
 285      /**
 286       * @note Migrated here from Title::newFromRedirectRecurse.
 287       *
 288       * @since 1.21
 289       *
 290       * @return Title|null
 291       *
 292       * @see Content::getUltimateRedirectTarget
 293       */
 294  	public function getUltimateRedirectTarget() {
 295          $titles = $this->getRedirectChain();
 296  
 297          return $titles ? array_pop( $titles ) : null;
 298      }
 299  
 300      /**
 301       * @since 1.21
 302       *
 303       * @return bool
 304       *
 305       * @see Content::isRedirect
 306       */
 307  	public function isRedirect() {
 308          return $this->getRedirectTarget() !== null;
 309      }
 310  
 311      /**
 312       * This default implementation always returns $this.
 313       * Subclasses that implement redirects should override this.
 314       *
 315       * @since 1.21
 316       *
 317       * @param Title $target
 318       *
 319       * @return Content $this
 320       *
 321       * @see Content::updateRedirect
 322       */
 323  	public function updateRedirect( Title $target ) {
 324          return $this;
 325      }
 326  
 327      /**
 328       * @since 1.21
 329       *
 330       * @return null
 331       *
 332       * @see Content::getSection
 333       */
 334  	public function getSection( $sectionId ) {
 335          return null;
 336      }
 337  
 338      /**
 339       * @since 1.21
 340       *
 341       * @return null
 342       *
 343       * @see Content::replaceSection
 344       */
 345  	public function replaceSection( $sectionId, Content $with, $sectionTitle = '' ) {
 346          return null;
 347      }
 348  
 349      /**
 350       * @since 1.21
 351       *
 352       * @return Content $this
 353       *
 354       * @see Content::preSaveTransform
 355       */
 356  	public function preSaveTransform( Title $title, User $user, ParserOptions $popts ) {
 357          return $this;
 358      }
 359  
 360      /**
 361       * @since 1.21
 362       *
 363       * @return Content $this
 364       *
 365       * @see Content::addSectionHeader
 366       */
 367  	public function addSectionHeader( $header ) {
 368          return $this;
 369      }
 370  
 371      /**
 372       * @since 1.21
 373       *
 374       * @return Content $this
 375       *
 376       * @see Content::preloadTransform
 377       */
 378  	public function preloadTransform( Title $title, ParserOptions $popts, $params = array() ) {
 379          return $this;
 380      }
 381  
 382      /**
 383       * @since 1.21
 384       *
 385       * @return Status
 386       *
 387       * @see Content::prepareSave
 388       */
 389  	public function prepareSave( WikiPage $page, $flags, $baseRevId, User $user ) {
 390          if ( $this->isValid() ) {
 391              return Status::newGood();
 392          } else {
 393              return Status::newFatal( "invalid-content-data" );
 394          }
 395      }
 396  
 397      /**
 398       * @since 1.21
 399       *
 400       * @param WikiPage $page
 401       * @param ParserOutput $parserOutput
 402       *
 403       * @return LinksDeletionUpdate[]
 404       *
 405       * @see Content::getDeletionUpdates
 406       */
 407  	public function getDeletionUpdates( WikiPage $page, ParserOutput $parserOutput = null ) {
 408          return array(
 409              new LinksDeletionUpdate( $page ),
 410          );
 411      }
 412  
 413      /**
 414       * This default implementation always returns false. Subclasses may override
 415       * this to supply matching logic.
 416       *
 417       * @since 1.21
 418       *
 419       * @param MagicWord $word
 420       *
 421       * @return bool Always false.
 422       *
 423       * @see Content::matchMagicWord
 424       */
 425  	public function matchMagicWord( MagicWord $word ) {
 426          return false;
 427      }
 428  
 429      /**
 430       * This base implementation calls the hook ConvertContent to enable custom conversions.
 431       * Subclasses may override this to implement conversion for "their" content model.
 432       *
 433       * @param string $toModel
 434       * @param string $lossy
 435       *
 436       * @return Content|bool
 437       *
 438       * @see Content::convert()
 439       */
 440  	public function convert( $toModel, $lossy = '' ) {
 441          if ( $this->getModel() === $toModel ) {
 442              //nothing to do, shorten out.
 443              return $this;
 444          }
 445  
 446          $lossy = ( $lossy === 'lossy' ); // string flag, convert to boolean for convenience
 447          $result = false;
 448  
 449          wfRunHooks( 'ConvertContent', array( $this, $toModel, $lossy, &$result ) );
 450  
 451          return $result;
 452      }
 453  
 454      /**
 455       * Returns a ParserOutput object containing information derived from this content.
 456       * Most importantly, unless $generateHtml was false, the return value contains an
 457       * HTML representation of the content.
 458       *
 459       * Subclasses that want to control the parser output may override this, but it is
 460       * preferred to override fillParserOutput() instead.
 461       *
 462       * Subclasses that override getParserOutput() itself should take care to call the
 463       * ContentGetParserOutput hook.
 464       *
 465       * @since 1.24
 466       *
 467       * @param Title $title Context title for parsing
 468       * @param int|null $revId Revision ID (for {{REVISIONID}})
 469       * @param ParserOptions|null $options Parser options
 470       * @param bool $generateHtml Whether or not to generate HTML
 471       *
 472       * @return ParserOutput Containing information derived from this content.
 473       */
 474  	public function getParserOutput( Title $title, $revId = null,
 475          ParserOptions $options = null, $generateHtml = true
 476      ) {
 477          if ( $options === null ) {
 478              $options = $this->getContentHandler()->makeParserOptions( 'canonical' );
 479          }
 480  
 481          $po = new ParserOutput();
 482  
 483          if ( wfRunHooks( 'ContentGetParserOutput',
 484              array( $this, $title, $revId, $options, $generateHtml, &$po ) ) ) {
 485  
 486              // Save and restore the old value, just in case something is reusing
 487              // the ParserOptions object in some weird way.
 488              $oldRedir = $options->getRedirectTarget();
 489              $options->setRedirectTarget( $this->getRedirectTarget() );
 490              $this->fillParserOutput( $title, $revId, $options, $generateHtml, $po );
 491              $options->setRedirectTarget( $oldRedir );
 492          }
 493  
 494          return $po;
 495      }
 496  
 497      /**
 498       * Fills the provided ParserOutput with information derived from the content.
 499       * Unless $generateHtml was false, this includes an HTML representation of the content.
 500       *
 501       * This is called by getParserOutput() after consulting the ContentGetParserOutput hook.
 502       * Subclasses are expected to override this method (or getParserOutput(), if need be).
 503       * Subclasses of TextContent should generally override getHtml() instead.
 504       *
 505       * This placeholder implementation always throws an exception.
 506       *
 507       * @since 1.24
 508       *
 509       * @param Title $title Context title for parsing
 510       * @param int|null $revId Revision ID (for {{REVISIONID}})
 511       * @param ParserOptions $options Parser options
 512       * @param bool $generateHtml Whether or not to generate HTML
 513       * @param ParserOutput &$output The output object to fill (reference).
 514       *
 515       * @throws MWException
 516       */
 517  	protected function fillParserOutput( Title $title, $revId,
 518          ParserOptions $options, $generateHtml, ParserOutput &$output
 519      ) {
 520          // Don't make abstract, so subclasses that override getParserOutput() directly don't fail.
 521          throw new MWException( 'Subclasses of AbstractContent must override fillParserOutput!' );
 522      }
 523  }


Generated: Fri Nov 28 14:03:12 2014 Cross-referenced by PHPXref 0.7.1