Merge "Simplify HTMLTitleTextField::validate"
[lhc/web/wiklou.git] / includes / poolcounter / PoolWorkArticleView.php
index 17b62d7..157b508 100644 (file)
  *
  * @file
  */
+
 use MediaWiki\MediaWikiServices;
+use MediaWiki\Revision\RevisionRenderer;
+use MediaWiki\Storage\MutableRevisionRecord;
+use MediaWiki\Storage\RevisionRecord;
+use MediaWiki\Storage\RevisionStore;
+use MediaWiki\Storage\SlotRecord;
 
 class PoolWorkArticleView extends PoolCounterWork {
        /** @var WikiPage */
@@ -35,8 +41,14 @@ class PoolWorkArticleView extends PoolCounterWork {
        /** @var ParserOptions */
        private $parserOptions;
 
-       /** @var Content|null */
-       private $content = null;
+       /** @var RevisionRecord|null */
+       private $revision = null;
+
+       /** @var RevisionStore */
+       private $revisionStore = null;
+
+       /** @var RevisionRenderer */
+       private $renderer = null;
 
        /** @var ParserOutput|bool */
        private $parserOutput = false;
@@ -53,33 +65,59 @@ class PoolWorkArticleView extends PoolCounterWork {
         * @param int $revid ID of the revision being parsed.
         * @param bool $useParserCache Whether to use the parser cache.
         *   operation.
-        * @param Content|string $content Content to parse or null to load it; may
-        *   also be given as a wikitext string, for BC.
+        * @param RevisionRecord|Content|string|null $revision Revision to render, or null to load it;
+        *        may also be given as a wikitext string, or a Content object, for BC.
         */
        public function __construct( WikiPage $page, ParserOptions $parserOptions,
-               $revid, $useParserCache, $content = null
+               $revid, $useParserCache, $revision = null
        ) {
-               if ( is_string( $content ) ) { // BC: old style call
+               if ( is_string( $revision ) ) { // BC: very old style call
                        $modelId = $page->getRevision()->getContentModel();
                        $format = $page->getRevision()->getContentFormat();
-                       $content = ContentHandler::makeContent( $content, $page->getTitle(), $modelId, $format );
+                       $revision = ContentHandler::makeContent( $revision, $page->getTitle(), $modelId, $format );
+               }
+
+               if ( $revision instanceof Content ) { // BC: old style call
+                       $content = $revision;
+                       $revision = new MutableRevisionRecord( $page->getTitle() );
+                       $revision->setId( $revid );
+                       $revision->setPageId( $page->getId() );
+                       $revision->setContent( SlotRecord::MAIN, $content );
                }
 
+               if ( $revision ) {
+                       // Check that the RevisionRecord matches $revid and $page, but still allow
+                       // fake RevisionRecords coming from errors or hooks in Article to be rendered.
+                       if ( $revision->getId() && $revision->getId() !== $revid ) {
+                               throw new InvalidArgumentException( '$revid parameter mismatches $revision parameter' );
+                       }
+                       if ( $revision->getPageId()
+                               && $revision->getPageId() !== $page->getTitle()->getArticleID()
+                       ) {
+                               throw new InvalidArgumentException( '$page parameter mismatches $revision parameter' );
+                       }
+               }
+
+               // TODO: DI: inject services
+               $this->renderer = MediaWikiServices::getInstance()->getRevisionRenderer();
+               $this->revisionStore = MediaWikiServices::getInstance()->getRevisionStore();
+               $this->parserCache = MediaWikiServices::getInstance()->getParserCache();
+
                $this->page = $page;
                $this->revid = $revid;
                $this->cacheable = $useParserCache;
                $this->parserOptions = $parserOptions;
-               $this->content = $content;
-               $this->parserCache = MediaWikiServices::getInstance()->getParserCache();
+               $this->revision = $revision;
                $this->cacheKey = $this->parserCache->getKey( $page, $parserOptions );
                $keyPrefix = $this->cacheKey ?: wfMemcKey( 'articleview', 'missingcachekey' );
+
                parent::__construct( 'ArticleView', $keyPrefix . ':revid:' . $revid );
        }
 
        /**
         * Get the ParserOutput from this object, or false in case of failure
         *
-        * @return ParserOutput
+        * @return ParserOutput|bool
         */
        public function getParserOutput() {
                return $this->parserOutput;
@@ -114,23 +152,33 @@ class PoolWorkArticleView extends PoolCounterWork {
 
                $isCurrent = $this->revid === $this->page->getLatest();
 
-               if ( $this->content !== null ) {
-                       $content = $this->content;
+               // Bypass audience check for current revision
+               $audience = $isCurrent ? RevisionRecord::RAW : RevisionRecord::FOR_PUBLIC;
+
+               if ( $this->revision !== null ) {
+                       $rev = $this->revision;
                } elseif ( $isCurrent ) {
-                       // XXX: why use RAW audience here, and PUBLIC (default) below?
-                       $content = $this->page->getContent( Revision::RAW );
+                       $rev = $this->page->getRevision()
+                               ? $this->page->getRevision()->getRevisionRecord()
+                               : null;
                } else {
-                       $rev = Revision::newFromTitle( $this->page->getTitle(), $this->revid );
+                       $rev = $this->revisionStore->getRevisionByTitle( $this->page->getTitle(), $this->revid );
+               }
 
-                       if ( $rev === null ) {
-                               $content = null;
-                       } else {
-                               // XXX: why use PUBLIC audience here (default), and RAW above?
-                               $content = $rev->getContent();
-                       }
+               if ( !$rev ) {
+                       // couldn't load
+                       return false;
                }
 
-               if ( $content === null ) {
+               $renderedRevision = $this->renderer->getRenderedRevision(
+                       $rev,
+                       $this->parserOptions,
+                       null,
+                       [ 'audience' => $audience ]
+               );
+
+               if ( !$renderedRevision ) {
+                       // audience check failed
                        return false;
                }
 
@@ -138,11 +186,7 @@ class PoolWorkArticleView extends PoolCounterWork {
                $cacheTime = wfTimestampNow();
 
                $time = - microtime( true );
-               $this->parserOutput = $content->getParserOutput(
-                       $this->page->getTitle(),
-                       $this->revid,
-                       $this->parserOptions
-               );
+               $this->parserOutput = $renderedRevision->getRevisionParserOutput();
                $time += microtime( true );
 
                // Timing hack