Exemple #1
0
 function getLagTimes($serverIndexes, $wiki)
 {
     wfProfileIn(__METHOD__);
     $expiry = 5;
     $requestRate = 10;
     global $wgMemc;
     if (empty($wgMemc)) {
         $wgMemc = wfGetMainCache();
     }
     $masterName = $this->parent->getServerName(0);
     $memcKey = wfMemcKey('lag_times', $masterName);
     $times = $wgMemc->get($memcKey);
     if ($times) {
         # Randomly recache with probability rising over $expiry
         $elapsed = time() - $times['timestamp'];
         $chance = max(0, ($expiry - $elapsed) * $requestRate);
         if (mt_rand(0, $chance) != 0) {
             unset($times['timestamp']);
             wfProfileOut(__METHOD__);
             return $times;
         }
         wfIncrStats('lag_cache_miss_expired');
     } else {
         wfIncrStats('lag_cache_miss_absent');
     }
     # Cache key missing or expired
     $times = array();
     foreach ($serverIndexes as $i) {
         if ($i == 0) {
             # Master
             $times[$i] = 0;
         } elseif (false !== ($conn = $this->parent->getAnyOpenConnection($i))) {
             $times[$i] = $conn->getLag();
         } elseif (false !== ($conn = $this->parent->openConnection($i, $wiki))) {
             $times[$i] = $conn->getLag();
         }
     }
     # Add a timestamp key so we know when it was cached
     $times['timestamp'] = time();
     $wgMemc->set($memcKey, $times, $expiry);
     # But don't give the timestamp to the caller
     unset($times['timestamp']);
     $lagTimes = $times;
     wfProfileOut(__METHOD__);
     return $lagTimes;
 }
Exemple #2
0
 function get(&$article, &$user)
 {
     global $wgCacheEpoch;
     $fname = 'ParserCache::get';
     wfProfileIn($fname);
     $key = $this->getKey($article, $user);
     wfDebug("Trying parser cache {$key}\n");
     $value = $this->mMemc->get($key);
     if (is_object($value)) {
         wfDebug("Found.\n");
         # Delete if article has changed since the cache was made
         $canCache = $article->checkTouched();
         $cacheTime = $value->getCacheTime();
         $touched = $article->mTouched;
         if (!$canCache || $value->expired($touched)) {
             if (!$canCache) {
                 wfIncrStats("pcache_miss_invalid");
                 wfDebug("Invalid cached redirect, touched {$touched}, epoch {$wgCacheEpoch}, cached {$cacheTime}\n");
             } else {
                 wfIncrStats("pcache_miss_expired");
                 wfDebug("Key expired, touched {$touched}, epoch {$wgCacheEpoch}, cached {$cacheTime}\n");
             }
             $this->mMemc->delete($key);
             $value = false;
         } else {
             if (isset($value->mTimestamp)) {
                 $article->mTimestamp = $value->mTimestamp;
             }
             wfIncrStats("pcache_hit");
         }
     } else {
         wfDebug("Parser cache miss.\n");
         wfIncrStats("pcache_miss_absent");
         $value = false;
     }
     wfProfileOut($fname);
     return $value;
 }
Exemple #3
0
 /**
  * Try to load file metadata from memcached. Returns true on success.
  * @return bool
  */
 function loadFromCache()
 {
     $this->dataLoaded = false;
     $this->extraDataLoaded = false;
     $key = $this->getCacheKey();
     if (!$key) {
         return false;
     }
     $cache = ObjectCache::getMainWANInstance();
     $cachedValues = $cache->get($key);
     // Check if the key existed and belongs to this version of MediaWiki
     if (is_array($cachedValues) && $cachedValues['version'] == MW_FILE_VERSION) {
         $this->fileExists = $cachedValues['fileExists'];
         if ($this->fileExists) {
             $this->setProps($cachedValues);
         }
         $this->dataLoaded = true;
         $this->extraDataLoaded = true;
         foreach ($this->getLazyCacheFields('') as $field) {
             $this->extraDataLoaded = $this->extraDataLoaded && isset($cachedValues[$field]);
         }
     }
     if ($this->dataLoaded) {
         wfIncrStats('image_cache.hit');
     } else {
         wfIncrStats('image_cache.miss');
     }
     return $this->dataLoaded;
 }
Exemple #4
0
 /**
  * Remove jobs in the job queue which are duplicates of this job.
  * This is deadlock-prone and so starts its own transaction.
  */
 function removeDuplicates()
 {
     if (!$this->removeDuplicates) {
         return;
     }
     $fields = $this->insertFields();
     unset($fields['job_id']);
     $dbw = wfGetDB(DB_MASTER);
     $dbw->begin(__METHOD__);
     $dbw->delete('job', $fields, __METHOD__);
     $affected = $dbw->affectedRows();
     $dbw->commit(__METHOD__);
     if ($affected) {
         wfIncrStats('job-dup-delete', $affected);
     }
 }
Exemple #5
0
 public function addWikiTextTitle($text, &$title, $linestart, $tidy = false)
 {
     global $wgParser;
     wfProfileIn(__METHOD__);
     wfIncrStats('pcache_not_possible');
     $popts = $this->parserOptions();
     $oldTidy = $popts->setTidy($tidy);
     $parserOutput = $wgParser->parse($text, $title, $popts, $linestart, true, $this->mRevisionId);
     $popts->setTidy($oldTidy);
     $this->addParserOutput($parserOutput);
     wfProfileOut(__METHOD__);
 }
Exemple #6
0
 /**
  * Get a ParserOutput for the given ParserOptions and revision ID.
  *
  * The parser cache will be used if possible. Cache misses that result
  * in parser runs are debounced with PoolCounter.
  *
  * @since 1.19
  * @param ParserOptions $parserOptions ParserOptions to use for the parse operation
  * @param null|int      $oldid Revision ID to get the text from, passing null or 0 will
  *                             get the current revision (default value)
  * @param bool          $forceParse Force reindexing, regardless of cache settings
  * @return bool|ParserOutput ParserOutput or false if the revision was not found
  */
 public function getParserOutput(ParserOptions $parserOptions, $oldid = null, $forceParse = false)
 {
     $useParserCache = !$forceParse && $this->shouldCheckParserCache($parserOptions, $oldid);
     wfDebug(__METHOD__ . ': using parser cache: ' . ($useParserCache ? 'yes' : 'no') . "\n");
     if ($parserOptions->getStubThreshold()) {
         wfIncrStats('pcache.miss.stub');
     }
     if ($useParserCache) {
         $parserOutput = ParserCache::singleton()->get($this, $parserOptions);
         if ($parserOutput !== false) {
             return $parserOutput;
         }
     }
     if ($oldid === null || $oldid === 0) {
         $oldid = $this->getLatest();
     }
     $pool = new PoolWorkArticleView($this, $parserOptions, $oldid, $useParserCache);
     $pool->execute();
     return $pool->getParserOutput();
 }
Exemple #7
0
 function addWikiTextTitle($text, &$title, $linestart)
 {
     global $wgParser;
     $fname = 'OutputPage:addWikiTextTitle';
     wfProfileIn($fname);
     wfIncrStats('pcache_not_possible');
     $parserOutput = $wgParser->parse($text, $title, $this->parserOptions(), $linestart, true, $this->mRevisionId);
     $this->addParserOutput($parserOutput);
     wfProfileOut($fname);
 }
Exemple #8
0
 /**
  * Retrieve the ParserOutput from ParserCache.
  * false if not found or outdated.
  *
  * @param WikiPage|Article $article
  * @param ParserOptions $popts
  * @param bool $useOutdated (default false)
  *
  * @return ParserOutput|bool False on failure
  */
 public function get($article, $popts, $useOutdated = false)
 {
     global $wgCacheEpoch;
     $canCache = $article->checkTouched();
     if (!$canCache) {
         // It's a redirect now
         return false;
     }
     $touched = $article->getTouched();
     $parserOutputKey = $this->getKey($article, $popts, $useOutdated);
     if ($parserOutputKey === false) {
         wfIncrStats('pcache.miss.absent');
         return false;
     }
     $value = $this->mMemc->get($parserOutputKey);
     if (!$value) {
         wfDebug("ParserOutput cache miss.\n");
         wfIncrStats("pcache.miss.absent");
         return false;
     }
     wfDebug("ParserOutput cache found.\n");
     // The edit section preference may not be the appropiate one in
     // the ParserOutput, as we are not storing it in the parsercache
     // key. Force it here. See bug 31445.
     $value->setEditSectionTokens($popts->getEditSection());
     $wikiPage = method_exists($article, 'getPage') ? $article->getPage() : $article;
     if (!$useOutdated && $value->expired($touched)) {
         wfIncrStats("pcache.miss.expired");
         $cacheTime = $value->getCacheTime();
         wfDebug("ParserOutput key expired, touched {$touched}, " . "epoch {$wgCacheEpoch}, cached {$cacheTime}\n");
         $value = false;
     } elseif ($value->isDifferentRevision($article->getLatest())) {
         wfIncrStats("pcache.miss.revid");
         $revId = $article->getLatest();
         $cachedRevId = $value->getCacheRevisionId();
         wfDebug("ParserOutput key is for an old revision, latest {$revId}, cached {$cachedRevId}\n");
         $value = false;
     } elseif (Hooks::run('RejectParserCacheValue', array($value, $wikiPage, $popts)) === false) {
         wfIncrStats('pcache.miss.rejected');
         wfDebug("ParserOutput key valid, but rejected by RejectParserCacheValue hook handler.\n");
         $value = false;
     } else {
         wfIncrStats("pcache.hit");
     }
     return $value;
 }
Exemple #9
0
 /**
  * Lightweight method to get the parser output for a page, checking the parser cache
  * and so on. Doesn't consider most of the stuff that Article::view is forced to
  * consider, so it's not appropriate to use there.
  *
  * @since 1.16 (r52326) for LiquidThreads
  * 
  * @param $oldid mixed integer Revision ID or null
  */
 public function getParserOutput($oldid = null)
 {
     global $wgEnableParserCache, $wgUser;
     // Should the parser cache be used?
     $useParserCache = $wgEnableParserCache && $wgUser->getStubThreshold() == 0 && $this->exists() && $oldid === null;
     wfDebug(__METHOD__ . ': using parser cache: ' . ($useParserCache ? 'yes' : 'no') . "\n");
     if ($wgUser->getStubThreshold()) {
         wfIncrStats('pcache_miss_stub');
     }
     $parserOutput = false;
     if ($useParserCache) {
         $parserOutput = ParserCache::singleton()->get($this, $this->getParserOptions());
     }
     if ($parserOutput === false) {
         // Cache miss; parse and output it.
         $rev = Revision::newFromTitle($this->getTitle(), $oldid);
         return $this->getOutputFromWikitext($rev->getText(), $useParserCache);
     } else {
         return $parserOutput;
     }
 }
Exemple #10
0
 /**
  * Get the diff table body, without header
  *
  * @return mixed
  */
 function getDiffBody()
 {
     global $wgMemc;
     $fname = 'DifferenceEngine::getDiffBody';
     wfProfileIn($fname);
     // Cacheable?
     $key = false;
     if ($this->mOldid && $this->mNewid) {
         $key = wfMemcKey('diff', 'version', MW_DIFF_VERSION, 'oldid', $this->mOldid, 'newid', $this->mNewid);
         // Try cache
         if (!$this->mRefreshCache) {
             $difftext = $wgMemc->get($key);
             if ($difftext) {
                 wfIncrStats('diff_cache_hit');
                 $difftext = $this->localiseLineNumbers($difftext);
                 $difftext .= "\n<!-- diff cache key {$key} -->\n";
                 wfProfileOut($fname);
                 return $difftext;
             }
         }
         // don't try to load but save the result
     } else {
     }
     // Loadtext is permission safe, this just clears out the diff
     if (!$this->loadText()) {
         wfProfileOut($fname);
         return false;
     } else {
         if ($this->mOldRev && !$this->mOldRev->userCan(Revision::DELETED_TEXT)) {
             return '';
         } else {
             if ($this->mNewRev && !$this->mNewRev->userCan(Revision::DELETED_TEXT)) {
                 return '';
             }
         }
     }
     $difftext = $this->generateDiffBody($this->mOldtext, $this->mNewtext);
     // Save to cache for 7 days
     // Only do this for public revs, otherwise an admin can view the diff and a non-admin can nab it!
     if ($this->mOldRev && $this->mOldRev->isDeleted(Revision::DELETED_TEXT)) {
         wfIncrStats('diff_uncacheable');
     } else {
         if ($this->mNewRev && $this->mNewRev->isDeleted(Revision::DELETED_TEXT)) {
             wfIncrStats('diff_uncacheable');
         } else {
             if ($key !== false && $difftext !== false) {
                 wfIncrStats('diff_cache_miss');
                 $wgMemc->set($key, $difftext, 7 * 86400);
             } else {
                 wfIncrStats('diff_uncacheable');
             }
         }
     }
     // Replace line numbers with the text in the user's language
     if ($difftext !== false) {
         $difftext = $this->localiseLineNumbers($difftext);
     }
     wfProfileOut($fname);
     return $difftext;
 }
Exemple #11
0
 /**
  * Try to load video metadata from memcached.
  * @return Boolean: true on success.
  */
 private function loadFromCache()
 {
     global $wgMemc;
     wfProfileIn(__METHOD__);
     $this->dataLoaded = false;
     $key = $this->getCacheKey();
     $data = $wgMemc->get($key);
     if (!empty($data) && is_array($data)) {
         $this->url = $data['url'];
         $this->type = $data['type'];
         $this->submitter_user_id = $data['user_id'];
         $this->submitter_user_name = $data['user_name'];
         $this->create_date = $data['create_date'];
         $this->dataLoaded = true;
         $this->exists = true;
     }
     if ($this->dataLoaded) {
         wfDebug("Loaded Video:{$this->name} from cache\n");
         wfIncrStats('video_cache_hit');
     } else {
         wfIncrStats('video_cache_miss');
     }
     wfProfileOut(__METHOD__);
     return $this->dataLoaded;
 }
Exemple #12
0
 /**
  * Retrieve the ParserOutput from ParserCache.
  * false if not found or outdated.
  *
  * @param Article $article
  * @param ParserOptions $popts
  * @param bool $useOutdated (default false)
  *
  * @return ParserOutput|bool False on failure
  */
 public function get($article, $popts, $useOutdated = false)
 {
     global $wgCacheEpoch;
     wfProfileIn(__METHOD__);
     $canCache = $article->checkTouched();
     if (!$canCache) {
         // It's a redirect now
         wfProfileOut(__METHOD__);
         return false;
     }
     $touched = $article->getTouched();
     $parserOutputKey = $this->getKey($article, $popts, $useOutdated);
     if ($parserOutputKey === false) {
         wfIncrStats('pcache_miss_absent');
         wfProfileOut(__METHOD__);
         return false;
     }
     $value = $this->mMemc->get($parserOutputKey);
     if (!$value) {
         wfDebug("ParserOutput cache miss.\n");
         wfIncrStats("pcache_miss_absent");
         wfProfileOut(__METHOD__);
         return false;
     }
     wfDebug("ParserOutput cache found.\n");
     // The edit section preference may not be the appropiate one in
     // the ParserOutput, as we are not storing it in the parsercache
     // key. Force it here. See bug 31445.
     $value->setEditSectionTokens($popts->getEditSection());
     if (!$useOutdated && $value->expired($touched)) {
         wfIncrStats("pcache_miss_expired");
         $cacheTime = $value->getCacheTime();
         wfDebug("ParserOutput key expired, touched {$touched}, " . "epoch {$wgCacheEpoch}, cached {$cacheTime}\n");
         $value = false;
     } elseif ($value->isDifferentRevision($article->getLatest())) {
         wfIncrStats("pcache_miss_revid");
         $revId = $article->getLatest();
         $cachedRevId = $value->getCacheRevisionId();
         wfDebug("ParserOutput key is for an old revision, latest {$revId}, cached {$cachedRevId}\n");
         $value = false;
     } else {
         wfIncrStats("pcache_hit");
     }
     wfProfileOut(__METHOD__);
     return $value;
 }
 /**
  * Retrieve the ParserOutput from ParserCache.
  * false if not found or outdated.
  *
  * @param $article Article
  * @param $popts ParserOptions
  * @param $useOutdated
  *
  * @return ParserOutput|false
  */
 public function get($article, $popts, $useOutdated = false)
 {
     global $wgCacheEpoch;
     wfProfileIn(__METHOD__);
     $canCache = $article->checkTouched();
     if (!$canCache) {
         // It's a redirect now
         wfProfileOut(__METHOD__);
         return false;
     }
     $touched = $article->getTouched();
     $parserOutputKey = $this->getKey($article, $popts, $useOutdated);
     if ($parserOutputKey === false) {
         wfIncrStats('pcache_miss_absent');
         wfProfileOut(__METHOD__);
         return false;
     }
     $value = $this->mMemc->get($parserOutputKey);
     if (self::try116cache && !$value && strpos($value, '*') !== -1) {
         wfDebug("New format parser cache miss.\n");
         $parserOutputKey = $this->getParserOutputKey($article, $popts->optionsHash(ParserOptions::legacyOptions(), $article->getTitle()));
         $value = $this->mMemc->get($parserOutputKey);
     }
     if (!$value) {
         wfDebug("ParserOutput cache miss.\n");
         wfIncrStats("pcache_miss_absent");
         wfProfileOut(__METHOD__);
         return false;
     }
     wfDebug("ParserOutput cache found.\n");
     // The edit section preference may not be the appropiate one in
     // the ParserOutput, as we are not storing it in the parsercache
     // key. Force it here. See bug 31445.
     $value->setEditSectionTokens($popts->getEditSection());
     if (!$useOutdated && $value->expired($touched)) {
         wfIncrStats("pcache_miss_expired");
         $cacheTime = $value->getCacheTime();
         wfDebug("ParserOutput key expired, touched {$touched}, epoch {$wgCacheEpoch}, cached {$cacheTime}\n");
         $value = false;
     } else {
         wfIncrStats("pcache_hit");
     }
     wfProfileOut(__METHOD__);
     return $value;
 }
 /**
  * @param $out OutputPage
  * @param $text String
  * @return bool
  */
 public function beforePageDisplayHTML(&$out, &$text)
 {
     global $wgContLang, $wgRequest, $wgMemc, $wgUser;
     wfProfileIn(__METHOD__);
     $userAgent = $_SERVER['HTTP_USER_AGENT'];
     $acceptHeader = isset($_SERVER["HTTP_ACCEPT"]) ? $_SERVER["HTTP_ACCEPT"] : '';
     $uAmd5 = md5($userAgent);
     $key = wfMemcKey('mobile', 'ua', $uAmd5);
     $props = null;
     try {
         $props = $wgMemc->get($key);
         if (!$props) {
             $wurflConfigFile = RESOURCES_DIR . 'wurfl-config.xml';
             $wurflConfig = new WURFL_Configuration_XmlConfig($wurflConfigFile);
             $wurflManagerFactory = new WURFL_WURFLManagerFactory($wurflConfig);
             $wurflManager = $wurflManagerFactory->create();
             $device = $wurflManager->getDeviceForHttpRequest($_SERVER);
             if ($device->isSpecific() === true) {
                 $props = $device->getAllCapabilities();
                 $wgMemc->set($key, $props, 86400);
             } else {
                 $wgMemc->set($key, 'generic', 86400);
                 $props = 'generic';
             }
         }
     } catch (Exception $e) {
         // echo $e->getMessage();
     }
     // Note: The WebRequest Class calls are made in this block because
     // since PHP 5.1.x, all objects have their destructors called
     // before the output buffer callback function executes.
     // Thus, globalized objects will not be available as expected in the function.
     // This is stated to be intended behavior, as per the following: [http://bugs.php.net/bug.php?id=40104]
     $xDevice = isset($_SERVER['HTTP_X_DEVICE']) ? $_SERVER['HTTP_X_DEVICE'] : '';
     self::$useFormat = $wgRequest->getText('useformat');
     $mobileAction = $wgRequest->getText('mobileaction');
     $action = $wgRequest->getText('action');
     if (self::$useFormat !== 'mobile' && self::$useFormat !== 'mobile-wap' && !$xDevice) {
         wfProfileOut(__METHOD__);
         return true;
     }
     if ($action === 'edit' || $mobileAction === 'view_normal_site') {
         wfProfileOut(__METHOD__);
         return true;
     }
     self::$title = $out->getTitle();
     if (self::$title->isMainPage()) {
         self::$isMainPage = true;
     }
     if (self::$title->getNamespace() == NS_FILE) {
         self::$isFilePage = true;
     }
     self::$htmlTitle = $out->getHTMLTitle();
     self::$disableImages = $wgRequest->getText('disableImages', 0);
     self::$enableImages = $wgRequest->getText('enableImages', 0);
     self::$displayNoticeId = $wgRequest->getText('noticeid', '');
     if (self::$disableImages == 1) {
         $wgRequest->response()->setcookie('disableImages', 1);
         $location = str_replace('?disableImages=1', '', str_replace('&disableImages=1', '', $wgRequest->getFullRequestURL()));
         $location = str_replace('&mfi=1', '', str_replace('&mfi=0', '', $location));
         $location = $this->getRelativeURL($location);
         $wgRequest->response()->header('Location: ' . $location . '&mfi=0');
     } elseif (self::$disableImages == 0) {
         $disableImages = $wgRequest->getCookie('disableImages');
         if ($disableImages) {
             self::$disableImages = $disableImages;
         }
     }
     if (self::$enableImages == 1) {
         $disableImages = $wgRequest->getCookie('disableImages');
         if ($disableImages) {
             $wgRequest->response()->setcookie('disableImages', '');
         }
         $location = str_replace('?enableImages=1', '', str_replace('&enableImages=1', '', $wgRequest->getFullRequestURL()));
         $location = str_replace('&mfi=1', '', str_replace('&mfi=0', '', $location));
         $location = $this->getRelativeURL($location);
         $wgRequest->response()->header('Location: ' . $location . '&mfi=1');
     }
     self::$format = $wgRequest->getText('format');
     self::$callback = $wgRequest->getText('callback');
     self::$requestedSegment = $wgRequest->getText('seg', 0);
     self::$search = $wgRequest->getText('search');
     self::$searchField = $wgRequest->getText('search', '');
     $device = new DeviceDetection();
     if ($xDevice) {
         $formatName = $xDevice;
     } else {
         $formatName = $device->formatName($userAgent, $acceptHeader);
     }
     self::$device = $device->format($formatName);
     if (self::$device['view_format'] === 'wml') {
         $this->contentFormat = 'WML';
     } elseif (self::$device['view_format'] === 'html') {
         $this->contentFormat = 'XHTML';
     }
     if (self::$useFormat === 'mobile-wap') {
         $this->contentFormat = 'WML';
     }
     if ($mobileAction == 'leave_feedback') {
         echo $this->renderLeaveFeedbackXHTML();
         wfProfileOut(__METHOD__);
         exit;
     }
     if ($mobileAction == 'leave_feedback_post') {
         $this->getMsg();
         $subject = $wgRequest->getText('subject', '');
         $message = $wgRequest->getText('message', '');
         $token = $wgRequest->getText('edittoken', '');
         $title = Title::newFromText(self::$messages['mobile-frontend-feedback-page']);
         if ($title->userCan('edit') && !$wgUser->isBlockedFrom($title) && $wgUser->matchEditToken($token)) {
             $article = new Article($title, 0);
             $rawtext = $article->getRawText();
             $rawtext .= "\n== {$subject} == \n {$message} ~~~~ \n <small>User agent: {$userAgent}</small> ";
             $article->doEdit($rawtext, '');
         }
         $location = str_replace('&mobileaction=leave_feedback_post', '', $wgRequest->getFullRequestURL() . '&noticeid=1&useformat=mobile');
         $location = $this->getRelativeURL($location);
         $wgRequest->response()->header('Location: ' . $location);
         wfProfileOut(__METHOD__);
         exit;
     }
     if ($mobileAction == 'disable_mobile_site' && $this->contentFormat == 'XHTML') {
         echo $this->renderDisableMobileSiteXHTML();
         wfProfileOut(__METHOD__);
         exit;
     }
     if ($mobileAction == 'opt_in_mobile_site' && $this->contentFormat == 'XHTML') {
         echo $this->renderOptInMobileSiteXHTML();
         wfProfileOut(__METHOD__);
         exit;
     }
     if ($mobileAction == 'opt_out_mobile_site' && $this->contentFormat == 'XHTML') {
         echo $this->renderOptOutMobileSiteXHTML();
         wfProfileOut(__METHOD__);
         exit;
     }
     if ($mobileAction == 'opt_in_cookie') {
         wfIncrStats('mobile.opt_in_cookie_set');
         $this->setOptInOutCookie('1');
         $this->disableCaching();
         $location = wfExpandUrl(Title::newMainPage()->getFullURL(), PROTO_CURRENT);
         $wgRequest->response()->header('Location: ' . $location);
     }
     if ($mobileAction == 'opt_out_cookie') {
         $this->setOptInOutCookie('');
     }
     $this->getMsg();
     $this->disableCaching();
     $this->sendXDeviceVaryHeader();
     $this->sendApplicationVersionVaryHeader();
     $this->checkUserStatus();
     $this->checkUserLoggedIn();
     if (self::$title->isSpecial('Userlogin') && self::$isBetaGroupMember) {
         self::$wsLoginToken = $wgRequest->getSessionData('wsLoginToken');
         $q = array('action' => 'submitlogin', 'type' => 'login');
         $returnToVal = $wgRequest->getVal('returnto');
         if ($returnToVal) {
             $q['returnto'] = $returnToVal;
         }
         self::$wsLoginFormAction = self::$title->getLocalURL($q);
     }
     $this->setDefaultLogo();
     ob_start(array($this, 'DOMParse'));
     wfProfileOut(__METHOD__);
     return true;
 }
Exemple #15
0
 /**
  * Get lag time for each DB
  * Results are cached for a short time in memcached
  */
 function getLagTimes()
 {
     wfProfileIn(__METHOD__);
     $expiry = 5;
     $requestRate = 10;
     global $wgMemc;
     $times = $wgMemc->get(wfMemcKey('lag_times'));
     if ($times) {
         # Randomly recache with probability rising over $expiry
         $elapsed = time() - $times['timestamp'];
         $chance = max(0, ($expiry - $elapsed) * $requestRate);
         if (mt_rand(0, $chance) != 0) {
             unset($times['timestamp']);
             wfProfileOut(__METHOD__);
             return $times;
         }
         wfIncrStats('lag_cache_miss_expired');
     } else {
         wfIncrStats('lag_cache_miss_absent');
     }
     # Cache key missing or expired
     $times = array();
     foreach ($this->mServers as $i => $conn) {
         if ($i == 0) {
             # Master
             $times[$i] = 0;
         } elseif ($this->openConnection($i)) {
             $times[$i] = $this->mConnections[$i]->getLag();
         }
     }
     # Add a timestamp key so we know when it was cached
     $times['timestamp'] = time();
     $wgMemc->set(wfMemcKey('lag_times'), $times, $expiry);
     # But don't give the timestamp to the caller
     unset($times['timestamp']);
     wfProfileOut(__METHOD__);
     return $times;
 }
 /**
  * Get data of requested article.
  * @param Title $title
  * @param boolean $noImages
  * @return array
  */
 private function getData(Title $title, $noImages)
 {
     global $wgMemc, $wgUseTidy, $wgMFTidyMobileViewSections, $wgMFMinCachedPageSize, $wgMFSpecialCaseMainPage;
     $wp = $this->makeWikiPage($title);
     if ($this->followRedirects && $wp->isRedirect()) {
         $newTitle = $wp->getRedirectTarget();
         if ($newTitle) {
             $title = $newTitle;
             $this->getResult()->addValue(null, $this->getModuleName(), array('redirected' => $title->getPrefixedText()));
             if ($title->getNamespace() < 0) {
                 $this->getResult()->addValue(null, $this->getModuleName(), array('viewable' => 'no'));
                 return array();
             }
             $wp = $this->makeWikiPage($title);
         }
     }
     $latest = $wp->getLatest();
     if ($this->file) {
         $key = wfMemcKey('mf', 'mobileview', self::CACHE_VERSION, $noImages, $latest, $this->noTransform, $this->file->getSha1(), $this->variant);
         $cacheExpiry = 3600;
     } else {
         if (!$latest) {
             // https://bugzilla.wikimedia.org/show_bug.cgi?id=53378
             // Title::exists() above doesn't seem to always catch recently deleted pages
             $this->dieUsageMsg(array('notanarticle', $title->getPrefixedText()));
         }
         $parserOptions = $this->makeParserOptions($wp);
         $parserCacheKey = ParserCache::singleton()->getKey($wp, $parserOptions);
         $key = wfMemcKey('mf', 'mobileview', self::CACHE_VERSION, $noImages, $latest, $this->noTransform, $parserCacheKey);
     }
     $data = $wgMemc->get($key);
     if ($data) {
         wfIncrStats('mobile.view.cache-hit');
         return $data;
     }
     wfIncrStats('mobile.view.cache-miss');
     if ($this->file) {
         $html = $this->getFilePage($title);
     } else {
         $parserOutput = $this->getParserOutput($wp, $parserOptions);
         $html = $parserOutput->getText();
         $cacheExpiry = $parserOutput->getCacheExpiry();
     }
     if (!$this->noTransform) {
         $mf = new MobileFormatter(MobileFormatter::wrapHTML($html), $title);
         $mf->setRemoveMedia($noImages);
         $mf->filterContent();
         $mf->setIsMainPage($this->mainPage && $wgMFSpecialCaseMainPage);
         $html = $mf->getText();
     }
     if ($this->mainPage || $this->file) {
         $data = array('sections' => array(), 'text' => array($html), 'refsections' => array());
     } else {
         $data = array();
         $data['sections'] = $parserOutput->getSections();
         $sectionCount = count($data['sections']);
         for ($i = 0; $i < $sectionCount; $i++) {
             $data['sections'][$i]['line'] = $title->getPageLanguage()->convert($data['sections'][$i]['line']);
         }
         $chunks = preg_split('/<h(?=[1-6]\\b)/i', $html);
         if (count($chunks) != count($data['sections']) + 1) {
             wfDebugLog('mobile', __METHOD__ . "(): mismatching number of " . "sections from parser and split on page {$title->getPrefixedText()}, oldid={$latest}");
             // We can't be sure about anything here, return all page HTML as one big section
             $chunks = array($html);
             $data['sections'] = array();
         }
         $data['text'] = array();
         $data['refsections'] = array();
         foreach ($chunks as $chunk) {
             if (count($data['text'])) {
                 $chunk = "<h{$chunk}";
             }
             if ($wgUseTidy && $wgMFTidyMobileViewSections && count($chunks) > 1) {
                 $chunk = MWTidy::tidy($chunk);
             }
             if (preg_match('/<ol\\b[^>]*?class="references"/', $chunk)) {
                 $data['refsections'][count($data['text'])] = true;
             }
             $data['text'][] = $chunk;
         }
         if ($this->usePageImages) {
             $image = $this->getPageImage($title);
             if ($image) {
                 $data['image'] = $image->getTitle()->getText();
             }
         }
     }
     $data['lastmodified'] = wfTimestamp(TS_ISO_8601, $wp->getTimestamp());
     // Page id
     $data['id'] = $wp->getId();
     $user = User::newFromId($wp->getUser());
     if (!$user->isAnon()) {
         $data['lastmodifiedby'] = array('name' => $wp->getUserText(), 'gender' => $user->getOption('gender'));
     } else {
         $data['lastmodifiedby'] = null;
     }
     $data['revision'] = $title->getLatestRevID();
     if (isset($parserOutput)) {
         $languages = $parserOutput->getLanguageLinks();
         $data['languagecount'] = count($languages);
         $data['displaytitle'] = $parserOutput->getDisplayTitle();
         // @fixme: Does no work for some extension properties that get added in LinksUpdate
         $data['pageprops'] = $parserOutput->getProperties();
     } else {
         $data['languagecount'] = 0;
         $data['displaytitle'] = $title->getPrefixedText();
         $data['pageprops'] = array();
     }
     if ($title->getPageLanguage()->hasVariants()) {
         $data['hasvariants'] = true;
     }
     // Don't store small pages to decrease cache size requirements
     if (strlen($html) >= $wgMFMinCachedPageSize) {
         // store for the same time as original parser output
         $wgMemc->set($key, $data, $cacheExpiry);
     }
     return $data;
 }
Exemple #17
0
 /**
  * Call wfIncrStats() for the queue overall and for the queue type
  *
  * @param string $key Event type
  * @param string $type Job type
  * @param int $delta
  * @param string $wiki Wiki ID (added in 1.23)
  * @since 1.22
  */
 public static function incrStats($key, $type, $delta = 1, $wiki = null)
 {
     wfIncrStats($key, $delta);
     wfIncrStats("{$key}-{$type}", $delta);
     if ($wiki !== null) {
         wfIncrStats("{$key}-{$type}-{$wiki}", $delta);
     }
 }
Exemple #18
0
 /**
  * This is the default action of the script: just view the page of
  * the given title.
  */
 function view()
 {
     global $wgUser, $wgOut, $wgRequest, $wgContLang;
     global $wgEnableParserCache, $wgStylePath, $wgUseRCPatrol, $wgParser;
     global $wgUseTrackbacks, $wgNamespaceRobotPolicies;
     $sk = $wgUser->getSkin();
     wfProfileIn(__METHOD__);
     $parserCache =& ParserCache::singleton();
     $ns = $this->mTitle->getNamespace();
     # shortcut
     # Get variables from query string
     $oldid = $this->getOldID();
     # getOldID may want us to redirect somewhere else
     if ($this->mRedirectUrl) {
         $wgOut->redirect($this->mRedirectUrl);
         wfProfileOut(__METHOD__);
         return;
     }
     $diff = $wgRequest->getVal('diff');
     $rcid = $wgRequest->getVal('rcid');
     $rdfrom = $wgRequest->getVal('rdfrom');
     $wgOut->setArticleFlag(true);
     if (isset($wgNamespaceRobotPolicies[$ns])) {
         $policy = $wgNamespaceRobotPolicies[$ns];
     } else {
         # The default policy. Dev note: make sure you change the documentation
         # in DefaultSettings.php before changing it.
         $policy = 'index,follow';
     }
     $wgOut->setRobotpolicy($policy);
     # If we got diff and oldid in the query, we want to see a
     # diff page instead of the article.
     if (!is_null($diff)) {
         $wgOut->setPageTitle($this->mTitle->getPrefixedText());
         $de = new DifferenceEngine($this->mTitle, $oldid, $diff, $rcid);
         // DifferenceEngine directly fetched the revision:
         $this->mRevIdFetched = $de->mNewid;
         $de->showDiffPage();
         // Needed to get the page's current revision
         $this->loadPageData();
         if ($diff == 0 || $diff == $this->mLatest) {
             # Run view updates for current revision only
             $this->viewUpdates();
         }
         wfProfileOut(__METHOD__);
         return;
     }
     if (empty($oldid) && $this->checkTouched()) {
         $wgOut->setETag($parserCache->getETag($this, $wgUser));
         if ($wgOut->checkLastModified($this->mTouched)) {
             wfProfileOut(__METHOD__);
             return;
         } else {
             if ($this->tryFileCache()) {
                 # tell wgOut that output is taken care of
                 $wgOut->disable();
                 $this->viewUpdates();
                 wfProfileOut(__METHOD__);
                 return;
             }
         }
     }
     # Should the parser cache be used?
     $pcache = $wgEnableParserCache && intval($wgUser->getOption('stubthreshold')) == 0 && $this->exists() && empty($oldid);
     wfDebug('Article::view using parser cache: ' . ($pcache ? 'yes' : 'no') . "\n");
     if ($wgUser->getOption('stubthreshold')) {
         wfIncrStats('pcache_miss_stub');
     }
     $wasRedirected = false;
     if (isset($this->mRedirectedFrom)) {
         // This is an internally redirected page view.
         // We'll need a backlink to the source page for navigation.
         if (wfRunHooks('ArticleViewRedirect', array(&$this))) {
             $sk = $wgUser->getSkin();
             $redir = $sk->makeKnownLinkObj($this->mRedirectedFrom, '', 'redirect=no');
             $s = wfMsg('redirectedfrom', $redir);
             $wgOut->setSubtitle($s);
             // Set the fragment if one was specified in the redirect
             if (strval($this->mTitle->getFragment()) != '') {
                 $fragment = Xml::escapeJsString($this->mTitle->getFragmentForURL());
                 $wgOut->addInlineScript("redirectToFragment(\"{$fragment}\");");
             }
             $wasRedirected = true;
         }
     } elseif (!empty($rdfrom)) {
         // This is an externally redirected view, from some other wiki.
         // If it was reported from a trusted site, supply a backlink.
         global $wgRedirectSources;
         if ($wgRedirectSources && preg_match($wgRedirectSources, $rdfrom)) {
             $sk = $wgUser->getSkin();
             $redir = $sk->makeExternalLink($rdfrom, $rdfrom);
             $s = wfMsg('redirectedfrom', $redir);
             $wgOut->setSubtitle($s);
             $wasRedirected = true;
         }
     }
     $outputDone = false;
     if ($pcache) {
         if ($wgOut->tryParserCache($this, $wgUser)) {
             wfRunHooks('ArticleViewHeader', array(&$this));
             $outputDone = true;
         }
     }
     if (!$outputDone) {
         $text = $this->getContent();
         if ($text === false) {
             # Failed to load, replace text with error message
             $t = $this->mTitle->getPrefixedText();
             if ($oldid) {
                 $t .= ',oldid=' . $oldid;
                 $text = wfMsg('missingarticle', $t);
             } else {
                 $text = wfMsg('noarticletext', $t);
             }
         }
         # Another whitelist check in case oldid is altering the title
         if (!$this->mTitle->userCanRead()) {
             $wgOut->loginToUse();
             $wgOut->output();
             exit;
         }
         # We're looking at an old revision
         if (!empty($oldid)) {
             $wgOut->setRobotpolicy('noindex,nofollow');
             if (is_null($this->mRevision)) {
                 // FIXME: This would be a nice place to load the 'no such page' text.
             } else {
                 $this->setOldSubtitle(isset($this->mOldId) ? $this->mOldId : $oldid);
                 if ($this->mRevision->isDeleted(Revision::DELETED_TEXT)) {
                     if (!$this->mRevision->userCan(Revision::DELETED_TEXT)) {
                         $wgOut->addWikiText(wfMsg('rev-deleted-text-permission'));
                         $wgOut->setPageTitle($this->mTitle->getPrefixedText());
                         return;
                     } else {
                         $wgOut->addWikiText(wfMsg('rev-deleted-text-view'));
                         // and we are allowed to see...
                     }
                 }
             }
         }
     }
     if (!$outputDone) {
         /**
          * @fixme: this hook doesn't work most of the time, as it doesn't
          * trigger when the parser cache is used.
          */
         wfRunHooks('ArticleViewHeader', array(&$this));
         $wgOut->setRevisionId($this->getRevIdFetched());
         # wrap user css and user js in pre and don't parse
         # XXX: use $this->mTitle->usCssJsSubpage() when php is fixed/ a workaround is found
         if ($ns == NS_USER && preg_match('/\\/[\\w]+\\.(css|js)$/', $this->mTitle->getDBkey())) {
             $wgOut->addWikiText(wfMsg('clearyourcache'));
             $wgOut->addHTML('<pre>' . htmlspecialchars($this->mContent) . "\n</pre>");
         } else {
             if ($rt = Title::newFromRedirect($text)) {
                 # Display redirect
                 $imageDir = $wgContLang->isRTL() ? 'rtl' : 'ltr';
                 $imageUrl = $wgStylePath . '/common/images/redirect' . $imageDir . '.png';
                 # Don't overwrite the subtitle if this was an old revision
                 if (!$wasRedirected && $this->isCurrent()) {
                     $wgOut->setSubtitle(wfMsgHtml('redirectpagesub'));
                 }
                 $link = $sk->makeLinkObj($rt, $rt->getFullText());
                 $wgOut->addHTML('<img src="' . $imageUrl . '" alt="#REDIRECT " />' . '<span class="redirectText">' . $link . '</span>');
                 $parseout = $wgParser->parse($text, $this->mTitle, ParserOptions::newFromUser($wgUser));
                 $wgOut->addParserOutputNoText($parseout);
             } else {
                 if ($pcache) {
                     # Display content and save to parser cache
                     $wgOut->addPrimaryWikiText($text, $this);
                 } else {
                     # Display content, don't attempt to save to parser cache
                     # Don't show section-edit links on old revisions... this way lies madness.
                     if (!$this->isCurrent()) {
                         $oldEditSectionSetting = $wgOut->parserOptions()->setEditSection(false);
                     }
                     # Display content and don't save to parser cache
                     $wgOut->addPrimaryWikiText($text, $this, false);
                     if (!$this->isCurrent()) {
                         $wgOut->parserOptions()->setEditSection($oldEditSectionSetting);
                     }
                 }
             }
         }
     }
     /* title may have been set from the cache */
     $t = $wgOut->getPageTitle();
     if (empty($t)) {
         $wgOut->setPageTitle($this->mTitle->getPrefixedText());
     }
     # check if we're displaying a [[User talk:x.x.x.x]] anonymous talk page
     if ($ns == NS_USER_TALK && User::isIP($this->mTitle->getText())) {
         $wgOut->addWikiText(wfMsg('anontalkpagetext'));
     }
     # If we have been passed an &rcid= parameter, we want to give the user a
     # chance to mark this new article as patrolled.
     if ($wgUseRCPatrol && !is_null($rcid) && $rcid != 0 && $wgUser->isAllowed('patrol')) {
         $wgOut->addHTML("<div class='patrollink'>" . wfMsg('markaspatrolledlink', $sk->makeKnownLinkObj($this->mTitle, wfMsg('markaspatrolledtext'), "action=markpatrolled&rcid={$rcid}")) . '</div>');
     }
     # Trackbacks
     if ($wgUseTrackbacks) {
         $this->addTrackbacks();
     }
     $this->viewUpdates();
     wfProfileOut(__METHOD__);
 }
Exemple #19
0
 /**
  * This is the default action of the index.php entry point: just view the
  * page of the given title.
  */
 public function view()
 {
     global $wgParser, $wgUseFileCache, $wgUseETag, $wgDebugToolbar;
     wfProfileIn(__METHOD__);
     # Get variables from query string
     # As side effect this will load the revision and update the title
     # in a revision ID is passed in the request, so this should remain
     # the first call of this method even if $oldid is used way below.
     $oldid = $this->getOldID();
     $user = $this->getContext()->getUser();
     # Another whitelist check in case getOldID() is altering the title
     $permErrors = $this->getTitle()->getUserPermissionsErrors('read', $user);
     if (count($permErrors)) {
         wfDebug(__METHOD__ . ": denied on secondary read check\n");
         wfProfileOut(__METHOD__);
         throw new PermissionsError('read', $permErrors);
     }
     $outputPage = $this->getContext()->getOutput();
     # getOldID() may as well want us to redirect somewhere else
     if ($this->mRedirectUrl) {
         $outputPage->redirect($this->mRedirectUrl);
         wfDebug(__METHOD__ . ": redirecting due to oldid\n");
         wfProfileOut(__METHOD__);
         return;
     }
     # If we got diff in the query, we want to see a diff page instead of the article.
     if ($this->getContext()->getRequest()->getCheck('diff')) {
         wfDebug(__METHOD__ . ": showing diff page\n");
         $this->showDiffPage();
         wfProfileOut(__METHOD__);
         return;
     }
     # Set page title (may be overridden by DISPLAYTITLE)
     $outputPage->setPageTitle($this->getTitle()->getPrefixedText());
     $outputPage->setArticleFlag(true);
     # Allow frames by default
     $outputPage->allowClickjacking();
     $parserCache = ParserCache::singleton();
     $parserOptions = $this->getParserOptions();
     # Render printable version, use printable version cache
     if ($outputPage->isPrintable()) {
         $parserOptions->setIsPrintable(true);
         $parserOptions->setEditSection(false);
     } elseif (!$this->isCurrent() || !$this->getTitle()->quickUserCan('edit', $user)) {
         $parserOptions->setEditSection(false);
     }
     # Try client and file cache
     if (!$wgDebugToolbar && $oldid === 0 && $this->mPage->checkTouched()) {
         if ($wgUseETag) {
             $outputPage->setETag($parserCache->getETag($this, $parserOptions));
         }
         # Is it client cached?
         if ($outputPage->checkLastModified($this->mPage->getTouched())) {
             wfDebug(__METHOD__ . ": done 304\n");
             wfProfileOut(__METHOD__);
             return;
             # Try file cache
         } elseif ($wgUseFileCache && $this->tryFileCache()) {
             wfDebug(__METHOD__ . ": done file cache\n");
             # tell wgOut that output is taken care of
             $outputPage->disable();
             $this->mPage->doViewUpdates($user);
             wfProfileOut(__METHOD__);
             return;
         }
     }
     # Should the parser cache be used?
     $useParserCache = $this->mPage->isParserCacheUsed($parserOptions, $oldid);
     wfDebug('Article::view using parser cache: ' . ($useParserCache ? 'yes' : 'no') . "\n");
     if ($user->getStubThreshold()) {
         wfIncrStats('pcache_miss_stub');
     }
     $this->showRedirectedFromHeader();
     $this->showNamespaceHeader();
     # Iterate through the possible ways of constructing the output text.
     # Keep going until $outputDone is set, or we run out of things to do.
     $pass = 0;
     $outputDone = false;
     $this->mParserOutput = false;
     while (!$outputDone && ++$pass) {
         switch ($pass) {
             case 1:
                 wfRunHooks('ArticleViewHeader', array(&$this, &$outputDone, &$useParserCache));
                 break;
             case 2:
                 # Early abort if the page doesn't exist
                 if (!$this->mPage->exists()) {
                     wfDebug(__METHOD__ . ": showing missing article\n");
                     $this->showMissingArticle();
                     wfProfileOut(__METHOD__);
                     return;
                 }
                 # Try the parser cache
                 if ($useParserCache) {
                     $this->mParserOutput = $parserCache->get($this, $parserOptions);
                     if ($this->mParserOutput !== false) {
                         if ($oldid) {
                             wfDebug(__METHOD__ . ": showing parser cache contents for current rev permalink\n");
                             $this->setOldSubtitle($oldid);
                         } else {
                             wfDebug(__METHOD__ . ": showing parser cache contents\n");
                         }
                         $outputPage->addParserOutput($this->mParserOutput);
                         # Ensure that UI elements requiring revision ID have
                         # the correct version information.
                         $outputPage->setRevisionId($this->mPage->getLatest());
                         # Preload timestamp to avoid a DB hit
                         $cachedTimestamp = $this->mParserOutput->getTimestamp();
                         if ($cachedTimestamp !== null) {
                             $outputPage->setRevisionTimestamp($cachedTimestamp);
                             $this->mPage->setTimestamp($cachedTimestamp);
                         }
                         $outputDone = true;
                     }
                 }
                 break;
             case 3:
                 # This will set $this->mRevision if needed
                 $this->fetchContentObject();
                 # Are we looking at an old revision
                 if ($oldid && $this->mRevision) {
                     $this->setOldSubtitle($oldid);
                     if (!$this->showDeletedRevisionHeader()) {
                         wfDebug(__METHOD__ . ": cannot view deleted revision\n");
                         wfProfileOut(__METHOD__);
                         return;
                     }
                 }
                 # Ensure that UI elements requiring revision ID have
                 # the correct version information.
                 $outputPage->setRevisionId($this->getRevIdFetched());
                 # Preload timestamp to avoid a DB hit
                 $outputPage->setRevisionTimestamp($this->getTimestamp());
                 # Pages containing custom CSS or JavaScript get special treatment
                 if ($this->getTitle()->isCssOrJsPage() || $this->getTitle()->isCssJsSubpage()) {
                     wfDebug(__METHOD__ . ": showing CSS/JS source\n");
                     $this->showCssOrJsPage();
                     $outputDone = true;
                 } elseif (!wfRunHooks('ArticleContentViewCustom', array($this->fetchContentObject(), $this->getTitle(), $outputPage))) {
                     # Allow extensions do their own custom view for certain pages
                     $outputDone = true;
                 } elseif (!ContentHandler::runLegacyHooks('ArticleViewCustom', array($this->fetchContentObject(), $this->getTitle(), $outputPage))) {
                     # Allow extensions do their own custom view for certain pages
                     $outputDone = true;
                 } else {
                     $content = $this->getContentObject();
                     $rt = $content->getRedirectChain();
                     if ($rt) {
                         wfDebug(__METHOD__ . ": showing redirect=no page\n");
                         # Viewing a redirect page (e.g. with parameter redirect=no)
                         $outputPage->addHTML($this->viewRedirect($rt));
                         # Parse just to get categories, displaytitle, etc.
                         $this->mParserOutput = $content->getParserOutput($this->getTitle(), $oldid, $parserOptions, false);
                         $outputPage->addParserOutputNoText($this->mParserOutput);
                         $outputDone = true;
                     }
                 }
                 break;
             case 4:
                 # Run the parse, protected by a pool counter
                 wfDebug(__METHOD__ . ": doing uncached parse\n");
                 // @todo: shouldn't we be passing $this->getPage() to PoolWorkArticleView instead of plain $this?
                 $poolArticleView = new PoolWorkArticleView($this, $parserOptions, $this->getRevIdFetched(), $useParserCache, $this->getContentObject(), $this->getContext());
                 if (!$poolArticleView->execute()) {
                     $error = $poolArticleView->getError();
                     if ($error) {
                         $outputPage->clearHTML();
                         // for release() errors
                         $outputPage->enableClientCache(false);
                         $outputPage->setRobotPolicy('noindex,nofollow');
                         $errortext = $error->getWikiText(false, 'view-pool-error');
                         $outputPage->addWikiText('<div class="errorbox">' . $errortext . '</div>');
                     }
                     # Connection or timeout error
                     wfProfileOut(__METHOD__);
                     return;
                 }
                 $this->mParserOutput = $poolArticleView->getParserOutput();
                 $outputPage->addParserOutput($this->mParserOutput);
                 # Don't cache a dirty ParserOutput object
                 if ($poolArticleView->getIsDirty()) {
                     $outputPage->setSquidMaxage(0);
                     $outputPage->addHTML("<!-- parser cache is expired, sending anyway due to pool overload-->\n");
                 }
                 $outputDone = true;
                 break;
                 # Should be unreachable, but just in case...
             # Should be unreachable, but just in case...
             default:
                 break 2;
         }
     }
     # Get the ParserOutput actually *displayed* here.
     # Note that $this->mParserOutput is the *current* version output.
     $pOutput = $outputDone instanceof ParserOutput ? $outputDone : $this->mParserOutput;
     # Adjust title for main page & pages with displaytitle
     if ($pOutput) {
         $this->adjustDisplayTitle($pOutput);
     }
     # For the main page, overwrite the <title> element with the con-
     # tents of 'pagetitle-view-mainpage' instead of the default (if
     # that's not empty).
     # This message always exists because it is in the i18n files
     if ($this->getTitle()->isMainPage()) {
         $msg = wfMessage('pagetitle-view-mainpage')->inContentLanguage();
         if (!$msg->isDisabled()) {
             $outputPage->setHTMLTitle($msg->title($this->getTitle())->text());
         }
     }
     # Check for any __NOINDEX__ tags on the page using $pOutput
     $policy = $this->getRobotPolicy('view', $pOutput);
     $outputPage->setIndexPolicy($policy['index']);
     $outputPage->setFollowPolicy($policy['follow']);
     $this->showViewFooter();
     $this->mPage->doViewUpdates($user);
     wfProfileOut(__METHOD__);
 }
 public function getLagTimes($serverIndexes, $wiki)
 {
     if (count($serverIndexes) == 1 && reset($serverIndexes) == 0) {
         // Single server only, just return zero without caching
         return array(0 => 0);
     }
     $section = new ProfileSection(__METHOD__);
     $expiry = 5;
     $requestRate = 10;
     global $wgMemc;
     if (empty($wgMemc)) {
         $wgMemc = wfGetMainCache();
     }
     $masterName = $this->parent->getServerName(0);
     $memcKey = wfMemcKey('lag_times', $masterName);
     $times = $wgMemc->get($memcKey);
     if (is_array($times)) {
         # Randomly recache with probability rising over $expiry
         $elapsed = time() - $times['timestamp'];
         $chance = max(0, ($expiry - $elapsed) * $requestRate);
         if (mt_rand(0, $chance) != 0) {
             unset($times['timestamp']);
             // hide from caller
             return $times;
         }
         wfIncrStats('lag_cache_miss_expired');
     } else {
         wfIncrStats('lag_cache_miss_absent');
     }
     # Cache key missing or expired
     if ($wgMemc->add("{$memcKey}:lock", 1, 10)) {
         # Let this process alone update the cache value
         $unlocker = new ScopedCallback(function () use($wgMemc, $memcKey) {
             $wgMemc->delete($memcKey);
         });
     } elseif (is_array($times)) {
         # Could not acquire lock but an old cache exists, so use it
         unset($times['timestamp']);
         // hide from caller
         return $times;
     }
     $times = array();
     foreach ($serverIndexes as $i) {
         if ($i == 0) {
             # Master
             $times[$i] = 0;
         } elseif (false !== ($conn = $this->parent->getAnyOpenConnection($i))) {
             $times[$i] = $conn->getLag();
         } elseif (false !== ($conn = $this->parent->openConnection($i, $wiki))) {
             $times[$i] = $conn->getLag();
         }
     }
     # Add a timestamp key so we know when it was cached
     $times['timestamp'] = time();
     $wgMemc->set($memcKey, $times, $expiry + 10);
     unset($times['timestamp']);
     // hide from caller
     return $times;
 }
 /**
  * Run JavaScript or CSS data through a filter, caching the filtered result for future calls.
  *
  * Available filters are:
  *
  *    - minify-js \see JavaScriptMinifier::minify
  *    - minify-css \see CSSMin::minify
  *
  * If $data is empty, only contains whitespace or the filter was unknown,
  * $data is returned unmodified.
  *
  * @param string $filter Name of filter to run
  * @param string $data Text to filter, such as JavaScript or CSS text
  * @param string $cacheReport Whether to include the cache key report
  * @return string Filtered data, or a comment containing an error message
  */
 public function filter($filter, $data, $cacheReport = true)
 {
     // For empty/whitespace-only data or for unknown filters, don't perform
     // any caching or processing
     if (trim($data) === '' || !in_array($filter, array('minify-js', 'minify-css'))) {
         return $data;
     }
     // Try for cache hit
     // Use CACHE_ANYTHING since filtering is very slow compared to DB queries
     $key = wfMemcKey('resourceloader', 'filter', $filter, self::$filterCacheVersion, md5($data));
     $cache = wfGetCache(CACHE_ANYTHING);
     $cacheEntry = $cache->get($key);
     if (is_string($cacheEntry)) {
         wfIncrStats("rl-{$filter}-cache-hits");
         return $cacheEntry;
     }
     $result = '';
     // Run the filter - we've already verified one of these will work
     try {
         wfIncrStats("rl-{$filter}-cache-misses");
         switch ($filter) {
             case 'minify-js':
                 $result = JavaScriptMinifier::minify($data, $this->config->get('ResourceLoaderMinifierStatementsOnOwnLine'), $this->config->get('ResourceLoaderMinifierMaxLineLength'));
                 if ($cacheReport) {
                     $result .= "\n/* cache key: {$key} */";
                 }
                 break;
             case 'minify-css':
                 $result = CSSMin::minify($data);
                 if ($cacheReport) {
                     $result .= "\n/* cache key: {$key} */";
                 }
                 break;
         }
         // Save filtered text to Memcached
         $cache->set($key, $result);
     } catch (Exception $e) {
         MWExceptionHandler::logException($e);
         wfDebugLog('resourceloader', __METHOD__ . ": minification failed: {$e}");
         $this->errors[] = self::formatExceptionNoComment($e);
     }
     return $result;
 }
 /**
  * Saves the settings submitted by the settings form. Redirects the user to the destination
  * of returnto or, if not set, back to this special page
  */
 private function submitSettingsForm()
 {
     $schema = 'MobileOptionsTracking';
     $schemaRevision = 14003392;
     $schemaData = array('action' => 'success', 'images' => "nochange", 'beta' => "nochange");
     $context = MobileContext::singleton();
     $request = $this->getRequest();
     $user = $this->getUser();
     if ($user->isLoggedIn() && !$user->matchEditToken($request->getVal('token'))) {
         $errorText = __METHOD__ . '(): token mismatch';
         wfIncrStats('mobile.options.errors');
         wfDebugLog('mobile', $errorText);
         $this->getOutput()->addHTML('<div class="error">' . $this->msg("mobile-frontend-save-error")->parse() . '</div>');
         $schemaData['action'] = 'error';
         $schemaData['errorText'] = $errorText;
         ExtMobileFrontend::eventLog($schema, $schemaRevision, $schemaData);
         $this->getSettingsForm();
         return;
     }
     wfIncrStats('mobile.options.saves');
     if ($request->getBool('enableBeta')) {
         $group = 'beta';
         if (!$context->isBetaGroupMember()) {
             // The request was to turn on beta
             $schemaData['beta'] = "on";
         }
     } else {
         $group = '';
         if ($context->isBetaGroupMember()) {
             // beta was turned off
             $schemaData['beta'] = "off";
         }
     }
     $context->setMobileMode($group);
     $imagesDisabled = !$request->getBool('enableImages');
     if ($context->imagesDisabled() !== $imagesDisabled) {
         // Only record when the state has changed
         $schemaData['images'] = $imagesDisabled ? "off" : "on";
     }
     $context->setDisableImagesCookie($imagesDisabled);
     $returnToTitle = Title::newFromText($request->getText('returnto'));
     if ($returnToTitle) {
         $url = $returnToTitle->getFullURL();
     } else {
         $url = $this->getPageTitle()->getFullURL('success');
     }
     ExtMobileFrontend::eventLog($schema, $schemaRevision, $schemaData);
     $context->getOutput()->redirect(MobileContext::singleton()->getMobileUrl($url));
 }
Exemple #23
0
 /**
  * Try to load file metadata from memcached. Returns true on success.
  * @return bool
  */
 function loadFromCache()
 {
     global $wgMemc;
     wfProfileIn(__METHOD__);
     $this->dataLoaded = false;
     $this->extraDataLoaded = false;
     $key = $this->getCacheKey();
     if (!$key) {
         wfProfileOut(__METHOD__);
         return false;
     }
     $cachedValues = $wgMemc->get($key);
     // Check if the key existed and belongs to this version of MediaWiki
     if (isset($cachedValues['version']) && $cachedValues['version'] == MW_FILE_VERSION) {
         wfDebug("Pulling file metadata from cache key {$key}\n");
         $this->fileExists = $cachedValues['fileExists'];
         if ($this->fileExists) {
             $this->setProps($cachedValues);
         }
         $this->dataLoaded = true;
         $this->extraDataLoaded = true;
         foreach ($this->getLazyCacheFields('') as $field) {
             $this->extraDataLoaded = $this->extraDataLoaded && isset($cachedValues[$field]);
         }
     }
     if ($this->dataLoaded) {
         wfIncrStats('image_cache_hit');
     } else {
         wfIncrStats('image_cache_miss');
     }
     wfProfileOut(__METHOD__);
     return $this->dataLoaded;
 }
Exemple #24
0
	/**
	 * Get a ParserOutput for the given ParserOptions and revision ID.
	 * The parser cache will be used if possible.
	 *
	 * @since 1.19
	 * @param ParserOptions $parserOptions ParserOptions to use for the parse operation
	 * @param null|int $oldid Revision ID to get the text from, passing null or 0 will
	 *               get the current revision (default value)
	 *
	 * @return ParserOutput or false if the revision was not found
	 */
	public function getParserOutput( ParserOptions $parserOptions, $oldid = null ) {
		wfProfileIn( __METHOD__ );

		$useParserCache = $this->isParserCacheUsed( $parserOptions, $oldid );
		wfDebug( __METHOD__ . ': using parser cache: ' . ( $useParserCache ? 'yes' : 'no' ) . "\n" );
		if ( $parserOptions->getStubThreshold() ) {
			wfIncrStats( 'pcache_miss_stub' );
		}

		if ( $useParserCache ) {
			$parserOutput = ParserCache::singleton()->get( $this, $parserOptions );
			if ( $parserOutput !== false ) {
				wfProfileOut( __METHOD__ );
				return $parserOutput;
			}
		}

		if ( $oldid === null || $oldid === 0 ) {
			$oldid = $this->getLatest();
		}

		$pool = new PoolWorkArticleView( $this, $parserOptions, $oldid, $useParserCache );
		$pool->execute();

		wfProfileOut( __METHOD__ );

		return $pool->getParserOutput();
	}
Exemple #25
0
 /**
  * Call wfIncrStats() for the queue overall and for the queue type
  *
  * @param string $key Event type
  * @param string $type Job type
  * @param integer $delta
  * @since 1.22
  */
 public static function incrStats($key, $type, $delta = 1)
 {
     wfIncrStats($key, $delta);
     wfIncrStats("{$key}-{$type}", $delta);
 }
 /**
  * Set the mf_useformat cookie
  *
  * This cookie can determine whether or not a user should see the mobile
  * version of pages.
  *
  * @param string $cookieFormat
  * @param null $expiry
  */
 public function setUseFormatCookie($cookieFormat = 'true', $expiry = null)
 {
     if (is_null($expiry)) {
         $expiry = $this->getUseFormatCookieExpiry();
     }
     $this->getRequest()->response()->setcookie(self::USEFORMAT_COOKIE_NAME, $cookieFormat, $expiry, array('prefix' => '', 'httpOnly' => false));
     wfIncrStats('mobile.useformat_' . $cookieFormat . '_cookie_set');
 }
 /**
  * Get the diff table body, without header
  *
  * @return mixed (string/false)
  */
 public function getDiffBody()
 {
     $this->mCacheHit = true;
     // Check if the diff should be hidden from this user
     if (!$this->loadRevisionData()) {
         return false;
     } elseif ($this->mOldRev && !$this->mOldRev->userCan(Revision::DELETED_TEXT, $this->getUser())) {
         return false;
     } elseif ($this->mNewRev && !$this->mNewRev->userCan(Revision::DELETED_TEXT, $this->getUser())) {
         return false;
     }
     // Short-circuit
     if ($this->mOldRev === false || $this->mOldRev && $this->mNewRev && $this->mOldRev->getID() == $this->mNewRev->getID()) {
         return '';
     }
     // Cacheable?
     $key = false;
     $cache = ObjectCache::getMainWANInstance();
     if ($this->mOldid && $this->mNewid) {
         $key = $this->getDiffBodyCacheKey();
         // Try cache
         if (!$this->mRefreshCache) {
             $difftext = $cache->get($key);
             if ($difftext) {
                 wfIncrStats('diff_cache.hit');
                 $difftext = $this->localiseLineNumbers($difftext);
                 $difftext .= "\n<!-- diff cache key {$key} -->\n";
                 return $difftext;
             }
         }
         // don't try to load but save the result
     }
     $this->mCacheHit = false;
     // Loadtext is permission safe, this just clears out the diff
     if (!$this->loadText()) {
         return false;
     }
     $difftext = $this->generateContentDiffBody($this->mOldContent, $this->mNewContent);
     // Save to cache for 7 days
     if (!Hooks::run('AbortDiffCache', array(&$this))) {
         wfIncrStats('diff_cache.uncacheable');
     } elseif ($key !== false && $difftext !== false) {
         wfIncrStats('diff_cache.miss');
         $cache->set($key, $difftext, 7 * 86400);
     } else {
         wfIncrStats('diff_cache.uncacheable');
     }
     // Replace line numbers with the text in the user's language
     if ($difftext !== false) {
         $difftext = $this->localiseLineNumbers($difftext);
     }
     return $difftext;
 }
Exemple #28
0
    } else {
        $wgCookiePrefix = $wgDBname;
    }
}
$wgCookiePrefix = strtr($wgCookiePrefix, "=,; +.\"'\\[", "__________");
# If session.auto_start is there, we can't touch session name
#
if (!wfIniGetBool('session.auto_start')) {
    session_name($wgSessionName ? $wgSessionName : $wgCookiePrefix . '_session');
}
if (!$wgCommandLineMode && ($wgRequest->checkSessionCookie() || isset($_COOKIE[$wgCookiePrefix . 'Token']))) {
    wfIncrStats('request_with_session');
    wfSetupSession();
    $wgSessionStarted = true;
} else {
    wfIncrStats('request_without_session');
    $wgSessionStarted = false;
}
wfProfileOut($fname . '-SetupSession');
wfProfileIn($fname . '-globals');
$wgContLang = new StubContLang();
// Now that variant lists may be available...
$wgRequest->interpolateTitle();
$wgUser = new StubUser();
$wgLang = new StubUserLang();
$wgOut = new StubObject('wgOut', 'OutputPage');
$wgParser = new StubObject('wgParser', $wgParserConf['class'], array($wgParserConf));
$wgMessageCache = new StubObject('wgMessageCache', 'MessageCache', array($messageMemc, $wgUseDatabaseMessages, $wgMsgCacheExpiry, wfWikiID()));
wfProfileOut($fname . '-globals');
wfProfileIn($fname . '-User');
# Skin setup functions
 /**
  * Get the diff table body, without header
  *
  * @return mixed (string/false)
  */
 public function getDiffBody()
 {
     global $wgMemc;
     wfProfileIn(__METHOD__);
     $this->mCacheHit = true;
     // Check if the diff should be hidden from this user
     if (!$this->loadRevisionData()) {
         wfProfileOut(__METHOD__);
         return false;
     } elseif ($this->mOldRev && !$this->mOldRev->userCan(Revision::DELETED_TEXT)) {
         wfProfileOut(__METHOD__);
         return false;
     } elseif ($this->mNewRev && !$this->mNewRev->userCan(Revision::DELETED_TEXT)) {
         wfProfileOut(__METHOD__);
         return false;
     }
     // Short-circuit
     if ($this->mOldRev && $this->mNewRev && $this->mOldRev->getID() == $this->mNewRev->getID()) {
         wfProfileOut(__METHOD__);
         return '';
     }
     // Cacheable?
     $key = false;
     if ($this->mOldid && $this->mNewid) {
         $key = wfMemcKey('diff', 'version', MW_DIFF_VERSION, 'oldid', $this->mOldid, 'newid', $this->mNewid);
         // Try cache
         if (!$this->mRefreshCache) {
             $difftext = $wgMemc->get($key);
             if ($difftext) {
                 wfIncrStats('diff_cache_hit');
                 $difftext = $this->localiseLineNumbers($difftext);
                 $difftext .= "\n<!-- diff cache key {$key} -->\n";
                 wfProfileOut(__METHOD__);
                 return $difftext;
             }
         }
         // don't try to load but save the result
     }
     $this->mCacheHit = false;
     // Loadtext is permission safe, this just clears out the diff
     if (!$this->loadText()) {
         wfProfileOut(__METHOD__);
         return false;
     }
     $difftext = $this->generateDiffBody($this->mOldtext, $this->mNewtext);
     // Save to cache for 7 days
     if (!wfRunHooks('AbortDiffCache', array(&$this))) {
         wfIncrStats('diff_uncacheable');
     } elseif ($key !== false && $difftext !== false) {
         wfIncrStats('diff_cache_miss');
         $wgMemc->set($key, $difftext, 7 * 86400);
     } else {
         wfIncrStats('diff_uncacheable');
     }
     // Replace line numbers with the text in the user's language
     if ($difftext !== false) {
         $difftext = $this->localiseLineNumbers($difftext);
     }
     wfProfileOut(__METHOD__);
     return $difftext;
 }
 /** 
  * Try to load image metadata from memcached. Returns true on success.
  */
 function loadFromCache()
 {
     global $wgUseSharedUploads, $wgMemc;
     $fname = 'Image::loadFromMemcached';
     wfProfileIn($fname);
     $this->dataLoaded = false;
     $keys = $this->getCacheKeys();
     $cachedValues = $wgMemc->get($keys[0]);
     // Check if the key existed and belongs to this version of MediaWiki
     if (!empty($cachedValues) && is_array($cachedValues) && isset($cachedValues['version']) && $cachedValues['version'] == MW_IMAGE_VERSION && $cachedValues['fileExists'] && isset($cachedValues['mime']) && isset($cachedValues['metadata'])) {
         if ($wgUseSharedUploads && $cachedValues['fromShared']) {
             # if this is shared file, we need to check if image
             # in shared repository has not changed
             if (isset($keys[1])) {
                 $commonsCachedValues = $wgMemc->get($keys[1]);
                 if (!empty($commonsCachedValues) && is_array($commonsCachedValues) && isset($commonsCachedValues['version']) && $commonsCachedValues['version'] == MW_IMAGE_VERSION && isset($commonsCachedValues['mime'])) {
                     wfDebug("Pulling image metadata from shared repository cache\n");
                     $this->name = $commonsCachedValues['name'];
                     $this->imagePath = $commonsCachedValues['imagePath'];
                     $this->fileExists = $commonsCachedValues['fileExists'];
                     $this->width = $commonsCachedValues['width'];
                     $this->height = $commonsCachedValues['height'];
                     $this->bits = $commonsCachedValues['bits'];
                     $this->type = $commonsCachedValues['type'];
                     $this->mime = $commonsCachedValues['mime'];
                     $this->metadata = $commonsCachedValues['metadata'];
                     $this->size = $commonsCachedValues['size'];
                     $this->fromSharedDirectory = true;
                     $this->dataLoaded = true;
                     $this->imagePath = $this->getFullPath(true);
                 }
             }
         } else {
             wfDebug("Pulling image metadata from local cache\n");
             $this->name = $cachedValues['name'];
             $this->imagePath = $cachedValues['imagePath'];
             $this->fileExists = $cachedValues['fileExists'];
             $this->width = $cachedValues['width'];
             $this->height = $cachedValues['height'];
             $this->bits = $cachedValues['bits'];
             $this->type = $cachedValues['type'];
             $this->mime = $cachedValues['mime'];
             $this->metadata = $cachedValues['metadata'];
             $this->size = $cachedValues['size'];
             $this->fromSharedDirectory = false;
             $this->dataLoaded = true;
             $this->imagePath = $this->getFullPath();
         }
     }
     if ($this->dataLoaded) {
         wfIncrStats('image_cache_hit');
     } else {
         wfIncrStats('image_cache_miss');
     }
     wfProfileOut($fname);
     return $this->dataLoaded;
 }