* LoginForm::getLoginToken() and LoginForm::getCreateaccountToken()
return a MediaWiki\Session\Token, and tokens must be checked using that
class's methods.
+* $wgEnotifUseJobQ was removed and the job queue is always used.
=== New features in 1.27 ===
-* $wgDataCenterId and $wgDataCenterRoles where added, which will serve as
- basic configuration settings needed for multi-datacenter setups.
- $wgDataCenterUpdateStickTTL was also added.
+* $wgDataCenterUpdateStickTTL was also added. This decides how long a user
+ sticks to the primary DC (via cookies) after they make changes to the site.
* Added a new hook, 'UserMailerTransformContent', to transform the contents
of an email. This is similar to the EmailUser hook but applies to all mail
sent via UserMailer.
* ApiQueryBase::getDirectionDescription() was removed (deprecated since 1.25).
* ApiQuery::getModules() was removed (deprecated since 1.21).
* ApiMain::getModules() was removed (deprecated since 1.21).
+* ApiBase::getVersion() was removed (deprecated since 1.21).
=== Languages updated in 1.27 ===
Each job clears $wgUpdateRowsPerJob pages (500 by default).
enotifNotify
- Used when $wgEnotifUseJobQ is true to send mail using the job queue.
+ Used to send mail using the job queue.
*/
$wgEnotifMaxRecips = 500;
-/**
- * Send mails via the job queue. This can be useful to reduce the time it
- * takes to save a page that a lot of people are watching.
- */
-$wgEnotifUseJobQ = false;
-
/**
* Use real name instead of username in e-mail "from" field.
*/
*/
$wgLBFactoryConf = array( 'class' => 'LBFactorySimple' );
-/**
- * The ID of the current data center
- * @since 1.27
- */
-$wgDataCenterId = 'default';
-
-/**
- * Map of data center IDs to their role ("master" or "slave")
- *
- * Multiple data centers can be setup to handle MediaWiki, with HTTP
- * POSTs routed to the master data center and GET/HEAD/OPTION routed to
- * any data center (usually the closest to the end user). In such setups,
- * this setting should be set to the appropriate value in the site
- * config for each data center.
- * @since 1.27
- */
-$wgDataCenterRoles = array( 'default' => 'master' );
-
/**
* After a state-changing request is done by a client, this determines
* how many seconds that client should keep using the master datacenter.
/************************************************************************//**
* @name Job queue
- * See also $wgEnotifUseJobQ.
* @{
*/
$config = $context->getConfig();
$factory = wfGetLBFactory();
- // Check if any transaction was too big
- $limit = $config->get( 'MaxUserDBWriteDuration' );
- $factory->forEachLB( function ( LoadBalancer $lb ) use ( $limit ) {
- $lb->forEachOpenConnection( function ( IDatabase $db ) use ( $limit ) {
- $time = $db->pendingWriteQueryDuration();
- if ( $limit > 0 && $time > $limit ) {
- throw new DBTransactionError(
- $db,
- wfMessage( 'transaction-duration-limit-exceeded', $time, $limit )->text()
- );
- }
- } );
- } );
// Commit all changes
- $factory->commitMasterChanges( __METHOD__ );
+ $factory->commitMasterChanges(
+ __METHOD__,
+ // Abort if any transaction was too big
+ array( 'maxWriteDuration' => $config->get( 'MaxUserDBWriteDuration' ) )
+ );
// Record ChronologyProtector positions
$factory->shutdown();
wfDebug( __METHOD__ . ': all transactions committed' );
$wgEnotifMaxRecips = 0;
$wgEnotifMinorEdits = false;
$wgEnotifRevealEditorAddress = false;
- $wgEnotifUseJobQ = false;
$wgEnotifUseRealName = false;
$wgEnotifUserTalk = false;
$wgEnotifWatchlist = false;
*/
class WatchedItem {
/** @var Title */
- public $mTitle;
+ private $mTitle;
/** @var User */
- public $mUser;
+ private $mUser;
/** @var int */
- public $mCheckRights;
+ private $mCheckRights;
/** @var bool */
private $loaded = false;
*/
const CHECK_USER_RIGHTS = 1;
- /**
- * Do DB master updates right now
- * @since 1.26
- */
- const IMMEDIATE = 0;
- /**
- * Do DB master updates via the job queue
- * @since 1.26
- */
- const DEFERRED = 1;
-
/**
* Create a WatchedItem object with the given user and title
* @since 1.22 $checkRights parameter added
* @param bool $force Whether to force the write query to be executed even if the
* page is not watched or the notification timestamp is already NULL.
* @param int $oldid The revision id being viewed. If not given or 0, latest revision is assumed.
- * @mode int $mode WatchedItem::DEFERRED/IMMEDIATE
*/
public function resetNotificationTimestamp(
- $force = '', $oldid = 0, $mode = self::IMMEDIATE
+ $force = '', $oldid = 0
) {
// Only loggedin user can have a watchlist
if ( wfReadOnly() || $this->mUser->isAnon() || !$this->isAllowed( 'editmywatchlist' ) ) {
}
// If the page is watched by the user (or may be watched), update the timestamp
- if ( $mode === self::DEFERRED ) {
- $job = new ActivityUpdateJob(
- $title,
- array(
- 'type' => 'updateWatchlistNotification',
- 'userid' => $this->getUserId(),
- 'notifTime' => $notificationTimestamp,
- 'curTime' => time()
- )
- );
- // Try to run this post-send
- DeferredUpdates::addCallableUpdate( function() use ( $job ) {
- $job->run();
- } );
- } else {
- $dbw = wfGetDB( DB_MASTER );
- $dbw->update( 'watchlist',
- array( 'wl_notificationtimestamp' => $dbw->timestampOrNull( $notificationTimestamp ) ),
- $this->dbCond(),
- __METHOD__
- );
- }
+ $job = new ActivityUpdateJob(
+ $title,
+ array(
+ 'type' => 'updateWatchlistNotification',
+ 'userid' => $this->getUserId(),
+ 'notifTime' => $notificationTimestamp,
+ 'curTime' => time()
+ )
+ );
+ // Try to run this post-send
+ DeferredUpdates::addCallableUpdate( function() use ( $job ) {
+ $job->run();
+ } );
$this->timestamp = null;
}
/// @deprecated since 1.24
const PROP_NULLABLE = 1;
- /**
- * Formerly returned a string that identifies the version of the extending
- * class. Typically included the class name, the svn revision, timestamp,
- * and last author. Usually done with SVN's Id keyword
- *
- * @deprecated since 1.21, version string is no longer supported
- * @return string
- */
- public function getVersion() {
- wfDeprecated( __METHOD__, '1.21' );
- return '';
- }
-
/**
* Formerly used to fetch a list of possible properites in the result,
* somehow organized with respect to the prop parameter that causes them to
$data['git-hash'] = $git;
$data['git-branch'] =
SpecialVersion::getGitCurrentBranch( $GLOBALS['IP'] );
- } else {
- $svn = SpecialVersion::getSvnRevision( $IP );
- if ( $svn ) {
- $data['rev'] = $svn;
- }
}
// 'case-insensitive' option is reserved for future
}
if ( isset( $ext['version'] ) ) {
$ret['version'] = $ext['version'];
- } elseif ( isset( $ext['svn-revision'] ) &&
- preg_match( '/\$(?:Rev|LastChangedRevision|Revision): *(\d+)/',
- $ext['svn-revision'], $m )
- ) {
- $ret['version'] = 'r' . $m[1];
}
if ( isset( $ext['path'] ) ) {
$extensionPath = dirname( $ext['path'] );
if ( $vcsDate !== false ) {
$ret['vcs-date'] = wfTimestamp( TS_ISO_8601, $vcsDate );
}
- } else {
- $svnInfo = SpecialVersion::getSvnInfo( $extensionPath );
- if ( $svnInfo !== false ) {
- $ret['vcs-system'] = 'svn';
- $ret['vcs-version'] = $svnInfo['checkout-rev'];
- $ret['vcs-url'] = isset( $svnInfo['viewvc-url'] ) ? $svnInfo['viewvc-url'] : '';
- }
}
if ( SpecialVersion::getExtLicenseFileName( $extensionPath ) ) {
* @return ParserOptions
*/
function getParserOptions() {
+ global $wgFullyInitialised, $wgContLang;
+
if ( !$this->mParserOptions ) {
+ if ( !$wgFullyInitialised ) {
+ // $wgUser isn't unstubbable yet, so don't try to get a
+ // ParserOptions for it. And don't cache this ParserOptions
+ // either.
+ $po = new ParserOptions( new User, $wgContLang );
+ $po->setEditSection( false );
+ return $po;
+ }
+
$this->mParserOptions = new ParserOptions;
$this->mParserOptions->setEditSection( false );
}
return $this->__call( __FUNCTION__, func_get_args() );
}
+ public function getScopedLockAndFlush( $lockKey, $fname, $timeout ) {
+ return $this->__call( __FUNCTION__, func_get_args() );
+ }
+
public function namedLocksEnqueue() {
return $this->__call( __FUNCTION__, func_get_args() );
}
return true;
}
+ public function getScopedLockAndFlush( $lockKey, $fname, $timeout ) {
+ if ( !$this->lock( $lockKey, $fname, $timeout ) ) {
+ return null;
+ }
+
+ $that = $this;
+ $unlocker = new ScopedCallback( function () use ( $that, $lockKey, $fname ) {
+ $that->unlock( $lockKey, $fname );
+ } );
+
+ $this->commit( __METHOD__, 'flush' );
+
+ return $unlocker;
+ }
+
public function namedLocksEnqueue() {
return false;
}
* Named locks are not related to transactions
*
* @param string $lockName Name of lock to aquire
- * @param string $method Name of method calling us
- * @param int $timeout
+ * @param string $method Name of the calling method
+ * @param int $timeout Acquisition timeout in seconds
* @return bool
*/
public function lock( $lockName, $method, $timeout = 5 );
* Named locks are not related to transactions
*
* @param string $lockName Name of lock to release
- * @param string $method Name of method calling us
+ * @param string $method Name of the calling method
*
* @return int Returns 1 if the lock was released, 0 if the lock was not established
* by this thread (in which case the lock is not released), and NULL if the named
*/
public function unlock( $lockName, $method );
+ /**
+ * Acquire a named lock, flush any transaction, and return an RAII style unlocker object
+ *
+ * This is suitiable for transactions that need to be serialized using cooperative locks,
+ * where each transaction can see each others' changes. Any transaction is flushed to clear
+ * out stale REPEATABLE-READ snapshot data. Once the returned object falls out of PHP scope,
+ * the lock will be released.
+ *
+ * If the lock acquisition failed, then no transaction flush happens, and null is returned.
+ *
+ * @param string $lockKey Name of lock to release
+ * @param string $fname Name of the calling method
+ * @param int $timeout Acquisition timeout in seconds
+ * @return ScopedCallback|null
+ * @throws DBUnexpectedError
+ * @since 1.27
+ */
+ public function getScopedLockAndFlush( $lockKey, $fname, $timeout );
+
/**
* Check to see if a named lock used by lock() use blocking queues
*
/**
* Commit changes on all master connections
* @param string $fname Caller name
+ * @param array $options Options map:
+ * - maxWriteDuration: abort if more than this much time was spent in write queries
*/
- public function commitMasterChanges( $fname = __METHOD__ ) {
+ public function commitMasterChanges( $fname = __METHOD__, array $options = array() ) {
+ $limit = isset( $options['maxWriteDuration'] ) ? $options['maxWriteDuration'] : 0;
+
$this->logMultiDbTransaction();
+ $this->forEachLB( function ( LoadBalancer $lb ) use ( $limit ) {
+ $lb->forEachOpenConnection( function ( IDatabase $db ) use ( $limit ) {
+ $time = $db->pendingWriteQueryDuration();
+ if ( $limit > 0 && $time > $limit ) {
+ throw new DBTransactionError(
+ $db,
+ wfMessage( 'transaction-duration-limit-exceeded', $time, $limit )->text()
+ );
+ }
+ } );
+ } );
$start = microtime( true );
$this->forEachLBCallMethod( 'commitMasterChanges', array( $fname ) );
* function instead of Database::getLag() avoids a fatal error in this
* case on many installations.
*
- * @param DatabaseBase $conn
+ * @param IDatabase $conn
* @return int
*/
- public function safeGetLag( $conn ) {
+ public function safeGetLag( IDatabase $conn ) {
if ( $this->getServerCount() == 1 ) {
return 0;
} else {
}
}
+ /**
+ * Wait for a slave DB to reach a specified master position
+ *
+ * This will connect to the master to get an accurate position if $pos is not given
+ *
+ * @param IDatabase $conn Slave DB
+ * @param DBMasterPos|bool $pos Master position; default: current position
+ * @param integer $timeout Timeout in seconds
+ * @return bool Success
+ * @since 1.27
+ */
+ public function safeWaitForPos( IDatabase $conn, $pos = false, $timeout = 10 ) {
+ if ( $this->getServerCount() == 1 || !$conn->getLBInfo( 'slave' ) ) {
+ return true; // server is not a slave DB
+ }
+
+ $pos = $pos ?: $this->getConnection( DB_MASTER )->getMasterPos();
+ if ( !$pos ) {
+ return false; // something is misconfigured
+ }
+
+ $result = $conn->masterPosWait( $pos, $timeout );
+ if ( $result == -1 || is_null( $result ) ) {
+ $msg = __METHOD__ . ": Timed out waiting on {$conn->getServer()} pos {$pos}";
+ wfDebugLog( 'replication', "$msg\n" );
+ wfDebugLog( 'DBPerformance', "$msg:\n" . wfBacktrace( true ) );
+ $ok = false;
+ } else {
+ wfDebugLog( 'replication', __METHOD__ . ": Done\n" );
+ $ok = true;
+ }
+
+ return $ok;
+ }
+
/**
* Clear the cache for slag lag delay times
*
) {
$metadata = new MetaDataFromKafka( $kafkaServers );
$produce = new Produce( $metadata );
+
+ if ( isset( $options['sendTimeout'] ) ) {
+ $timeOut = $options['sendTimeout'];
+ $produce->getClient()->setStreamOption( 'SendTimeoutSec', 0 );
+ $produce->getClient()->setStreamOption( 'SendTimeoutUSec',
+ intval( $timeOut * 1000000 )
+ );
+ }
+ if ( isset( $options['recvTimeout'] ) ) {
+ $timeOut = $options['recvTimeout'];
+ $produce->getClient()->setStreamOption( 'RecvTimeoutSec', 0 );
+ $produce->getClient()->setStreamOption( 'RecvTimeoutUSec',
+ intval( $timeOut * 1000000 )
+ );
+ }
if ( isset( $options['logExceptions'] ) && is_string( $options['logExceptions'] ) ) {
$options['logExceptions'] = LoggerFactory::getInstance( $options['logExceptions'] );
}
+
return new self( $produce, $options, $level, $bubble );
}
"config-localsettings-upgrade": "Востановена е податотека <code>LocalSettings.php</code>.\nЗа да ја надградите инсталцијава, внесете ја вредноста на <code>$wgUpgradeKey</code> во полето подолу.\nТоа е го најдете во <code>LocalSettings.php</code>.",
"config-localsettings-cli-upgrade": "Утврдено е присуството на податотеката „<code>LocalSettings.php</code>“.\nЗа да ја надградите воспоставката, пуштете ја „<code>update.php</code>“ наместо горенаведената.",
"config-localsettings-key": "Надградбен клуч:",
- "config-localsettings-badkey": "Ð\9aлÑ\83Ñ\87оÑ\82 Ñ\88Ñ\82о го наведовÑ\82е е погÑ\80еÑ\88ен",
+ "config-localsettings-badkey": "Ð\9dадгÑ\80адбениоÑ\82 клÑ\83Ñ\87 Ñ\88Ñ\82о го наведовÑ\82е е погÑ\80еÑ\88ен.",
"config-upgrade-key-missing": "Востановена е постоечка воспоставка на МедијаВики.\nЗа да ја надградите, вметнете го следниов ред на дното од вашата страница <code>LocalSettings.php</code>:\n\n$1",
"config-localsettings-incomplete": "Постоечката страница <code>LocalSettings.php</code> е нецелосна.\nНе е поставена променливата $1.\nИзменете ја страницата <code>LocalSettings.php</code> така што ќе ѝ зададете вредност на променливата, па стиснете на „{{int:Config-continue}}“.",
"config-localsettings-connection-error": "Се појави грешка при поврзувањето со базата користејќи ги поставките назначени во <code>LocalSettings.php</code>. Исправете ги овие поставки и обидете се повторно.\n\n$1",
if ( $this->params['type'] === 'updateWatchlistNotification' ) {
$this->updateWatchlistNotification();
} else {
- throw new Exception( "Invalid 'type' parameter '{$this->params['type']}'." );
+ throw new InvalidArgumentException(
+ "Invalid 'type' parameter '{$this->params['type']}'." );
}
return true;
$dbw = wfGetDB( DB_MASTER );
// Use a named lock so that jobs for this page see each others' changes
- $fname = __METHOD__;
$lockKey = "CategoryMembershipUpdates:{$page->getId()}";
- if ( !$dbw->lock( $lockKey, $fname, 10 ) ) {
+ $scopedLock = $dbw->getScopedLockAndFlush( $lockKey, __METHOD__, 10 );
+ if ( !$scopedLock ) {
$this->setLastError( "Could not acquire lock '$lockKey'" );
return false;
}
- $unlocker = new ScopedCallback( function () use ( $dbw, $lockKey, $fname ) {
- $dbw->unlock( $lockKey, $fname );
- } );
-
- // Sanity: clear any DB transaction snapshot
- $dbw->commit( __METHOD__, 'flush' );
-
$cutoffUnix = wfTimestamp( TS_UNIX, $this->params['revTimestamp'] );
// Using ENQUEUE_FUDGE_SEC handles jobs inserted out of revision order due to the delay
// between COMMIT and actual enqueueing of the CategoryMembershipChangeJob job.
$this->notifyUpdatesForRevision( $page, Revision::newFromRow( $row ) );
}
- ScopedCallback::consume( $unlocker );
-
return true;
}
// @codingStandardsIgnoreStart Long line
//case 'revision': // Revision deletion
//case 'event': // Log deletion
- // see https://svn.wikimedia.org/viewvc/mediawiki/trunk/phase3/includes/LogPage.php?&pathrev=97044&r1=97043&r2=97044
+ // see https://github.com/wikimedia/mediawiki/commit/a9c243b7b5289dad204278dbe7ed571fd914e395
//default:
// @codingStandardsIgnoreEnd
}
case 'patrol':
// @codingStandardsIgnoreStart Long line
- // https://svn.wikimedia.org/viewvc/mediawiki/trunk/phase3/includes/PatrolLog.php?&pathrev=97495&r1=97494&r2=97495
+ // https://github.com/wikimedia/mediawiki/commit/1a05f8faf78675dc85984f27f355b8825b43efff
// @codingStandardsIgnoreEnd
// Create a diff link to the patrolled revision
if ( $entry->getSubtype() === 'patrol' ) {
public function notifyOnPageChange( $editor, $title, $timestamp, $summary,
$minorEdit, $oldid = false, $pageStatus = 'changed'
) {
- global $wgEnotifUseJobQ, $wgEnotifMinorEdits, $wgUsersNotifiedOnAllChanges, $wgEnotifUserTalk;
+ global $wgEnotifMinorEdits, $wgUsersNotifiedOnAllChanges, $wgEnotifUserTalk;
if ( $title->getNamespace() < 0 ) {
return;
return;
}
- if ( $wgEnotifUseJobQ ) {
- $params = array(
- 'editor' => $editor->getName(),
- 'editorID' => $editor->getID(),
- 'timestamp' => $timestamp,
- 'summary' => $summary,
- 'minorEdit' => $minorEdit,
- 'oldid' => $oldid,
- 'watchers' => $watchers,
- 'pageStatus' => $pageStatus
- );
- $job = new EnotifNotifyJob( $title, $params );
- JobQueueGroup::singleton()->lazyPush( $job );
- } else {
- $this->actuallyNotifyOnPageChange(
- $editor,
- $title,
- $timestamp,
- $summary,
- $minorEdit,
- $oldid,
- $watchers,
- $pageStatus
- );
- }
+ $params = array(
+ 'editor' => $editor->getName(),
+ 'editorID' => $editor->getID(),
+ 'timestamp' => $timestamp,
+ 'summary' => $summary,
+ 'minorEdit' => $minorEdit,
+ 'oldid' => $oldid,
+ 'watchers' => $watchers,
+ 'pageStatus' => $pageStatus
+ );
+ $job = new EnotifNotifyJob( $title, $params );
+ JobQueueGroup::singleton()->lazyPush( $job );
}
/**
private $dataHash = null;
/** @var BagOStuff */
- private $store;
+ private $tempStore;
+ /** @var BagOStuff */
+ private $permStore;
/** @var LoggerInterface */
private $logger;
/**
* @param SessionId $id Session ID object
* @param SessionInfo $info Session info to populate from
- * @param BagOStuff $store Backend data store
+ * @param BagOStuff $tempStore In-process data store
+ * @param BagOStuff $permstore Backend data store for persisted sessions
* @param LoggerInterface $logger
* @param int $lifetime Session data lifetime in seconds
*/
public function __construct(
- SessionId $id, SessionInfo $info, BagOStuff $store, LoggerInterface $logger, $lifetime
+ SessionId $id, SessionInfo $info, BagOStuff $tempStore, BagOStuff $permStore,
+ LoggerInterface $logger, $lifetime
) {
$phpSessionHandling = \RequestContext::getMain()->getConfig()->get( 'PHPSessionHandling' );
$this->usePhpSessionHandling = $phpSessionHandling !== 'disable';
$this->id = $id;
$this->user = $info->getUserInfo() ? $info->getUserInfo()->getUser() : new User;
- $this->store = $store;
+ $this->tempStore = $tempStore;
+ $this->permStore = $permStore;
$this->logger = $logger;
$this->lifetime = $lifetime;
$this->provider = $info->getProvider();
$this->forceHTTPS = $info->forceHTTPS();
$this->providerMetadata = $info->getProviderMetadata();
- $blob = $store->get( wfMemcKey( 'MWSession', (string)$this->id ) );
+ $key = wfMemcKey( 'MWSession', (string)$this->id );
+ $blob = $tempStore->get( $key );
+ if ( $blob === false ) {
+ $blob = $permStore->get( $key );
+ if ( $blob !== false ) {
+ $tempStore->set( $key, $blob );
+ }
+ }
if ( !is_array( $blob ) ||
!isset( $blob['metadata'] ) || !is_array( $blob['metadata'] ) ||
!isset( $blob['data'] ) || !is_array( $blob['data'] )
$this->autosave();
// Delete the data for the old session ID now
- $this->store->delete( wfMemcKey( 'MWSession', $oldId ) );
+ $this->tempStore->delete( wfMemcKey( 'MWSession', $oldId ) );
+ $this->permStore->delete( wfMemcKey( 'MWSession', $oldId ) );
}
}
}
}
- $this->store->set(
+ $this->tempStore->set(
wfMemcKey( 'MWSession', (string)$this->id ),
array(
'data' => $this->data,
),
$metadata['expires']
);
+ if ( $this->persist ) {
+ $this->permStore->set(
+ wfMemcKey( 'MWSession', (string)$this->id ),
+ array(
+ 'data' => $this->data,
+ 'metadata' => $metadata,
+ ),
+ $metadata['expires']
+ );
+ }
$this->metaDirty = false;
$this->dataDirty = false;
private $config;
/** @var BagOStuff|null */
- private $store;
+ private $tempStore;
+
+ /** @var BagOStuff|null */
+ private $permStore;
/** @var SessionProvider[] */
private $sessionProviders = null;
$this->setLogger( \MediaWiki\Logger\LoggerFactory::getInstance( 'session' ) );
}
+ $this->tempStore = new \HashBagOStuff;
if ( isset( $options['store'] ) ) {
if ( !$options['store'] instanceof BagOStuff ) {
throw new \InvalidArgumentException(
'$options[\'store\'] must be an instance of BagOStuff'
);
}
- $this->store = $options['store'];
+ $this->permStore = $options['store'];
} else {
- $this->store = \ObjectCache::getInstance( $this->config->get( 'SessionCacheType' ) );
- $this->store->setLogger( $this->logger );
+ $this->permStore = \ObjectCache::getInstance( $this->config->get( 'SessionCacheType' ) );
+ $this->permStore->setLogger( $this->logger );
}
register_shutdown_function( array( $this, 'shutdown' ) );
// Test this here to provide a better log message for the common case
// of "no such ID"
$key = wfMemcKey( 'MWSession', $id );
- if ( is_array( $this->store->get( $key ) ) ) {
+ $existing = $this->tempStore->get( $key );
+ if ( $existing === false ) {
+ $existing = $this->permStore->get( $key );
+ if ( $existing !== false ) {
+ $this->tempStore->set( $key, $existing );
+ }
+ }
+ if ( is_array( $existing ) ) {
$info = new SessionInfo( SessionInfo::MIN_PRIORITY, array( 'id' => $id, 'idIsSafe' => true ) );
if ( $this->loadSessionInfoFromStore( $info, $request ) ) {
$session = $this->getSessionFromInfo( $info, $request );
}
$key = wfMemcKey( 'MWSession', $id );
- if ( is_array( $this->store->get( $key ) ) ) {
+ $existing = $this->tempStore->get( $key );
+ if ( $existing === false ) {
+ $existing = $this->permStore->get( $key );
+ if ( $existing !== false ) {
+ $this->tempStore->set( $key, $existing );
+ }
+ }
+ if ( is_array( $existing ) ) {
throw new \InvalidArgumentException( 'Session ID already exists' );
}
}
// Reset the user's token to kill existing sessions
$user = User::newFromName( $username );
if ( $user && $user->getToken( false ) ) {
- $user->setToken( true );
+ $user->setToken();
$user->saveSettings();
}
*/
private function loadSessionInfoFromStore( SessionInfo &$info, WebRequest $request ) {
$key = wfMemcKey( 'MWSession', $info->getId() );
- $blob = $this->store->get( $key );
+ $blob = $this->tempStore->get( $key );
+ if ( $blob === false ) {
+ $blob = $this->permStore->get( $key );
+ if ( $blob !== false ) {
+ $this->tempStore->set( $key, $blob );
+ }
+ }
$newParams = array();
// Sanity check: blob must be an array, if it's saved at all
if ( !is_array( $blob ) ) {
$this->logger->warning( "Session $info: Bad data" );
- $this->store->delete( $key );
+ $this->tempStore->delete( $key );
+ $this->permStore->delete( $key );
return false;
}
!isset( $blob['metadata'] ) || !is_array( $blob['metadata'] )
) {
$this->logger->warning( "Session $info: Bad data structure" );
- $this->store->delete( $key );
+ $this->tempStore->delete( $key );
+ $this->permStore->delete( $key );
return false;
}
!array_key_exists( 'provider', $metadata )
) {
$this->logger->warning( "Session $info: Bad metadata" );
- $this->store->delete( $key );
+ $this->tempStore->delete( $key );
+ $this->permStore->delete( $key );
return false;
}
$newParams['provider'] = $provider = $this->getProvider( $metadata['provider'] );
if ( !$provider ) {
$this->logger->warning( "Session $info: Unknown provider, " . $metadata['provider'] );
- $this->store->delete( $key );
+ $this->tempStore->delete( $key );
+ $this->permStore->delete( $key );
return false;
}
} elseif ( $metadata['provider'] !== (string)$provider ) {
$backend = new SessionBackend(
$this->allSessionIds[$id],
$info,
- $this->store,
+ $this->tempStore,
+ $this->permStore,
$this->logger,
$this->config->get( 'ObjectCacheSessionExpiry' )
);
do {
$id = wfBaseConvert( \MWCryptRand::generateHex( 40 ), 16, 32, 32 );
$key = wfMemcKey( 'MWSession', $id );
- } while ( isset( $this->allSessionIds[$id] ) || is_array( $this->store->get( $key ) ) );
+ } while ( isset( $this->allSessionIds[$id] ) ||
+ is_array( $this->tempStore->get( $key ) ) || is_array( $this->permStore->get( $key ) )
+ );
return $id;
}
* @param PHPSessionHandler $handler
*/
public function setupPHPSessionHandler( PHPSessionHandler $handler ) {
- $handler->setManager( $this, $this->store, $this->logger );
+ $handler->setManager( $this, $this->permStore, $this->logger );
}
/**
$opts->add( 'hideliu', false );
$opts->add( 'hidepatrolled', $user->getBoolOption( 'hidepatrolled' ) );
$opts->add( 'hidemyself', false );
-
- if ( $config->get( 'RCWatchCategoryMembership' ) ) {
- $opts->add( 'hidecategorization', $user->getBoolOption( 'hidecategorization' ) );
- }
+ $opts->add( 'hidecategorization', $user->getBoolOption( 'hidecategorization' ) );
$opts->add( 'categories', '' );
$opts->add( 'categories_any', false );
protected static $extensionTypes = false;
- protected static $viewvcUrls = array(
- 'svn+ssh://svn.wikimedia.org/svnroot/mediawiki' => 'http://svn.wikimedia.org/viewvc/mediawiki',
- 'http://svn.wikimedia.org/svnroot/mediawiki' => 'http://svn.wikimedia.org/viewvc/mediawiki',
- 'https://svn.wikimedia.org/svnroot/mediawiki' => 'https://svn.wikimedia.org/viewvc/mediawiki',
- );
-
public function __construct() {
parent::__construct( 'Version' );
}
}
/**
- * Return a string of the MediaWiki version with SVN revision if available.
+ * Return a string of the MediaWiki version with Git revision if available.
*
* @param string $flags
* @return mixed
global $wgVersion, $IP;
$gitInfo = self::getGitHeadSha1( $IP );
- $svnInfo = self::getSvnInfo( $IP );
- if ( !$svnInfo && !$gitInfo ) {
+ if ( !$gitInfo ) {
$version = $wgVersion;
- } elseif ( $gitInfo && $flags === 'nodb' ) {
+ } elseif ( $flags === 'nodb' ) {
$shortSha1 = substr( $gitInfo, 0, 7 );
$version = "$wgVersion ($shortSha1)";
- } elseif ( $gitInfo ) {
+ } else {
$shortSha1 = substr( $gitInfo, 0, 7 );
$shortSha1 = wfMessage( 'parentheses' )->params( $shortSha1 )->escaped();
$version = "$wgVersion $shortSha1";
- } elseif ( $flags === 'nodb' ) {
- $version = "$wgVersion (r{$svnInfo['checkout-rev']})";
- } else {
- $version = $wgVersion . ' ' .
- wfMessage(
- 'version-svn-revision',
- isset( $svnInfo['directory-rev'] ) ? $svnInfo['directory-rev'] : '',
- isset( $svnInfo['checkout-rev'] ) ? $svnInfo['checkout-rev'] : ''
- )->text();
}
return $version;
/**
* Return a wikitext-formatted string of the MediaWiki version with a link to
- * the SVN revision or the git SHA1 of head if available.
- * Git is prefered over Svn
+ * the Git SHA1 of head if available.
* The fallback is just $wgVersion
*
* @return mixed
if ( $gitVersion ) {
$v = $gitVersion;
} else {
- $svnVersion = self::getVersionLinkedSvn();
- if ( $svnVersion ) {
- $v = $svnVersion;
- } else {
- $v = $wgVersion; // fallback
- }
+ $v = $wgVersion; // fallback
}
return $v;
}
- /**
- * @return string Global wgVersion + a link to subversion revision of svn BASE
- */
- private static function getVersionLinkedSvn() {
- global $IP;
-
- $info = self::getSvnInfo( $IP );
- if ( !isset( $info['checkout-rev'] ) ) {
- return false;
- }
-
- $linkText = wfMessage(
- 'version-svn-revision',
- isset( $info['directory-rev'] ) ? $info['directory-rev'] : '',
- $info['checkout-rev']
- )->text();
-
- if ( isset( $info['viewvc-url'] ) ) {
- $version = "[{$info['viewvc-url']} $linkText]";
- } else {
- $version = $linkText;
- }
-
- return self::getwgVersionLinked() . " $version";
- }
-
/**
* @return string
*/
}
// ... and the version information
- // If the extension path is set we will check that directory for GIT and SVN
+ // If the extension path is set we will check that directory for GIT
// metadata in an attempt to extract date and vcs commit metadata.
$canonicalVersion = '–';
$extensionPath = null;
$coreHeadSHA1 = self::getGitHeadSha1( $IP );
if ( $coreHeadSHA1 ) {
$this->coreId = $coreHeadSHA1;
- } else {
- $svnInfo = self::getSvnInfo( $IP );
- if ( $svnInfo !== false ) {
- $this->coreId = $svnInfo['checkout-rev'];
- }
}
}
$cache = wfGetCache( CACHE_ANYTHING );
$vcsVersion = substr( $vcsVersion, 0, 7 );
$vcsLink = $gitInfo->getHeadViewUrl();
$vcsDate = $gitInfo->getHeadCommitDate();
- } else {
- $svnInfo = self::getSvnInfo( $extensionPath );
- if ( $svnInfo !== false ) {
- $vcsVersion = $this->msg( 'version-svn-revision', $svnInfo['checkout-rev'] )->text();
- $vcsLink = isset( $svnInfo['viewvc-url'] ) ? $svnInfo['viewvc-url'] : '';
- }
}
$cache->set( $memcKey, array( $vcsVersion, $vcsLink, $vcsDate ), 60 * 60 * 24 );
} else {
}
}
- /**
- * Get an associative array of information about a given path, from its .svn
- * subdirectory. Returns false on error, such as if the directory was not
- * checked out with subversion.
- *
- * Returned keys are:
- * Required:
- * checkout-rev The revision which was checked out
- * Optional:
- * directory-rev The revision when the directory was last modified
- * url The subversion URL of the directory
- * repo-url The base URL of the repository
- * viewvc-url A ViewVC URL pointing to the checked-out revision
- * @param string $dir
- * @return array|bool
- */
- public static function getSvnInfo( $dir ) {
- // http://svnbook.red-bean.com/nightly/en/svn.developer.insidewc.html
- $entries = $dir . '/.svn/entries';
-
- if ( !file_exists( $entries ) ) {
- return false;
- }
-
- $lines = file( $entries );
- if ( !count( $lines ) ) {
- return false;
- }
-
- // check if file is xml (subversion release <= 1.3) or not (subversion release = 1.4)
- if ( preg_match( '/^<\?xml/', $lines[0] ) ) {
- // subversion is release <= 1.3
- if ( !function_exists( 'simplexml_load_file' ) ) {
- // We could fall back to expat... YUCK
- return false;
- }
-
- // SimpleXml whines about the xmlns...
- MediaWiki\suppressWarnings();
- $xml = simplexml_load_file( $entries );
- MediaWiki\restoreWarnings();
-
- if ( $xml ) {
- foreach ( $xml->entry as $entry ) {
- if ( $xml->entry[0]['name'] == '' ) {
- // The directory entry should always have a revision marker.
- if ( $entry['revision'] ) {
- return array( 'checkout-rev' => intval( $entry['revision'] ) );
- }
- }
- }
- }
-
- return false;
- }
-
- // Subversion is release 1.4 or above.
- if ( count( $lines ) < 11 ) {
- return false;
- }
-
- $info = array(
- 'checkout-rev' => intval( trim( $lines[3] ) ),
- 'url' => trim( $lines[4] ),
- 'repo-url' => trim( $lines[5] ),
- 'directory-rev' => intval( trim( $lines[10] ) )
- );
-
- if ( isset( self::$viewvcUrls[$info['repo-url']] ) ) {
- $viewvc = str_replace(
- $info['repo-url'],
- self::$viewvcUrls[$info['repo-url']],
- $info['url']
- );
-
- $viewvc .= '/?pathrev=';
- $viewvc .= urlencode( $info['checkout-rev'] );
- $info['viewvc-url'] = $viewvc;
- }
-
- return $info;
- }
-
- /**
- * Retrieve the revision number of a Subversion working directory.
- *
- * @param string $dir Directory of the svn checkout
- *
- * @return int Revision number
- */
- public static function getSvnRevision( $dir ) {
- $info = self::getSvnInfo( $dir );
-
- if ( $info === false ) {
- return false;
- } elseif ( isset( $info['checkout-rev'] ) ) {
- return $info['checkout-rev'];
- } else {
- return false;
- }
- }
-
/**
* @param string $dir Directory of the git checkout
* @return bool|string Sha1 of commit HEAD points to
$opts->add( 'hideliu', $user->getBoolOption( 'watchlisthideliu' ) );
$opts->add( 'hidepatrolled', $user->getBoolOption( 'watchlisthidepatrolled' ) );
$opts->add( 'hidemyself', $user->getBoolOption( 'watchlisthideown' ) );
-
- if ( $this->getConfig()->get( 'RCWatchCategoryMembership' ) ) {
- $opts->add( 'hidecategorization', $user->getBoolOption( 'watchlisthidecategorization' ) );
- }
+ $opts->add( 'hidecategorization', $user->getBoolOption( 'watchlisthidecategorization' ) );
return $opts;
}
}
$this->getWatchedItem( $title )->resetNotificationTimestamp(
- $force, $oldid, WatchedItem::DEFERRED
+ $force, $oldid
);
}
"botpasswords-label-grants-column": "Дазволена",
"botpasswords-bad-appid": "Назва робата «$1» зьяўляецца няслушнай.",
"botpasswords-insert-failed": "Не атрымалася дадаць робата зь імем «$1». Магчыма, ён ужо быў дададзены?",
+ "botpasswords-update-failed": "Не атрымалася абнавіць робата зь імем «$1». Магчыма, ён быў выдалены?",
"resetpass_forbidden": "Пароль ня можа быць зьменены",
"resetpass-no-info": "Для непасрэднага доступу да гэтай старонкі Вам неабходна ўвайсьці ў сыстэму.",
"resetpass-submit-loggedin": "Зьмяніць пароль",
"action-pagelang": "зьмену мовы старонкі",
"log-name-pagelang": "Журнал зьменаў мовы",
"log-description-pagelang": "Гэта журнал зьменаў мовы старонак.",
- "logentry-pagelang-pagelang": "$1 {{GENDER:$2|зьмяніў|зьмяніла}} мову старонкі $3 з $4 на $5.",
+ "logentry-pagelang-pagelang": "$1 {{GENDER:$2|зьмяніў|зьмяніла}} мову старонкі $3 з $4 на $5",
"default-skin-not-found": "Упс! Тэма афармленьня па змоўчаньні для вашай вікі, вызначаная ў <code dir=\"ltr\">$wgDefaultSkin</code> як <code>$1</code> недаступная.\n\nВашае ўсталяваньне, падобна, уключае {{PLURAL:$4|наступную тэму афармленьне|наступныя тэмы афармленьня}}. Глядзіце старонку [https://www.mediawiki.org/wiki/Manual:Skin_configuration Інструкцыя:Наладка тэмаў афармленьня] дзеля інфармацыі, як падключыць {{PLURAL:$4|яе|іх і абраць тэму па змоўчаньні}}.\n\n$2\n\n; Калі вы толькі што ўсталявалі MediaWiki:\n: Напэўна вы ўсталявалі з git або наўпрост з крынічнага коду з ужываньнем іншага мэтаду. Гэта чакана. Паспрабуйце ўсталяваць некалькі тэмаў афармленьня з [https://www.mediawiki.org/wiki/Category:All_skins каталёгу тэмаў mediawiki.org]:\n:* Спампуйце [https://www.mediawiki.org/wiki/Download tarball-усталёўнік], які ўтрымлівае некалькі тэмаў і пашырэньняў. Вы можаце скапіяваць каталёг <code>skins/</code> зь яго.\n:* Спампуйце tarball-усталёўнікі для асобных тэмаў з [https://www.mediawiki.org/wiki/Special:SkinDistributor mediawiki.org].\n:* [https://www.mediawiki.org/wiki/Download_from_Git#Using_Git_to_download_MediaWiki_skins Выкарыстайце Git, каб спампаваць тэмы афармленьня].\n: Калі вы распрацоўнік MediaWiki, гэта не павінна ўплываць на вашае git-сховішча.\n\n; Калі вы толькі што абнавілі MediaWiki:\n: MediaWiki вэрсіі 1.24 і навейшыя больш не падключаюць тэмы афармленьня аўтаматычна (глядзіце [https://www.mediawiki.org/wiki/Manual:Skin_autodiscovery Інструкцыя:Аўтаматычнае выяўленьне тэмаў афармленьня]). Вы можаце дадаць {{PLURAL:$5|наступны радок у|наступныя радкі ў}} <code>LocalSettings.php</code>, каб падключыць {{PLURAL:$5|усталяваную тэму|усе ўсталяваныя тэмы}} афармленьня:\n\n<pre dir=\"ltr\">$3</pre>\n\n; Калі вы толькі што зьмянілі <code>LocalSettings.php</code>:\n: Пераправерце назвы тэмаў афармленьня на наяўнасьць памылак.",
"default-skin-not-found-no-skins": "Упс! Тэма афармленьня па змоўчаньні для вашай вікі, вызначаная ў <code>$wgDefaultSkin</code> як <code>$1</code>, недаступная.\n\nВы ня маеце ўсталяваных тэмаў афармленьня.\n\n; Калі вы толькі што ўсталявалі або абнавілі MediaWiki:\n: Напэўна вы ўсталявалі з git або наўпрост з крынічнага коду з ужываньнем іншага мэтаду. Гэта чакана. MediaWiki вэрсіі 1.24 і навейшыя ня ўтрымліваюць тэмы афармленьня ў галоўным сховішчы. Паспрабуйце ўсталяваць некалькі тэмаў афармленьня з [https://www.mediawiki.org/wiki/Category:All_skins каталёгу тэмаў mediawiki.org]:\n:* Спампуйце [https://www.mediawiki.org/wiki/Download tarball-усталёўнік], які ўтрымлівае некалькі тэмаў і пашырэньняў. Вы можаце скапіяваць каталёг <code dir=\"ltr\">skins/</code> зь яго.\n:* Спампуйце tarball-усталёўнікі для асобны тэмаў афармленьня з [https://www.mediawiki.org/wiki/Special:SkinDistributor mediawiki.org].\n:* [https://www.mediawiki.org/wiki/Download_from_Git#Using_Git_to_download_MediaWiki_skins Выкарыстайце Git, каб спампаваць тэмы афармленьня].\n: Калі вы распрацоўнік MediaWiki, гэта не павінна ўплываць на вашае git-сховішча. Глядзіце [https://www.mediawiki.org/wiki/Manual:Skin_configuration Інструкцыя:Наладка тэмаў афармленьня] дзеля інфармацыі, як падключыць іх і абраць тэму па змоўчаньні.",
"default-skin-not-found-row-enabled": "* <code>$1</code> / $2 (уключана)",
"pageinfo-category-files": "ফাইলের সংখ্যা",
"markaspatrolleddiff": "পরীক্ষিত হিসেবে চিহ্নিত করুন",
"markaspatrolledtext": "এই পাতাটি পরীক্ষিত হিসেবে চিহ্নিত করুন",
+ "markaspatrolledtext-file": "এই ফাইলের সংস্করণ পরীক্ষিত হিসেবে চিহ্নিত করুন",
"markedaspatrolled": "পরীক্ষিত বলে চিহ্নিত করুন",
"markedaspatrolledtext": "আপনার নির্বাচিত সংস্করণ [[:$1]] পরীক্ষিত বলে চিহ্নিত করা হয়েছে।",
"rcpatroldisabled": "সাম্প্রতিক পরিবর্তন প্যাট্রোল নিষ্ক্রিয়",
"exif-morepermissionsurl": "অতিরিক্ত লাইসেন্সিং তথ্যাদি",
"exif-attributionurl": "যখন এই কাজটি পুনরায় ব্যবহার করবেন, অনুগ্রহ করে এই লিংকটি যোগ করুন",
"exif-preferredattributionname": "যখন এই কাজটি পুনরায় ব্যবহার করবেন, অনুগ্রহ করে প্রণেতাকে ক্রেডিট দিন",
- "exif-pngfilecomment": "পিএনজি ফাইল কমেন্ট",
+ "exif-pngfilecomment": "পিএনজি ফাইলের মন্তব্য",
"exif-disclaimer": "দাবিত্যাগ",
"exif-contentwarning": "বিষয়বস্তু সতর্কবার্তা",
- "exif-giffilecomment": "জিআইএফ ফাইল কমেন্ট",
+ "exif-giffilecomment": "জিআইএফ ফাইলের মন্তব্য",
"exif-intellectualgenre": "উপাদানের প্রকার",
"exif-subjectnewscode": "বিষয় কোড",
"exif-scenecode": "আইপিটিসি সিন কোড",
"htmlform-title-not-exists": "$1-এর অস্তিত্ব নেই।",
"htmlform-user-not-exists": "<strong>$1</strong>-এর অস্তিত্ব নেই।",
"htmlform-user-not-valid": "<strong>$1</strong> একটি বৈধ ব্যবহারকারীর নাম নয়।",
- "sqlite-has-fts": "$1 সহ পূর্ণ টেক্সট সার্চ সমর্থন",
- "sqlite-no-fts": "$1 বাদে পূর্ণ টেক্সট সার্চ সমর্থন",
+ "sqlite-has-fts": "$1 সহ পূর্ণ-পাঠ্য অনুসন্ধান সমর্থন",
+ "sqlite-no-fts": "$1 বাদে পূর্ণ-পাঠ্য অনুসন্ধান সমর্থন",
"logentry-delete-delete": "$1 কর্তৃক $3 পাতাটি অপসারিত হয়েছে",
"logentry-delete-restore": "$1 কর্তৃক $3 পাতাটি {{GENDER:$2|ফিরিয়ে আনা}} হয়েছে",
"logentry-delete-event": "$1 {{PLURAL:$5|একটি লগ ইভেন্টের|$5 লগ ইভেন্টসমূহের}} দৃশ্যমানতা {{GENDER:$2|পরিবর্তন}} করেছেন $3: $4",
"recentchangeslinked-page": "АгӀон цӀе:",
"recentchangeslinked-to": "Кхечу агӀор, гайта хийцамаш агӀонашца, хӀоттийначу агӀонтӀе хьажорг йолуш",
"recentchanges-page-added-to-category": "[[:$1]] категори чу тоьхна",
+ "recentchanges-page-removed-from-category": "[[:$1]] дӀаяьккхина категори чура",
"upload": "Файл чуяккхар",
"uploadbtn": "Файл чуяккхар",
"reuploaddesc": "Юху гӀо файл чуйоккху агӀоне",
"changeemail-newemail": "Nová e-mailová adresa:",
"changeemail-newemail-help": "Toto pole by mělo zůstat prázdné, pokud chcete odstranit svou e-mailovou adresu. Pokud bude e-mailová adresa odstraněná, nebudete si moct obnovit zapomenuté heslo a přijímat e-maily z této wiki.",
"changeemail-none": "(žádná)",
- "changeemail-password": "Vaše heslo do {{gender:2sg|{{SITENAME}}}}:",
+ "changeemail-password": "{{GENDER:|Vaše heslo}} do {{GRAMMAR:2sg|{{SITENAME}}}}:",
"changeemail-submit": "Změnit e-mail",
"changeemail-throttled": "Provedli jste příliš mnoho pokusů o přihlášení.\nČekejte prosím $1 a zkuste to znovu.",
"changeemail-nochange": "Zadejte prosím odlišnou e-mailovou adresu.",
"version-hook-subscribedby": "Subscribed by",
"version-version": "($1)",
"version-no-ext-name": "[no name]",
- "version-svn-revision": "r$1",
"version-license": "MediaWiki License",
"version-ext-license": "License",
"version-ext-colheader-name": "Extension",
"expensive-parserfunction-warning": "Averto: Ĉi tiu paĝo enhavas tro da multekostaj sintaksaj funkcio-vokoj.\n\nĜi havu malpli ol $2 {{PLURAL:$2|vokon|vokojn}}, sed nun estas $1 {{PLURAL:$1|voko|vokoj}}.",
"expensive-parserfunction-category": "Paĝoj kun tro da multekostaj sintaksaj funkcio-vokoj",
"post-expand-template-inclusion-warning": "Averto: Inkluziva pezo de ŝablonoj estas tro granda.\nIuj ŝablonoj ne estos inkluzivitaj.",
- "post-expand-template-inclusion-category": "Paĝoj kie inkluziva pezo de ŝablonoj estas tro granda.",
+ "post-expand-template-inclusion-category": "Paĝoj kie inkluziva pezo de ŝablonoj estas tro granda",
"post-expand-template-argument-warning": "Averto: Ĉi tiu paĝo enhavas almenaŭ unu ŝablonan argumenton, kiu havas tro grandan etendan pezon.\nĈi tiuj argumentoj estis forlasitaj.",
"post-expand-template-argument-category": "Paĝoj enhavantaj forlasitajn argumentojn de ŝablonoj",
"parser-template-loop-warning": "Rekursiva ŝablono estis trovita: [[$1]]",
"tooltip-ca-move": "Alinomigi tiun ĉi paĝon",
"tooltip-ca-watch": "Aldoni tiun ĉi paĝon al via atentaro",
"tooltip-ca-unwatch": "Forigi tiun ĉi paĝon el via atentaro",
- "tooltip-search": "Traserĉi {{SITENAME}}n",
+ "tooltip-search": "Serĉi tra {{SITENAME}}",
"tooltip-search-go": "Iru al paĝo kun ĉi preciza nomo se ĝi ekzistas",
"tooltip-search-fulltext": "Serĉi la paĝojn por ĉi tiu teksto",
"tooltip-p-logo": "Ĉefpaĝo",
"resetpass_submit": "Поставете лозинка и најавете се",
"changepassword-success": "Вашата лозинка е успешно сменета!",
"changepassword-throttled": "Имате премногу обиди за најава за кратко време.\nПочекајте $1 пред да се обидете повторно.",
+ "botpasswords-label-appid": "Име на ботот:",
+ "botpasswords-label-create": "Создај",
+ "botpasswords-label-update": "Поднови",
+ "botpasswords-label-cancel": "Откажи",
+ "botpasswords-label-delete": "Избриши",
+ "botpasswords-label-resetpassword": "Ставете нова лозинка",
+ "botpasswords-label-grants": "Применливи доделувања:",
"resetpass_forbidden": "Лозинките не може да се менуваат",
"resetpass-no-info": "Мора да сте најавени ако сакате да имате директен пристап до оваа страница.",
"resetpass-submit-loggedin": "Смени лозинка",
"log-title-wildcard": "Пребарај наслови кои почнуваат со овој текст",
"showhideselectedlogentries": "Прикажи/скриј одбрани записи",
"log-edit-tags": "Измени ознаки на одредени дневнички записи",
+ "checkbox-select": "Одбери: $1",
+ "checkbox-all": "Сите",
+ "checkbox-none": "Ништо",
+ "checkbox-invert": "Избери обратно",
"allpages": "Сите страници",
"nextpage": "Следна страница ($1)",
"prevpage": "Претходна страница ($1)",
"lockedbyandtime": "(од $1 на $2 цо $3 ч.)",
"move-page": "Премести $1",
"move-page-legend": "Премести страница",
- "movepagetext": "Со коÑ\80иÑ\81Ñ\82еÑ\9aеÑ\82о на овоÑ\98 обÑ\80азеÑ\86 можеÑ\82е да пÑ\80еименÑ\83ваÑ\82е Ñ\81Ñ\82Ñ\80аниÑ\86а, пÑ\80емеÑ\81Ñ\82Ñ\83ваÑ\98Ñ\9cи Ñ\98а Ñ\86елаÑ\82а неÑ\98зина иÑ\81Ñ\82оÑ\80иÑ\98а под ново име.\nСÑ\82аÑ\80иоÑ\82 наÑ\81лов Ñ\9cе Ñ\81Ñ\82ане пÑ\80енаÑ\81оÑ\87Ñ\83ваÑ\87ка Ñ\81Ñ\82Ñ\80аниÑ\86а кон новиоÑ\82 наÑ\81лов.\nÐ\90вÑ\82омаÑ\82Ñ\81ки можеÑ\82е да ги подновиÑ\82е пÑ\80енаÑ\81оÑ\87Ñ\83ваÑ\9aаÑ\82а кои покажÑ\83вааÑ\82 кон пÑ\80вобиÑ\82ниоÑ\82 наÑ\81лов.\nÐ\90ко не избеÑ\80еÑ\82е авÑ\82омаÑ\82Ñ\81ко подновÑ\83ваÑ\9aе, пÑ\80овеÑ\80еÑ\82е на [[Special:DoubleRedirects|двоÑ\98ни]] или [[Special:BrokenRedirects|пÑ\80екинаÑ\82и пÑ\80енаÑ\81оÑ\87Ñ\83ваÑ\9aа]].\nÐ\9dа ваÑ\81 е одговоÑ\80ноÑ\81Ñ\82а да Ñ\81е оÑ\81игÑ\83Ñ\80аÑ\82е дека вÑ\80Ñ\81киÑ\82е Ñ\9cе пÑ\80одолжаÑ\82 да наÑ\81оÑ\87Ñ\83вааÑ\82 Ñ\82амÑ\83 за каде Ñ\81е пÑ\80едвидени.\n\nÐ\98маÑ\98Ñ\82е пÑ\80едвид дека Ñ\81Ñ\82Ñ\80аниÑ\86аÑ\82а '''нема''' да биде пÑ\80емеÑ\81Ñ\82ена ако веÑ\9cе поÑ\81Ñ\82ои Ñ\81Ñ\82Ñ\80аниÑ\86а Ñ\81о новиоÑ\82 наÑ\81лов, оÑ\81вен ако е не е пÑ\80енаÑ\81оÑ\87Ñ\83ваÑ\9aе и нема иÑ\81Ñ\82оÑ\80иÑ\98а на минаÑ\82и Ñ\83Ñ\80едÑ\83ваÑ\9aа. Тоа знаÑ\87и дека можеÑ\82е да Ñ\98а пÑ\80еименÑ\83ваÑ\82е Ñ\81Ñ\82Ñ\80аниÑ\86аÑ\82а како Ñ\88Ñ\82о била пÑ\80еÑ\82Ñ\85одно доколкÑ\83 Ñ\81Ñ\82е напÑ\80авиле гÑ\80еÑ\88ка без да Ñ\98а пÑ\80екÑ\80иеÑ\82е поÑ\81Ñ\82оеÑ\87каÑ\82а Ñ\81Ñ\82Ñ\80аниÑ\86а.\n\n'''Ð\9fÑ\80едÑ\83пÑ\80едÑ\83ваÑ\9aе!'''\nОва може да биде драстична и неочекувана промена за популарна страница;\nосигурајте се дека сте ги разбрале последиците од ова пред да продолжите.",
- "movepagetext-noredirectfixer": "Со коÑ\80иÑ\81Ñ\82еÑ\9aеÑ\82о на овоÑ\98 обÑ\80азеÑ\86 можеÑ\82е да пÑ\80еименÑ\83ваÑ\82е Ñ\81Ñ\82Ñ\80аниÑ\86а, пÑ\80емеÑ\81Ñ\82Ñ\83ваÑ\98Ñ\9cи Ñ\98а Ñ\86елаÑ\82а неÑ\98зина иÑ\81Ñ\82оÑ\80иÑ\98а под ново име.\nСÑ\82аÑ\80иоÑ\82 наÑ\81лов Ñ\9cе Ñ\81Ñ\82ане пÑ\80енаÑ\81оÑ\87Ñ\83ваÑ\87ка Ñ\81Ñ\82Ñ\80аниÑ\86а кон новиоÑ\82 наÑ\81лов.\nÐ\90вÑ\82омаÑ\82Ñ\81ки можеÑ\82е да ги подновиÑ\82е пÑ\80енаÑ\81оÑ\87Ñ\83ваÑ\9aаÑ\82а кои покажÑ\83вааÑ\82 кон пÑ\80вобиÑ\82ниоÑ\82 наÑ\81лов.\nÐ\9dе забоÑ\80аваÑ\98Ñ\82е да пÑ\80овеÑ\80иÑ\82е [[Special:DoubleRedirects|двоÑ\98ни]] и [[Special:BrokenRedirects|пÑ\80екинаÑ\82и пÑ\80енаÑ\81оÑ\87Ñ\83ваÑ\9aа]].\nÐ\9dа ваÑ\81 е одговоÑ\80ноÑ\81Ñ\82а да Ñ\81е оÑ\81игÑ\83Ñ\80аÑ\82е дека вÑ\80Ñ\81киÑ\82е Ñ\9cе пÑ\80одолжаÑ\82 да наÑ\81оÑ\87Ñ\83вааÑ\82 Ñ\82амÑ\83 за каде Ñ\81е пÑ\80едвидени.\n\nÐ\98маÑ\98Ñ\82е пÑ\80едвид дека Ñ\81Ñ\82Ñ\80аниÑ\86аÑ\82а '''Ð\9dÐ\95Ð\9cÐ\90''' да биде пÑ\80емеÑ\81Ñ\82ена ако веÑ\9cе поÑ\81Ñ\82ои Ñ\81Ñ\82Ñ\80аниÑ\86а Ñ\81о новиоÑ\82 наÑ\81лов, оÑ\81вен ако е пÑ\80азна или ако е пÑ\80енаÑ\81оÑ\87Ñ\83ваÑ\9aе и нема иÑ\81Ñ\82оÑ\80иÑ\98а на минаÑ\82и Ñ\83Ñ\80едÑ\83ваÑ\9aа. Тоа знаÑ\87и дека можеÑ\82е да Ñ\98а пÑ\80еименÑ\83ваÑ\82е Ñ\81Ñ\82Ñ\80аниÑ\86аÑ\82а како Ñ\88Ñ\82о била пÑ\80еÑ\82Ñ\85одно доколкÑ\83 Ñ\81Ñ\82е напÑ\80авиле гÑ\80еÑ\88ка без да Ñ\98а пÑ\80екÑ\80иеÑ\82е поÑ\81Ñ\82оеÑ\87каÑ\82а Ñ\81Ñ\82Ñ\80аниÑ\86а.\n\n'''Ð\9fÐ Ð\95Ð\94УÐ\9fÐ Ð\95Ð\94УÐ\92Ð\90Ð\8aÐ\95!'''\nОва може да биде драстична и неочекувана промена за популарна страница;\nосигурајте се дека сте ги разбрале последиците од ова пред да продолжите.",
+ "movepagetext": "Со коÑ\80иÑ\81Ñ\82еÑ\9aеÑ\82о на овоÑ\98 обÑ\80азеÑ\86 можеÑ\82е да пÑ\80еименÑ\83ваÑ\82е Ñ\81Ñ\82Ñ\80аниÑ\86а, пÑ\80емеÑ\81Ñ\82Ñ\83ваÑ\98Ñ\9cи Ñ\98а Ñ\86елаÑ\82а неÑ\98зина иÑ\81Ñ\82оÑ\80иÑ\98а под ново име.\nСÑ\82аÑ\80иоÑ\82 наÑ\81лов Ñ\9cе Ñ\81Ñ\82ане пÑ\80енаÑ\81оÑ\87Ñ\83ваÑ\87ка Ñ\81Ñ\82Ñ\80аниÑ\86а кон новиоÑ\82 наÑ\81лов.\nÐ\90вÑ\82омаÑ\82Ñ\81ки можеÑ\82е да ги подновиÑ\82е пÑ\80енаÑ\81оÑ\87Ñ\83ваÑ\9aаÑ\82а кои покажÑ\83вааÑ\82 кон пÑ\80вобиÑ\82ниоÑ\82 наÑ\81лов.\nÐ\90ко не избеÑ\80еÑ\82е авÑ\82омаÑ\82Ñ\81ко подновÑ\83ваÑ\9aе, пÑ\80овеÑ\80еÑ\82е на [[Special:DoubleRedirects|двоÑ\98ни]] или [[Special:BrokenRedirects|пÑ\80екинаÑ\82и пÑ\80енаÑ\81оÑ\87Ñ\83ваÑ\9aа]].\nÐ\9dа ваÑ\81 е одговоÑ\80ноÑ\81Ñ\82а да Ñ\81е оÑ\81игÑ\83Ñ\80аÑ\82е дека вÑ\80Ñ\81киÑ\82е Ñ\9cе пÑ\80одолжаÑ\82 да наÑ\81оÑ\87Ñ\83вааÑ\82 Ñ\82амÑ\83 за каде Ñ\81е пÑ\80едвидени.\n\nÐ\98маÑ\98Ñ\82е пÑ\80едвид дека Ñ\81Ñ\82Ñ\80аниÑ\86аÑ\82а '''нема''' да биде пÑ\80емеÑ\81Ñ\82ена ако веÑ\9cе поÑ\81Ñ\82ои Ñ\81Ñ\82Ñ\80аниÑ\86а Ñ\81о новиоÑ\82 наÑ\81лов, оÑ\81вен ако е не е пÑ\80енаÑ\81оÑ\87Ñ\83ваÑ\9aе и нема иÑ\81Ñ\82оÑ\80иÑ\98а на минаÑ\82и Ñ\83Ñ\80едÑ\83ваÑ\9aа. Тоа знаÑ\87и дека можеÑ\82е да Ñ\98а пÑ\80еименÑ\83ваÑ\82е Ñ\81Ñ\82Ñ\80аниÑ\86аÑ\82а како Ñ\88Ñ\82о била пÑ\80еÑ\82Ñ\85одно доколкÑ\83 Ñ\81Ñ\82е напÑ\80авиле гÑ\80еÑ\88ка без да Ñ\98а пÑ\80екÑ\80иеÑ\82е поÑ\81Ñ\82оеÑ\87каÑ\82а Ñ\81Ñ\82Ñ\80аниÑ\86а.\n\n'''Ð\9dапомена:'''\nОва може да биде драстична и неочекувана промена за популарна страница;\nосигурајте се дека сте ги разбрале последиците од ова пред да продолжите.",
+ "movepagetext-noredirectfixer": "Со коÑ\80иÑ\81Ñ\82еÑ\9aеÑ\82о на овоÑ\98 обÑ\80азеÑ\86 можеÑ\82е да пÑ\80еименÑ\83ваÑ\82е Ñ\81Ñ\82Ñ\80аниÑ\86а, пÑ\80емеÑ\81Ñ\82Ñ\83ваÑ\98Ñ\9cи Ñ\98а Ñ\86елаÑ\82а неÑ\98зина иÑ\81Ñ\82оÑ\80иÑ\98а под ново име.\nСÑ\82аÑ\80иоÑ\82 наÑ\81лов Ñ\9cе Ñ\81Ñ\82ане пÑ\80енаÑ\81оÑ\87Ñ\83ваÑ\87ка Ñ\81Ñ\82Ñ\80аниÑ\86а кон новиоÑ\82 наÑ\81лов.\nÐ\90вÑ\82омаÑ\82Ñ\81ки можеÑ\82е да ги подновиÑ\82е пÑ\80енаÑ\81оÑ\87Ñ\83ваÑ\9aаÑ\82а кои покажÑ\83вааÑ\82 кон пÑ\80вобиÑ\82ниоÑ\82 наÑ\81лов.\nÐ\9dе забоÑ\80аваÑ\98Ñ\82е да пÑ\80овеÑ\80иÑ\82е [[Special:DoubleRedirects|двоÑ\98ни]] и [[Special:BrokenRedirects|пÑ\80екинаÑ\82и пÑ\80енаÑ\81оÑ\87Ñ\83ваÑ\9aа]].\nÐ\9dа ваÑ\81 е одговоÑ\80ноÑ\81Ñ\82а да Ñ\81е оÑ\81игÑ\83Ñ\80аÑ\82е дека вÑ\80Ñ\81киÑ\82е Ñ\9cе пÑ\80одолжаÑ\82 да наÑ\81оÑ\87Ñ\83вааÑ\82 Ñ\82амÑ\83 за каде Ñ\81е пÑ\80едвидени.\n\nÐ\98маÑ\98Ñ\82е пÑ\80едвид дека Ñ\81Ñ\82Ñ\80аниÑ\86аÑ\82а '''Ð\9dÐ\95Ð\9cÐ\90''' да биде пÑ\80емеÑ\81Ñ\82ена ако веÑ\9cе поÑ\81Ñ\82ои Ñ\81Ñ\82Ñ\80аниÑ\86а Ñ\81о новиоÑ\82 наÑ\81лов, оÑ\81вен ако е пÑ\80азна или ако е пÑ\80енаÑ\81оÑ\87Ñ\83ваÑ\9aе и нема иÑ\81Ñ\82оÑ\80иÑ\98а на минаÑ\82и Ñ\83Ñ\80едÑ\83ваÑ\9aа. Тоа знаÑ\87и дека можеÑ\82е да Ñ\98а пÑ\80еименÑ\83ваÑ\82е Ñ\81Ñ\82Ñ\80аниÑ\86аÑ\82а како Ñ\88Ñ\82о била пÑ\80еÑ\82Ñ\85одно доколкÑ\83 Ñ\81Ñ\82е напÑ\80авиле гÑ\80еÑ\88ка без да Ñ\98а пÑ\80екÑ\80иеÑ\82е поÑ\81Ñ\82оеÑ\87каÑ\82а Ñ\81Ñ\82Ñ\80аниÑ\86а.\n\n'''Ð\9dапомена:'''\nОва може да биде драстична и неочекувана промена за популарна страница;\nосигурајте се дека сте ги разбрале последиците од ова пред да продолжите.",
"movepagetalktext": "Ако го штиклирате кутивчево, соодветната страница за разговор ќе биде автоматски преместена на нов наслов, освен ако таму веќе постои страница за разговор што не е празна.\n\nВо тој случај, ќе треба да ја преместите или споите страницата рачно, доколку сакате.",
"moveuserpage-warning": "'''Предупредување:''' На пат сте да преместите корисничка страница. Имајте предвид дека само страницата ќе биде преместена, а самиот корисник ''нема'' да биде преименуван.",
"movecategorypage-warning": "<strong>Предупредување:</strong> Преместувате категориска страница. Имајте предвид дека ќе се премести само страницата, а страниците во старата категорија <em>нема</em> да се прекатегоризираат во новата.",
"movenosubpage": "Оваа страница нема потстраници.",
"movereason": "Причина:",
"revertmove": "врати",
- "delete_and_move_text": "==Потребно бришење==\nЦелната статија „[[:$1]]“ веќе постои.\nДали сакате да ја избришете за да ослободите место за преместувањето?",
+ "delete_and_move_text": "Целната статија „[[:$1]]“ веќе постои.\nДали сакате да ја избришете за да ослободите место за преместувањето?",
"delete_and_move_confirm": "Да, избриши ја страницата",
"delete_and_move_reason": "Избришано за да се ослободи место за преместувањето од „[[$1]]“",
"selfmove": "Појдовната и целната страница се истоветни;\nне можам да преместам.",
"move-leave-redirect": "Направи пренасочување",
"protectedpagemovewarning": "'''Предупредување:''' Оваа страница е заштитена, така што само може да ја преместуваат само корисници со администраторски привилегии.\nЗа ваша информација, подолу е прикажана последната ставка во дневникот на измени:",
"semiprotectedpagemovewarning": "'''Напомена:''' Оваа страница е заштитена, така што може да ја преместуваат само регистрирани корисници.\nЗа ваша информација, подолу е прикажана последната ставка во дневникот на измени:",
- "move-over-sharedrepo": "== Податотеката постои ==\n[[:$1]] постои на заедничко складиште. Ако податотеката ја преместите на овој наслов, тоа ќе ја потисне заедничката податотека.",
+ "move-over-sharedrepo": "[[:$1]] постои на заедничко складиште. Ако податотеката ја преместите на овој наслов, тоа ќе ја потисне заедничката податотека.",
"file-exists-sharedrepo": "Одбраното име на податотеката веќе се користи на заедничко складиште.\nОдберете друго име.",
"export": "Извоз на страници",
"exporttext": "Можете да го извезете текстот и историјата на уредување на избрана страница или група на страници во XML формат.\nОвие податоци може да бидат вчитани на некое друго вики кое се користи со МедијаВики преку [[Special:Import|увезување на страница]].\n\nЗа извезување на страници, внесете ги насловите во полето прикажано подолу, еден наслов на статија во ред, потоа изберете дали сакате да ја извезете само последната преработка или и сите постари преработки.\n\nАко ја сакате само тековната верзија, би можеле да искористите врска од видот [[{{#Special:Export}}/{{MediaWiki:Mainpage}}]] за страницата „[[{{MediaWiki:Mainpage}}]]“.",
"tooltip-feed-rss": "RSS емитување за оваа страница",
"tooltip-feed-atom": "Атом-емитување за оваа страница",
"tooltip-t-contributions": "Список на придонеси {{GENDER:$1|на овој корисник}}",
- "tooltip-t-emailuser": "Испрати е-пошта на овој корисник",
+ "tooltip-t-emailuser": "Испрати е-пошта {{GENDER:$1|на овој корисник}}",
"tooltip-t-info": "Повеќе информаици за страницава",
"tooltip-t-upload": "Подигни податотеки",
"tooltip-t-specialpages": "Список на сите службени страници",
"lastmodifiedatby": "Последната промена на страницава е извршена на $1 г Сво $2 ч. Промената ја направи $3.",
"othercontribs": "Засновано на работата на $1.",
"others": "други",
- "siteusers": "{{PLURAL:$2|корисникот|корисниците}} на {{SITENAME}} $1",
+ "siteusers": "{{SITENAME}} {{PLURAL:$2|{{GENDER:$1|корисник}}|корисници}} $1",
"anonusers": "{{PLURAL:$2|анонимен корисник|анонимни корисници}} на {{SITENAME}} $1",
"creditspage": "Автори на страницата",
"nocredits": "Не постојат податоци за авторите на оваа страница.",
"redirect-page": "Назнака на страницата",
"redirect-revision": "Преработка на страницата",
"redirect-file": "Име на податотека",
+ "redirect-logid": "Назнака на дневникот",
"redirect-not-exists": "Вредноста не е најдена",
"fileduplicatesearch": "Барање на дуплирани податотеки",
"fileduplicatesearch-summary": "Пребарување на дуплирани податотеки по тарабни вредности.",
"expand_templates_preview_fail_html": "<em>Бидејќи {{SITENAME}} има овозможено сиров HTML и се јави губиток на седнички податоци, прегледот е скриен како мерка на претпазливост против напади со JavaScript.</em>\n\n<strong>Ако ова е е легитимен обид за преглед, тогаш обидете се повторно.</strong>\nАко не работи и тогаш, [[Special:UserLogout|одјавете се]] и повторно најавете се.",
"expand_templates_preview_fail_html_anon": "<em>Бидејќи {{SITENAME}} има овозможено сиров HTML, а вие не сте најавени, прегледот е скриен како мерка на претпазливост против напади со JavaScript.</em>\n\n<strong>Ако ова е е легитимен обид за преглед, тогаш обидете се повторно.</strong>\nАко не работи и тогаш, [[Special:UserLogout|одјавете се]] и повторно најавете се.",
"expand_templates_input_missing": "Треба да внесете некаков текст.",
- "pagelanguage": "Ð\98збоÑ\80ник за Ñ\98азик на Ñ\81Ñ\82Ñ\80аниÑ\86аÑ\82а",
+ "pagelanguage": "Ð\9cенÑ\83ваÑ\9aе Ñ\98азик на Ñ\81Ñ\82Ñ\80аниÑ\86а",
"pagelang-name": "Страница",
"pagelang-language": "Јазик",
"pagelang-use-default": "Користи стандарден јазик",
"mw-widgets-titleinput-description-new-page": "страницата сè уште не постои",
"mw-widgets-titleinput-description-redirect": "пренасочување кон $1",
"api-error-blacklisted": "Одберете поинаков, описен наслов.",
+ "sessionprovider-generic": "$1 седници",
+ "sessionprovider-mediawiki-session-cookiesessionprovider": "седници со колачиња",
"randomrootpage": "Случајна основна страница"
}
"version-hook-subscribedby": "Shown in [[Special:Version]]",
"version-version": "{{Optional}}\nUsed in [[Special:Version]]. Preceded by the MediaWiki extension name.\n\nParameters:\n* $1 - version number of the extension",
"version-no-ext-name": "Used in [[Special:Version]], in the rows of the main table when a name for an extension is not provided.",
- "version-svn-revision": "{{Identical|Revision}}{{optional}}\nUsed in [[Special:Version]], preceeding the Subversion revision numbers of the extensions loaded inside brackets, like this: \"({{int:version-revision}} r012345\"). Parameters:\n* $1 - (Unused) directory revision number or empty string\n* $2 - checkout revision number",
"version-license": "Used specifically for the MediaWiki software.\n\nUsed as heading in [[Special:Version]].",
"version-ext-license": "Used in [[Special:Version]].\n\nUsed as label for the link pointing to the extension's license page. e.g. [[Special:Version/License/Maps]]\n{{Identical|License}}",
"version-ext-colheader-name": "Column header for the name of an extension.\n{{Identical|Extension}}",
"log-title-wildcard": "ค้นหาชื่อเรื่องซึ่งขึ้นต้นด้วยข้อความนี้",
"showhideselectedlogentries": "เปลี่ยนทัศนวิสัยของหน่วยปูมที่เลือก",
"log-edit-tags": "ป้ายระบุการแก้ไขของรายการปูมที่เลือก",
+ "checkbox-select": "เลือก: $1",
+ "checkbox-all": "ทั้งหมด",
+ "checkbox-none": "ไม่เลือก",
+ "checkbox-invert": "กลับ",
"allpages": "หน้าทั้งหมด",
"nextpage": "หน้าถัดไป ($1)",
"prevpage": "หน้าก่อนหน้า ($1)",
"wlheader-showupdated": "หน้าที่มีการเปลี่ยนแปลงตั้งแต่คุณเยี่ยมครั้งสุดท้ายแสดงด้วย<strong>ตัวหนา</strong>",
"wlnote": "ด้านล่างเป็น{{PLURAL:$1|การเปลี่ยนแปลงหลังสุด| <strong>$1</strong> การเปลี่ยนแปลงหลังสุด}} ใน{{PLURAL:$2|ชั่วโมง| <strong>$2</strong> ชั่วโมง}}ที่หลังสุด จนถึง $3, $4",
"wlshowlast": "แสดง $1 ชั่วโมง $2 วันล่าสุด",
- "watchlistall2": "ทั้งหมด",
"watchlist-hide": "ซ่อน",
"watchlist-submit": "แสดง",
"wlshowtime": "ระยะเวลาที่แสดง:",
"wlshowhideanons": "ผู้ใช้นิรนาม",
"wlshowhidepatr": "การแก้ไขที่ตรวจสอบแล้ว",
"wlshowhidemine": "การแก้ไขของฉัน",
+ "wlshowhidecategorization": "การจัดหมวดหมู่หน้า",
"watchlist-options": "ตัวเลือกรายการเฝ้าดู",
"watching": "กำลังเฝ้าดู...",
"unwatching": "กำลังเลิกเฝ้าดู...",
"tooltip-pt-preferences": "การตั้งค่าของคุณ",
"tooltip-pt-watchlist": "รายการหน้าที่คุณกำลังเฝ้าดูการเปลี่ยนแปลง",
"tooltip-pt-mycontris": "รายการหน้าที่คุณเขียน",
+ "tooltip-pt-anoncontribs": "รายการการแก้ไขจากเลขที่อยู่ไอพีนี้",
"tooltip-pt-login": "สนับสนุนให้คุณล็อกอิน แต่ไม่บังคับ",
"tooltip-pt-logout": "ล็อกเอาต์",
"tooltip-pt-createaccount": "สนับสนุนให้คุณสร้างบัญชีและล็อกอิน แต่ไม่บังคับ",
"pageinfo-category-files": "จำนวนไฟล์",
"markaspatrolleddiff": "ทำเครื่องหมายว่าตรวจสอบแล้ว",
"markaspatrolledtext": "ทำเครื่องหมายว่าหน้านี้ถูกตรวจสอบแล้ว",
+ "markaspatrolledtext-file": "ทำเครื่องหมายรุ่นไฟล์นี้ว่าตรวจสอบแล้ว",
"markedaspatrolled": "ตรวจสอบแล้ว",
"markedaspatrolledtext": "กำหนดรุ่นที่เลือกของ [[:$1]] ว่าตรวจสอบแล้ว",
"rcpatroldisabled": "การตรวจสอบหน้าปรับปรุงล่าสุดถูกปิดใช้งาน",
"newimages-legend": "ตัวกรอง",
"newimages-label": "ชื่อไฟล์ (หรือส่วนหนึ่งของชื่อ):",
"newimages-showbots": "แสดงไฟล์ที่บอตอัปโหลด",
+ "newimages-hidepatrolled": "ซ่อนการอัปโหลดที่ตรวจสอบแล้ว",
"noimages": "ไม่มีให้ดู",
"ilsubmit": "สืบค้น",
"bydate": "ตามวันที่",
"version-software-version": "รุ่น",
"version-entrypoints-articlepath": "[https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgArticlePath เส้นทางบทความ]",
"version-entrypoints-scriptpath": "[https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgScriptPath เส้นทางสคริปต์]",
- "redirect": "การเปลี่ยนทางตามชื่อไฟล์ รหัสประจำผู้ใช้ หน้าหรือรุ่น",
+ "redirect": "การเปลี่ยนทางตามชื่อไฟล์ รหัสประจำผู้ใช้ หน้า รุ่นหรือปูม",
"redirect-legend": "การเปลี่ยนทางไปยังไฟล์หรือหน้า",
"redirect-summary": "หน้าพิเศษนี้เปลี่ยนทางไปยังไฟล์ (ระบุเป็นชื่อไฟล์) หน้า (ระบุเป็นรหัสรุ่นหรือรหัสหน้า) หรือหน้าผู้ใช้ (ระบุเป็นรหัสผู้ใช้ตัวเลข) การใช้งาน: [[{{#Special:Redirect}}/file/Example.jpg]], [[{{#Special:Redirect}}/page/64308]], [[{{#Special:Redirect}}/revision/328429]] หรือ [[{{#Special:Redirect}}/user/101]]",
"redirect-submit": "ไป",
"expand_templates_ok": "ตกลง",
"expand_templates_remove_comments": "นำส่วนความเห็นออก",
"expand_templates_preview": "ตัวอย่างผลแสดง",
- "pagelanguage": "ตัวเลือกภาษาหน้า",
+ "expand_templates_input_missing": "คุณต้องให้ข้อความป้อนเข้าบ้าง",
+ "pagelanguage": "เปลี่ยนภาษาของหน้า",
"pagelang-name": "หน้า",
"pagelang-language": "ภาษา",
"pagelang-use-default": "ใช้ภาษาโดยปริยาย",
"pagelang-select-lang": "เลือกภาษา",
+ "pagelang-submit": "ส่ง",
"right-pagelang": "เปลี่ยนภาษาหน้า",
"action-pagelang": "เปลี่ยนภาษาหน้า",
"log-name-pagelang": "ปูมการเปลี่ยนภาษา",
"statistics-users": "Теркәлгән [[Special:ListUsers|кулланучылар]]",
"statistics-users-active": "Актив кулланучылар",
"statistics-users-active-desc": "{{PLURAL:$1|$1 көн }} өчендә нинди дә булса үзгәртүләр керткән кулланучылар",
+ "pageswithprop": "Үзенчәлекләре кабаттан билгеләнгән битләр",
+ "pageswithprop-legend": "Үзенчәлекләре кабаттан билгеләнгән битләр",
+ "pageswithprop-text": "Монда кайбер үзенчәлекләре кулдан яңартылган битләр күрсәтелгән.",
"pageswithprop-prop": "Үзенчәлекнең атамасы:",
"pageswithprop-submit": "Табу",
"doubleredirects": "Икеләтә юнәлтүләр",
"duration-days": "$1 {{PLURAL:$1|көн}}",
"expandtemplates": "Үрнәкләрне ачу",
"expand_templates_ok": "OK",
+ "mediastatistics": "Медиа хисабы",
"special-characters-group-latin": "Латин",
"special-characters-group-latinextended": "Латин (киңәйтелгән)",
"special-characters-group-ipa": "ХФӘ (IPA)",
"recentchangeslinked-title": "\"$1\" سے متعلقہ تبدیلیاں",
"recentchangeslinked-summary": "یہ ان تبدیلیوں کی فہرست ہے جو حال ہی میں کسی مخصوص صفحہ سے مربوط صفحات (یا مخصوص زمرہ کے اراکین) میں کی گئی ہیں\n\n[[Special:Watchlist|آپ کی زیر نظر فہرست]] میں یہ صفحات متجل (bold) نظر آئیں گےـ",
"recentchangeslinked-page": "صفحۂ منصوبہ دیکھئے",
+ "recentchanges-page-added-to-category": "[[:$1]] کو زمرہ میں شامل کیا گیا",
+ "recentchanges-page-added-to-category-bundled": "[[:$1]] اور {{PLURAL:$2|ایک صفحہ|$2 صفحات}} زمرہ میں شامل {{PLURAL:$2|کیا گیا|$2 کیے گئے}}",
+ "recentchanges-page-removed-from-category": "[[:$1]] کو زمرہ سے ہٹایا",
"autochange-username": "میڈیاویکی خودکار تبدیلیاں",
"upload": "فائل اثقال/اپلوڈ فائل",
"uploadbtn": "زبراثقال ملف (اپ لوڈ فائل)",
"changepassword-success": "密碼改好哉!\n能界登錄當中...",
"changepassword-throttled": "侬试登录忒多次哉。等$1再试试看。",
"resetpass_forbidden": "密码弗好更改",
- "resetpass-no-info": "侬必须登录ä»\94å\86\8d好ç\9b´æ\8e¥è¿\9bå\85¥ç®\87å\8fªé¡µé\9d¢ã\80\82",
+ "resetpass-no-info": "侬必须登录è\91\97æ\89\8d好ç\9b´æ\8e¥è¿\9bå\85¥ç®\87å\8fªé¡µé\9d¢ã\80\82",
"resetpass-submit-loggedin": "更改密码",
"resetpass-submit-cancel": "取消",
"resetpass-wrong-oldpass": "无效个临时或者现有密码。\n侬作兴已经成功拿密码改脱,或者已经请求一个新个临时密码。",
"passwordreset-emailelement": "用户名:\n$1\n\n临时密码:\n$2",
"changeemail": "更改或删脱电子邮箱地址",
"changeemail-passwordrequired": "侬需要输入密码来确认本次更改。",
- "changeemail-no-info": "侬必须登录著å\86\8d好ç\9b´æ\8e¥è¿\9bå\85¥ç®\87å\8fªé¡µé\9d¢ã\80\82",
+ "changeemail-no-info": "侬必须登录著æ\89\8d好ç\9b´æ\8e¥è¿\9bå\85¥ç®\87å\8fªé¡µé\9d¢ã\80\82",
"changeemail-oldemail": "当前电子邮件地址:",
"changeemail-newemail": "新个电子邮件地址:",
"changeemail-password": "侬个{{SITENAME}}密码:",
"nosuchsectiontext": "侬尝试编辑个章节弗存在。\n作兴是垃拉侬查看页面个辰光已经移动或者畀删除。",
"loginreqtitle": "必须登录",
"loginreqlink": "登录",
- "loginreqpagetext": "侬必须$1再好查看其它页面。",
+ "loginreqpagetext": "请$1来望其他页面。",
"accmailtitle": "密码已发送哉。",
"accmailtext": "已经为[[User talk:$1|$1]]产生只随机密码,并且已经发送到$2。登录之后,侬可以垃拉<em>[[Special:ChangePassword|箇只页面]]</em>更改密码。",
"newarticle": "(新)",
"userpage-userdoesnotexist": "用户账户“<nowiki>$1</nowiki>”弗曾创建。请垃拉创建/编辑迭个页面前头先检查一记。",
"userpage-userdoesnotexist-view": "用户账户“$1”弗曾创建。",
"blocked-notice-logextract": "箇位用户箇歇畀封锁垃许。\n下头有最近个封锁纪录以供参考:",
- "clearyourcache": "<strong>注意:</strong>垃拉保存之后,侬作兴要清除浏览器个缓存å\86\8d好ç\9c\8bè§\81æ\94¹å\8f\98ã\80\82\n* <strong>Firefoxæ\88\96Safariï¼\9a</strong>æ\8f¿ç\89¢â\80\9cShiftâ\80\9d个å\90\8cæ\97¶ç\82¹å\87»â\80\9cå\88·æ\96°â\80\9dï¼\8cæ\88\96æ\8f¿â\80\9cCtrl-F5â\80\9dæ\88\96â\80\9cCtrl-Râ\80\9dï¼\88Macä¸\8aæ\98¯â\80\9câ\8c\98-Râ\80\9dï¼\89\n* <strong>Google Chromeï¼\9a</strong>æ\8f¿â\80\9cCtrl-Shift-Râ\80\9dï¼\88Macä¸\8aæ\98¯â\80\9câ\8c\98-Shift-Râ\80\9dï¼\89\n* <strong>Internet Explorerï¼\9a</strong>æ\8f¿ç\89¢â\80\9cCtrlâ\80\9d个å\90\8cæ\97¶ç\82¹å\87»â\80\9cå\88·æ\96°â\80\9dï¼\8cæ\88\96æ\8f¿â\80\9cCtrl-F5â\80\9d\n* <strong>Operaï¼\9a</strong>å\9e\83æ\8b\89â\80\9cå·¥å\85·â\86\92é¦\96é\80\89项â\80\9dé\87\8cå\90\91æ¸\85é\99¤ç¼\93å\98",
+ "clearyourcache": "<strong>注意:</strong>垃拉保存之后,侬作兴要清除浏览器个缓存æ\89\8d好ç\9c\8bè§\81æ\94¹å\8f\98ã\80\82\n* <strong>Firefoxæ\88\96Safariï¼\9a</strong>æ\8f¿ç\89¢â\80\9cShiftâ\80\9d个å\90\8cæ\97¶ç\82¹å\87»â\80\9cå\88·æ\96°â\80\9dï¼\8cæ\88\96æ\8f¿â\80\9cCtrl-F5â\80\9dæ\88\96â\80\9cCtrl-Râ\80\9dï¼\88Macä¸\8aæ\98¯â\80\9câ\8c\98-Râ\80\9dï¼\89\n* <strong>Google Chromeï¼\9a</strong>æ\8f¿â\80\9cCtrl-Shift-Râ\80\9dï¼\88Macä¸\8aæ\98¯â\80\9câ\8c\98-Shift-Râ\80\9dï¼\89\n* <strong>Internet Explorerï¼\9a</strong>æ\8f¿ç\89¢â\80\9cCtrlâ\80\9d个å\90\8cæ\97¶ç\82¹å\87»â\80\9cå\88·æ\96°â\80\9dï¼\8cæ\88\96æ\8f¿â\80\9cCtrl-F5â\80\9d\n* <strong>Operaï¼\9a</strong>å\9e\83æ\8b\89â\80\9cå·¥å\85·â\86\92é¦\96é\80\89项â\80\9dé\87\8cå\90\91æ¸\85é\99¤ç¼\93å\98",
"usercssyoucanpreview": "'''提示:''' 垃拉保存之前请用“{{int:showpreview}}”揿钮来测试新 CSS 。",
"userjsyoucanpreview": "'''提示:''' 垃拉保存之前请用“{{int:showpreview}}”揿钮来测试新 JavaScript 。",
"usercsspreview": "'''注意侬只是垃许预览侬个 CSS。'''\n'''还弗曾保存!'''",
"copyrightwarning2": "请注意侬对{{SITENAME}}个所有贡献\n侪可能畀别个贡献者编辑,修改或删除。\n假使侬弗希望侬个文字畀任意修改搭仔再发布,请弗要提交。<br />\n侬同时也要向我伲保证侬提交个内容是侬自家所作,或得自一个弗受版权保护或相似自由个来源(参阅$1个细节)。\n''' 弗要垃拉弗曾获得授权个情况下头发表!'''",
"longpageerror": "<strong>错误:侬提交个文本长度有$1KB,大于$2KB个顶大值。</strong>该文本弗能保存。",
"readonlywarning": "<strong>警告:数据库锁定垃许维护,侬箇歇弗好保存侬个修改。</strong>侬作兴希望先拿侬个文字复制并保存到文本文件,等歇再修改。\n\n锁牢数据库个系统管理员有如下解释:$1",
- "protectedpagewarning": "<strong>警告:此页已经畀保护,只有拥有管理员权限个用户å\86\8d好修æ\94¹ã\80\82</strong>æ\9c\80è¿\91个æ\97¥å¿\97å\9e\83æ\8b\89ä¸\8båº\95æ\8f\90ä¾\9b以便å\8f\82è\80\83ï¼\9a",
+ "protectedpagewarning": "<strong>警告:此页已经畀保护,只有拥有管理员权限个用户æ\89\8d好修æ\94¹ã\80\82</strong>æ\9c\80è¿\91个æ\97¥å¿\97å\9e\83æ\8b\89ä¸\8båº\95æ\8f\90ä¾\9b以便å\8f\82è\80\83ï¼\9a",
"semiprotectedpagewarning": "'''注意:''' 本页面畀锁定,仅限注册用户编辑。\n最近个日志垃拉下底提供以便参考:",
- "cascadeprotectedwarning": "<strong>警告:</strong>本页已经畀保护,只有拥有管理员权限个用户å\86\8d好修æ\94¹ï¼\8cå\9b 为æ\9c¬é¡µå·²ç\95\80ä¸\8båº\95ç\9c¼çº§è\81\94ä¿\9dæ\8a¤ä¸ª{{PLURAL:$1|ä¸\80å\8fª|å¤\9aå\8fª}}页é\9d¢æ\89\80åµ\8cå\85¥ï¼\9a",
+ "cascadeprotectedwarning": "<strong>警告:</strong>本页已经畀保护,只有拥有管理员权限个用户æ\89\8d好修æ\94¹ï¼\8cå\9b 为æ\9c¬é¡µå·²ç\95\80ä¸\8båº\95ç\9c¼çº§è\81\94ä¿\9dæ\8a¤ä¸ª{{PLURAL:$1|ä¸\80å\8fª|å¤\9aå\8fª}}页é\9d¢æ\89\80åµ\8cå\85¥ï¼\9a",
"titleprotectedwarning": "'''警告:本页面已畀锁定,需要[[Special:ListGroupRights|指定权限]]方可创建。'''\n最近个日志垃拉下底提供以便参考:",
"templatesused": "箇页有{{PLURAL:$1|个模板}}:",
"templatesusedpreview": "{{PLURAL:$1|只模板}}垃拉箇趟预览里向拨使用:",
"revdelete-selected-file": "已选择文件[[:$2]]个$1只版本:",
"logdelete-selected": "选取$1个日志事件:",
"revdelete-confirm": "假使侬想箇能介做个闲话,请确认侬已经清爽箇能介做个后果,外加箇个程序符合[[{{MediaWiki:Policy-url}}|政策]]。",
- "revdelete-suppress-text": "<strong>只有</strong>出现下头眼情况å\86\8dåº\94é\98»æ¢è®¿é\97®ï¼\9a\n* æ½\9cå\9c¨ä¸ªè¯½è°¤ä¿¡æ\81¯\n* å¼\97é\80\82å\90\88个个人信æ\81¯\n*: <em>家åºå\9c°å\9d\80ã\80\81ç\94µè¯\9då\8f·ç \81ã\80\81身份è¯\81å\8f·ç \81ç\89ã\80\82</em>",
+ "revdelete-suppress-text": "<strong>只有</strong>出现下头眼情况æ\89\8dåº\94é\98»æ¢è®¿é\97®ï¼\9a\n* æ½\9cå\9c¨ä¸ªè¯½è°¤ä¿¡æ\81¯\n* å¼\97é\80\82å\90\88个个人信æ\81¯\n*: <em>家åºå\9c°å\9d\80ã\80\81ç\94µè¯\9då\8f·ç \81ã\80\81身份è¯\81å\8f·ç \81ç\89ã\80\82</em>",
"revdelete-legend": "设置可见性之限制",
"revdelete-hide-text": "修订文本",
"revdelete-hide-image": "隐藏文件内容",
"uploadbtn": "上载文件",
"reuploaddesc": "弗傳,轉到傳表單",
"uploadnologin": "朆登录",
- "uploadnologintext": "倷板定要$1再好上载文件。",
+ "uploadnologintext": "请$1来上载文件。",
"uploaderror": "上载出错",
"uploadtext": "拿下头只表格来上载文件。要查看或者搜寻之前上载个图片个说法,请到[[Special:FileList|已上载文件列表]],上载搭仔删脱也记录勒拉[[Special:Log/upload|上载日志]]里向。\n\n要勒拉页面里向摆进图片个说法,用下头该种形式个链接\n'''<nowiki>[[{{ns:file}}:文件.jpg]]</nowiki>''',\n'''<nowiki>[[{{ns:file}}:文件.png|替代文本]]</nowiki>''' 或者用\n'''<nowiki>[[{{ns:media}}:文件.ogg]]</nowiki>''' 直接链到文件。",
"uploadlogpage": "文件上传日志",
"whatlinkshere-hidelinks": "$1链接",
"whatlinkshere-filters": "过滤器",
"blockip": "查封{{GENDER:$1|用户}}",
- "blockiptext": "用下头个表单来禁止来自某一特定IP地址或用户名个修改权限。只有勒勒为仔防止破坏,及符合[[{{MediaWiki:Policy-url}}|政策]]个情况下底再好采取此行动。请勒勒下底输入一个具体个理由(譬如引述一只畀破坏个页面)。",
+ "blockiptext": "用下头个表单来禁止来自某一特定IP地址或用户名个修改权限。只有勒勒为仔防止破坏,及符合[[{{MediaWiki:Policy-url}}|政策]]个情况下底才好采取此行动。请勒勒下底输入一个具体个理由(譬如引述一只畀破坏个页面)。侬好用[https://zh.wikipedia.org/wiki/无类别域间路由 CIDR]语法查封IP地址段;允许个最大段是/$1(针对IPv4)搭/$2(针对IPv6)。",
"ipaddressorusername": "IP地址或用户名:",
"ipbreason": "理由:",
"ipbsubmit": "封杀该个用户",
"move-page-legend": "页面捅荡",
"movepagetext": "用下底个表会重命名一只页面,全部历史侪移到新名字里。老个名字会变成戳到新名字个重定向页。注意检查[[Special:DoubleRedirects|双重重定向]]或者[[Special:BrokenRedirects|坏脱个重定向]]。倷有实概个责任,让链接仍旧链到俚笃应该链到个场化去。\n\n注意,如果新名字归面搭已经有页面个说话,老名字个页面'''弗'''会畀移动,除非归个是只空页面或者是只重定向并且呒不编辑历史。箇也就是讲,假使倷犯错误个说话,倷好拿一只重命名过个页面还原到原来个名字,但倷弗好覆盖一只已经来上个页面。\n\n<strong>警告!</strong>箇呒数会引起对一只热门页面剧烈个、想弗着个改变。来操作前头请倷确定倷已经充分了解行为个后果。",
"movepagetalktext": "如果侬勾选此框,相关讨论页会自动移动到新标题,除非箇𡍲已经有著一只非空个讨论页。\n\n来箇种情况下底,如果有需要,侬必须手工移动或合并页面。",
- "movenologintext": "倷板定要是å·²ç\99»è®°ç\94¨æ\88·ä¸\94å\8b\92æ\8b\89[[Special:UserLogin|ç\99»å½\95]]ç\8a¶æ\80\81ä¸\8b头å\86\8d好æ\8b¿é¡µé\9d¢æ\8d\85è\8d¡ã\80\82",
+ "movenologintext": "倷板定要是注å\86\8cç\94¨æ\88·å¹¶ä¸\94[[Special:UserLogin|ç\99»å½\95]]è\91\97æ\89\8d好æ\8b¿é¡µé\9d¢æ\8d\85è\8d¡ã\80\82",
"newtitle": "新标题:",
"move-watch": "监控来源以及目标页",
"movepagebtn": "页面移动",
"pageinfo-robot-index": "允许",
"pageinfo-robot-noindex": "不允许",
"pageinfo-watchers": "页面监视者数",
- "pageinfo-visiting-watchers": "访问最近编辑的页面浏览者数量",
+ "pageinfo-visiting-watchers": "已访问最近编辑的页面监视者数",
"pageinfo-few-watchers": "少于$1个监视者",
"pageinfo-few-visiting-watchers": "这里可能有或可能没有观察用户正在访问最近编辑",
"pageinfo-redirects-name": "至该页面的重定向数",
"pageinfo-robot-index": "允許",
"pageinfo-robot-noindex": "不允許",
"pageinfo-watchers": "頁面監視者數",
- "pageinfo-visiting-watchers": "最後一次編輯後參觀人數",
+ "pageinfo-visiting-watchers": "已訪問最近編輯的頁面監視者數",
"pageinfo-few-watchers": "少於 $1 名監視者",
"pageinfo-few-visiting-watchers": "參觀近期編輯的使用者可能為監視使用者",
"pageinfo-redirects-name": "指向此頁面的重新導向頁面數量",
'idIsSafe' => true,
) ),
$store,
+ $store,
new \Psr\Log\NullLogger(),
10
);
'idIsSafe' => true,
) ),
new \EmptyBagOStuff(),
+ new \EmptyBagOStuff(),
new \Psr\Log\NullLogger(),
10
);
'idIsSafe' => true,
) ),
$store,
+ $store,
new \Psr\Log\NullLogger(),
10
);
'idIsSafe' => true,
) ),
new \EmptyBagOStuff(),
+ new \EmptyBagOStuff(),
new \Psr\Log\NullLogger(),
10
);
$this->assertSame( $expect, $_SESSION );
}
- // Test expiry
- session_write_close();
- ini_set( 'session.gc_divisor', 1 );
- ini_set( 'session.gc_probability', 1 );
- sleep( 3 );
- session_start();
- $this->assertSame( array(), $_SESSION );
-
// Re-fill the session, then test that session_destroy() works.
$_SESSION['AuthenticationSessionTest'] = $rand;
session_write_close();
) );
$id = new SessionId( $info->getId() );
- $backend = new SessionBackend( $id, $info, $this->store, $logger, 10 );
+ $backend = new SessionBackend( $id, $info, $this->store, $this->store, $logger, 10 );
$priv = \TestingAccessWrapper::newFromObject( $backend );
$priv->persist = false;
$priv->requests = array( 100 => new \FauxRequest() );
$id = new SessionId( $info->getId() );
$logger = new \Psr\Log\NullLogger();
try {
- new SessionBackend( $id, $info, $this->store, $logger, 10 );
+ new SessionBackend( $id, $info, $this->store, $this->store, $logger, 10 );
$this->fail( 'Expected exception not thrown' );
} catch ( \InvalidArgumentException $ex ) {
$this->assertSame(
) );
$id = new SessionId( $info->getId() );
try {
- new SessionBackend( $id, $info, $this->store, $logger, 10 );
+ new SessionBackend( $id, $info, $this->store, $this->store, $logger, 10 );
$this->fail( 'Expected exception not thrown' );
} catch ( \InvalidArgumentException $ex ) {
$this->assertSame( 'Cannot create session without a provider', $ex->getMessage() );
) );
$id = new SessionId( '!' . $info->getId() );
try {
- new SessionBackend( $id, $info, $this->store, $logger, 10 );
+ new SessionBackend( $id, $info, $this->store, $this->store, $logger, 10 );
$this->fail( 'Expected exception not thrown' );
} catch ( \InvalidArgumentException $ex ) {
$this->assertSame(
'idIsSafe' => true,
) );
$id = new SessionId( $info->getId() );
- $backend = new SessionBackend( $id, $info, $this->store, $logger, 10 );
+ $backend = new SessionBackend( $id, $info, $this->store, $this->store, $logger, 10 );
$this->assertSame( self::SESSIONID, $backend->getId() );
$this->assertSame( $id, $backend->getSessionId() );
$this->assertSame( $this->provider, $backend->getProvider() );
'idIsSafe' => true,
) );
$id = new SessionId( $info->getId() );
- $backend = new SessionBackend( $id, $info, $this->store, $logger, 10 );
+ $backend = new SessionBackend( $id, $info, $this->store, $this->store, $logger, 10 );
$this->assertSame( self::SESSIONID, $backend->getId() );
$this->assertSame( $id, $backend->getSessionId() );
$this->assertSame( $this->provider, $backend->getProvider() );
$manager = \TestingAccessWrapper::newFromObject( $this->getManager() );
$this->assertSame( $this->config, $manager->config );
$this->assertSame( $this->logger, $manager->logger );
- $this->assertSame( $this->store, $manager->store );
+ $this->assertSame( $this->store, $manager->permStore );
$manager = \TestingAccessWrapper::newFromObject( new SessionManager() );
$this->assertSame( \RequestContext::getMain()->getConfig(), $manager->config );
$manager = \TestingAccessWrapper::newFromObject( new SessionManager( array(
'config' => $this->config,
) ) );
- $this->assertSame( \ObjectCache::$instances['testSessionStore'], $manager->store );
+ $this->assertSame( \ObjectCache::$instances['testSessionStore'], $manager->permStore );
foreach ( array(
'config' => '$options[\'config\'] must be an instance of Config',
public function testGetSessionById() {
$manager = $this->getManager();
+ // Disable the in-process cache so our $this->store->setSession() takes effect.
+ \TestingAccessWrapper::newFromObject( $manager )->tempStore = new \EmptyBagOStuff;
+
try {
$manager->getSessionById( 'bad' );
$this->fail( 'Expected exception not thrown' );
$manager->setLogger( $logger );
$request = new \FauxRequest();
+ // Disable the in-process cache so our $this->store->setSession() takes effect.
+ \TestingAccessWrapper::newFromObject( $manager )->tempStore = new \EmptyBagOStuff;
+
// TestingAccessWrapper can't handle methods with reference arguments, sigh.
$rClass = new \ReflectionClass( $manager );
$rMethod = $rClass->getMethod( 'loadSessionInfoFromStore' );