merge latest master into Wikidata branch
[lhc/web/wiklou.git] / includes / api / ApiQueryRevisions.php
index 41dfc33..731fff9 100644 (file)
 class ApiQueryRevisions extends ApiQueryBase {
 
        private $diffto, $difftotext, $expandTemplates, $generateXML, $section,
-               $token, $parseContent;
+               $token, $parseContent, $contentFormat;
 
        public function __construct( $query, $moduleName ) {
                parent::__construct( $query, $moduleName, 'rv' );
        }
 
-       private $fld_ids = false, $fld_flags = false, $fld_timestamp = false, $fld_size = false,
+       private $fld_ids = false, $fld_flags = false, $fld_timestamp = false, $fld_size = false, $fld_sha1 = false,
                        $fld_comment = false, $fld_parsedcomment = false, $fld_user = false, $fld_userid = false,
-                       $fld_content = false, $fld_tags = false;
+                       $fld_content = false, $fld_tags = false, $fld_contentmodel = false;
 
        private $tokenFunctions;
 
@@ -155,10 +155,15 @@ class ApiQueryRevisions extends ApiQueryBase {
                $this->fld_parsedcomment = isset ( $prop['parsedcomment'] );
                $this->fld_size = isset ( $prop['size'] );
                $this->fld_sha1 = isset ( $prop['sha1'] );
+               $this->fld_contentmodel = isset ( $prop['contentmodel'] );
                $this->fld_userid = isset( $prop['userid'] );
                $this->fld_user = isset ( $prop['user'] );
                $this->token = $params['token'];
 
+               if ( !empty( $params['contentformat'] ) ) {
+                       $this->contentFormat = $params['contentformat'];
+               }
+
                // Possible indexes used
                $index = array();
 
@@ -442,6 +447,10 @@ class ApiQueryRevisions extends ApiQueryBase {
                        }
                }
 
+               if ( $this->fld_contentmodel ) {
+                       $vals['contentmodel'] = $revision->getContentModel();
+               }
+
                if ( $this->fld_comment || $this->fld_parsedcomment ) {
                        if ( $revision->isDeleted( Revision::DELETED_COMMENT ) ) {
                                $vals['commenthidden'] = '';
@@ -480,39 +489,79 @@ class ApiQueryRevisions extends ApiQueryBase {
                        }
                }
 
-               $text = null;
+               $content = null;
                global $wgParser;
                if ( $this->fld_content || !is_null( $this->difftotext ) ) {
-                       $text = $revision->getText();
+                       $content = $revision->getContent();
                        // Expand templates after getting section content because
                        // template-added sections don't count and Parser::preprocess()
                        // will have less input
                        if ( $this->section !== false ) {
-                               $text = $wgParser->getSection( $text, $this->section, false );
-                               if ( $text === false ) {
+                               $content = $content->getSection( $this->section, false );
+                               if ( !$content ) {
                                        $this->dieUsage( "There is no section {$this->section} in r" . $revision->getId(), 'nosuchsection' );
                                }
                        }
                }
                if ( $this->fld_content && !$revision->isDeleted( Revision::DELETED_TEXT ) ) {
+                       $text = null;
+
                        if ( $this->generateXML ) {
-                               $wgParser->startExternalParse( $title, ParserOptions::newFromContext( $this->getContext() ), OT_PREPROCESS );
-                               $dom = $wgParser->preprocessToDom( $text );
-                               if ( is_callable( array( $dom, 'saveXML' ) ) ) {
-                                       $xml = $dom->saveXML();
+                               if ( $content->getModel() === CONTENT_MODEL_WIKITEXT ) {
+                                       $t = $content->getNativeData(); # note: don't set $text
+
+                                       $wgParser->startExternalParse( $title, ParserOptions::newFromContext( $this->getContext() ), OT_PREPROCESS );
+                                       $dom = $wgParser->preprocessToDom( $t );
+                                       if ( is_callable( array( $dom, 'saveXML' ) ) ) {
+                                               $xml = $dom->saveXML();
+                                       } else {
+                                               $xml = $dom->__toString();
+                                       }
+                                       $vals['parsetree'] = $xml;
                                } else {
-                                       $xml = $dom->__toString();
+                                       $this->setWarning( "Conversion to XML is supported for wikitext only, " .
+                                                                               $title->getPrefixedDBkey() .
+                                                                               " uses content model " . $content->getModel() . ")" );
                                }
-                               $vals['parsetree'] = $xml;
-
                        }
+
                        if ( $this->expandTemplates && !$this->parseContent ) {
-                               $text = $wgParser->preprocess( $text, $title, ParserOptions::newFromContext( $this->getContext() ) );
+                               #XXX: implement template expansion for all content types in ContentHandler?
+                               if ( $content->getModel() === CONTENT_MODEL_WIKITEXT ) {
+                                       $text = $content->getNativeData();
+
+                                       $text = $wgParser->preprocess( $text, $title, ParserOptions::newFromContext( $this->getContext() ) );
+                               } else {
+                                       $this->setWarning( "Template expansion is supported for wikitext only, " .
+                                               $title->getPrefixedDBkey() .
+                                               " uses content model " . $content->getModel() . ")" );
+
+                                       $text = false;
+                               }
                        }
                        if ( $this->parseContent ) {
-                               $text = $wgParser->parse( $text, $title, ParserOptions::newFromContext( $this->getContext() ) )->getText();
+                               $po = $content->getParserOutput( $title, ParserOptions::newFromContext( $this->getContext() ) );
+                               $text = $po->getText();
+                       }
+
+                       if ( $text === null ) {
+                               $format = $this->contentFormat ? $this->contentFormat : $content->getDefaultFormat();
+
+                               if ( !$content->isSupportedFormat( $format ) ) {
+                                       $model = $content->getModel();
+                                       $name = $title->getPrefixedDBkey();
+
+                                       $this->dieUsage( "The requested format {$this->contentFormat} is not supported ".
+                                                                       "for content model $model used by $name", 'badformat' );
+                               }
+
+                               $text = $content->serialize( $format );
+                               $vals['contentformat'] = $format;
+                       }
+
+                       if ( $text !== false ) {
+                               ApiResult::setContent( $vals, $text );
                        }
-                       ApiResult::setContent( $vals, $text );
                } elseif ( $this->fld_content ) {
                        $vals['texthidden'] = '';
                }
@@ -524,11 +573,26 @@ class ApiQueryRevisions extends ApiQueryBase {
                                $vals['diff'] = array();
                                $context = new DerivativeContext( $this->getContext() );
                                $context->setTitle( $title );
+                               $handler = $revision->getContentHandler();
+
                                if ( !is_null( $this->difftotext ) ) {
-                                       $engine = new DifferenceEngine( $context );
-                                       $engine->setText( $text, $this->difftotext );
+                                       $model = $title->getContentModel();
+
+                                       if ( $this->contentFormat
+                                               && !ContentHandler::getForModelID( $model )->isSupportedFormat( $this->contentFormat ) ) {
+
+                                               $name = $title->getPrefixedDBkey();
+
+                                               $this->dieUsage( "The requested format {$this->contentFormat} is not supported for ".
+                                                                                       "content model $model used by $name", 'badformat' );
+                                       }
+
+                                       $difftocontent = ContentHandler::makeContent( $this->difftotext, $title, $model, $this->contentFormat );
+
+                                       $engine = $handler->createDifferenceEngine( $context );
+                                       $engine->setContent( $content, $difftocontent );
                                } else {
-                                       $engine = new DifferenceEngine( $context, $revision->getID(), $this->diffto );
+                                       $engine = $handler->createDifferenceEngine( $context, $revision->getID(), $this->diffto );
                                        $vals['diff']['from'] = $engine->getOldid();
                                        $vals['diff']['to'] = $engine->getNewid();
                                }
@@ -568,6 +632,7 @@ class ApiQueryRevisions extends ApiQueryBase {
                                        'userid',
                                        'size',
                                        'sha1',
+                                       'contentmodel',
                                        'comment',
                                        'parsedcomment',
                                        'content',
@@ -617,6 +682,10 @@ class ApiQueryRevisions extends ApiQueryBase {
                        'continue' => null,
                        'diffto' => null,
                        'difftotext' => null,
+                       'contentformat' => array(
+                               ApiBase::PARAM_TYPE => ContentHandler::getAllContentFormats(),
+                               ApiBase::PARAM_DFLT => null
+                       ),
                );
        }
 
@@ -632,6 +701,7 @@ class ApiQueryRevisions extends ApiQueryBase {
                                ' userid         - User id of revision creator',
                                ' size           - Length (bytes) of the revision',
                                ' sha1           - SHA-1 (base 16) of the revision',
+                               ' contentmodel   - Content model id',
                                ' comment        - Comment by the user for revision',
                                ' parsedcomment  - Parsed comment by the user for the revision',
                                ' content        - Text of the revision',
@@ -656,6 +726,7 @@ class ApiQueryRevisions extends ApiQueryBase {
                        'difftotext' => array( 'Text to diff each revision to. Only diffs a limited number of revisions.',
                                "Overrides {$p}diffto. If {$p}section is set, only that section will be diffed against this text" ),
                        'tag' => 'Only list revisions tagged with this tag',
+                       'contentformat' => 'Serialization format used for difftotext and expected for output of content',
                );
        }
 
@@ -733,13 +804,18 @@ class ApiQueryRevisions extends ApiQueryBase {
        public function getPossibleErrors() {
                return array_merge( parent::getPossibleErrors(), array(
                        array( 'nosuchrevid', 'diffto' ),
-                       array( 'code' => 'revids', 'info' => 'The revids= parameter may not be used with the list options (limit, startid, endid, dirNewer, start, end).' ),
-                       array( 'code' => 'multpages', 'info' => 'titles, pageids or a generator was used to supply multiple pages, but the limit, startid, endid, dirNewer, user, excludeuser, start and end parameters may only be used on a single page.' ),
+                       array( 'code' => 'revids', 'info' => 'The revids= parameter may not be used with the list options '
+                                                                                                       . '(limit, startid, endid, dirNewer, start, end).' ),
+                       array( 'code' => 'multpages', 'info' => 'titles, pageids or a generator was used to supply multiple pages, '
+                                                                                                       . ' but the limit, startid, endid, dirNewer, user, excludeuser, '
+                                                                                                       . 'start and end parameters may only be used on a single page.' ),
                        array( 'code' => 'diffto', 'info' => 'rvdiffto must be set to a non-negative number, "prev", "next" or "cur"' ),
                        array( 'code' => 'badparams', 'info' => 'start and startid cannot be used together' ),
                        array( 'code' => 'badparams', 'info' => 'end and endid cannot be used together' ),
                        array( 'code' => 'badparams', 'info' => 'user and excludeuser cannot be used together' ),
                        array( 'code' => 'nosuchsection', 'info' => 'There is no section section in rID' ),
+                       array( 'code' => 'badformat', 'info' => 'The requested serialization format can not be applied '
+                                                                                                       . ' to the page\'s content model' ),
                ) );
        }