('bovender') * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301, USA. */ namespace LinkTitles; /// @defgroup batch Batch processing /// @cond if ( !defined( 'MEDIAWIKI' ) ) { die( 'Not an entry point.' ); } /// @endcond /// Provides a special page that can be used to batch-process all pages in /// the wiki. By default, this can only be performed by sysops. /// @ingroup batch class Special extends \SpecialPage { /// Constructor. Announces the special page title and required user right /// to the parent constructor. function __construct() { // the second parameter in the following function call ensures that only // users who have the 'linktitles-batch' right get to see this page (by // default, this are all sysop users). parent::__construct( 'LinkTitles', 'linktitles-batch' ); } function getGroupName() { return 'pagetools'; } /// Entry function of the special page class. Will abort if the user does /// not have appropriate permissions ('linktitles-batch'). /// @return undefined function execute($par) { // Prevent non-authorized users from executing the batch processing. if ( !$this->userCanExecute( $this->getUser() ) ) { $this->displayRestrictionError(); return; } $request = $this->getRequest(); $output = $this->getOutput(); $this->setHeaders(); // Determine whether this page was requested via GET or POST. // If GET, display information and a button to start linking. // If POST, start or continue the linking process. if ( $request->wasPosted() ) { if ( array_key_exists( 's', $request->getValues() ) ) { $this->process( $request, $output ); } else { $this->buildInfoPage( $request, $output ); } } else { $this->buildInfoPage( $request, $output ); } } /// Processes wiki articles, starting at the page indicated by /// $startTitle. If $wgLinkTitlesTimeLimit is reached before all pages are /// processed, returns the title of the next page that needs processing. /// @param WebRequest $request WebRequest object that is associated with the special /// page. /// @param OutputPage $output Output page for the special page. private function process( \WebRequest &$request, \OutputPage &$output) { global $wgLinkTitlesTimeLimit; global $wgLinkTitlesNamespaces; // get our Namespaces $namespacesClause = str_replace( '_', ' ','(' . implode( ', ',$wgLinkTitlesNamespaces ) . ')' ); // Start the stopwatch $startTime = microtime(true); // Connect to the database $dbr = wfGetDB( DB_SLAVE ); // Fetch the start index and max number of records from the POST // request. $postValues = $request->getValues(); // Convert the start index to an integer; this helps preventing // SQL injection attacks via forged POST requests. $start = intval($postValues['s']); // If an end index was given, we don't need to query the database if ( array_key_exists('e', $postValues) ) { $end = intval($postValues['e']); } else { // No end index was given. Therefore, count pages now. $end = $this->countPages($dbr, $namespacesClause ); }; array_key_exists('r', $postValues) ? $reloads = $postValues['r'] : $reloads = 0; // Retrieve page names from the database. $res = $dbr->select( 'page', array('page_title', 'page_namespace'), array( 'page_namespace IN ' . $namespacesClause, ), __METHOD__, array( 'LIMIT' => 999999999, 'OFFSET' => $start ) ); // Iterate through the pages; break if a time limit is exceeded. foreach ( $res as $row ) { $curTitle = Title::makeTitleSafe( $row->page_namespace, $row->page_title); Extension::processPage($curTitle, $this->getContext()); $start += 1; // Check if the time limit is exceeded if ( microtime(true)-$startTime > $wgLinkTitlesTimeLimit ) { break; } } $this->addProgressInfo($output, $curTitle, $start, $end); // If we have not reached the last page yet, produce code to reload // the extension's special page. if ( $start < $end ) { $reloads += 1; // Build a form with hidden values and output JavaScript code that // immediately submits the form in order to continue the process. $output->addHTML($this->getReloaderForm($request->getRequestURL(), $start, $end, $reloads)); } else // Last page has been processed { $this->addCompletedInfo($output, $start, $end, $reloads); } } /// Adds WikiText to the output containing information about the extension /// and a form and button to start linking. private function buildInfoPage( &$request, &$output ) { $url = $request->getRequestURL(); // TODO: Put the page contents in messages in the i18n file. $output->addWikiText( <<addHTML( << EOF ); } /// Produces informative output in WikiText format to show while working. /// @param $output Output object. /// @param $curTitle Title of the currently processed page. /// @param $index Index of the currently processed page. /// @param $end Last index that will be processed (i.e., number of /// pages). private function addProgressInfo( &$output, $curTitle, $index, $end ) { $progress = $index / $end * 100; $percent = sprintf("%01.1f", $progress); $output->addWikiText( <<addHTML( <<Page ${index} of ${end}.

${percent}%
EOF ); $output->addWikiText( << EOF ; } /// Adds statistics to the page when all processing is done. /// @param $output Output object /// @param $start Index of the first page that was processed. /// @param $end Index of the last processed page. /// @param $reloads Number of reloads of the page. /// @returns undefined private function addCompletedInfo( &$output, $start, $end, $reloads ) { global $wgLinkTitlesTimeLimit; $pagesPerReload = sprintf('%0.1f', $end / $reloads); $output->addWikiText( <<select( 'page', array('pagecount' => "COUNT(page_id)"), array( 'page_namespace IN ' . $namespacesClause, ), __METHOD__ ); return $res->current()->pagecount; } } // vim: ts=2:sw=2:noet:comments^=\:///