private static function getVariables() { ObjectCache::getInstance(); $site = Site::getInstance(); define('GUEST_ROLE_ID', (int) $site->getGuestRoleID()->getValue()); define('SITE_EMAIL', $site->getEmail()); define('SITE_TITLE', $site->getTitle()); date_default_timezone_set($site->getTimeZone()); if ($site->isInMaintenanceMode()) { if (!PermissionEngine::getInstance()->currentUserCanDo('bypasssMaintenanceMode')) { return; } } $blockEngine = BlockEngine::getInstance(); $user = CurrentUser::getUserSession(); $hookEngine = HookEngine::getInstance(); $router = Router::getInstance(); $hookEngine->runAction('addStaticRoutes'); $moduleInCharge = $router->whichModuleHandlesRequest(); $response = self::getResponse($moduleInCharge); http_response_code($response->getResponseCode()); $headers = $response->getHeaders(); foreach ($headers as $header => $value) { header($header . ": " . $value, true); } define('PAGE_TYPE', $response->getPageType()); $blocks = $blockEngine->getBlocks($site->getTheme(), PAGE_TYPE, $user->getRoleID()); if ($blocks === null) { $blocks = array(); } self::render($site, $response, $blocks); }
public static function getBlackList() { $cache = \ObjectCache::getMainWANInstance(); return $cache->getWithSetCallback(wfMemcKey('flowthread', 'spamblacklist'), 60, function () { return self::buildBlacklist(); }); }
private static function clearOldCache() { if (self::$instance->lastClear > strtotime("-30 minutes")) { return; } self::$instance = new ObjectCache(); }
public function __construct($parent) { global $wgMemc; $this->parent = $parent; $this->srvCache = ObjectCache::newAccelerator(array(), 'hash'); $this->mainCache = $wgMemc ?: wfGetMainCache(); }
public static function show($objectId, $jsonLast = null) { $db = Core::getDb(); $user = Core::getUser(); $comments = array(); $qLast = $jsonLast ? "and c.id>" . $db->escape($jsonLast) : ""; $q = $db->buildQuery("SELECT c.id, c.body, o.ctime, u.id as local_user_id, o.user_id, c.user_connection_id, con.service, con.external_id\n FROM comments c\n LEFT JOIN objects o ON o.object_id=c.object_id\n LEFT JOIN connections con ON c.user_connection_id=con.id\n\t\t\tLEFT JOIN users u ON u.id=o.user_id\n WHERE c.in_reply_to_id=%d {$qLast}\n ORDER BY o.ctime ASC", $objectId); $rs = $db->query($q); if ($rs && $db->numrows($rs)) { while ($o = $db->fetchObject($rs)) { $commentAuthor = ObjectCache::getByType('\\Kiki\\User', $o->user_id ? $o->user_id : $o->local_user_id); if ($commentAuthor) { if ($o->external_id) { // HACK: should not always have to load this, but this is quicker than getStoredConnections for User 0 $connection = User\Factory::getInstance($o->service, $o->external_id, 0); // $connection = $commentAuthor->getConnection($o->service. "_". $o->external_id, true); if ($connection) { $serviceName = $connection->serviceName(); $name = $connection->name(); $pic = $connection->picture(); } else { $serviceName = 'None'; // SNH $name = $commentAuthor->name(); $pic = $commentAuthor->picture(); } } else { $serviceName = 'None'; // Kiki $name = $commentAuthor->name(); $pic = $commentAuthor->picture(); } } else { $serviceName = 'None'; $name = "Anonymous"; $pic = null; } if ($jsonLast !== null) { $comments[] = Comments::showSingle($objectId, $o->id, $name, $pic, $serviceName, $o->body, $o->ctime); } else { $comment = array('objectId' => $objectId, 'id' => $o->id, 'name' => $name, 'pic' => $pic, 'type' => $serviceName, 'body' => $o->body, 'ctime' => $o->ctime, 'dateTime' => date("c", strtotime($o->ctime)), 'relTime' => Misc::relativeTime($o->ctime)); $comments[] = $comment; } } } else { if ($jsonLast === null) { $comments[] = Comments::showDummy($objectId); } } if ($jsonLast !== null) { return $comments; } $template = new Template('parts/comments'); $template->assign('objectId', $objectId); $template->assign('comments', $comments); return $template->fetch(); }
public function delete() { $query = "DELETE from " . self::DB_TABLE; $query .= " WHERE user_id = " . $this->userID; $query .= " AND project_id = " . $this->projectID; $db = Db::instance(); $db->execute($query); ObjectCache::remove(get_class($this), $this->id); }
/** * @covers BagOStuff::makeGlobalKey * @covers BagOStuff::makeKeyInternal */ public function testMakeKey() { $cache = ObjectCache::newFromId('hash'); $localKey = $cache->makeKey('first', 'second', 'third'); $globalKey = $cache->makeGlobalKey('first', 'second', 'third'); $this->assertStringMatchesFormat('%Sfirst%Ssecond%Sthird%S', $localKey, 'Local key interpolates parameters'); $this->assertStringMatchesFormat('global%Sfirst%Ssecond%Sthird%S', $globalKey, 'Global key interpolates parameters and contains global prefix'); $this->assertNotEquals($localKey, $globalKey, 'Local key and global key with same parameters should not be equal'); }
public function templateData() { $uAuthor = ObjectCache::getByType('\\Kiki\\User', $this->userId); $data = array('id' => $this->id, 'url' => $this->url(), 'ctime' => strtotime($this->ctime), 'relTime' => Misc::relativeTime($this->ctime), 'title' => $this->title(), 'body' => $this->body, 'author' => $uAuthor->name(), 'publications' => array(), 'likes' => $this->likes(), 'comments' => Comments::count($this->objectId), 'html' => array('comments' => Comments::show($this->objectId))); $publications = $this->publications(); foreach ($publications as $publication) { $data['publications'][] = $publication->templateData(); } return $data; }
/** * Constructor. Parameters are: * * - caches: This should have a numbered array of cache parameter * structures, in the style required by $wgObjectCaches. See * the documentation of $wgObjectCaches for more detail. * * @param array $params * @throws MWException */ public function __construct($params) { if (!isset($params['caches'])) { throw new MWException(__METHOD__ . ': the caches parameter is required'); } $this->caches = array(); foreach ($params['caches'] as $cacheInfo) { $this->caches[] = ObjectCache::newFromParams($cacheInfo); } }
public function save(array $data) { if ($this->__testForApc() === false) { return false; } if (apc_add(parent::getName(), serialize($data), parent::getTimeToLive()) === false) { return false; } return true; }
/** * Check whether feed's cache should be cleared; for changes feeds * If the feed should be purged; $timekey and $key will be removed from cache * * @param string $timekey Cache key of the timestamp of the last item * @param string $key Cache key of feed's content */ public static function checkPurge($timekey, $key) { global $wgRequest, $wgUser; $purge = $wgRequest->getVal('action') === 'purge'; if ($purge && $wgUser->isAllowed('purge')) { $cache = ObjectCache::getMainWANInstance(); $cache->delete($timekey, 1); $cache->delete($key, 1); } }
protected function setUp() { parent::setUp(); if ($this->getCliArg('use-wanobjectcache')) { $name = $this->getCliArg('use-wanobjectcache'); $this->cache = ObjectCache::getWANInstance($name); } else { $this->cache = new WANObjectCache(array('cache' => new HashBagOStuff(), 'pool' => 'testcache-hash', 'relayer' => new EventRelayerNull(array()))); } }
/** * @param array $lbConf Config for LBFactory::__construct() * @param Config $mainConfig Main config object from MediaWikiServices * @return array */ public static function applyDefaultConfig(array $lbConf, Config $mainConfig) { global $wgCommandLineMode; $lbConf += ['localDomain' => new DatabaseDomain($mainConfig->get('DBname'), null, $mainConfig->get('DBprefix')), 'profiler' => Profiler::instance(), 'trxProfiler' => Profiler::instance()->getTransactionProfiler(), 'replLogger' => LoggerFactory::getInstance('DBReplication'), 'queryLogger' => LoggerFactory::getInstance('DBQuery'), 'connLogger' => LoggerFactory::getInstance('DBConnection'), 'perfLogger' => LoggerFactory::getInstance('DBPerformance'), 'errorLogger' => [MWExceptionHandler::class, 'logException'], 'cliMode' => $wgCommandLineMode, 'hostname' => wfHostname(), 'readOnlyReason' => wfConfiguredReadOnlyReason()]; if ($lbConf['class'] === 'LBFactorySimple') { if (isset($lbConf['servers'])) { // Server array is already explicitly configured; leave alone } elseif (is_array($mainConfig->get('DBservers'))) { foreach ($mainConfig->get('DBservers') as $i => $server) { if ($server['type'] === 'sqlite') { $server += ['dbDirectory' => $mainConfig->get('SQLiteDataDir')]; } elseif ($server['type'] === 'postgres') { $server += ['port' => $mainConfig->get('DBport')]; } $lbConf['servers'][$i] = $server + ['schema' => $mainConfig->get('DBmwschema'), 'tablePrefix' => $mainConfig->get('DBprefix'), 'flags' => DBO_DEFAULT, 'sqlMode' => $mainConfig->get('SQLMode'), 'utf8Mode' => $mainConfig->get('DBmysql5')]; } } else { $flags = DBO_DEFAULT; $flags |= $mainConfig->get('DebugDumpSql') ? DBO_DEBUG : 0; $flags |= $mainConfig->get('DBssl') ? DBO_SSL : 0; $flags |= $mainConfig->get('DBcompress') ? DBO_COMPRESS : 0; $server = ['host' => $mainConfig->get('DBserver'), 'user' => $mainConfig->get('DBuser'), 'password' => $mainConfig->get('DBpassword'), 'dbname' => $mainConfig->get('DBname'), 'schema' => $mainConfig->get('DBmwschema'), 'tablePrefix' => $mainConfig->get('DBprefix'), 'type' => $mainConfig->get('DBtype'), 'load' => 1, 'flags' => $flags, 'sqlMode' => $mainConfig->get('SQLMode'), 'utf8Mode' => $mainConfig->get('DBmysql5')]; if ($server['type'] === 'sqlite') { $server['dbDirectory'] = $mainConfig->get('SQLiteDataDir'); } elseif ($server['type'] === 'postgres') { $server['port'] = $mainConfig->get('DBport'); } $lbConf['servers'] = [$server]; } if (!isset($lbConf['externalClusters'])) { $lbConf['externalClusters'] = $mainConfig->get('ExternalServers'); } } elseif ($lbConf['class'] === 'LBFactoryMulti') { if (isset($lbConf['serverTemplate'])) { $lbConf['serverTemplate']['schema'] = $mainConfig->get('DBmwschema'); $lbConf['serverTemplate']['sqlMode'] = $mainConfig->get('SQLMode'); $lbConf['serverTemplate']['utf8Mode'] = $mainConfig->get('DBmysql5'); } } // Use APC/memcached style caching, but avoids loops with CACHE_DB (T141804) $sCache = MediaWikiServices::getInstance()->getLocalServerObjectCache(); if ($sCache->getQoS($sCache::ATTR_EMULATION) > $sCache::QOS_EMULATION_SQL) { $lbConf['srvCache'] = $sCache; } $cCache = ObjectCache::getLocalClusterInstance(); if ($cCache->getQoS($cCache::ATTR_EMULATION) > $cCache::QOS_EMULATION_SQL) { $lbConf['memCache'] = $cCache; } $wCache = MediaWikiServices::getInstance()->getMainWANObjectCache(); if ($wCache->getQoS($wCache::ATTR_EMULATION) > $wCache::QOS_EMULATION_SQL) { $lbConf['wanCache'] = $wCache; } return $lbConf; }
public function __construct() { // We use a try/catch instead of the $fallback parameter because // we don't want to fail here if $wgObjectCaches is not configured // properly for APC setup try { $this->cache = ObjectCache::newAccelerator(); } catch (MWException $e) { $this->cache = new EmptyBagOStuff(); } }
/** * Tests saving data. */ public function testSaveData() { $object = $this->saveObject(); $this->assertSame($object, $this->cache->get(self::CACHE_KEY)); // Saving using one way ObjectCache::set(self::CACHE_KEY, $object); $this->assertSame($object, $this->cache->get(self::CACHE_KEY)); // Saving using the other way $this->cache->{self::CACHE_KEY} = $object; $this->assertSame($object, $this->cache->get(self::CACHE_KEY)); $this->cache->clear(); }
public function save(array $data) { if (apc_add(parent::getName(), serialize($data), parent::getTimeToLive()) === false) { # logging me hearties # logging me hearties $types = parent::getTypes(); $urgency = parent::getUrgency(); parent::writeLog($types['error'], $urgency['high'], 'Could not successfully save to cache', 'APC Cache info: ' . PHP_EOL . serialize(apc_cache_info())); return false; } return true; }
protected function setUp() { parent::setUp(); if ($this->getCliArg('use-wanobjectcache')) { $name = $this->getCliArg('use-wanobjectcache'); $this->cache = ObjectCache::getWANInstance($name); } else { $this->cache = new WANObjectCache(['cache' => new HashBagOStuff(), 'pool' => 'testcache-hash', 'relayer' => new EventRelayerNull([])]); } $wanCache = TestingAccessWrapper::newFromObject($this->cache); $this->internalCache = $wanCache->cache; }
/** * $params include: * - caches: This should have a numbered array of cache parameter * structures, in the style required by $wgObjectCaches. See * the documentation of $wgObjectCaches for more detail. * BagOStuff objects can also be used as values. * The first cache is the primary one, being the first to * be read in the fallback chain. Writes happen to all stores * in the order they are defined. However, lock()/unlock() calls * only use the primary store. * - replication: Either 'sync' or 'async'. This controls whether writes to * secondary stores are deferred when possible. Async writes * require the HHVM register_postsend_function() function. * Async writes can increase the chance of some race conditions * or cause keys to expire seconds later than expected. It is * safe to use for modules when cached values: are immutable, * invalidation uses logical TTLs, invalidation uses etag/timestamp * validation against the DB, or merge() is used to handle races. * * @param array $params * @throws InvalidArgumentException */ public function __construct($params) { parent::__construct($params); if (empty($params['caches']) || !is_array($params['caches'])) { throw new InvalidArgumentException(__METHOD__ . ': "caches" parameter must be an array of caches'); } $this->caches = array(); foreach ($params['caches'] as $cacheInfo) { $this->caches[] = $cacheInfo instanceof BagOStuff ? $cacheInfo : ObjectCache::newFromParams($cacheInfo); } $this->asyncWrites = isset($params['replication']) && $params['replication'] === 'async'; }
protected function setUp() { parent::setUp(); // type defined through parameter if ($this->getCliArg('use-bagostuff')) { $name = $this->getCliArg('use-bagostuff'); $this->cache = ObjectCache::newFromId($name); } else { // no type defined - use simple hash $this->cache = new HashBagOStuff(); } $this->cache->delete(wfMemcKey('test')); }
/** * Run query and return array of results * * @param string $error_message * @param boolean $die_on_error * @return array */ function run($error_message = '', $die_on_error = true) { $q = $this->get_query(); if ($this->cache_lifespan) { $cache = new ObjectCache('db_selector_cache_' . get_current_db_connection_name() . '_' . $q, $this->cache_lifespan); $results =& $cache->fetch(); if (false !== $results) { return $results; } } $results = array(); $r = db_query($q, $error_message, $die_on_error); if ($r) { while ($row = mysql_fetch_array($r, MYSQL_ASSOC)) { $results[] = $row; } mysql_free_result($r); } if (!empty($cache)) { $cache->set($results); } return $results; }
/** * Returns a given template function if found, otherwise throws an exception. * @param string $templateName The name of the template (without file suffix) * @return callable * @throws RuntimeException */ protected function getTemplate($templateName) { // If a renderer has already been defined for this template, reuse it if (isset($this->renderers[$templateName]) && is_callable($this->renderers[$templateName])) { return $this->renderers[$templateName]; } $filename = $this->getTemplateFilename($templateName); if (!file_exists($filename)) { throw new RuntimeException("Could not locate template: {$filename}"); } // Read the template file $fileContents = file_get_contents($filename); // Generate a quick hash for cache invalidation $fastHash = md5($fileContents); // Fetch a secret key for building a keyed hash of the PHP code $config = ConfigFactory::getDefaultInstance()->makeConfig('main'); $secretKey = $config->get('SecretKey'); if ($secretKey) { // See if the compiled PHP code is stored in cache. $cache = ObjectCache::getLocalServerInstance(CACHE_ANYTHING); $key = $cache->makeKey('template', $templateName, $fastHash); $code = $this->forceRecompile ? null : $cache->get($key); if (!$code) { $code = $this->compileForEval($fileContents, $filename); // Prefix the cached code with a keyed hash (64 hex chars) as an integrity check $cache->set($key, hash_hmac('sha256', $code, $secretKey) . $code); } else { // Verify the integrity of the cached PHP code $keyedHash = substr($code, 0, 64); $code = substr($code, 64); if ($keyedHash !== hash_hmac('sha256', $code, $secretKey)) { // Generate a notice if integrity check fails trigger_error("Template failed integrity check: {$filename}"); } } // If there is no secret key available, don't use cache } else { $code = $this->compileForEval($fileContents, $filename); } $renderer = eval($code); if (!is_callable($renderer)) { throw new RuntimeException("Requested template, {$templateName}, is not callable"); } $this->renderers[$templateName] = $renderer; return $renderer; }
/** * Construct a new instance from configuration. * * @param array $config Parameters include: * - lockServers : Associative array of server names to "<IP>:<port>" strings. * - srvsByBucket : Array of 1-16 consecutive integer keys, starting from 0, * each having an odd-numbered list of server names (peers) as values. * - memcConfig : Configuration array for ObjectCache::newFromParams. [optional] * If set, this must use one of the memcached classes. * @throws Exception */ public function __construct(array $config) { parent::__construct($config); // Sanitize srvsByBucket config to prevent PHP errors $this->srvsByBucket = array_filter($config['srvsByBucket'], 'is_array'); $this->srvsByBucket = array_values($this->srvsByBucket); // consecutive $memcConfig = isset($config['memcConfig']) ? $config['memcConfig'] : ['class' => 'MemcachedPhpBagOStuff']; foreach ($config['lockServers'] as $name => $address) { $params = ['servers' => [$address]] + $memcConfig; $cache = ObjectCache::newFromParams($params); if ($cache instanceof MemcachedBagOStuff) { $this->bagOStuffs[$name] = $cache; } else { throw new Exception('Only MemcachedBagOStuff classes are supported by MemcLockManager.'); } } $this->session = wfRandomString(32); }
/** * @param array $conditions An array of arrays describing throttling conditions. * Defaults to $wgPasswordAttemptThrottle. See documentation of that variable for format. * @param array $params Parameters (all optional): * - type: throttle type, used as a namespace for counters, * - cache: a BagOStuff object where throttle counters are stored. * - warningLimit: the log level will be raised to warning when rejecting an attempt after * no less than this many failures. */ public function __construct(array $conditions = null, array $params = []) { $invalidParams = array_diff_key($params, array_fill_keys(['type', 'cache', 'warningLimit'], true)); if ($invalidParams) { throw new \InvalidArgumentException('unrecognized parameters: ' . implode(', ', array_keys($invalidParams))); } if ($conditions === null) { $config = \ConfigFactory::getDefaultInstance()->makeConfig('main'); $conditions = $config->get('PasswordAttemptThrottle'); $params += ['type' => 'password', 'cache' => \ObjectCache::getLocalClusterInstance(), 'warningLimit' => 50]; } else { $params += ['type' => 'custom', 'cache' => \ObjectCache::getLocalClusterInstance(), 'warningLimit' => INF]; } $this->type = $params['type']; $this->conditions = static::normalizeThrottleConditions($conditions); $this->cache = $params['cache']; $this->warningLimit = $params['warningLimit']; $this->setLogger(LoggerFactory::getInstance('throttler')); }
public function testGetLinkClasses() { $wanCache = ObjectCache::getMainWANInstance(); $titleFormatter = MediaWikiServices::getInstance()->getTitleFormatter(); $linkCache = new LinkCache($titleFormatter, $wanCache); $foobarTitle = new TitleValue(NS_MAIN, 'FooBar'); $redirectTitle = new TitleValue(NS_MAIN, 'Redirect'); $userTitle = new TitleValue(NS_USER, 'Someuser'); $linkCache->addGoodLinkObj(1, $foobarTitle, 10, 0); $linkCache->addGoodLinkObj(2, $redirectTitle, 10, 1); $linkCache->addGoodLinkObj(3, $userTitle, 10, 0); $linkRenderer = new LinkRenderer($titleFormatter, $linkCache); $linkRenderer->setStubThreshold(0); $this->assertEquals('', $linkRenderer->getLinkClasses($foobarTitle)); $linkRenderer->setStubThreshold(20); $this->assertEquals('stub', $linkRenderer->getLinkClasses($foobarTitle)); $linkRenderer->setStubThreshold(0); $this->assertEquals('mw-redirect', $linkRenderer->getLinkClasses($redirectTitle)); $linkRenderer->setStubThreshold(20); $this->assertEquals('', $linkRenderer->getLinkClasses($userTitle)); }
/** * Attempt to load a precomputed document tree for some given wikitext * from the cache. * * @param string $text * @param int $flags * @return PPNode_Hash_Tree|bool */ protected function cacheGetTree($text, $flags) { $config = RequestContext::getMain()->getConfig(); $length = strlen($text); $threshold = $config->get('PreprocessorCacheThreshold'); if ($threshold === false || $length < $threshold || $length > 1000000.0) { return false; } $cache = ObjectCache::getInstance($config->get('MainCacheType')); $key = wfMemcKey(defined('static::CACHE_PREFIX') ? static::CACHE_PREFIX : get_called_class(), md5($text), $flags); $value = $cache->get($key); if (!$value) { return false; } $version = intval(substr($value, 0, 8)); if ($version !== static::CACHE_VERSION) { return false; } LoggerFactory::getInstance('Preprocessor')->info("Loaded preprocessor output from cache (key: {$key})"); return substr($value, 8); }
private function buildMinifiedCSS() { $siteObject = Site::getInstance(); $minifiedSoFar = ""; $themesCssFiles = glob(EDUCASK_ROOT . "/site/themes/{$siteObject->getTheme()}/css/*.css"); foreach ($themesCssFiles as $cssFile) { if (!is_readable($cssFile)) { continue; } $rawFile = file_get_contents($cssFile); $rawFile = $this->minifyCssString($rawFile); $minifiedSoFar .= $rawFile; } $minifiedSoFar .= $this->getOtherCssFiles(); $minifiedSoFar .= $this->getRawCss(); $objectCache = ObjectCache::getInstance(); $objectCache->setObject('minifiedCSS', $minifiedSoFar, true); $response = Response::fiveHundred(); $response->setRawContent($minifiedSoFar); $response->setHeader('Content-Type', "text/css"); $response->setResponseCode(200); return $response; }
/** * Construct a new instance from configuration. * * $config paramaters include: * - lockServers : Associative array of server names to "<IP>:<port>" strings. * - srvsByBucket : Array of 1-16 consecutive integer keys, starting from 0, * each having an odd-numbered list of server names (peers) as values. * - memcConfig : Configuration array for ObjectCache::newFromParams. [optional] * If set, this must use one of the memcached classes. * - wikiId : Wiki ID string that all resources are relative to. [optional] * * @param Array $config */ public function __construct(array $config) { parent::__construct($config); // Sanitize srvsByBucket config to prevent PHP errors $this->srvsByBucket = array_filter($config['srvsByBucket'], 'is_array'); $this->srvsByBucket = array_values($this->srvsByBucket); // consecutive $memcConfig = isset($config['memcConfig']) ? $config['memcConfig'] : array('class' => 'MemcachedPhpBagOStuff'); foreach ($config['lockServers'] as $name => $address) { $params = array('servers' => array($address)) + $memcConfig; $cache = ObjectCache::newFromParams($params); if ($cache instanceof MemcachedBagOStuff) { $this->bagOStuffs[$name] = $cache; } else { throw new MWException('Only MemcachedBagOStuff classes are supported by MemcLockManager.'); } } $this->wikiId = isset($config['wikiId']) ? $config['wikiId'] : wfWikiID(); $met = ini_get('max_execution_time'); // this is 0 in CLI mode $this->lockExpiry = $met ? 2 * (int) $met : 2 * 3600; $this->session = wfRandomString(32); }
/** * Auto-create the given user, if necessary * @private Don't call this yourself. Let Setup.php do it for you at the right time. * @note This more properly belongs in AuthManager, but we need it now. * When AuthManager comes, this will be deprecated and will pass-through * to the corresponding AuthManager method. * @param User $user User to auto-create * @return bool Success */ public static function autoCreateUser(User $user) { global $wgAuth; $logger = self::singleton()->logger; // Much of this code is based on that in CentralAuth // Try the local user from the slave DB $localId = User::idFromName($user->getName()); // Fetch the user ID from the master, so that we don't try to create the user // when they already exist, due to replication lag // @codeCoverageIgnoreStart if (!$localId && wfGetLB()->getReaderIndex() != 0) { $localId = User::idFromName($user->getName(), User::READ_LATEST); } // @codeCoverageIgnoreEnd if ($localId) { // User exists after all. $user->setId($localId); $user->loadFromId(); return false; } // Denied by AuthPlugin? But ignore AuthPlugin itself. if (get_class($wgAuth) !== 'AuthPlugin' && !$wgAuth->autoCreate()) { $logger->debug(__METHOD__ . ': denied by AuthPlugin'); $user->setId(0); $user->loadFromId(); return false; } // Wiki is read-only? if (wfReadOnly()) { $logger->debug(__METHOD__ . ': denied by wfReadOnly()'); $user->setId(0); $user->loadFromId(); return false; } $userName = $user->getName(); // Check the session, if we tried to create this user already there's // no point in retrying. $session = self::getGlobalSession(); $reason = $session->get('MWSession::AutoCreateBlacklist'); if ($reason) { $logger->debug(__METHOD__ . ": blacklisted in session ({$reason})"); $user->setId(0); $user->loadFromId(); return false; } // Is the IP user able to create accounts? $anon = new User(); if (!$anon->isAllowedAny('createaccount', 'autocreateaccount') || $anon->isBlockedFromCreateAccount()) { // Blacklist the user to avoid repeated DB queries subsequently $logger->debug(__METHOD__ . ': user is blocked from this wiki, blacklisting'); $session->set('MWSession::AutoCreateBlacklist', 'blocked', 600); $session->persist(); $user->setId(0); $user->loadFromId(); return false; } // Check for validity of username if (!User::isCreatableName($userName)) { $logger->debug(__METHOD__ . ': Invalid username, blacklisting'); $session->set('MWSession::AutoCreateBlacklist', 'invalid username', 600); $session->persist(); $user->setId(0); $user->loadFromId(); return false; } // Give other extensions a chance to stop auto creation. $user->loadDefaults($userName); $abortMessage = ''; if (!\Hooks::run('AbortAutoAccount', array($user, &$abortMessage))) { // In this case we have no way to return the message to the user, // but we can log it. $logger->debug(__METHOD__ . ": denied by hook: {$abortMessage}"); $session->set('MWSession::AutoCreateBlacklist', "hook aborted: {$abortMessage}", 600); $session->persist(); $user->setId(0); $user->loadFromId(); return false; } // Make sure the name has not been changed if ($user->getName() !== $userName) { $user->setId(0); $user->loadFromId(); throw new \UnexpectedValueException('AbortAutoAccount hook tried to change the user name'); } // Ignore warnings about master connections/writes...hard to avoid here \Profiler::instance()->getTransactionProfiler()->resetExpectations(); $cache = \ObjectCache::getLocalClusterInstance(); $backoffKey = wfMemcKey('MWSession', 'autocreate-failed', md5($userName)); if ($cache->get($backoffKey)) { $logger->debug(__METHOD__ . ': denied by prior creation attempt failures'); $user->setId(0); $user->loadFromId(); return false; } // Checks passed, create the user... $from = isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : 'CLI'; $logger->info(__METHOD__ . ": creating new user ({$userName}) - from: {$from}"); try { // Insert the user into the local DB master $status = $user->addToDatabase(); if (!$status->isOK()) { // @codeCoverageIgnoreStart $logger->error(__METHOD__ . ': failed with message ' . $status->getWikiText()); $user->setId(0); $user->loadFromId(); return false; // @codeCoverageIgnoreEnd } } catch (\Exception $ex) { // @codeCoverageIgnoreStart $logger->error(__METHOD__ . ': failed with exception ' . $ex->getMessage()); // Do not keep throwing errors for a while $cache->set($backoffKey, 1, 600); // Bubble up error; which should normally trigger DB rollbacks throw $ex; // @codeCoverageIgnoreEnd } # Notify hooks (e.g. Newuserlog) \Hooks::run('AuthPluginAutoCreate', array($user)); \Hooks::run('LocalUserCreated', array($user, true)); # Notify AuthPlugin too $tmpUser = $user; $wgAuth->initUser($tmpUser, true); if ($tmpUser !== $user) { $logger->warning(__METHOD__ . ': ' . get_class($wgAuth) . '::initUser() replaced the user object'); } $user->saveSettings(); # Update user count \DeferredUpdates::addUpdate(new \SiteStatsUpdate(0, 0, 0, 0, 1)); # Watch user's userpage and talk page $user->addWatch($user->getUserPage(), \WatchedItem::IGNORE_USER_RIGHTS); return true; }
/** * Get the backend object with a given name * * @param string $name * @return FileBackend * @throws FileBackendException */ public function get($name) { if (!isset($this->backends[$name])) { throw new FileBackendException("No backend defined with the name `{$name}`."); } // Lazy-load the actual backend instance if (!isset($this->backends[$name]['instance'])) { $class = $this->backends[$name]['class']; $config = $this->backends[$name]['config']; $config['wikiId'] = isset($config['wikiId']) ? $config['wikiId'] : wfWikiID(); // e.g. "my_wiki-en_" $config['lockManager'] = LockManagerGroup::singleton($config['wikiId'])->get($config['lockManager']); $config['fileJournal'] = isset($config['fileJournal']) ? FileJournal::factory($config['fileJournal'], $name) : FileJournal::factory(array('class' => 'NullFileJournal'), $name); $config['wanCache'] = ObjectCache::getMainWANInstance(); $this->backends[$name]['instance'] = new $class($config); } return $this->backends[$name]['instance']; }
/** * Load conversion tables either from the cache or the disk. * @private * @param bool $fromCache Load from memcached? Defaults to true. */ function loadTables($fromCache = true) { global $wgLanguageConverterCacheType; if ($this->mTablesLoaded) { return; } $this->mTablesLoaded = true; $this->mTables = false; $cache = ObjectCache::getInstance($wgLanguageConverterCacheType); if ($fromCache) { wfProfileIn(__METHOD__ . '-cache'); $this->mTables = $cache->get($this->mCacheKey); wfProfileOut(__METHOD__ . '-cache'); } if (!$this->mTables || !array_key_exists(self::CACHE_VERSION_KEY, $this->mTables)) { wfProfileIn(__METHOD__ . '-recache'); // not in cache, or we need a fresh reload. // We will first load the default tables // then update them using things in MediaWiki:Conversiontable/* $this->loadDefaultTables(); foreach ($this->mVariants as $var) { $cached = $this->parseCachedTable($var); $this->mTables[$var]->mergeArray($cached); } $this->postLoadTables(); $this->mTables[self::CACHE_VERSION_KEY] = true; $cache->set($this->mCacheKey, $this->mTables, 43200); wfProfileOut(__METHOD__ . '-recache'); } }