MediaWiki REL1_34
PoolWorkArticleView.php
Go to the documentation of this file.
1<?php
27
30 private $page;
31
33 private $cacheKey;
34
36 private $revid;
37
39 private $parserCache;
40
43
45 private $revision = null;
46
48 private $audience;
49
51 private $revisionStore = null;
52
54 private $renderer = null;
55
57 private $parserOutput = false;
58
60 private $isDirty = false;
61
63 private $error = false;
64
76 $revid, $useParserCache, $revision = null, $audience = RevisionRecord::FOR_PUBLIC
77 ) {
78 if ( is_string( $revision ) ) { // BC: very old style call
79 $modelId = $page->getRevision()->getContentModel();
80 $format = $page->getRevision()->getContentFormat();
81 $revision = ContentHandler::makeContent( $revision, $page->getTitle(), $modelId, $format );
82 }
83
84 if ( $revision instanceof Content ) { // BC: old style call
87 $revision->setId( $revid );
88 $revision->setPageId( $page->getId() );
89 $revision->setContent( SlotRecord::MAIN, $content );
90 }
91
92 if ( $revision ) {
93 // Check that the RevisionRecord matches $revid and $page, but still allow
94 // fake RevisionRecords coming from errors or hooks in Article to be rendered.
95 if ( $revision->getId() && $revision->getId() !== $revid ) {
96 throw new InvalidArgumentException( '$revid parameter mismatches $revision parameter' );
97 }
98 if ( $revision->getPageId()
99 && $revision->getPageId() !== $page->getTitle()->getArticleID()
100 ) {
101 throw new InvalidArgumentException( '$page parameter mismatches $revision parameter' );
102 }
103 }
104
105 // TODO: DI: inject services
106 $this->renderer = MediaWikiServices::getInstance()->getRevisionRenderer();
107 $this->revisionStore = MediaWikiServices::getInstance()->getRevisionStore();
108 $this->parserCache = MediaWikiServices::getInstance()->getParserCache();
109
110 $this->page = $page;
111 $this->revid = $revid;
112 $this->cacheable = $useParserCache;
113 $this->parserOptions = $parserOptions;
114 $this->revision = $revision;
115 $this->audience = $audience;
116 $this->cacheKey = $this->parserCache->getKey( $page, $parserOptions );
117 $keyPrefix = $this->cacheKey ?: ObjectCache::getLocalClusterInstance()->makeKey(
118 'articleview', 'missingcachekey'
119 );
120
121 parent::__construct( 'ArticleView', $keyPrefix . ':revid:' . $revid );
122 }
123
129 public function getParserOutput() {
130 return $this->parserOutput;
131 }
132
138 public function getIsDirty() {
139 return $this->isDirty;
140 }
141
147 public function getError() {
148 return $this->error;
149 }
150
154 public function doWork() {
155 global $wgUseFileCache;
156
157 // @todo several of the methods called on $this->page are not declared in Page, but present
158 // in WikiPage and delegated by Article.
159
160 $isCurrent = $this->revid === $this->page->getLatest();
161
162 // The current revision cannot be hidden so we can skip some checks.
163 $audience = $isCurrent ? RevisionRecord::RAW : $this->audience;
164
165 if ( $this->revision !== null ) {
166 $rev = $this->revision;
167 } elseif ( $isCurrent ) {
168 $rev = $this->page->getRevision()
169 ? $this->page->getRevision()->getRevisionRecord()
170 : null;
171 } else {
172 $rev = $this->revisionStore->getRevisionByTitle( $this->page->getTitle(), $this->revid );
173 }
174
175 if ( !$rev ) {
176 // couldn't load
177 return false;
178 }
179
180 $renderedRevision = $this->renderer->getRenderedRevision(
181 $rev,
182 $this->parserOptions,
183 null,
184 [ 'audience' => $audience ]
185 );
186
187 if ( !$renderedRevision ) {
188 // audience check failed
189 return false;
190 }
191
192 // Reduce effects of race conditions for slow parses (T48014)
193 $cacheTime = wfTimestampNow();
194
195 $time = - microtime( true );
196 $this->parserOutput = $renderedRevision->getRevisionParserOutput();
197 $time += microtime( true );
198
199 // Timing hack
200 if ( $time > 3 ) {
201 // TODO: Use Parser's logger (once it has one)
202 $logger = MediaWiki\Logger\LoggerFactory::getInstance( 'slow-parse' );
203 $logger->info( '{time} {title}', [
204 'time' => number_format( $time, 2 ),
205 'title' => $this->page->getTitle()->getPrefixedDBkey(),
206 'ns' => $this->page->getTitle()->getNamespace(),
207 'trigger' => 'view',
208 ] );
209 }
210
211 if ( $this->cacheable && $this->parserOutput->isCacheable() && $isCurrent ) {
212 $this->parserCache->save(
213 $this->parserOutput, $this->page, $this->parserOptions, $cacheTime, $this->revid );
214 }
215
216 // Make sure file cache is not used on uncacheable content.
217 // Output that has magic words in it can still use the parser cache
218 // (if enabled), though it will generally expire sooner.
219 if ( !$this->parserOutput->isCacheable() ) {
220 $wgUseFileCache = false;
221 }
222
223 if ( $isCurrent ) {
224 $this->page->triggerOpportunisticLinksUpdate( $this->parserOutput );
225 }
226
227 return true;
228 }
229
233 public function getCachedWork() {
234 $this->parserOutput = $this->parserCache->get( $this->page, $this->parserOptions );
235
236 if ( $this->parserOutput === false ) {
237 wfDebug( __METHOD__ . ": parser cache miss\n" );
238 return false;
239 } else {
240 wfDebug( __METHOD__ . ": parser cache hit\n" );
241 return true;
242 }
243 }
244
248 public function fallback() {
249 $this->parserOutput = $this->parserCache->getDirty( $this->page, $this->parserOptions );
250
251 if ( $this->parserOutput === false ) {
252 wfDebugLog( 'dirty', 'dirty missing' );
253 wfDebug( __METHOD__ . ": no dirty cache\n" );
254 return false;
255 } else {
256 wfDebug( __METHOD__ . ": sending dirty output\n" );
257 wfDebugLog( 'dirty', "dirty output {$this->cacheKey}" );
258 $this->isDirty = true;
259 return true;
260 }
261 }
262
267 public function error( $status ) {
268 $this->error = $status;
269 return false;
270 }
271}
$wgUseFileCache
This will cache static pages for non-logged-in users to reduce database traffic on public sites.
wfDebug( $text, $dest='all', array $context=[])
Sends a line to the debug log if enabled or, optionally, to a comment in output.
wfTimestampNow()
Convenience function; returns MediaWiki timestamp for the present time.
wfDebugLog( $logGroup, $text, $dest='all', array $context=[])
Send a line to a supplementary debug log file, if configured, or main debug log if not.
MediaWikiServices is the service locator for the application scope of MediaWiki.
Page revision base class.
The RevisionRenderer service provides access to rendered output for revisions.
Service for looking up page revisions.
Value object representing a content slot associated with a page revision.
Set options of the Parser.
Class for dealing with PoolCounters using class members.
RevisionRenderer $renderer
getError()
Get a Status object in case of error or false otherwise.
ParserOutput bool $parserOutput
getParserOutput()
Get the ParserOutput from this object, or false in case of failure.
getIsDirty()
Get whether the ParserOutput is a dirty one (i.e.
RevisionRecord null $revision
__construct(WikiPage $page, ParserOptions $parserOptions, $revid, $useParserCache, $revision=null, $audience=RevisionRecord::FOR_PUBLIC)
Generic operation result class Has warning/error list, boolean status and arbitrary value.
Definition Status.php:40
Class representing a MediaWiki article and history.
Definition WikiPage.php:47
getRevision()
Get the latest revision.
Definition WikiPage.php:787
getTitle()
Get the title object of the article.
Definition WikiPage.php:298
Base interface for content objects.
Definition Content.php:34
$content
Definition router.php:78