From 0fca9a79918a889aa9ff02345aa3784bd8450009 Mon Sep 17 00:00:00 2001 From: Roan Kattouw Date: Wed, 21 Mar 2012 00:16:50 +0000 Subject: [PATCH] Revert r107309, r113601, r113704, r113742, r113792, r113838, r113859, r113893, r113894, r113952, r114047, r114252, r114256, r114257. This reverts the remaining 'new' revisions in core. All of these revisions are tagged with 'gerritmigration' and will be resubmitted into Gerrit after the Gerrit switchover. See also http://lists.wikimedia.org/pipermail/wikitech-l/2012-March/059124.html --- includes/AutoLoader.php | 3 - includes/api/ApiFeedContributions.php | 112 +++----- includes/db/Database.php | 4 +- includes/db/DatabasePostgres.php | 13 +- includes/filerepo/FileRepo.php | 9 - includes/filerepo/backend/FileBackend.php | 11 +- .../backend/FileBackendMultiWrite.php | 2 +- .../filerepo/backend/FileBackendStore.php | 2 +- includes/filerepo/backend/FileOp.php | 106 ++----- .../backend/filejournal/DBFileJournal.php | 112 -------- .../backend/filejournal/FileJournal.php | 131 --------- includes/filerepo/file/File.php | 18 +- includes/filerepo/file/LocalFile.php | 56 +--- includes/installer/DatabaseInstaller.php | 2 +- includes/installer/PostgresUpdater.php | 8 +- includes/specials/SpecialBlock.php | 27 +- languages/messages/MessagesEn.php | 3 - languages/messages/MessagesFrp.php | 17 +- languages/messages/MessagesIg.php | 36 +-- languages/messages/MessagesMk.php | 7 +- languages/messages/MessagesMzn.php | 34 +-- languages/messages/MessagesNds_nl.php | 27 +- languages/messages/MessagesOr.php | 21 +- languages/messages/MessagesOs.php | 16 +- languages/messages/MessagesQug.php | 19 -- languages/messages/MessagesSa.php | 3 +- languages/messages/MessagesSr_ec.php | 12 +- languages/messages/MessagesWar.php | 19 -- languages/messages/MessagesYue.php | 9 +- maintenance/archives/patch-filejournal.sql | 24 -- maintenance/dumpTextPass.php | 244 +++++----------- maintenance/language/messages.inc | 6 - .../mediawiki.action.watch.ajax.js | 262 +++++++++--------- .../mediawiki.api/mediawiki.api.watch.js | 54 ++-- 34 files changed, 386 insertions(+), 1043 deletions(-) delete mode 100644 includes/filerepo/backend/filejournal/DBFileJournal.php delete mode 100644 includes/filerepo/backend/filejournal/FileJournal.php delete mode 100644 maintenance/archives/patch-filejournal.sql diff --git a/includes/AutoLoader.php b/includes/AutoLoader.php index ca31248d64..4ab5de868b 100644 --- a/includes/AutoLoader.php +++ b/includes/AutoLoader.php @@ -508,9 +508,6 @@ $wgAutoloadLocalClasses = array( 'FSFileBackendFileList' => 'includes/filerepo/backend/FSFileBackend.php', 'SwiftFileBackend' => 'includes/filerepo/backend/SwiftFileBackend.php', 'SwiftFileBackendFileList' => 'includes/filerepo/backend/SwiftFileBackend.php', - 'FileJournal' => 'includes/filerepo/backend/filejournal/FileJournal.php', - 'DBFileJournal' => 'includes/filerepo/backend/filejournal/DBFileJournal.php', - 'NullFileJournal' => 'includes/filerepo/backend/filejournal/FileJournal.php', 'LockManagerGroup' => 'includes/filerepo/backend/lockmanager/LockManagerGroup.php', 'LockManager' => 'includes/filerepo/backend/lockmanager/LockManager.php', 'ScopedLock' => 'includes/filerepo/backend/lockmanager/LockManager.php', diff --git a/includes/api/ApiFeedContributions.php b/includes/api/ApiFeedContributions.php index 4c12e1bce5..5df1ff6e19 100644 --- a/includes/api/ApiFeedContributions.php +++ b/includes/api/ApiFeedContributions.php @@ -43,80 +43,56 @@ class ApiFeedContributions extends ApiBase { } public function execute() { + $params = $this->extractRequestParams(); global $wgFeed, $wgFeedClasses, $wgSitename, $wgLanguageCode; - try { - $params = $this->extractRequestParams(); - - if( !$wgFeed ) { - $this->dieUsage( 'Syndication feeds are not available', 'feed-unavailable' ); - } - - if( !isset( $wgFeedClasses[ $params['feedformat'] ] ) ) { - $this->dieUsage( 'Invalid subscription feed type', 'feed-invalid' ); - } + if( !$wgFeed ) { + $this->dieUsage( 'Syndication feeds are not available', 'feed-unavailable' ); + } - global $wgMiserMode; - if ( $params['showsizediff'] && $wgMiserMode ) { - $this->dieUsage( 'Size difference is disabled in Miser Mode', 'sizediffdisabled' ); - } - - $msg = wfMsgForContent( 'Contributions' ); - $feedTitle = $wgSitename . ' - ' . $msg . ' [' . $wgLanguageCode . ']'; - $feedUrl = SpecialPage::getTitleFor( 'Contributions', $params['user'] )->getFullURL(); - - $target = $params['user'] == 'newbies' - ? 'newbies' - : Title::makeTitleSafe( NS_USER, $params['user'] )->getText(); - - $feed = new $wgFeedClasses[$params['feedformat']] ( - $feedTitle, - htmlspecialchars( $msg ), - $feedUrl - ); - - $pager = new ContribsPager( $this->getContext(), array( - 'target' => $target, - 'namespace' => $params['namespace'], - 'year' => $params['year'], - 'month' => $params['month'], - 'tagFilter' => $params['tagfilter'], - 'deletedOnly' => $params['deletedonly'], - 'topOnly' => $params['toponly'], - 'showSizeDiff' => $params['showsizediff'], - ) ); - - $feedItems = array(); - if( $pager->getNumRows() > 0 ) { - foreach ( $pager->mResult as $row ) { - $feedItems[] = $this->feedItem( $row ); - } - } - - ApiFormatFeedWrapper::setResult( $this->getResult(), $feed, $feedItems ); - - } catch ( Exception $e ) { - // Error results should not be cached - $this->getMain()->setCacheMaxAge( 0 ); - - $feedTitle = $wgSitename . ' - Error - ' . wfMsgForContent( 'contributions' ) . ' [' . $wgLanguageCode . ']'; - $feedUrl = SpecialPage::getTitleFor( 'Contributions', $params['user'] )->getFullURL(); - - $feedFormat = isset( $params['feedformat'] ) ? $params['feedformat'] : 'rss'; - $feed = new $wgFeedClasses[$feedFormat] ( $feedTitle, htmlspecialchars( wfMsgForContent( 'contributions' ) ), $feedUrl ); - - if ( $e instanceof UsageException ) { - $errorCode = $e->getCodeString(); - } else { - // Something is seriously wrong - $errorCode = 'internal_api_error'; - } + if( !isset( $wgFeedClasses[ $params['feedformat'] ] ) ) { + $this->dieUsage( 'Invalid subscription feed type', 'feed-invalid' ); + } + + global $wgMiserMode; + if ( $params['showsizediff'] && $wgMiserMode ) { + $this->dieUsage( 'Size difference is disabled in Miser Mode', 'sizediffdisabled' ); + } + + $msg = wfMsgForContent( 'Contributions' ); + $feedTitle = $wgSitename . ' - ' . $msg . ' [' . $wgLanguageCode . ']'; + $feedUrl = SpecialPage::getTitleFor( 'Contributions', $params['user'] )->getFullURL(); + + $target = $params['user'] == 'newbies' + ? 'newbies' + : Title::makeTitleSafe( NS_USER, $params['user'] )->getText(); + + $feed = new $wgFeedClasses[$params['feedformat']] ( + $feedTitle, + htmlspecialchars( $msg ), + $feedUrl + ); - $errorText = $e->getMessage(); - $feedItems[] = new FeedItem( "Error ($errorCode)", $errorText, '', '', '' ); - ApiFormatFeedWrapper::setResult( $this->getResult(), $feed, $feedItems ); + $pager = new ContribsPager( $this->getContext(), array( + 'target' => $target, + 'namespace' => $params['namespace'], + 'year' => $params['year'], + 'month' => $params['month'], + 'tagFilter' => $params['tagfilter'], + 'deletedOnly' => $params['deletedonly'], + 'topOnly' => $params['toponly'], + 'showSizeDiff' => $params['showsizediff'], + ) ); + + $feedItems = array(); + if( $pager->getNumRows() > 0 ) { + foreach ( $pager->mResult as $row ) { + $feedItems[] = $this->feedItem( $row ); + } } + + ApiFormatFeedWrapper::setResult( $this->getResult(), $feed, $feedItems ); } protected function feedItem( $row ) { diff --git a/includes/db/Database.php b/includes/db/Database.php index 5c03617445..47eb596d6a 100644 --- a/includes/db/Database.php +++ b/includes/db/Database.php @@ -680,7 +680,7 @@ abstract class DatabaseBase implements DatabaseType { $dbType = strtolower( $dbType ); $class = 'Database' . ucfirst( $dbType ); - if( in_array( $dbType, $canonicalDBTypes ) || ( class_exists( $class ) && is_subclass_of( $class, 'DatabaseBase' ) ) ) { + if( in_array( $dbType, $canonicalDBTypes ) ) { return new $class( isset( $p['host'] ) ? $p['host'] : false, isset( $p['user'] ) ? $p['user'] : false, @@ -689,6 +689,8 @@ abstract class DatabaseBase implements DatabaseType { isset( $p['flags'] ) ? $p['flags'] : 0, isset( $p['tablePrefix'] ) ? $p['tablePrefix'] : 'get from global' ); + } elseif ( class_exists( $class ) && is_subclass_of( $class, 'DatabaseBase' ) ) { + return new $class( $p ); } else { return null; } diff --git a/includes/db/DatabasePostgres.php b/includes/db/DatabasePostgres.php index e2b38f5203..6452f54069 100644 --- a/includes/db/DatabasePostgres.php +++ b/includes/db/DatabasePostgres.php @@ -708,19 +708,14 @@ class DatabasePostgres extends DatabaseBase { # Replace reserved words with better ones switch( $name ) { case 'user': - return $this->realTableName( 'mwuser', $format ); + return 'mwuser'; case 'text': - return $this->realTableName( 'pagecontent', $format ); + return 'pagecontent'; default: - return $this->realTableName( $name, $format ); + return parent::tableName( $name, $format ); } } - /* Don't cheat on installer */ - function realTableName( $name, $format = 'quoted' ) { - return parent::tableName( $name, $format ); - } - /** * Return the next in a sequence, save the value for retrieval via insertId() * @return null @@ -995,7 +990,7 @@ class DatabasePostgres extends DatabaseBase { if ( !$schema ) { $schema = $this->getCoreSchema(); } - $table = $this->realTableName( $table, 'raw' ); + $table = $this->tableName( $table, 'raw' ); $etable = $this->addQuotes( $table ); $eschema = $this->addQuotes( $schema ); $SQL = "SELECT 1 FROM pg_catalog.pg_class c, pg_catalog.pg_namespace n " diff --git a/includes/filerepo/FileRepo.php b/includes/filerepo/FileRepo.php index 1475043116..0dd5466bc8 100644 --- a/includes/filerepo/FileRepo.php +++ b/includes/filerepo/FileRepo.php @@ -119,15 +119,6 @@ class FileRepo { return $this->backend; } - /** - * Get an explanatory message if this repo is read-only - * - * @return string|bool Returns false if the repo is not read-only - */ - public function getReadOnlyReason() { - return $this->backend->getReadOnlyReason(); - } - /** * Prepare a single zone or list of zones for usage. * See initDeletedDir() for additional setup needed for the 'deleted' zone. diff --git a/includes/filerepo/backend/FileBackend.php b/includes/filerepo/backend/FileBackend.php index 9d82b5e632..2a97afab89 100644 --- a/includes/filerepo/backend/FileBackend.php +++ b/includes/filerepo/backend/FileBackend.php @@ -45,8 +45,6 @@ abstract class FileBackend { protected $readOnly; // string; read-only explanation message /** @var LockManager */ protected $lockManager; - /** @var FileJournal */ - protected $fileJournal; /** * Create a new backend instance from configuration. @@ -57,10 +55,8 @@ abstract class FileBackend { * This should consist of alphanumberic, '-', and '_' characters. * This name should not be changed after use. * 'wikiId' : Prefix to container names that is unique to this wiki. - * It should only consist of alphanumberic, '-', and '_' characters. + * This should consist of alphanumberic, '-', and '_' characters. * 'lockManager' : Registered name of a file lock manager to use. - * 'fileJournal' : File journal configuration; see FileJournal::factory(). - * Journals simply log changes to files stored in the backend. * 'readOnly' : Write operations are disallowed if this is a non-empty string. * It should be an explanation for the backend being read-only. * @@ -77,9 +73,6 @@ abstract class FileBackend { $this->lockManager = ( $config['lockManager'] instanceof LockManager ) ? $config['lockManager'] : LockManagerGroup::singleton()->get( $config['lockManager'] ); - $this->fileJournal = isset( $config['fileJournal'] ) - ? FileJournal::factory( $config['fileJournal'], $this->name ) - : FileJournal::factory( array( 'class' => 'NullFileJournal' ), $this->name ); $this->readOnly = isset( $config['readOnly'] ) ? (string)$config['readOnly'] : ''; @@ -184,8 +177,6 @@ abstract class FileBackend { * 'allowStale' : Don't require the latest available data. * This can increase performance for non-critical writes. * This has no effect unless the 'force' flag is set. - * 'nonJournaled' : Don't log this operation batch in the file journal. - * This limits the ability of recovery scripts. * * Remarks on locking: * File system paths given to operations should refer to files that are diff --git a/includes/filerepo/backend/FileBackendMultiWrite.php b/includes/filerepo/backend/FileBackendMultiWrite.php index 9c3cf5b5e7..52c71d6f02 100644 --- a/includes/filerepo/backend/FileBackendMultiWrite.php +++ b/includes/filerepo/backend/FileBackendMultiWrite.php @@ -133,7 +133,7 @@ class FileBackendMultiWrite extends FileBackend { } // Actually attempt the operation batch... - $subStatus = FileOp::attemptBatch( $performOps, $opts, $this->fileJournal ); + $subStatus = FileOp::attemptBatch( $performOps, $opts ); $success = array(); $failCount = 0; diff --git a/includes/filerepo/backend/FileBackendStore.php b/includes/filerepo/backend/FileBackendStore.php index ff32925f05..e96f257c8f 100644 --- a/includes/filerepo/backend/FileBackendStore.php +++ b/includes/filerepo/backend/FileBackendStore.php @@ -708,7 +708,7 @@ abstract class FileBackendStore extends FileBackend { $this->clearCache(); // Actually attempt the operation batch... - $subStatus = FileOp::attemptBatch( $performOps, $opts, $this->fileJournal ); + $subStatus = FileOp::attemptBatch( $performOps, $opts ); // Merge errors into status fields $status->merge( $subStatus ); diff --git a/includes/filerepo/backend/FileOp.php b/includes/filerepo/backend/FileOp.php index 6cee9f9a85..825a666b55 100644 --- a/includes/filerepo/backend/FileOp.php +++ b/includes/filerepo/backend/FileOp.php @@ -24,7 +24,6 @@ abstract class FileOp { protected $state = self::STATE_NEW; // integer protected $failed = false; // boolean protected $useLatest = true; // boolean - protected $batchId; // string protected $sourceSha1; // string protected $destSameAsSource; // boolean @@ -63,16 +62,6 @@ abstract class FileOp { $this->params = $params; } - /** - * Set the batch UUID this operation belongs to - * - * @param $batchId string - * @return void - */ - final protected function setBatchId( $batchId ) { - $this->batchId = $batchId; - } - /** * Whether to allow stale data for file reads and stat checks * @@ -84,57 +73,43 @@ abstract class FileOp { } /** - * Attempt to perform a series of file operations. + * Attempt a series of file operations. * Callers are responsible for handling file locking. * * $opts is an array of options, including: - * 'force' : Errors that would normally cause a rollback do not. - * The remaining operations are still attempted if any fail. - * 'allowStale' : Don't require the latest available data. - * This can increase performance for non-critical writes. - * This has no effect unless the 'force' flag is set. - * 'nonJournaled' : Don't log this operation batch in the file journal. - * + * 'force' : Errors that would normally cause a rollback do not. + * The remaining operations are still attempted if any fail. + * 'allowStale' : Don't require the latest available data. + * This can increase performance for non-critical writes. + * This has no effect unless the 'force' flag is set. + * * The resulting Status will be "OK" unless: * a) unexpected operation errors occurred (network partitions, disk full...) * b) significant operation errors occured and 'force' was not set * * @param $performOps Array List of FileOp operations * @param $opts Array Batch operation options - * @param $journal FileJournal Journal to log operations to * @return Status */ - final public static function attemptBatch( - array $performOps, array $opts, FileJournal $journal - ) { + final public static function attemptBatch( array $performOps, array $opts ) { $status = Status::newGood(); + $allowStale = !empty( $opts['allowStale'] ); + $ignoreErrors = !empty( $opts['force'] ); + $n = count( $performOps ); if ( $n > self::MAX_BATCH_SIZE ) { $status->fatal( 'backend-fail-batchsize', $n, self::MAX_BATCH_SIZE ); return $status; } - $batchId = $journal->getTimestampedUUID(); - $allowStale = !empty( $opts['allowStale'] ); - $ignoreErrors = !empty( $opts['force'] ); - $journaled = empty( $opts['nonJournaled'] ); - - $entries = array(); // file journal entries $predicates = FileOp::newPredicates(); // account for previous op in prechecks // Do pre-checks for each operation; abort on failure... foreach ( $performOps as $index => $fileOp ) { - $fileOp->setBatchId( $batchId ); $fileOp->allowStaleReads( $allowStale ); - $oldPredicates = $predicates; - $subStatus = $fileOp->precheck( $predicates ); // updates $predicates + $subStatus = $fileOp->precheck( $predicates ); $status->merge( $subStatus ); - if ( $subStatus->isOK() ) { - if ( $journaled ) { // journal log entry - $entries = array_merge( $entries, - self::getJournalEntries( $fileOp, $oldPredicates, $predicates ) ); - } - } else { // operation failed? + if ( !$subStatus->isOK() ) { // operation failed? $status->success[$index] = false; ++$status->failCount; if ( !$ignoreErrors ) { @@ -143,15 +118,8 @@ abstract class FileOp { } } - // Log the operations in file journal... - if ( count( $entries ) ) { - $subStatus = $journal->logChangeBatch( $entries, $batchId ); - if ( !$subStatus->isOK() ) { - return $subStatus; // abort - } - } - - if ( $ignoreErrors ) { // treat precheck() fatals as mere warnings + if ( $ignoreErrors ) { + # Treat all precheck() fatals as merely warnings $status->setResult( true, $status->value ); } @@ -186,46 +154,6 @@ abstract class FileOp { return $status; } - /** - * Get the file journal entries for a single file operation - * - * @param $fileOp FileOp - * @param $oPredicates Array Pre-op information about files - * @param $nPredicates Array Post-op information about files - * @return Array - */ - final protected static function getJournalEntries( - FileOp $fileOp, array $oPredicates, array $nPredicates - ) { - $nullEntries = array(); - $updateEntries = array(); - $deleteEntries = array(); - $pathsUsed = array_merge( $fileOp->storagePathsRead(), $fileOp->storagePathsChanged() ); - foreach ( $pathsUsed as $path ) { - $nullEntries[] = array( // assertion for recovery - 'op' => 'null', - 'path' => $path, - 'newSha1' => $fileOp->fileSha1( $path, $oPredicates ) - ); - } - foreach ( $fileOp->storagePathsChanged() as $path ) { - if ( $nPredicates['sha1'][$path] === false ) { // deleted - $deleteEntries[] = array( - 'op' => 'delete', - 'path' => $path, - 'newSha1' => '' - ); - } else { // created/updated - $updateEntries[] = array( - 'op' => $fileOp->fileExists( $path, $oPredicates ) ? 'update' : 'create', - 'path' => $path, - 'newSha1' => $nPredicates['sha1'][$path] - ); - } - } - return array_merge( $nullEntries, $updateEntries, $deleteEntries ); - } - /** * Get the value of the parameter with the given name * @@ -424,8 +352,8 @@ abstract class FileOp { $params = $this->params; $params['failedAction'] = $action; try { - wfDebugLog( 'FileOperation', get_class( $this ) . - " failed (batch #{$this->batchId}): " . FormatJson::encode( $params ) ); + wfDebugLog( 'FileOperation', + get_class( $this ) . ' failed: ' . FormatJson::encode( $params ) ); } catch ( Exception $e ) { // bad config? debug log error? } diff --git a/includes/filerepo/backend/filejournal/DBFileJournal.php b/includes/filerepo/backend/filejournal/DBFileJournal.php deleted file mode 100644 index 1eb9ecada1..0000000000 --- a/includes/filerepo/backend/filejournal/DBFileJournal.php +++ /dev/null @@ -1,112 +0,0 @@ -wiki = $config['wiki']; - } - - /** - * @see FileJournal::logChangeBatch() - * @return Status - */ - protected function doLogChangeBatch( array $entries, $batchId ) { - $status = Status::newGood(); - - $dbw = $this->getMasterDB(); - if ( !$dbw ) { - $status->fatal( 'filejournal-fail-dbconnect', $this->backend ); - return $status; - } - $now = wfTimestamp( TS_UNIX ); - - $data = array(); - foreach ( $entries as $entry ) { - $data[] = array( - 'fj_batch_uuid' => $batchId, - 'fj_backend' => $this->backend, - 'fj_op' => $entry['op'], - 'fj_path' => $entry['path'], - 'fj_path_sha1' => wfBaseConvert( sha1( $entry['path'] ), 16, 36, 31 ), - 'fj_new_sha1' => $entry['newSha1'], - 'fj_timestamp' => $dbw->timestamp( $now ) - ); - } - - try { - $dbw->begin(); - $dbw->insert( 'filejournal', $data, __METHOD__ ); - $dbw->commit(); - } catch ( DBError $e ) { - $status->fatal( 'filejournal-fail-dbquery', $this->backend ); - return $status; - } - - return $status; - } - - /** - * @see FileJournal::purgeOldLogs() - * @return Status - */ - protected function doPurgeOldLogs() { - $status = Status::newGood(); - if ( $this->ttlDays <= 0 ) { - return $status; // nothing to do - } - - $dbw = $this->getMasterDB(); - if ( !$dbw ) { - $status->fatal( 'filejournal-fail-dbconnect', $this->backend ); - return $status; - } - $dbCutoff = $dbw->timestamp( time() - 86400 * $this->ttlDays ); - - try { - $dbw->begin(); - $dbw->delete( 'filejournal', - array( 'fj_timestamp < ' . $dbw->addQuotes( $dbCutoff ) ), - __METHOD__ - ); - $dbw->commit(); - } catch ( DBError $e ) { - $status->fatal( 'filejournal-fail-dbquery', $this->backend ); - return $status; - } - - return $status; - } - - /** - * Get a master connection to the logging DB - * - * @return DatabaseBase|null - */ - protected function getMasterDB() { - try { - $lb = wfGetLBFactory()->newMainLB(); - return $lb->getConnection( DB_MASTER, array(), $this->wiki ); - } catch ( DBConnectionError $e ) { - return null; - } - } -} diff --git a/includes/filerepo/backend/filejournal/FileJournal.php b/includes/filerepo/backend/filejournal/FileJournal.php deleted file mode 100644 index f60b7f9b4e..0000000000 --- a/includes/filerepo/backend/filejournal/FileJournal.php +++ /dev/null @@ -1,131 +0,0 @@ -ttlDays = isset( $config['ttlDays'] ) ? $config['ttlDays'] : false; - } - - /** - * Create an appropriate FileJournal object from config - * - * @param $config Array - * @param $backend string A registered file backend name - * @return FileJournal - */ - final public static function factory( array $config, $backend ) { - $class = $config['class']; - $jrn = new $class( $config ); - if ( !$jrn instanceof self ) { - throw new MWException( "Class given is not an instance of FileJournal." ); - } - $jrn->backend = $backend; - return $jrn; - } - - /** - * Get a statistically unique ID string - * - * @return string <9 char TS_MW timestamp in base 36><22 random base 36 chars> - */ - final public function getTimestampedUUID() { - $s = ''; - for ( $i = 0; $i < 5; $i++ ) { - $s .= mt_rand( 0, 2147483647 ); - } - $s = wfBaseConvert( sha1( $s ), 16, 36, 31 ); - return substr( wfBaseConvert( wfTimestamp( TS_MW ), 10, 36, 9 ) . $s, 0, 31 ); - } - - /** - * Log changes made by a batch file operation. - * $entries is an array of log entries, each of which contains: - * op : Basic operation name (create, store, copy, delete) - * path : The storage path of the file - * newSha1 : The final base 36 SHA-1 of the file - * Note that 'false' should be used as the SHA-1 for non-existing files. - * - * @param $entries Array List of file operations (each an array of parameters) - * @param $batchId string UUID string that identifies the operation batch - * @return Status - */ - final public function logChangeBatch( array $entries, $batchId ) { - if ( !count( $entries ) ) { - return Status::newGood(); - } - return $this->doLogChangeBatch( $entries, $batchId ); - } - - /** - * @see FileJournal::logChangeBatch() - * - * @param $entries Array List of file operations (each an array of parameters) - * @param $batchId string UUID string that identifies the operation batch - * @return Status - */ - abstract protected function doLogChangeBatch( array $entries, $batchId ); - - /** - * Purge any old log entries - * - * @return Status - */ - final public function purgeOldLogs() { - return $this->doPurgeOldLogs(); - } - - /** - * @see FileJournal::purgeOldLogs() - * @return Status - */ - abstract protected function doPurgeOldLogs(); -} - -/** - * Simple version of FileJournal that does nothing - * @since 1.20 - */ -class NullFileJournal extends FileJournal { - /** - * @see FileJournal::logChangeBatch() - * @return Status - */ - protected function doLogChangeBatch( array $entries, $batchId ) { - return Status::newGood(); - } - - /** - * @see FileJournal::purgeOldLogs() - * @return Status - */ - protected function doPurgeOldLogs() { - return Status::newGood(); - } -} diff --git a/includes/filerepo/file/File.php b/includes/filerepo/file/File.php index 5e3763cd41..543f23fc83 100644 --- a/includes/filerepo/file/File.php +++ b/includes/filerepo/file/File.php @@ -760,27 +760,16 @@ abstract class File { * @param $thumbUrl string Thumbnail URL * @param $params Array * @param $flags integer - * @param $status Status Optional status object to use for errors * @return MediaTransformOutput */ - protected function transformErrorOutput( - $thumbPath, $thumbUrl, $params, $flags, Status $status = null - ) { + protected function transformErrorOutput( $thumbPath, $thumbUrl, $params, $flags ) { global $wgIgnoreImageErrors; if ( $wgIgnoreImageErrors && !( $flags & self::RENDER_NOW ) ) { return $this->handler->getTransform( $this, $thumbPath, $thumbUrl, $params ); } else { - $badStatus = Status::newFatal( 'thumbnail-dest-create' ); - if ( $status ) { // additional, more detailed errors - $badStatus->merge( $status ); - } - $err = array(); - foreach ( $badStatus->getErrorsArray() as $item ) { - $err[] = wfMsg( $item[0], array_slice( $item, 1 ) ); - } return new MediaTransformError( 'thumbnail_error', - $params['width'], 0, implode( "\n", $err ) ); // MTO does "\n" => "
" + $params['width'], 0, wfMsg( 'thumbnail-dest-create' ) ); } } @@ -886,8 +875,7 @@ abstract class File { if ( $status->isOK() ) { $thumb->setStoragePath( $thumbPath ); } else { - $thumb = $this->transformErrorOutput( - $thumbPath, $thumbUrl, $params, $flags, $status ); + $thumb = $this->transformErrorOutput( $thumbPath, $thumbUrl, $params, $flags ); } } diff --git a/includes/filerepo/file/LocalFile.php b/includes/filerepo/file/LocalFile.php index 9731efcc6b..cd2617045e 100644 --- a/includes/filerepo/file/LocalFile.php +++ b/includes/filerepo/file/LocalFile.php @@ -908,13 +908,9 @@ class LocalFile extends File { */ function upload( $srcPath, $comment, $pageText, $flags = 0, $props = false, $timestamp = false, $user = null ) { global $wgContLang; - - if ( $this->getRepo()->getReadOnlyReason() !== false ) { - return $this->readOnlyFatalStatus(); - } - // truncate nicely or the DB will do it for us - // non-nicely (dangling multi-byte chars, non-truncated version in cache). + // non-nicely (dangling multi-byte chars, non-truncated + // version in cache). $comment = $wgContLang->truncate( $comment, 255 ); $this->lock(); // begin $status = $this->publish( $srcPath, $flags ); @@ -1179,10 +1175,6 @@ class LocalFile extends File { * archive name, or an empty string if it was a new file. */ function publishTo( $srcPath, $dstRel, $flags = 0 ) { - if ( $this->getRepo()->getReadOnlyReason() !== false ) { - return $this->readOnlyFatalStatus(); - } - $this->lock(); // begin $archiveName = wfTimestamp( TS_MW ) . '!'. $this->getName(); @@ -1219,10 +1211,6 @@ class LocalFile extends File { * @return FileRepoStatus object. */ function move( $target ) { - if ( $this->getRepo()->getReadOnlyReason() !== false ) { - return $this->readOnlyFatalStatus(); - } - wfDebugLog( 'imagemove', "Got request to move {$this->name} to " . $target->getText() ); $this->lock(); // begin @@ -1262,10 +1250,6 @@ class LocalFile extends File { * @return FileRepoStatus object. */ function delete( $reason, $suppress = false ) { - if ( $this->getRepo()->getReadOnlyReason() !== false ) { - return $this->readOnlyFatalStatus(); - } - $this->lock(); // begin $batch = new LocalFileDeleteBatch( $this, $reason, $suppress ); @@ -1282,7 +1266,7 @@ class LocalFile extends File { } $status = $batch->execute(); - if ( $status->isOK() ) { + if ( $status->ok ) { // Update site_stats $site_stats = $dbw->tableName( 'site_stats' ); $dbw->query( "UPDATE $site_stats SET ss_images=ss_images-1", __METHOD__ ); @@ -1309,10 +1293,6 @@ class LocalFile extends File { * @return FileRepoStatus object. */ function deleteOld( $archiveName, $reason, $suppress = false ) { - if ( $this->getRepo()->getReadOnlyReason() !== false ) { - return $this->readOnlyFatalStatus(); - } - $this->lock(); // begin $batch = new LocalFileDeleteBatch( $this, $reason, $suppress ); @@ -1322,7 +1302,7 @@ class LocalFile extends File { $this->unlock(); // done - if ( $status->isOK() ) { + if ( $status->ok ) { $this->purgeDescription(); $this->purgeHistory(); } @@ -1342,12 +1322,6 @@ class LocalFile extends File { * @return FileRepoStatus */ function restore( $versions = array(), $unsuppress = false ) { - if ( $this->getRepo()->getReadOnlyReason() !== false ) { - return $this->readOnlyFatalStatus(); - } - - $this->lock(); // begin - $batch = new LocalFileRestoreBatch( $this, $unsuppress ); if ( !$versions ) { @@ -1358,14 +1332,14 @@ class LocalFile extends File { $status = $batch->execute(); - if ( $status->isGood() ) { - $cleanupStatus = $batch->cleanup(); - $cleanupStatus->successCount = 0; - $cleanupStatus->failCount = 0; - $status->merge( $cleanupStatus ); + if ( !$status->isGood() ) { + return $status; } - $this->unlock(); // done + $cleanupStatus = $batch->cleanup(); + $cleanupStatus->successCount = 0; + $cleanupStatus->failCount = 0; + $status->merge( $cleanupStatus ); return $status; } @@ -1470,14 +1444,6 @@ class LocalFile extends File { $dbw = $this->repo->getMasterDB(); $dbw->rollback( __METHOD__ ); } - - /** - * @return Status - */ - protected function readOnlyFatalStatus() { - return $this->getRepo()->newFatal( 'filereadonlyerror', $this->getName(), - $this->getRepo()->getName(), $this->getRepo()->getReadOnlyReason() ); - } } // LocalFile class # ------------------------------------------------------------------------------ @@ -1745,7 +1711,7 @@ class LocalFileDeleteBatch { $this->status->merge( $status ); } - if ( !$this->status->isOK() ) { + if ( !$this->status->ok ) { // Critical file deletion error // Roll back inserts, release lock and abort // TODO: delete the defunct filearchive rows if we are using a non-transactional DB diff --git a/includes/installer/DatabaseInstaller.php b/includes/installer/DatabaseInstaller.php index 046fa16431..14604c162b 100644 --- a/includes/installer/DatabaseInstaller.php +++ b/includes/installer/DatabaseInstaller.php @@ -158,7 +158,7 @@ abstract class DatabaseInstaller { } $this->db->selectDB( $this->getVar( 'wgDBname' ) ); - if( $this->db->tableExists( 'archive', __METHOD__ ) ) { + if( $this->db->tableExists( 'user', __METHOD__ ) ) { $status->warning( 'config-install-tables-exist' ); $this->enableLB(); return $status; diff --git a/includes/installer/PostgresUpdater.php b/includes/installer/PostgresUpdater.php index 301c6d4b8c..d4412cb2e2 100644 --- a/includes/installer/PostgresUpdater.php +++ b/includes/installer/PostgresUpdater.php @@ -27,11 +27,6 @@ class PostgresUpdater extends DatabaseUpdater { */ protected function getCoreUpdateList() { return array( - # rename tables 1.7.3 - # r15791 Change reserved word table names "user" and "text" - array( 'renameTable', 'user', 'mwuser'), - array( 'renameTable', 'text', 'pagecontent'), - # new sequences array( 'addSequence', 'logging_log_id_seq' ), array( 'addSequence', 'page_restrictions_pr_id_seq' ), @@ -411,8 +406,7 @@ END; protected function renameTable( $old, $new ) { if ( $this->db->tableExists( $old ) ) { $this->output( "Renaming table $old to $new\n" ); - $old = $this->db->realTableName( $old, "quoted" ); - $new = $this->db->realTableName( $new, "quoted" ); + $old = $this->db->addQuotes( $old ); $this->db->query( "ALTER TABLE $old RENAME TO $new" ); } } diff --git a/includes/specials/SpecialBlock.php b/includes/specials/SpecialBlock.php index a58e62ea27..5b5b356fd3 100644 --- a/includes/specials/SpecialBlock.php +++ b/includes/specials/SpecialBlock.php @@ -381,19 +381,19 @@ class SpecialBlock extends FormSpecialPage { $this->getLanguage()->pipeList( $links ) ); - $userTitle = self::getTargetUserTitle( $this->target ); - if( $userTitle ){ + if( $this->target instanceof User ){ # Get relevant extracts from the block and suppression logs, if possible + $userpage = $this->target->getUserPage(); $out = ''; LogEventsList::showLogExtract( $out, 'block', - $userTitle, + $userpage, '', array( 'lim' => 10, - 'msgKey' => array( 'blocklog-showlog', $userTitle->getText() ), + 'msgKey' => array( 'blocklog-showlog', $userpage->getText() ), 'showIfEmpty' => false ) ); @@ -404,12 +404,12 @@ class SpecialBlock extends FormSpecialPage { LogEventsList::showLogExtract( $out, 'suppress', - $userTitle, + $userpage, '', array( 'lim' => 10, 'conds' => array( 'log_action' => array( 'block', 'reblock', 'unblock' ) ), - 'msgKey' => array( 'blocklog-showsuppresslog', $userTitle->getText() ), + 'msgKey' => array( 'blocklog-showsuppresslog', $userpage->getText() ), 'showIfEmpty' => false ) ); @@ -421,21 +421,6 @@ class SpecialBlock extends FormSpecialPage { return $text; } - /** - * Get a user page target for things like logs. - * This handles account and IP range targets. - * @param $target User|string - * @return Title|null - */ - protected static function getTargetUserTitle( $target ) { - if( $target instanceof User ) { - return $target->getUserPage(); - } elseif ( IP::isIPAddress( $target ) ) { - return Title::makeTitleSafe( NS_USER, $target ); - } - return null; - } - /** * Determine the target of the block, and the type of target * TODO: should be in Block.php? diff --git a/languages/messages/MessagesEn.php b/languages/messages/MessagesEn.php index 39dcb3f405..933cff1706 100644 --- a/languages/messages/MessagesEn.php +++ b/languages/messages/MessagesEn.php @@ -2277,9 +2277,6 @@ If the problem persists, contact an [[Special:ListUsers/sysop|administrator]].', 'backend-fail-contenttype' => 'Could not determine the content type of the file to store at "$1".', 'backend-fail-batchsize' => 'Storage backend given a batch of $1 file {{PLURAL:$1|operation|operations}}; the limit is $2 {{PLURAL:$2|operation|operations}}.', -'filejournal-fail-dbconnect' => 'Could not connect to the journal database for storage backend "$1".', -'filejournal-fail-dbquery' => 'Could not update the journal database for storage backend "$1".', - # Lock manager 'lockmanager-notlocked' => 'Could not unlock "$1"; it is not locked.', 'lockmanager-fail-closelock' => 'Could not close lock file for "$1".', diff --git a/languages/messages/MessagesFrp.php b/languages/messages/MessagesFrp.php index a5f0420676..bcb5377391 100644 --- a/languages/messages/MessagesFrp.php +++ b/languages/messages/MessagesFrp.php @@ -26,8 +26,8 @@ $namespaceNames = array( NS_MEDIA => 'Mèdia', NS_SPECIAL => 'Spèciâl', NS_TALK => 'Discussion', - NS_USER => 'Usanciér', - NS_USER_TALK => 'Discussion_usanciér', + NS_USER => 'Utilisator', + NS_USER_TALK => 'Discussion_utilisator', NS_PROJECT_TALK => 'Discussion_$1', NS_FILE => 'Fichiér', NS_FILE_TALK => 'Discussion_fichiér', @@ -42,14 +42,13 @@ $namespaceNames = array( ); $namespaceAliases = array( - 'Discutar' => NS_TALK, - 'Utilisator' => NS_USER, + 'Discutar' => NS_TALK, 'Discussion_Utilisator' => NS_USER_TALK, - 'Émâge' => NS_FILE, - 'Discussion_Émâge' => NS_FILE_TALK, - 'Discussion_Modèlo' => NS_TEMPLATE_TALK, - 'Discussion_Éde' => NS_HELP_TALK, - 'Discussion_Catègorie' => NS_CATEGORY_TALK + 'Émâge' => NS_FILE, + 'Discussion_Émâge' => NS_FILE_TALK, + 'Discussion_Modèlo' => NS_TEMPLATE_TALK, + 'Discussion_Éde' => NS_HELP_TALK, + 'Discussion_Catègorie' => NS_CATEGORY_TALK ); $specialPageAliases = array( diff --git a/languages/messages/MessagesIg.php b/languages/messages/MessagesIg.php index cda68db636..5c8a413cdb 100644 --- a/languages/messages/MessagesIg.php +++ b/languages/messages/MessagesIg.php @@ -12,36 +12,22 @@ */ $namespaceNames = array( - NS_MEDIA => 'Midia', + NS_MEDIA => 'Nká', NS_SPECIAL => 'Ihü_kárírí', NS_TALK => 'Okwu', - NS_USER => 'Ọbanife', - NS_USER_TALK => 'Okwu_ọbanife', + NS_USER => 'Ọ\'bànifé', + NS_USER_TALK => 'Okwu_ọ\'bànifé', NS_PROJECT_TALK => 'Okwu_$1', - NS_FILE => 'Usòrò', - NS_FILE_TALK => 'Okwu_usòrò', - NS_MEDIAWIKI => 'MidiaWiki', - NS_MEDIAWIKI_TALK => 'Okwu_MidiaWiki', + NS_FILE => 'Ákwúkwó_orünotu', + NS_FILE_TALK => 'Okwu_ákwúkwó_orünotu', + NS_MEDIAWIKI => 'NkáWiki', + NS_MEDIAWIKI_TALK => 'Okwu_NkáWiki', NS_TEMPLATE => 'Àtụ', NS_TEMPLATE_TALK => 'Okwu_àtụ', - NS_HELP => 'Nkwadọ', - NS_HELP_TALK => 'Okwu_nkwadọ', - NS_CATEGORY => 'Òtù', - NS_CATEGORY_TALK => 'Okwu_òtù', -); - -$namespaceAliases = array( - 'Nká' => NS_MEDIA, - 'Ọ\'bànifé' => NS_USER, - 'Okwu_ọ\'bànifé' => NS_USER_TALK, - 'Ákwúkwó_orünotu' => NS_FILE, - 'Okwu_ákwúkwó_orünotu' => NS_FILE_TALK, - 'NkáWiki' => NS_MEDIAWIKI, - 'Okwu_NkáWiki' => NS_MEDIAWIKI_TALK, - 'Nkwádọ' => NS_HELP, - 'Okwu_nkwádọ' => NS_HELP_TALK, - 'Ébéonọr' => NS_CATEGORY, - 'Okwu_ébéonọr' => NS_CATEGORY_TALK, + NS_HELP => 'Nkwádọ', + NS_HELP_TALK => 'Okwu_nkwádọ', + NS_CATEGORY => 'Ébéonọr', + NS_CATEGORY_TALK => 'Okwu_ébéonọr', ); $specialPageAliases = array( diff --git a/languages/messages/MessagesMk.php b/languages/messages/MessagesMk.php index 7fcca67b80..d5a2ba5030 100644 --- a/languages/messages/MessagesMk.php +++ b/languages/messages/MessagesMk.php @@ -23,7 +23,7 @@ */ $namespaceNames = array( - NS_MEDIA => 'Медиум', + NS_MEDIA => 'Медија', NS_SPECIAL => 'Специјална', NS_TALK => 'Разговор', NS_USER => 'Корисник', @@ -42,9 +42,8 @@ $namespaceNames = array( ); $namespaceAliases = array( - 'Медија' => NS_MEDIA, - 'Специјални' => NS_SPECIAL, - 'Слика' => NS_FILE, + 'Специјални' => NS_SPECIAL, + 'Слика' => NS_FILE, 'Разговор_за_слика' => NS_FILE_TALK, ); diff --git a/languages/messages/MessagesMzn.php b/languages/messages/MessagesMzn.php index c6ab3d77a6..d29cbe22a4 100644 --- a/languages/messages/MessagesMzn.php +++ b/languages/messages/MessagesMzn.php @@ -24,52 +24,46 @@ $fallback8bitEncoding = 'windows-1256'; $rtl = true; $namespaceNames = array( - NS_MEDIA => 'مدیا', + NS_MEDIA => 'مه‌دیا', NS_SPECIAL => 'شا', - NS_MAIN => '', NS_TALK => 'گپ', NS_USER => 'کارور', NS_USER_TALK => 'کارور_گپ', NS_PROJECT_TALK => '$1_گپ', NS_FILE => 'پرونده', NS_FILE_TALK => 'پرونده_گپ', - NS_MEDIAWIKI => 'مدیاویکی', - NS_MEDIAWIKI_TALK => 'مدیاویکی_گپ', + NS_MEDIAWIKI => 'مه‌دیاویکی', + NS_MEDIAWIKI_TALK => 'مه‌دیاویکی_گپ', NS_TEMPLATE => 'شابلون', NS_TEMPLATE_TALK => 'شابلون_گپ', - NS_HELP => 'رانما', - NS_HELP_TALK => 'رانما_گپ', + NS_HELP => 'رانه‌ما', + NS_HELP_TALK => 'رانه‌مائه_گپ', NS_CATEGORY => 'رج', NS_CATEGORY_TALK => 'رج_گپ', ); $namespaceAliases = array( - 'مه‌دیا' => NS_MEDIA, 'مدیا' => NS_MEDIA, 'ویژه' => NS_SPECIAL, - 'بحث' => NS_TALK, + 'بحث' => NS_TALK, 'کاربر' => NS_USER, - 'بحث_کاربر' => NS_USER_TALK, - 'بحث_$1' => NS_PROJECT_TALK, + 'بحث_کاربر' => NS_USER_TALK, + 'بحث_$1' => NS_PROJECT_TALK, 'تصویر' => NS_FILE, 'پرونده' => NS_FILE, - 'بحث_تصویر' => NS_FILE_TALK, - 'بحث_پرونده' => NS_FILE_TALK, + 'بحث_تصویر' => NS_FILE_TALK, + 'بحث_پرونده' => NS_FILE_TALK, 'مدیاویکی' => NS_MEDIAWIKI, 'مه‌دیا ویکی' => NS_MEDIAWIKI, - 'مه‌دیاویکی' => NS_MEDIAWIKI, - 'مه‌دیاویکی_گپ' => NS_MEDIAWIKI_TALK, - 'بحث_مدیاویکی' => NS_MEDIAWIKI_TALK, + 'بحث_مدیاویکی' => NS_MEDIAWIKI_TALK, 'مه‌دیا ویکی گپ' => NS_MEDIAWIKI_TALK, 'الگو' => NS_TEMPLATE, - 'بحث_الگو' => NS_TEMPLATE_TALK, + 'بحث_الگو' => NS_TEMPLATE_TALK, 'راهنما' => NS_HELP, - 'رانه‌ما' => NS_HELP, - 'رانه‌مائه_گپ' => NS_HELP_TALK, - 'بحث_راهنما' => NS_HELP_TALK, + 'بحث_راهنما' => NS_HELP_TALK, 'رانه‌مای گپ' => NS_HELP_TALK, 'رده' => NS_CATEGORY, - 'بحث_رده' => NS_CATEGORY_TALK, + 'بحث_رده' => NS_CATEGORY_TALK, ); $magicWords = array( diff --git a/languages/messages/MessagesNds_nl.php b/languages/messages/MessagesNds_nl.php index 68006e2c5c..db48562158 100644 --- a/languages/messages/MessagesNds_nl.php +++ b/languages/messages/MessagesNds_nl.php @@ -23,35 +23,30 @@ $fallback = 'nl'; $namespaceNames = array( NS_MEDIA => 'Media', - NS_SPECIAL => 'Spesiaal', + NS_SPECIAL => 'Speciaal', NS_TALK => 'Overleg', NS_USER => 'Gebruker', NS_USER_TALK => 'Overleg_gebruker', NS_PROJECT_TALK => 'Overleg_$1', - NS_FILE => 'Bestaand', - NS_FILE_TALK => 'Overleg_bestaand', + NS_FILE => 'Ofbeelding', + NS_FILE_TALK => 'Overleg_ofbeelding', NS_MEDIAWIKI => 'MediaWiki', NS_MEDIAWIKI_TALK => 'Overleg_MediaWiki', NS_TEMPLATE => 'Mal', NS_TEMPLATE_TALK => 'Overleg_mal', NS_HELP => 'Hulpe', NS_HELP_TALK => 'Overleg_hulpe', - NS_CATEGORY => 'Kategorie', - NS_CATEGORY_TALK => 'Overleg_kategorie', + NS_CATEGORY => 'Kattegerie', + NS_CATEGORY_TALK => 'Overleg_kattegerie', ); $namespaceAliases = array( - 'Speciaol' => NS_SPECIAL, - 'Speciaal' => NS_SPECIAL, - 'Sjabloon' => NS_TEMPLATE, - 'Overleg_sjabloon' => NS_TEMPLATE_TALK, - 'Ofbeelding' => NS_FILE, - 'Overleg_ofbeelding' => NS_FILE_TALK, - 'Categorie' => NS_CATEGORY, - 'Overleg_categorie' => NS_CATEGORY_TALK, - 'Kattegerie' => NS_CATEGORY, - 'Overleg_categorie' => NS_CATEGORY_TALK, - 'Overleg_kattegerie' => NS_HELP_TALK, + 'Speciaol' => NS_SPECIAL, + 'Sjabloon' => NS_TEMPLATE, + 'Overleg_sjabloon' => NS_TEMPLATE_TALK, + 'Categorie' => NS_CATEGORY, + 'Overleg_categorie' => NS_CATEGORY_TALK, + 'Overleg_help' => NS_HELP_TALK, ); $dateFormats = array( diff --git a/languages/messages/MessagesOr.php b/languages/messages/MessagesOr.php index 25a3f17bf8..cae067967a 100644 --- a/languages/messages/MessagesOr.php +++ b/languages/messages/MessagesOr.php @@ -40,17 +40,17 @@ $namespaceNames = array( NS_MEDIA => 'ମାଧ୍ୟମ', NS_SPECIAL => 'ବିଶେଷ', NS_TALK => 'ଆଲୋଚନା', - NS_USER => 'ବ୍ୟବହାରକାରୀ', - NS_USER_TALK => 'ବ୍ୟବହାରକାରୀଙ୍କ_ଆଲୋଚନା', - NS_PROJECT_TALK => '$1_ଆଲୋଚନା', + NS_USER => 'ବ୍ୟବାହାରକାରୀ', + NS_USER_TALK => 'ବ୍ୟବାହାରକାରୀଙ୍କ_ଆଲୋଚନା', + NS_PROJECT_TALK => 'ଉଇକିପିଡ଼ିଆ_ଆଲୋଚନା', NS_FILE => 'ଫାଇଲ', NS_FILE_TALK => 'ଫାଇଲ_ଆଲୋଚନା', NS_MEDIAWIKI => 'ମିଡ଼ିଆଉଇକି', NS_MEDIAWIKI_TALK => 'ମିଡ଼ିଆଉଇକି_ଆଲୋଚନା', - NS_TEMPLATE => 'ଛାଞ୍ଚ', - NS_TEMPLATE_TALK => 'ଛାଞ୍ଚ_ଆଲୋଚନା', - NS_HELP => 'ସହଯୋଗ', - NS_HELP_TALK => 'ସହଯୋଗ_ଆଲୋଚନା', + NS_TEMPLATE => 'ଟେମ୍ପଲେଟ', + NS_TEMPLATE_TALK => 'ଟେମ୍ପଲେଟ_ଆଲୋଚନା', + NS_HELP => 'ସାହାଯ୍ୟ', + NS_HELP_TALK => 'ସାହାଯ୍ୟ_ଆଲୋଚନା', NS_CATEGORY => 'ଶ୍ରେଣୀ', NS_CATEGORY_TALK => 'ଶ୍ରେଣୀ_ଆଲୋଚନା', ); @@ -58,17 +58,10 @@ $namespaceNames = array( $namespaceAliases = array( 'ବ୍ୟବହାରକାରି' => NS_USER, 'ବ୍ୟବହାରକାରିଁକ_ଆଲୋଚନା' => NS_USER_TALK, - 'ବ୍ୟବାହାରକାରୀ' => NS_USER, - 'ବ୍ୟବାହାରକାରୀଙ୍କ_ଆଲୋଚନା' => NS_USER_TALK, - 'ଉଇକିପିଡ଼ିଆ_ଆଲୋଚନା' => NS_PROJECT_TALK, 'ଟେଁପଲେଟ' => NS_TEMPLATE, 'ଟେଁପଲେଟ_ଆଲୋଚନା' => NS_TEMPLATE_TALK, - 'ଟେମ୍ପଲେଟ' => NS_TEMPLATE, - 'ଟେମ୍ପଲେଟ_ଆଲୋଚନା' => NS_TEMPLATE_TALK, 'ବିଭାଗ' => NS_CATEGORY, 'ବିଭାଗିୟ_ଆଲୋଚନା' => NS_CATEGORY_TALK, - 'ସାହାଯ୍ୟ' => NS_HELP, - 'ସାହାଯ୍ୟ_ଆଲୋଚନା' => NS_HELP_TALK, ); $specialPageAliases = array( diff --git a/languages/messages/MessagesOs.php b/languages/messages/MessagesOs.php index b6ed501cc3..f4aa85b99c 100644 --- a/languages/messages/MessagesOs.php +++ b/languages/messages/MessagesOs.php @@ -17,16 +17,16 @@ $fallback = 'ru'; $namespaceNames = array( - NS_MEDIA => 'Медиа', + NS_MEDIA => 'Media', NS_SPECIAL => 'Сæрмагонд', NS_TALK => 'Тæрхон', NS_USER => 'Архайæг', NS_USER_TALK => 'Архайæджы_ныхас', - NS_PROJECT_TALK => '{{GRAMMAR:genitive|$1}}_тæрхон', - NS_FILE => 'Файл', - NS_FILE_TALK => 'Файлы_тæрхон', + NS_PROJECT_TALK => 'Дискусси_$1', + NS_FILE => 'Ныв', + NS_FILE_TALK => 'Нывы_тæрхон', NS_MEDIAWIKI => 'MediaWiki', - NS_MEDIAWIKI_TALK => 'MediaWiki-йы_тæрхон', + NS_MEDIAWIKI_TALK => 'Тæрхон_MediaWiki', NS_TEMPLATE => 'Шаблон', NS_TEMPLATE_TALK => 'Шаблоны_тæрхон', NS_HELP => 'Æххуыс', @@ -38,19 +38,13 @@ $namespaceNames = array( $namespaceAliases = array( 'Дискусси' => NS_TALK, 'Архайæджы_дискусси' => NS_USER_TALK, - 'Дискусси_$1' => NS_PROJECT_TALK, - 'Ныв' => NS_FILE, - 'Нывы_тæрхон' => NS_FILE_TALK, 'Нывы_тыххæй_дискусси' => NS_FILE_TALK, 'Дискусси_MediaWiki' => NS_MEDIAWIKI_TALK, - 'Тæрхон_MediaWiki' => NS_MEDIAWIKI_TALK, 'Шаблоны_тыххæй_дискусси' => NS_TEMPLATE_TALK, 'Æххуысы_тыххæй_дискусси' => NS_HELP_TALK, 'Категорийы_тыххæй_дискусси' => NS_CATEGORY_TALK, ); -// Remove Russian aliases -$namespaceGenderAliases = array(); $magicWords = array( 'redirect' => array( '0', '#РАРВЫСТ', '#перенаправление', '#перенапр', '#REDIRECT' ), diff --git a/languages/messages/MessagesQug.php b/languages/messages/MessagesQug.php index 6021bedc27..e22f416adb 100644 --- a/languages/messages/MessagesQug.php +++ b/languages/messages/MessagesQug.php @@ -14,25 +14,6 @@ $fallback = 'qu, es'; -$namespaceNames = array( - NS_MEDIA => 'Midya', - NS_SPECIAL => 'Sapak', - NS_TALK => 'Rimanakuy', - NS_USER => 'Rurak', - NS_USER_TALK => 'Rurakpa_rimanakuy', - NS_PROJECT_TALK => '$1-pa_rimanakuy', - NS_FILE => 'Rikcha', - NS_FILE_TALK => 'Rikchapa_rimanakuy', - NS_MEDIAWIKI => 'MediaWiki', - NS_MEDIAWIKI_TALK => 'MediaWikipa_rimanakuy', - NS_TEMPLATE => 'Plantilla', - NS_TEMPLATE_TALK => 'Plantillapa_rimanakuy', - NS_HELP => 'Yanapa', - NS_HELP_TALK => 'Yanapapak_rimanakuy', - NS_CATEGORY => 'Samiyachiy', - NS_CATEGORY_TALK => 'Samiyachiy_rimanakuy', -); - $messages = array( # User preference toggles 'tog-underline' => 'Tinkikunana uraypi aspishpa rikuchina', diff --git a/languages/messages/MessagesSa.php b/languages/messages/MessagesSa.php index adc5a76b11..019fc5ad4b 100644 --- a/languages/messages/MessagesSa.php +++ b/languages/messages/MessagesSa.php @@ -44,7 +44,7 @@ $linkPrefixExtension = false; $namespaceNames = array( NS_MEDIA => 'माध्यमम्', - NS_SPECIAL => 'विशेषम्', + NS_SPECIAL => 'विशेष', NS_TALK => 'सम्भाषणम्', NS_USER => 'योजकः', NS_USER_TALK => 'योजकसम्भाषणम्', @@ -63,7 +63,6 @@ $namespaceNames = array( $namespaceAliases = array( 'माध्यम' => NS_MEDIA, - 'विशेष' => NS_SPECIAL, 'संभाषणं' => NS_TALK, 'योजकसंभाषणं' => NS_USER_TALK, '$1संभाषणं' => NS_PROJECT_TALK, diff --git a/languages/messages/MessagesSr_ec.php b/languages/messages/MessagesSr_ec.php index 7215184945..aea4c8bd5f 100644 --- a/languages/messages/MessagesSr_ec.php +++ b/languages/messages/MessagesSr_ec.php @@ -35,10 +35,10 @@ $namespaceNames = array( NS_USER => 'Корисник', NS_USER_TALK => 'Разговор_са_корисником', NS_PROJECT_TALK => 'Разговор_о_$1', - NS_FILE => 'Фајл', - NS_FILE_TALK => 'Разговор_о_фајлу', - NS_MEDIAWIKI => 'МедијаВики', - NS_MEDIAWIKI_TALK => 'Разговор_о_МедијаВикију', + NS_FILE => 'Датотека', + NS_FILE_TALK => 'Разговор_о_датотеци', + NS_MEDIAWIKI => 'Медијавики', + NS_MEDIAWIKI_TALK => 'Разговор_о_Медијавикију', NS_TEMPLATE => 'Шаблон', NS_TEMPLATE_TALK => 'Разговор_о_шаблону', NS_HELP => 'Помоћ', @@ -68,10 +68,6 @@ $namespaceAliases = array( 'Слика' => NS_FILE, 'Разговор_о_слици' => NS_FILE_TALK, - "Датотека" => NS_FILE, - "Разговор_о_датотеци" => NS_FILE_TALK, - "Медијавики" => NS_MEDIAWIKI, - "Разговор_о_Медијавикију" => NS_MEDIAWIKI_TALK, 'МедијаВики' => NS_MEDIAWIKI, 'Разговор_о_МедијаВикију' => NS_MEDIAWIKI_TALK, ); diff --git a/languages/messages/MessagesWar.php b/languages/messages/MessagesWar.php index a4d4463332..01dbb36315 100644 --- a/languages/messages/MessagesWar.php +++ b/languages/messages/MessagesWar.php @@ -14,25 +14,6 @@ * @author לערי ריינהארט */ -$namespaceNames = array( - NS_MEDIA => 'Medya', - NS_SPECIAL => 'Pinaurog', - NS_TALK => 'Hiruhimangraw', - NS_USER => 'Gumaramit', - NS_USER_TALK => 'Hiruhimangaw_hiton_gumaramit', - NS_PROJECT_TALK => 'Hiruhimangraw_hiton_$1', - NS_FILE => 'Fayl', - NS_FILE_TALK => 'Hiruhimangraw_hiton_fayl', - NS_MEDIAWIKI => 'MediaWiki', - NS_MEDIAWIKI_TALK => 'Hiruhimangraw_hiton_MediaWiki', - NS_TEMPLATE => 'Batakan', - NS_TEMPLATE_TALK => 'Hiruhimangraw_hiton_batakan', - NS_HELP => 'Bulig', - NS_HELP_TALK => 'Hiruhimangaw_hiton_bulig', - NS_CATEGORY => 'Kaarangay', - NS_CATEGORY_TALK => 'Hiruhimangraw_hiton_kaarangay', -); - $specialPageAliases = array( 'Allpages' => array( 'NgatananngaPakli' ), 'Categories' => array( 'Mga_kaarangay' ), diff --git a/languages/messages/MessagesYue.php b/languages/messages/MessagesYue.php index 928dd18579..161695e26a 100644 --- a/languages/messages/MessagesYue.php +++ b/languages/messages/MessagesYue.php @@ -22,11 +22,11 @@ $namespaceNames = array( NS_TALK => '傾偈', NS_USER => '用戶', NS_USER_TALK => '用戶傾偈', - NS_PROJECT_TALK => '$1傾偈', + NS_PROJECT_TALK => '$1_傾偈', NS_FILE => '文件', NS_FILE_TALK => '文件傾偈', NS_MEDIAWIKI => 'MediaWiki', - NS_MEDIAWIKI_TALK => 'MediaWiki傾偈', + NS_MEDIAWIKI_TALK => 'MediaWiki_傾偈', NS_TEMPLATE => '模', NS_TEMPLATE_TALK => '模傾偈', NS_HELP => '幫手', @@ -47,7 +47,9 @@ $namespaceAliases = array( "用户 对话" => NS_USER_TALK, "用戶 討論" => NS_USER_TALK, "用户 讨论" => NS_USER_TALK, - '$1_傾偈' => NS_PROJECT_TALK, + # This has never worked so it's unlikely to annoy anyone if I disable it -- TS + # "{$wgMetaNamespace} 討論" => NS_PROJECT_TALK, + # "{$wgMetaNamespace} 讨论" => NS_PROJECT_TALK, "檔" => NS_FILE, "檔案" => NS_FILE, "档" => NS_FILE, @@ -66,7 +68,6 @@ $namespaceAliases = array( "图 讨论" => NS_FILE_TALK, "圖像 討論" => NS_FILE_TALK, "图像 讨论" => NS_FILE_TALK, - 'MediaWiki_傾偈' => NS_FILE_TALK, "模 討論" => NS_TEMPLATE_TALK, "模 讨论" => NS_TEMPLATE_TALK, "幫助" => NS_HELP, diff --git a/maintenance/archives/patch-filejournal.sql b/maintenance/archives/patch-filejournal.sql deleted file mode 100644 index b7a7d09f7b..0000000000 --- a/maintenance/archives/patch-filejournal.sql +++ /dev/null @@ -1,24 +0,0 @@ --- File backend operation journal -CREATE TABLE /*_*/filejournal ( - -- Unique ID for each file operation - fj_id bigint unsigned NOT NULL PRIMARY KEY auto_increment, - -- UUID of the batch this operation belongs to - fj_batch_uuid varbinary(32) NOT NULL, - -- The registered file backend name - fj_backend varchar(255) NOT NULL, - -- The storage path that was affected (may be internal paths) - fj_path blob NOT NULL, - -- SHA-1 file path hash in base-36 - fj_path_sha1 varbinary(32) NOT NULL default '', - -- Primitive operation description (create/update/delete) - fj_op varchar(16) NOT NULL default '', - -- SHA-1 file content hash in base-36 - fj_new_sha1 varbinary(32) NOT NULL default '', - -- Timestamp of the batch operation - fj_timestamp varbinary(14) NOT NULL default '' -); - -CREATE INDEX /*i*/fj_batch_id ON /*_*/filejournal (fj_batch_uuid,fj_id); -CREATE INDEX /*i*/fj_path_id ON /*_*/filejournal (fj_path_sha1,fj_id); -CREATE INDEX /*i*/fj_new_sha1 ON /*_*/filejournal (fj_new_sha1,fj_id); -CREATE INDEX /*i*/fj_timestamp ON /*_*/filejournal (fj_timestamp); diff --git a/maintenance/dumpTextPass.php b/maintenance/dumpTextPass.php index cdbd546361..c03f3df893 100644 --- a/maintenance/dumpTextPass.php +++ b/maintenance/dumpTextPass.php @@ -41,7 +41,9 @@ class TextPassDumper extends BackupDumper { var $prefetchCountLast = 0; var $fetchCountLast = 0; + var $failures = 0; var $maxFailures = 5; + var $failedTextRetrievals = 0; var $maxConsecutiveFailedTextRetrievals = 200; var $failureTimeout = 5; // Seconds to sleep after db failure @@ -69,54 +71,6 @@ class TextPassDumper extends BackupDumper { */ protected $db; - - /** - * Drop the database connection $this->db and try to get a new one. - * - * This function tries to get a /different/ connection if this is - * possible. Hence, (if this is possible) it switches to a different - * failover upon each call. - * - * This function resets $this->lb and closes all connections on it. - * - * @throws MWException - */ - function rotateDb() { - // Cleaning up old connections - if ( isset( $this->lb ) ) { - $this->lb->closeAll(); - unset( $this->lb ); - } - - if ( isset( $this->db ) && $this->db->isOpen() ) - { - throw new MWException( 'DB is set and has not been closed by the Load Balancer' ); - } - - - unset( $this->db ); - - // Trying to set up new connection. - // We do /not/ retry upon failure, but delegate to encapsulating logic, to avoid - // individually retrying at different layers of code. - - // 1. The LoadBalancer. - try { - $this->lb = wfGetLBFactory()->newMainLB(); - } catch (Exception $e) { - throw new MWException( __METHOD__ . " rotating DB failed to obtain new load balancer (" . $e->getMessage() . ")" ); - } - - - // 2. The Connection, through the load balancer. - try { - $this->db = $this->lb->getConnection( DB_SLAVE, 'backup' ); - } catch (Exception $e) { - throw new MWException( __METHOD__ . " rotating DB failed to obtain new database (" . $e->getMessage() . ")" ); - } - } - - function initProgress( $history ) { parent::initProgress(); $this->timeOfCheckpoint = $this->startTime; @@ -133,19 +87,7 @@ class TextPassDumper extends BackupDumper { $this->initProgress( $this->history ); - // We are trying to get an initial database connection to avoid that the - // first try of this request's first call to getText fails. However, if - // obtaining a good DB connection fails it's not a serious issue, as - // getText does retry upon failure and can start without having a working - // DB connection. - try { - $this->rotateDb(); - } catch (Exception $e) { - // We do not even count this as failure. Just let eventual - // watchdogs know. - $this->progress( "Getting initial DB connection failed (" . - $e->getMessage() . ")" ); - } + $this->db = $this->backupDb(); $this->egress = new ExportProgressFilter( $this->sink, $this ); @@ -374,142 +316,98 @@ class TextPassDumper extends BackupDumper { return true; } - /** - * Tries to get the revision text for a revision id. - * - * Upon errors, retries (Up to $this->maxFailures tries each call). - * If still no good revision get could be found even after this retrying, "" is returned. - * If no good revision text could be returned for - * $this->maxConsecutiveFailedTextRetrievals consecutive calls to getText, MWException - * is thrown. - * - * @param $id string The revision id to get the text for - * - * @return string The revision text for $id, or "" - * @throws MWException - */ function getText( $id ) { - $prefetchNotTried = true; // Whether or not we already tried to get the text via prefetch. - $text = false; // The candidate for a good text. false if no proper value. - $failures = 0; // The number of times, this invocation of getText already failed. - - static $consecutiveFailedTextRetrievals = 0; // The number of times getText failed without - // yielding a good text in between. - $this->fetchCount++; - - // To allow to simply return on success and do not have to worry about book keeping, - // we assume, this fetch works (possible after some retries). Nevertheless, we koop - // the old value, so we can restore it, if problems occur (See after the while loop). - $oldConsecutiveFailedTextRetrievals = $consecutiveFailedTextRetrievals; - $consecutiveFailedTextRetrievals = 0; - - while ( $failures < $this->maxFailures ) { - - // As soon as we found a good text for the $id, we will return immediately. - // Hence, if we make it past the try catch block, we know that we did not - // find a good text. - - try { - // Step 1: Get some text (or reuse from previous iteratuon if checking - // for plausibility failed) - - // Trying to get prefetch, if it has not been tried before - if ( $text === false && isset( $this->prefetch ) && $prefetchNotTried ) { - $prefetchNotTried = false; - $tryIsPrefetch = true; - $text = $this->prefetch->prefetch( $this->thisPage, $this->thisRev ); - if ( $text === null ) { - $text = false; - } - } - - if ( $text === false ) { - // Fallback to asking the database - $tryIsPrefetch = false; - if ( $this->spawn ) { - $text = $this->getTextSpawned( $id ); - } else { - $text = $this->getTextDb( $id ); - } - } - - if ( $text === false ) { - throw new MWException( "Generic error while obtaining text for id " . $id ); - } - - // We received a good candidate for the text of $id via some method - - // Step 2: Checking for plausibility and return the text if it is - // plausible + if ( isset( $this->prefetch ) ) { + $text = $this->prefetch->prefetch( $this->thisPage, $this->thisRev ); + if ( $text !== null ) { // Entry missing from prefetch dump + $dbr = wfGetDB( DB_SLAVE ); $revID = intval( $this->thisRev ); - if ( ! isset( $this->db ) ) { - throw new MWException( "No database available" ); - } - $revLength = $this->db->selectField( 'revision', 'rev_len', array( 'rev_id' => $revID ) ); + $revLength = $dbr->selectField( 'revision', 'rev_len', array( 'rev_id' => $revID ) ); + // if length of rev text in file doesn't match length in db, we reload + // this avoids carrying forward broken data from previous xml dumps if( strlen( $text ) == $revLength ) { - if ( $tryIsPrefetch ) { - $this->prefetchCount++; - } + $this->prefetchCount++; return $text; } - - $text = false; - throw new MWException( "Received text is unplausible for id " . $id ); - - } catch (Exception $e) { - $msg = "getting/checking text " . $id . " failed (".$e->getMessage().")"; - if ( $failures + 1 < $this->maxFailures ) { - $msg .= " (Will retry " . ( $this->maxFailures - $failures - 1) . " more times)"; - } - $this->progress( $msg ); } - - // Something went wrong; we did not a text that was plausible :( - $failures++; - + } + return $this->doGetText( $id ); + } - // After backing off for some time, we try to reboot the whole process as - // much as possible to not carry over failures from one part to the other - // parts - sleep( $this->failureTimeout ); - try { - $this->rotateDb(); - if ( $this->spawn ) { + private function doGetText( $id ) { + $id = intval( $id ); + $this->failures = 0; + $ex = new MWException( "Graceful storage failure" ); + while (true) { + if ( $this->spawn ) { + if ($this->failures) { + // we don't know why it failed, could be the child process + // borked, could be db entry busted, could be db server out to lunch, + // so cover all bases $this->closeSpawn(); $this->openSpawn(); } - } catch (Exception $e) { - $this->progress( "Rebooting getText infrastructure failed (".$e->getMessage().")" . - " Trying to continue anyways" ); + $text = $this->getTextSpawned( $id ); + } else { + $text = $this->getTextDbSafe( $id ); + } + if ( $text === false ) { + $this->failures++; + if ( $this->failures > $this->maxFailures) { + $this->progress( "Failed to retrieve revision text for text id ". + "$id after $this->maxFailures tries, giving up" ); + // were there so many bad retrievals in a row we want to bail? + // at some point we have to declare the dump irretrievably broken + $this->failedTextRetrievals++; + if ($this->failedTextRetrievals > $this->maxConsecutiveFailedTextRetrievals) { + throw $ex; + } else { + // would be nice to return something better to the caller someday, + // log what we know about the failure and about the revision + return ""; + } + } else { + $this->progress( "Error $this->failures " . + "of allowed $this->maxFailures retrieving revision text for text id $id! " . + "Pausing $this->failureTimeout seconds before retry..." ); + sleep( $this->failureTimeout ); + } + } else { + $this->failedTextRetrievals= 0; + return $text; } } + return ''; + } - // Retirieving a good text for $id failed (at least) maxFailures times. - // We abort for this $id. - - // Restoring the consecutive failures, and maybe aborting, if the dump - // is too broken. - $consecutiveFailedTextRetrievals = $oldConsecutiveFailedTextRetrievals + 1; - if ( $consecutiveFailedTextRetrievals > $this->maxConsecutiveFailedTextRetrievals ) { - throw new MWException( "Graceful storage failure" ); + /** + * Fetch a text revision from the database, retrying in case of failure. + * This may survive some transitory errors by reconnecting, but + * may not survive a long-term server outage. + * + * FIXME: WTF? Why is it using a loop and then returning unconditionally? + * @param $id int + * @return bool|string + */ + private function getTextDbSafe( $id ) { + while ( true ) { + try { + $text = $this->getTextDb( $id ); + } catch ( DBQueryError $ex ) { + $text = false; + } + return $text; } - - return ""; } - /** * May throw a database error if, say, the server dies during query. * @param $id * @return bool|string - * @throws MWException */ private function getTextDb( $id ) { global $wgContLang; - if ( ! isset( $this->db ) ) { - throw new MWException( __METHOD__ . "No database available" ); - } $row = $this->db->selectRow( 'text', array( 'old_text', 'old_flags' ), array( 'old_id' => $id ), diff --git a/maintenance/language/messages.inc b/maintenance/language/messages.inc index 093305eb2d..c9afbfa87e 100644 --- a/maintenance/language/messages.inc +++ b/maintenance/language/messages.inc @@ -408,7 +408,6 @@ $wgMessageStructure = array( 'customjsprotected', 'ns-specialprotected', 'titleprotected', - 'filereadonlyerror' ), 'virus' => array( 'virus-badscanner', @@ -1378,11 +1377,6 @@ $wgMessageStructure = array( 'backend-fail-batchsize' ), - 'filejournal-errors' => array( - 'filejournal-fail-dbconnect', - 'filejournal-fail-dbquery' - ), - 'lockmanager-errors' => array( 'lockmanager-notlocked', 'lockmanager-fail-closelock', diff --git a/resources/mediawiki.action/mediawiki.action.watch.ajax.js b/resources/mediawiki.action/mediawiki.action.watch.ajax.js index 8d3b8fabc3..f5f09f52a1 100644 --- a/resources/mediawiki.action/mediawiki.action.watch.ajax.js +++ b/resources/mediawiki.action/mediawiki.action.watch.ajax.js @@ -4,158 +4,152 @@ */ ( function ( $, mw, undefined ) { - /** - * The name of the page to watch or unwatch. - */ - var title = mw.config.get( 'wgRelevantPageName', mw.config.get( 'wgPageName' ) ); - - /** - * Update the link text, link href attribute and (if applicable) - * "loading" class. - * - * @param $link {jQuery} Anchor tag of (un)watch link. - * @param action {String} One of 'watch', 'unwatch'. - * @param state {String} [optional] 'idle' or 'loading'. Default is 'idle'. - */ - function updateWatchLink( $link, action, state ) { - var accesskeyTip, msgKey, $li; - - // message keys 'watch', 'watching', 'unwatch' or 'unwatching'. - msgKey = state === 'loading' ? action + 'ing' : action; - accesskeyTip = $link.attr( 'title' ).match( mw.util.tooltipAccessKeyRegexp ); +/** + * The name of the page to watch or unwatch. + */ +var title = mw.config.get( 'wgRelevantPageName', mw.config.get( 'wgPageName' ) ); + +/** + * Update the link text, link href attribute and (if applicable) + * "loading" class. + * + * @param $link {jQuery} Anchor tag of (un)watch link + * @param action {String} One of 'watch', 'unwatch'. + * @param state {String} [optional] 'idle' or 'loading'. Default is 'idle'. + */ +function updateWatchLink( $link, action, state ) { + // message keys 'watch', 'watching', 'unwatch' or 'unwatching'. + var msgKey = state === 'loading' ? action + 'ing' : action, + accesskeyTip = $link.attr( 'title' ).match( mw.util.tooltipAccessKeyRegexp ), $li = $link.closest( 'li' ); - $link - .text( mw.msg( msgKey ) ) - .attr( 'title', mw.msg( 'tooltip-ca-' + action ) + - ( accesskeyTip ? ' ' + accesskeyTip[0] : '' ) - ) - .attr( 'href', mw.util.wikiScript() + '?' + $.param({ - title: title, - action: action - }) - ); - - // Special case for vector icon - if ( $li.hasClass( 'icon' ) ) { - if ( state === 'loading' ) { - $link.addClass( 'loading' ); - } else { - $link.removeClass( 'loading' ); - } + $link + .text( mw.msg( msgKey ) ) + .attr( 'title', mw.msg( 'tooltip-ca-' + action ) + + ( accesskeyTip ? ' ' + accesskeyTip[0] : '' ) + ) + .attr( 'href', mw.util.wikiScript() + '?' + $.param({ + title: title, + action: action + }) + ); + + // Special case for vector icon + if ( $li.hasClass( 'icon' ) ) { + if ( state === 'loading' ) { + $link.addClass( 'loading' ); + } else { + $link.removeClass( 'loading' ); } } +} - /** - * @todo This should be moved somewhere more accessible. - * @param url {String} - * @return {String} The extracted action, defaults to 'view'. - */ - function mwUriGetAction( url ) { - var action, actionPaths, key, i, m, parts; - - actionPaths = mw.config.get( 'wgActionPaths' ); - - // @todo: Does MediaWiki give action path or query param - // precedence ? If the former, move this to the bottom - action = mw.util.getParamValue( 'action', url ); - if ( action !== null ) { - return action; - } - - for ( key in actionPaths ) { - if ( actionPaths.hasOwnProperty( key ) ) { - parts = actionPaths[key].split( '$1' ); - for ( i = 0; i < parts.length; i += 1 ) { - parts[i] = $.escapeRE( parts[i] ); - } - m = new RegExp( parts.join( '(.+)' ) ).exec( url ); - if ( m && m[1] ) { - return key; - } +/** + * @todo This should be moved somewhere more accessible. + * @param url {String} + * @return {String} The extracted action, defaults to 'view'. + */ +function mwUriGetAction( url ) { + var actionPaths = mw.config.get( 'wgActionPaths' ), + key, parts, m, action; + + // @todo: Does MediaWiki give action path or query param + // precedence ? If the former, move this to the bottom + action = mw.util.getParamValue( 'action', url ); + if ( action !== null ) { + return action; + } + for ( key in actionPaths ) { + if ( actionPaths.hasOwnProperty( key ) ) { + parts = actionPaths[key].split( '$1' ); + for ( i = 0; i < parts.length; i += 1 ) { + parts[i] = $.escapeRE( parts[i] ); } + m = new RegExp( parts.join( '(.+)' ) ).exec( url ); + if ( m && m[1] ) { + return key; + } + } - - return 'view'; } - $( document ).ready( function () { - var $links = $( '.mw-watchlink a, a.mw-watchlink, ' + - '#ca-watch a, #ca-unwatch a, #mw-unwatch-link1, ' + - '#mw-unwatch-link2, #mw-watch-link2, #mw-watch-link1' ); + return 'view'; +} - // Allowing people to add inline animated links is a little scary - $links = $links.filter( ':not( #bodyContent *, #content * )' ); +$( document ).ready( function() { + var $links = $( '.mw-watchlink a, a.mw-watchlink, ' + + '#ca-watch a, #ca-unwatch a, #mw-unwatch-link1, ' + + '#mw-unwatch-link2, #mw-watch-link2, #mw-watch-link1' ); - $links.click( function ( e ) { - var action, api, $link; + // Allowing people to add inline animated links is a little scary + $links = $links.filter( ':not( #bodyContent *, #content * )' ); + $links.click( function( e ) { + var $link, api, action = mwUriGetAction( this.href ); - if ( action !== 'watch' && action !== 'unwatch' ) { - // Could not extract target action from link url, - // let native browsing handle it further - return true; - } - e.preventDefault(); - e.stopPropagation(); - - $link = $( this ); - - updateWatchLink( $link, action, 'loading' ); - - api = new mw.Api(); - api[action]( - title, - // Success - function ( watchResponse ) { - var $li, otherAction; - - otherAction = action === 'watch' ? 'unwatch' : 'watch'; + if ( action !== 'watch' && action !== 'unwatch' ) { + // Could not extract target action from link url, + // let native browsing handle it further + return true; + } + e.preventDefault(); + e.stopPropagation(); + + $link = $( this ); + + updateWatchLink( $link, action, 'loading' ); + + api = new mw.Api(); + api[action]( + title, + // Success + function( watchResponse ) { + var otherAction = action === 'watch' ? 'unwatch' : 'watch', $li = $link.closest( 'li' ); - mw.util.jsMessage( watchResponse.message, 'ajaxwatch' ); - - // Set link to opposite - updateWatchLink( $link, otherAction ); - - // Most common ID style - if ( $li.prop( 'id' ) === 'ca-' + otherAction || $li.prop( 'id' ) === 'ca-' + action ) { - $li.prop( 'id', 'ca-' + otherAction ); - } - - // Bug 12395 - update the watch checkbox on edit pages when the - // page is watched or unwatched via the tab. - if ( watchResponse.watched !== undefined ) { - $( '#wpWatchthis' ).prop( 'checked', true ); - } else { - $( '#wpWatchthis' ).removeProp( 'checked' ); - } - }, - // Error - function () { - var cleanTitle, html, link; - - // Reset link to non-loading mode - updateWatchLink( $link, action ); - - // Format error message - cleanTitle = title.replace( /_/g, ' ' ); - link = mw.html.element( - 'a', { - href: mw.util.wikiGetlink( title ), - title: cleanTitle - }, cleanTitle - ); - html = mw.msg( 'watcherrortext', link ); - - // Report to user about the error - mw.util.jsMessage( html, 'ajaxwatch' ); + mw.util.jsMessage( watchResponse.message, 'ajaxwatch' ); + + // Set link to opposite + updateWatchLink( $link, otherAction ); + // Most common ID style + if ( $li.prop( 'id' ) === 'ca-' + otherAction || $li.prop( 'id' ) === 'ca-' + action ) { + $li.prop( 'id', 'ca-' + otherAction ); + } + + // Bug 12395 - update the watch checkbox on edit pages when the + // page is watched or unwatched via the tab. + if ( watchResponse.watched !== undefined ) { + $( '#wpWatchthis' ).prop( 'checked', true ); + } else { + $( '#wpWatchthis' ).removeProp( 'checked' ); } - ); - }); + }, + // Error + function(){ + + // Reset link to non-loading mode + updateWatchLink( $link, action ); + + // Format error message + var cleanTitle = title.replace( /_/g, ' ' ); + var link = mw.html.element( + 'a', { + 'href': mw.util.wikiGetlink( title ), + 'title': cleanTitle + }, cleanTitle + ); + var html = mw.msg( 'watcherrortext', link ); + + // Report to user about the error + mw.util.jsMessage( html, 'ajaxwatch' ); + + } + ); }); -}( jQuery, mediaWiki ) ); +}); + +})( jQuery, mediaWiki ); diff --git a/resources/mediawiki.api/mediawiki.api.watch.js b/resources/mediawiki.api/mediawiki.api.watch.js index 302a2d31dc..8ed6832091 100644 --- a/resources/mediawiki.api/mediawiki.api.watch.js +++ b/resources/mediawiki.api/mediawiki.api.watch.js @@ -4,51 +4,47 @@ */ ( function( $, mw ) { - /** - * @context {mw.Api} - */ - function doWatchInternal( page, success, err, addParams ) { - var params = { - action: 'watch', - title: String( page ), - token: mw.user.tokens.get( 'watchToken' ), - uselang: mw.config.get( 'wgUserLanguage' ) - }; - function ok( data ) { - success( data.watch ); - } - if ( addParams ) { - $.extend( params, addParams ); - } - return this.post( params, { ok: ok, err: err } ); - } - $.extend( mw.Api.prototype, { /** * Convinience method for 'action=watch'. * * @param page {String|mw.Title} Full page name or instance of mw.Title - * @param success {Function} Callback to which the watch object will be passed. - * Watch object contains properties 'title' (full pagename), 'watched' (boolean) and + * @param success {Function} callback to which the watch object will be passed + * watch object contains 'title' (full page name), 'watched' (boolean) and * 'message' (parsed HTML of the 'addedwatchtext' message). - * @param err {Function} Error callback (optional) + * @param _unwatch {Boolean} Internally used to re-use this logic for unwatch(), + * do not use outside this module. + * @param err {Function} callback if error (optional) * @return {jqXHR} */ - watch: function ( page, success, err ) { - return doWatchInternal.call( this, page, success, err ); + watch: function( page, success, err, _unwatch ) { + var params, ok; + params = { + action: 'watch', + title: String( page ), + token: mw.user.tokens.get( 'watchToken' ), + uselang: mw.config.get( 'wgUserLanguage' ) + }; + if ( _unwatch ) { + params.unwatch = 1; + } + ok = function( data ) { + success( data.watch ); + }; + return this.post( params, { ok: ok, err: err } ); }, /** * Convinience method for 'action=watch&unwatch=1'. * * @param page {String|mw.Title} Full page name or instance of mw.Title - * @param success {Function} Callback to which the watch object will be passed. - * Watch object contains properties 'title' (full pagename), 'watched' (boolean) and + * @param success {Function} callback to which the watch object will be passed + * watch object contains 'title' (full page name), 'unwatched' (boolean) and * 'message' (parsed HTML of the 'removedwatchtext' message). - * @param err {Function} Error callback (optional) + * @param err {Function} callback if error (optional) * @return {jqXHR} */ - unwatch: function ( page, success, err ) { - return doWatchInternal.call( this, page, success, err, { unwatch: 1 } ); + unwatch: function( page, success, err ) { + return this.watch( page, success, err, true ); } } ); -- 2.20.1