MediaWiki  master
rebuildFileCache.php
Go to the documentation of this file.
1 <?php
25 
26 require_once __DIR__ . '/Maintenance.php';
27 
34  private $enabled = true;
35 
36  public function __construct() {
37  parent::__construct();
38  $this->addDescription( 'Build the file cache' );
39  $this->addOption( 'start', 'Page_id to start from', false, true );
40  $this->addOption( 'end', 'Page_id to end on', false, true );
41  $this->addOption( 'overwrite', 'Refresh page cache' );
42  $this->addOption( 'all', 'Build the file cache for pages in all namespaces, not just content pages' );
43  $this->setBatchSize( 100 );
44  }
45 
46  public function finalSetup() {
47  global $wgUseFileCache;
48 
49  $this->enabled = $wgUseFileCache;
50  // Script will handle capturing output and saving it itself
51  $wgUseFileCache = false;
52  // Avoid DB writes (like enotif/counters)
53  MediaWiki\MediaWikiServices::getInstance()->getReadOnlyMode()
54  ->setReason( 'Building cache' );
55 
56  // Ensure no debug-specific logic ends up in the cache (must be after Setup.php)
58 
59  parent::finalSetup();
60  }
61 
62  public function execute() {
63  if ( !$this->enabled ) {
64  $this->fatalError( "Nothing to do -- \$wgUseFileCache is disabled." );
65  }
66 
67  $start = $this->getOption( 'start', "0" );
68  if ( !ctype_digit( $start ) ) {
69  $this->fatalError( "Invalid value for start parameter." );
70  }
71  $start = intval( $start );
72 
73  $end = $this->getOption( 'end', "0" );
74  if ( !ctype_digit( $end ) ) {
75  $this->fatalError( "Invalid value for end parameter." );
76  }
77  $end = intval( $end );
78 
79  $this->output( "Building page file cache from page_id {$start}!\n" );
80 
81  $dbr = $this->getDB( DB_REPLICA );
82  $batchSize = $this->getBatchSize();
83  $overwrite = $this->hasOption( 'overwrite' );
84  $start = ( $start > 0 )
85  ? $start
86  : $dbr->selectField( 'page', 'MIN(page_id)', '', __METHOD__ );
87  $end = ( $end > 0 )
88  ? $end
89  : $dbr->selectField( 'page', 'MAX(page_id)', '', __METHOD__ );
90  if ( !$start ) {
91  $this->fatalError( "Nothing to do." );
92  }
93 
94  $where = [];
95  if ( !$this->getOption( 'all' ) ) {
96  // If 'all' isn't passed as an option, just fall back to previous behaviour
97  // of using content namespaces
98  $where['page_namespace'] =
99  MediaWikiServices::getInstance()->getNamespaceInfo()->getContentNamespaces();
100  }
101 
102  // Mock request (hack, no real client)
103  $_SERVER['HTTP_ACCEPT_ENCODING'] = 'bgzip';
104 
105  # Do remaining chunk
106  $end += $batchSize - 1;
107  $blockStart = $start;
108  $blockEnd = $start + $batchSize - 1;
109 
110  $dbw = $this->getDB( DB_MASTER );
111  // Go through each page and save the output
112  while ( $blockEnd <= $end ) {
113  // Get the pages
114  $res = $dbr->select( 'page',
115  [ 'page_namespace', 'page_title', 'page_id' ],
116  $where + [ "page_id BETWEEN " . (int)$blockStart . " AND " . (int)$blockEnd ],
117  __METHOD__,
118  [ 'ORDER BY' => 'page_id ASC', 'USE INDEX' => 'PRIMARY' ]
119  );
120 
121  $this->beginTransaction( $dbw, __METHOD__ ); // for any changes
122  foreach ( $res as $row ) {
123  $rebuilt = false;
124 
125  $title = Title::makeTitleSafe( $row->page_namespace, $row->page_title );
126  if ( $title === null ) {
127  $this->output( "Page {$row->page_id} has bad title\n" );
128  continue; // broken title?
129  }
130 
131  $context = new RequestContext();
132  $context->setTitle( $title );
133  $article = Article::newFromTitle( $title, $context );
134  $context->setWikiPage( $article->getPage() );
135 
136  // Some extensions like FlaggedRevs while error out if this is unset
137  RequestContext::getMain()->setTitle( $title );
138 
139  // If the article is cacheable, then load it
140  if ( $article->isFileCacheable( HTMLFileCache::MODE_REBUILD ) ) {
141  $viewCache = new HTMLFileCache( $title, 'view' );
142  $historyCache = new HTMLFileCache( $title, 'history' );
143  if ( $viewCache->isCacheGood() && $historyCache->isCacheGood() ) {
144  if ( $overwrite ) {
145  $rebuilt = true;
146  } else {
147  $this->output( "Page '$title' (id {$row->page_id}) already cached\n" );
148  continue; // done already!
149  }
150  }
151 
152  Wikimedia\suppressWarnings(); // header notices
153 
154  // 1. Cache ?action=view
155  // Be sure to reset the mocked request time (T24852)
156  $_SERVER['REQUEST_TIME_FLOAT'] = microtime( true );
157  ob_start();
158  $article->view();
159  $context->getOutput()->output();
160  $context->getOutput()->clearHTML();
161  $viewHtml = ob_get_clean();
162  $viewCache->saveToFileCache( $viewHtml );
163 
164  // 2. Cache ?action=history
165  // Be sure to reset the mocked request time (T24852)
166  $_SERVER['REQUEST_TIME_FLOAT'] = microtime( true );
167  ob_start();
168  Action::factory( 'history', $article, $context )->show();
169  $context->getOutput()->output();
170  $context->getOutput()->clearHTML();
171  $historyHtml = ob_get_clean();
172  $historyCache->saveToFileCache( $historyHtml );
173 
174  Wikimedia\restoreWarnings();
175 
176  if ( $rebuilt ) {
177  $this->output( "Re-cached page '$title' (id {$row->page_id})..." );
178  } else {
179  $this->output( "Cached page '$title' (id {$row->page_id})..." );
180  }
181  $this->output( "[view: " . strlen( $viewHtml ) . " bytes; " .
182  "history: " . strlen( $historyHtml ) . " bytes]\n" );
183  } else {
184  $this->output( "Page '$title' (id {$row->page_id}) not cacheable\n" );
185  }
186  }
187  $this->commitTransaction( $dbw, __METHOD__ ); // commit any changes (just for sanity)
188 
189  $blockStart += $batchSize;
190  $blockEnd += $batchSize;
191  }
192  $this->output( "Done!\n" );
193  }
194 }
195 
196 $maintClass = RebuildFileCache::class;
197 require_once RUN_MAINTENANCE_IF_MAIN;
RUN_MAINTENANCE_IF_MAIN
const RUN_MAINTENANCE_IF_MAIN
Definition: Maintenance.php:38
MediaWiki\MediaWikiServices
MediaWikiServices is the service locator for the application scope of MediaWiki.
Definition: MediaWikiServices.php:162
HTMLFileCache
Page view caching in the file system.
Definition: HTMLFileCache.php:33
Maintenance\fatalError
fatalError( $msg, $exitCode=1)
Output a message and terminate the current script.
Definition: Maintenance.php:487
Maintenance\addDescription
addDescription( $text)
Set the description text.
Definition: Maintenance.php:327
Maintenance
Abstract maintenance class for quickly writing and churning out maintenance scripts with minimal effo...
Definition: Maintenance.php:55
$res
$res
Definition: testCompression.php:57
Action\factory
static factory(?string $action, Page $article, IContextSource $context=null)
Get an appropriate Action subclass for the given action.
Definition: Action.php:115
RebuildFileCache
Maintenance script that builds the file cache.
Definition: rebuildFileCache.php:33
$dbr
$dbr
Definition: testCompression.php:54
RebuildFileCache\$enabled
$enabled
Definition: rebuildFileCache.php:34
MediaWiki\MediaWikiServices\getInstance
static getInstance()
Returns the global default instance of the top level service locator.
Definition: MediaWikiServices.php:194
Maintenance\beginTransaction
beginTransaction(IDatabase $dbw, $fname)
Begin a transcation on a DB.
Definition: Maintenance.php:1401
RebuildFileCache\__construct
__construct()
Default constructor.
Definition: rebuildFileCache.php:36
$wgUseFileCache
$wgUseFileCache
This will cache static pages for non-logged-in users to reduce database traffic on public sites.
Definition: DefaultSettings.php:2791
Maintenance\addOption
addOption( $name, $description, $required=false, $withArg=false, $shortName=false, $multiOccurrence=false)
Add a parameter to the script.
Definition: Maintenance.php:245
$title
$title
Definition: testCompression.php:38
DB_REPLICA
const DB_REPLICA
Definition: defines.php:25
RequestContext
Group all the pieces relevant to the context of a request into one instance @newable.
Definition: RequestContext.php:39
DB_MASTER
const DB_MASTER
Definition: defines.php:26
$maintClass
$maintClass
Definition: rebuildFileCache.php:196
Title\makeTitleSafe
static makeTitleSafe( $ns, $title, $fragment='', $interwiki='')
Create a new Title from a namespace index and a DB key.
Definition: Title.php:617
Maintenance\commitTransaction
commitTransaction(IDatabase $dbw, $fname)
Commit the transcation on a DB handle and wait for replica DBs to catch up.
Definition: Maintenance.php:1416
Maintenance\getDB
getDB( $db, $groups=[], $dbDomain=false)
Returns a database to be used by current maintenance script.
Definition: Maintenance.php:1370
MWDebug\deinit
static deinit()
Disable the debugger.
Definition: MWDebug.php:114
RequestContext\getMain
static getMain()
Get the RequestContext object associated with the main request.
Definition: RequestContext.php:454
Maintenance\getOption
getOption( $name, $default=null)
Get an option, or return the default.
Definition: Maintenance.php:281
RebuildFileCache\execute
execute()
Do the actual work.
Definition: rebuildFileCache.php:62
Maintenance\getBatchSize
getBatchSize()
Returns batch size.
Definition: Maintenance.php:366
HTMLFileCache\MODE_REBUILD
const MODE_REBUILD
Definition: HTMLFileCache.php:36
Maintenance\output
output( $out, $channel=null)
Throw some output to the user.
Definition: Maintenance.php:434
Maintenance\hasOption
hasOption( $name)
Checks to see if a particular option exists.
Definition: Maintenance.php:266
Maintenance\setBatchSize
setBatchSize( $s=0)
Set the batch size.
Definition: Maintenance.php:374
Article\newFromTitle
static newFromTitle( $title, IContextSource $context)
Create an Article object of the appropriate class for the given page.
Definition: Article.php:196
RebuildFileCache\finalSetup
finalSetup()
Handle some last-minute setup here.
Definition: rebuildFileCache.php:46