summaryrefslogtreecommitdiff
path: root/includes/content/AbstractContent.php
diff options
context:
space:
mode:
Diffstat (limited to 'includes/content/AbstractContent.php')
-rw-r--r--includes/content/AbstractContent.php277
1 files changed, 178 insertions, 99 deletions
diff --git a/includes/content/AbstractContent.php b/includes/content/AbstractContent.php
index 137efb8a..9d257a6a 100644
--- a/includes/content/AbstractContent.php
+++ b/includes/content/AbstractContent.php
@@ -32,7 +32,6 @@
* @ingroup Content
*/
abstract class AbstractContent implements Content {
-
/**
* Name of the content model this Content object represents.
* Use with CONTENT_MODEL_XXX constants
@@ -44,7 +43,7 @@ abstract class AbstractContent implements Content {
protected $model_id;
/**
- * @param string|null $modelId
+ * @param string $modelId
*
* @since 1.21
*/
@@ -53,23 +52,21 @@ abstract class AbstractContent implements Content {
}
/**
- * @see Content::getModel
- *
* @since 1.21
+ *
+ * @see Content::getModel
*/
public function getModel() {
return $this->model_id;
}
/**
- * Throws an MWException if $model_id is not the id of the content model
- * supported by this Content object.
- *
* @since 1.21
*
* @param string $modelId The model to check
*
- * @throws MWException
+ * @throws MWException If the provided ID is not the ID of the content model supported by this
+ * Content object.
*/
protected function checkModelID( $modelId ) {
if ( $modelId !== $this->model_id ) {
@@ -82,40 +79,40 @@ abstract class AbstractContent implements Content {
}
/**
- * @see Content::getContentHandler
- *
* @since 1.21
+ *
+ * @see Content::getContentHandler
*/
public function getContentHandler() {
return ContentHandler::getForContent( $this );
}
/**
- * @see Content::getDefaultFormat
- *
* @since 1.21
+ *
+ * @see Content::getDefaultFormat
*/
public function getDefaultFormat() {
return $this->getContentHandler()->getDefaultFormat();
}
/**
- * @see Content::getSupportedFormats
- *
* @since 1.21
+ *
+ * @see Content::getSupportedFormats
*/
public function getSupportedFormats() {
return $this->getContentHandler()->getSupportedFormats();
}
/**
- * @see Content::isSupportedFormat
+ * @since 1.21
*
* @param string $format
*
- * @since 1.21
+ * @return bool
*
- * @return boolean
+ * @see Content::isSupportedFormat
*/
public function isSupportedFormat( $format ) {
if ( !$format ) {
@@ -126,13 +123,11 @@ abstract class AbstractContent implements Content {
}
/**
- * Throws an MWException if $this->isSupportedFormat( $format ) does not
- * return true.
- *
* @since 1.21
*
- * @param string $format
- * @throws MWException
+ * @param string $format The serialization format to check.
+ *
+ * @throws MWException If the format is not supported by this content handler.
*/
protected function checkFormat( $format ) {
if ( !$this->isSupportedFormat( $format ) ) {
@@ -144,48 +139,50 @@ abstract class AbstractContent implements Content {
}
/**
- * @see Content::serialize
- *
- * @param string|null $format
- *
* @since 1.21
*
+ * @param string $format
+ *
* @return string
+ *
+ * @see Content::serialize
*/
public function serialize( $format = null ) {
return $this->getContentHandler()->serializeContent( $this, $format );
}
/**
- * @see Content::isEmpty
- *
* @since 1.21
*
- * @return boolean
+ * @return bool
+ *
+ * @see Content::isEmpty
*/
public function isEmpty() {
return $this->getSize() === 0;
}
/**
- * @see Content::isValid
+ * Subclasses may override this to implement (light weight) validation.
*
* @since 1.21
*
- * @return boolean
+ * @return bool Always true.
+ *
+ * @see Content::isValid
*/
public function isValid() {
return true;
}
/**
- * @see Content::equals
- *
* @since 1.21
*
- * @param Content|null $that
+ * @param Content $that
+ *
+ * @return bool
*
- * @return boolean
+ * @see Content::equals
*/
public function equals( Content $that = null ) {
if ( is_null( $that ) ) {
@@ -215,26 +212,19 @@ abstract class AbstractContent implements Content {
* Subclasses may override this to determine the secondary data updates more
* efficiently, preferably without the need to generate a parser output object.
*
- * @see Content::getSecondaryDataUpdates()
+ * @since 1.21
*
- * @param $title Title The context for determining the necessary updates
- * @param $old Content|null An optional Content object representing the
- * previous content, i.e. the content being replaced by this Content
- * object.
- * @param $recursive boolean Whether to include recursive updates (default:
- * false).
- * @param $parserOutput ParserOutput|null Optional ParserOutput object.
- * Provide if you have one handy, to avoid re-parsing of the content.
+ * @param Title $title
+ * @param Content $old
+ * @param bool $recursive
+ * @param ParserOutput $parserOutput
*
- * @return Array. A list of DataUpdate objects for putting information
- * about this content object somewhere.
+ * @return DataUpdate[]
*
- * @since 1.21
+ * @see Content::getSecondaryDataUpdates()
*/
- public function getSecondaryDataUpdates( Title $title,
- Content $old = null,
- $recursive = true, ParserOutput $parserOutput = null
- ) {
+ public function getSecondaryDataUpdates( Title $title, Content $old = null,
+ $recursive = true, ParserOutput $parserOutput = null ) {
if ( $parserOutput === null ) {
$parserOutput = $this->getParserOutput( $title, null, null, false );
}
@@ -243,9 +233,11 @@ abstract class AbstractContent implements Content {
}
/**
- * @see Content::getRedirectChain
- *
* @since 1.21
+ *
+ * @return Title[]|null
+ *
+ * @see Content::getRedirectChain
*/
public function getRedirectChain() {
global $wgMaxRedirects;
@@ -264,7 +256,7 @@ abstract class AbstractContent implements Content {
break;
}
// Redirects to some special pages are not permitted
- if ( $newtitle instanceOf Title && $newtitle->isValidRedirectTarget() ) {
+ if ( $newtitle instanceof Title && $newtitle->isValidRedirectTarget() ) {
// The new title passes the checks, so make that our current
// title so that further recursion can be checked
$title = $newtitle;
@@ -273,104 +265,126 @@ abstract class AbstractContent implements Content {
break;
}
}
+
return $titles;
}
/**
- * @see Content::getRedirectTarget
+ * Subclasses that implement redirects should override this.
*
* @since 1.21
+ *
+ * @return null
+ *
+ * @see Content::getRedirectTarget
*/
public function getRedirectTarget() {
return null;
}
/**
- * @see Content::getUltimateRedirectTarget
- * @note: migrated here from Title::newFromRedirectRecurse
+ * @note Migrated here from Title::newFromRedirectRecurse.
*
* @since 1.21
+ *
+ * @return Title|null
+ *
+ * @see Content::getUltimateRedirectTarget
*/
public function getUltimateRedirectTarget() {
$titles = $this->getRedirectChain();
+
return $titles ? array_pop( $titles ) : null;
}
/**
- * @see Content::isRedirect
- *
* @since 1.21
*
* @return bool
+ *
+ * @see Content::isRedirect
*/
public function isRedirect() {
return $this->getRedirectTarget() !== null;
}
/**
- * @see Content::updateRedirect
- *
* This default implementation always returns $this.
- *
- * @param Title $target
+ * Subclasses that implement redirects should override this.
*
* @since 1.21
*
+ * @param Title $target
+ *
* @return Content $this
+ *
+ * @see Content::updateRedirect
*/
public function updateRedirect( Title $target ) {
return $this;
}
/**
- * @see Content::getSection
- *
* @since 1.21
+ *
+ * @return null
+ *
+ * @see Content::getSection
*/
public function getSection( $sectionId ) {
return null;
}
/**
- * @see Content::replaceSection
- *
* @since 1.21
+ *
+ * @return null
+ *
+ * @see Content::replaceSection
*/
- public function replaceSection( $section, Content $with, $sectionTitle = '' ) {
+ public function replaceSection( $sectionId, Content $with, $sectionTitle = '' ) {
return null;
}
/**
- * @see Content::preSaveTransform
- *
* @since 1.21
+ *
+ * @return Content $this
+ *
+ * @see Content::preSaveTransform
*/
public function preSaveTransform( Title $title, User $user, ParserOptions $popts ) {
return $this;
}
/**
- * @see Content::addSectionHeader
- *
* @since 1.21
+ *
+ * @return Content $this
+ *
+ * @see Content::addSectionHeader
*/
public function addSectionHeader( $header ) {
return $this;
}
/**
- * @see Content::preloadTransform
- *
* @since 1.21
+ *
+ * @return Content $this
+ *
+ * @see Content::preloadTransform
*/
- public function preloadTransform( Title $title, ParserOptions $popts ) {
+ public function preloadTransform( Title $title, ParserOptions $popts, $params = array() ) {
return $this;
}
/**
- * @see Content::prepareSave
- *
* @since 1.21
+ *
+ * @return Status
+ *
+ * @see Content::prepareSave
*/
public function prepareSave( WikiPage $page, $flags, $baseRevId, User $user ) {
if ( $this->isValid() ) {
@@ -381,53 +395,47 @@ abstract class AbstractContent implements Content {
}
/**
- * @see Content::getDeletionUpdates
- *
* @since 1.21
*
- * @param $page WikiPage the deleted page
- * @param $parserOutput null|ParserOutput optional parser output object
- * for efficient access to meta-information about the content object.
- * Provide if you have one handy.
+ * @param WikiPage $page
+ * @param ParserOutput $parserOutput
+ *
+ * @return LinksDeletionUpdate[]
*
- * @return array A list of DataUpdate instances that will clean up the
- * database after deletion.
+ * @see Content::getDeletionUpdates
*/
- public function getDeletionUpdates( WikiPage $page,
- ParserOutput $parserOutput = null )
- {
+ public function getDeletionUpdates( WikiPage $page, ParserOutput $parserOutput = null ) {
return array(
new LinksDeletionUpdate( $page ),
);
}
/**
- * This default implementation always returns false. Subclasses may override this to supply matching logic.
- *
- * @see Content::matchMagicWord
+ * This default implementation always returns false. Subclasses may override
+ * this to supply matching logic.
*
* @since 1.21
*
* @param MagicWord $word
*
- * @return bool
+ * @return bool Always false.
+ *
+ * @see Content::matchMagicWord
*/
public function matchMagicWord( MagicWord $word ) {
return false;
}
/**
- * @see Content::convert()
- *
* This base implementation calls the hook ConvertContent to enable custom conversions.
* Subclasses may override this to implement conversion for "their" content model.
*
- * @param string $toModel the desired content model, use the CONTENT_MODEL_XXX flags.
- * @param string $lossy flag, set to "lossy" to allow lossy conversion. If lossy conversion is
- * not allowed, full round-trip conversion is expected to work without losing information.
+ * @param string $toModel
+ * @param string $lossy
*
- * @return Content|bool A content object with the content model $toModel, or false if
- * that conversion is not supported.
+ * @return Content|bool
+ *
+ * @see Content::convert()
*/
public function convert( $toModel, $lossy = '' ) {
if ( $this->getModel() === $toModel ) {
@@ -439,6 +447,77 @@ abstract class AbstractContent implements Content {
$result = false;
wfRunHooks( 'ConvertContent', array( $this, $toModel, $lossy, &$result ) );
+
return $result;
}
+
+ /**
+ * Returns a ParserOutput object containing information derived from this content.
+ * Most importantly, unless $generateHtml was false, the return value contains an
+ * HTML representation of the content.
+ *
+ * Subclasses that want to control the parser output may override this, but it is
+ * preferred to override fillParserOutput() instead.
+ *
+ * Subclasses that override getParserOutput() itself should take care to call the
+ * ContentGetParserOutput hook.
+ *
+ * @since 1.24
+ *
+ * @param Title $title Context title for parsing
+ * @param int|null $revId Revision ID (for {{REVISIONID}})
+ * @param ParserOptions|null $options Parser options
+ * @param bool $generateHtml Whether or not to generate HTML
+ *
+ * @return ParserOutput Containing information derived from this content.
+ */
+ public function getParserOutput( Title $title, $revId = null,
+ ParserOptions $options = null, $generateHtml = true
+ ) {
+ if ( $options === null ) {
+ $options = $this->getContentHandler()->makeParserOptions( 'canonical' );
+ }
+
+ $po = new ParserOutput();
+
+ if ( wfRunHooks( 'ContentGetParserOutput',
+ array( $this, $title, $revId, $options, $generateHtml, &$po ) ) ) {
+
+ // Save and restore the old value, just in case something is reusing
+ // the ParserOptions object in some weird way.
+ $oldRedir = $options->getRedirectTarget();
+ $options->setRedirectTarget( $this->getRedirectTarget() );
+ $this->fillParserOutput( $title, $revId, $options, $generateHtml, $po );
+ $options->setRedirectTarget( $oldRedir );
+ }
+
+ return $po;
+ }
+
+ /**
+ * Fills the provided ParserOutput with information derived from the content.
+ * Unless $generateHtml was false, this includes an HTML representation of the content.
+ *
+ * This is called by getParserOutput() after consulting the ContentGetParserOutput hook.
+ * Subclasses are expected to override this method (or getParserOutput(), if need be).
+ * Subclasses of TextContent should generally override getHtml() instead.
+ *
+ * This placeholder implementation always throws an exception.
+ *
+ * @since 1.24
+ *
+ * @param Title $title Context title for parsing
+ * @param int|null $revId Revision ID (for {{REVISIONID}})
+ * @param ParserOptions $options Parser options
+ * @param bool $generateHtml Whether or not to generate HTML
+ * @param ParserOutput &$output The output object to fill (reference).
+ *
+ * @throws MWException
+ */
+ protected function fillParserOutput( Title $title, $revId,
+ ParserOptions $options, $generateHtml, ParserOutput &$output
+ ) {
+ // Don't make abstract, so subclasses that override getParserOutput() directly don't fail.
+ throw new MWException( 'Subclasses of AbstractContent must override fillParserOutput!' );
+ }
}