diff options
Diffstat (limited to 'includes/content/AbstractContent.php')
-rw-r--r-- | includes/content/AbstractContent.php | 277 |
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!' ); + } } |