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