* @ingroup Maintenance
*/
class RefreshLinks extends Maintenance {
+ /** @var int|bool */
+ protected $namespace = false;
+
public function __construct() {
parent::__construct();
- $this->mDescription = "Refresh link tables";
+ $this->addDescription( 'Refresh link tables' );
$this->addOption( 'dfn-only', 'Delete links from nonexistent articles only' );
$this->addOption( 'new-only', 'Only affect articles with just a single edit' );
$this->addOption( 'redirects-only', 'Only fix redirects, not all links' );
$this->addOption( 'e', 'Last page id to refresh', false, true );
$this->addOption( 'dfn-chunk-size', 'Maximum number of existent IDs to check per ' .
'query, default 100000', false, true );
+ $this->addOption( 'namespace', 'Only fix pages in this namespace', false, true );
$this->addArg( 'start', 'Page_id to start from, default 1', false );
$this->setBatchSize( 100 );
}
$start = (int)$this->getArg( 0 ) ?: null;
$end = (int)$this->getOption( 'e' ) ?: null;
$dfnChunkSize = (int)$this->getOption( 'dfn-chunk-size', 100000 );
+ $ns = $this->getOption( 'namespace' );
+ if ( $ns === null ) {
+ $this->namespace = false;
+ } else {
+ $this->namespace = (int)$ns;
+ }
if ( !$this->hasOption( 'dfn-only' ) ) {
$new = $this->getOption( 'new-only', false );
$redir = $this->getOption( 'redirects-only', false );
}
}
+ private function namespaceCond() {
+ return $this->namespace !== false
+ ? [ 'page_namespace' => $this->namespace ]
+ : [];
+ }
+
/**
* Do the actual link refreshing.
* @param int|null $start Page_id to start from
$end = null, $redirectsOnly = false, $oldRedirectsOnly = false
) {
$reportingInterval = 100;
- $dbr = $this->getDB( DB_SLAVE );
+ $dbr = $this->getDB( DB_REPLICA );
if ( $start === null ) {
$start = 1;
}
// Give extensions a chance to optimize settings
- Hooks::run( 'MaintenanceRefreshLinksInit', array( $this ) );
+ Hooks::run( 'MaintenanceRefreshLinksInit', [ $this ] );
$what = $redirectsOnly ? "redirects" : "links";
if ( $oldRedirectsOnly ) {
# This entire code path is cut-and-pasted from below. Hurrah.
- $conds = array(
+ $conds = [
"page_is_redirect=1",
"rd_from IS NULL",
self::intervalCond( $dbr, 'page_id', $start, $end ),
- );
+ ] + $this->namespaceCond();
$res = $dbr->select(
- array( 'page', 'redirect' ),
+ [ 'page', 'redirect' ],
'page_id',
$conds,
__METHOD__,
- array(),
- array( 'redirect' => array( "LEFT JOIN", "page_id=rd_from" ) )
+ [],
+ [ 'redirect' => [ "LEFT JOIN", "page_id=rd_from" ] ]
);
$num = $res->numRows();
$this->output( "Refreshing $num old redirects from $start...\n" );
} elseif ( $newOnly ) {
$this->output( "Refreshing $what from " );
$res = $dbr->select( 'page',
- array( 'page_id' ),
- array(
+ [ 'page_id' ],
+ [
'page_is_new' => 1,
self::intervalCond( $dbr, 'page_id', $start, $end ),
- ),
+ ] + $this->namespaceCond(),
__METHOD__
);
$num = $res->numRows();
if ( $redirectsOnly ) {
$this->fixRedirect( $row->page_id );
} else {
- self::fixLinksFromArticle( $row->page_id );
+ self::fixLinksFromArticle( $row->page_id, $this->namespace );
}
}
} else {
$this->output( "$id\n" );
wfWaitForSlaves();
}
- self::fixLinksFromArticle( $id );
+ self::fixLinksFromArticle( $id, $this->namespace );
}
}
}
if ( $page === null ) {
// This page doesn't exist (any more)
// Delete any redirect table entry for it
- $dbw->delete( 'redirect', array( 'rd_from' => $id ),
+ $dbw->delete( 'redirect', [ 'rd_from' => $id ],
__METHOD__ );
+ return;
+ } elseif ( $this->namespace !== false
+ && !$page->getTitle()->inNamespace( $this->namespace )
+ ) {
return;
}
if ( $rt === null ) {
// The page is not a redirect
// Delete any redirect table entry for it
- $dbw->delete( 'redirect', array( 'rd_from' => $id ), __METHOD__ );
+ $dbw->delete( 'redirect', [ 'rd_from' => $id ], __METHOD__ );
$fieldValue = 0;
} else {
$page->insertRedirectEntry( $rt );
}
// Update the page table to be sure it is an a consistent state
- $dbw->update( 'page', array( 'page_is_redirect' => $fieldValue ),
- array( 'page_id' => $id ), __METHOD__ );
+ $dbw->update( 'page', [ 'page_is_redirect' => $fieldValue ],
+ [ 'page_id' => $id ], __METHOD__ );
}
/**
* Run LinksUpdate for all links on a given page_id
* @param int $id The page_id
+ * @param int|bool $ns Only fix links if it is in this namespace
*/
- public static function fixLinksFromArticle( $id ) {
+ public static function fixLinksFromArticle( $id, $ns = false ) {
$page = WikiPage::newFromID( $id );
LinkCache::singleton()->clear();
if ( $page === null ) {
return;
+ } elseif ( $ns !== false
+ && !$page->getTitle()->inNamespace( $ns ) ) {
+ return;
}
$content = $page->getContent( Revision::RAW );
return;
}
- $updates = $content->getSecondaryDataUpdates( $page->getTitle() );
- DataUpdate::runUpdates( $updates );
+ foreach ( $content->getSecondaryDataUpdates( $page->getTitle() ) as $update ) {
+ DeferredUpdates::addUpdate( $update );
+ }
}
/**
) {
wfWaitForSlaves();
$this->output( "Deleting illegal entries from the links tables...\n" );
- $dbr = $this->getDB( DB_SLAVE );
+ $dbr = $this->getDB( DB_REPLICA );
do {
// Find the start of the next chunk. This is based only
// on existent page_ids.
$nextStart = $dbr->selectField(
'page',
'page_id',
- self::intervalCond( $dbr, 'page_id', $start, $end ),
+ [ self::intervalCond( $dbr, 'page_id', $start, $end ) ]
+ + $this->namespaceCond(),
__METHOD__,
- array( 'ORDER BY' => 'page_id', 'OFFSET' => $chunkSize )
+ [ 'ORDER BY' => 'page_id', 'OFFSET' => $chunkSize ]
);
if ( $nextStart !== false ) {
*/
private function dfnCheckInterval( $start = null, $end = null, $batchSize = 100 ) {
$dbw = $this->getDB( DB_MASTER );
- $dbr = $this->getDB( DB_SLAVE );
+ $dbr = $this->getDB( DB_REPLICA );
- $linksTables = array( // table name => page_id field
+ $linksTables = [ // table name => page_id field
'pagelinks' => 'pl_from',
'imagelinks' => 'il_from',
'categorylinks' => 'cl_from',
'langlinks' => 'll_from',
'redirect' => 'rd_from',
'page_props' => 'pp_page',
- );
+ ];
foreach ( $linksTables as $table => $field ) {
$this->output( " $table: 0" );
$ids = $dbr->selectFieldValues(
$table,
$field,
- array(
+ [
self::intervalCond( $dbr, $field, $tableStart, $end ),
"$field NOT IN ({$dbr->selectSQLText( 'page', 'page_id' )})",
- ),
+ ],
__METHOD__,
- array( 'DISTINCT', 'ORDER BY' => $field, 'LIMIT' => $batchSize )
+ [ 'DISTINCT', 'ORDER BY' => $field, 'LIMIT' => $batchSize ]
);
$numIds = count( $ids );
if ( $numIds ) {
$counter += $numIds;
- $dbw->delete( $table, array( $field => $ids ), __METHOD__ );
+ $dbw->delete( $table, [ $field => $ids ], __METHOD__ );
$this->output( ", $counter" );
$tableStart = $ids[$numIds - 1] + 1;
wfWaitForSlaves();