/**
  * @params include:
  *   - objectCache : Name of an object cache registered in $wgObjectCaches.
  *                   This defaults to the one specified by $wgMainCacheType.
  *   - cacheTTL    : Seconds to cache the aggregate data before regenerating.
  * @param array $params
  */
 protected function __construct(array $params)
 {
     parent::__construct($params);
     $this->cache = isset($params['objectCache']) ? wfGetCache($params['objectCache']) : wfGetMainCache();
     $this->cacheTTL = isset($params['cacheTTL']) ? $params['cacheTTL'] : 180;
     // 3 min
 }
 /**
  * Prepares the environment before running a test.
  */
 protected function setUp()
 {
     global $wgMemc;
     parent::setUp();
     $this->user = User::newFromName("someReviewer");
     $wgMemc = wfGetCache(CACHE_DB);
 }
 /**
  * Get contents of a javascript file for inline use.
  *
  * Roughly based MediaWiki core methods:
  * - ResourceLoader::filter()
  * - ResourceLoaderFileModule::readScriptFiles()
  *
  * @param string $name Path to file relative to /modules/inline/
  * @return string Minified script
  * @throws Exception If file doesn't exist
  */
 protected static function getInlineScript($name)
 {
     // Get file
     $filePath = __DIR__ . '/../../modules/inline/' . $name;
     if (!file_exists($filePath)) {
         throw new Exception(__METHOD__ . ": file not found: \"{$filePath}\"");
     }
     $contents = file_get_contents($filePath);
     // Try minified from cache
     $key = wfMemcKey('centralauth', 'minify-js', md5($contents));
     $cache = wfGetCache(CACHE_ANYTHING);
     $cacheEntry = $cache->get($key);
     if (is_string($cacheEntry)) {
         return $cacheEntry;
     }
     // Compute new value
     $result = '';
     try {
         $result = JavaScriptMinifier::minify($contents) . "\n/* cache key: {$key} */";
         $cache->set($key, $result);
     } catch (Exception $e) {
         MWExceptionHandler::logException($e);
         wfDebugLog('CentralAuth', __METHOD__ . ": minification failed for {$name}: {$e}");
         $result = ResourceLoader::formatException($e) . "\n" . $contents;
     }
     return $result;
 }
 /**
  * @since 1.21
  * @deprecated 1.25 Construct a SiteStore instance directly instead.
  *
  * @param ORMTable|null $sitesTable
  * @param BagOStuff|null $cache
  *
  * @return SiteStore
  */
 public static function newInstance(ORMTable $sitesTable = null, BagOStuff $cache = null)
 {
     if ($cache === null) {
         $cache = wfGetCache(wfIsHHVM() ? CACHE_ACCEL : CACHE_ANYTHING);
     }
     $siteStore = new DBSiteStore();
     return new static($siteStore, $cache);
 }
 /**
  * Constructor.
  * @param string $title
  * @param integer $revision
  * @param ObjectCache $cache: (optional) cache client.
  * @param Http $http: (optional) HTTP client.
  */
 function __construct($title, $revision, $cache = NULL, $http = NULL)
 {
     global $wgEventLoggingDBname;
     $this->title = $title;
     $this->revision = $revision;
     $this->cache = $cache ?: wfGetCache(CACHE_ANYTHING);
     $this->http = $http ?: new Http();
     $this->key = "schema:{$wgEventLoggingDBname}:{$title}:{$revision}";
 }
Exemple #6
0
 function __construct($memCached, $useDB, $expiry)
 {
     if (!$memCached) {
         $memCached = wfGetCache(CACHE_NONE);
     }
     $this->mMemc = $memCached;
     $this->mDisable = !$useDB;
     $this->mExpiry = $expiry;
 }
 protected function setUp()
 {
     parent::setUp();
     global $wgHooks;
     $this->setMwGlobals(array('wgHooks' => $wgHooks, 'wgTranslateTranslationServices' => array()));
     $wgHooks['TranslatePostInitGroups'] = array(array($this, 'getTestGroups'));
     $mg = MessageGroups::singleton();
     $mg->setCache(wfGetCache('hash'));
     $mg->recache();
 }
	function run() {
		global $wgUser;

		// Initialization
		$title = $this->title;
		// Other stuff
		$user    = $this->getUser();
		$summary = $this->getSummary();
		$base    = $this->getBase();

		PageTranslationHooks::$allowTargetEdit = true;
		$oldUser = $wgUser;
		$wgUser = $user;

		$error = '';
		$article = new Article( $title, 0 );
		$ok = $article->doDeleteArticle( $summary, false, 0, true, $error );
		if ( !$ok ) {
			$logger = new LogPage( 'pagetranslation' );
			$params = array(
				'user' => $this->getPerformer(),
				'target' => $base,
				'error' => base64_encode( serialize( $ok ) ), // This is getting ridiculous
			);
			$doer = User::newFromName( $this->getPerformer() );
			$msg = $this->getFull() ? 'deletefnok' : 'deletelnok';
			$logger->addEntry( $msg, $title, null, array( serialize( $params ) ), $doer );
		}

		PageTranslationHooks::$allowTargetEdit = false;

		$cache = wfGetCache( CACHE_DB );
		$pages = (array) $cache->get( wfMemcKey( 'pt-base', $base ) );
		$lastitem = array_pop( $pages );
		if ( $title->getPrefixedText() === $lastitem ) {
			$cache->delete( wfMemcKey( 'pt-base', $base ) );
			$logger = new LogPage( 'pagetranslation' );
			$params = array( 'user' => $this->getPerformer() );
			$doer = User::newFromName( $this->getPerformer() );
			$msg = $this->getFull() ? 'deletefok' : 'deletelok';
			$logger->addEntry( $msg, Title::newFromText( $base ), null, array( serialize( $params ) ), $doer );

			$tpage = TranslatablePage::newFromTitle( $title );
			$tpage->getTranslationPercentages( true );
			foreach ( $tpage->getTranslationPages() as $page ) {
				$page->invalidateCache();
			}
			$title->invalidateCache();
		}

		$wgUser = $oldUser;

		return true;
	}
 protected function setUp()
 {
     parent::setUp();
     global $wgHooks;
     $this->setMwGlobals(array('wgHooks' => $wgHooks, 'wgGroupPermissions' => array(), 'wgTranslateMessageNamespaces' => array(NS_MEDIAWIKI)));
     $wgHooks['TranslatePostInitGroups'] = array(array($this, 'getTestGroups'));
     $mg = MessageGroups::singleton();
     $mg->setCache(wfGetCache('hash'));
     $mg->recache();
     MessageIndex::setInstance(new HashMessageIndex());
     MessageIndex::singleton()->rebuild();
 }
 public function setUp()
 {
     parent::setUp();
     global $wgHooks;
     $this->setMwGlobals(array('wgHooks' => $wgHooks, 'wgTranslateTranslationServices' => array(), 'wgTranslateDelayedMessageIndexRebuild' => false));
     $wgHooks['TranslatePostInitGroups'] = array();
     $mg = MessageGroups::singleton();
     $mg->setCache(wfGetCache('hash'));
     $mg->recache();
     MessageIndex::setInstance(new HashMessageIndex());
     MessageIndex::singleton()->rebuild();
 }
 protected function setUp()
 {
     parent::setUp();
     global $wgHooks;
     $this->setMwGlobals(array('wgHooks' => $wgHooks, 'wgTranslateTranslationServices' => array(), 'wgTranslateCacheDirectory' => $this->getNewTempDirectory()));
     $wgHooks['TranslatePostInitGroups'] = array();
     $mg = MessageGroups::singleton();
     $mg->setCache(wfGetCache('hash'));
     $mg->recache();
     MessageIndex::setInstance(new HashMessageIndex());
     MessageIndex::singleton()->rebuild();
 }
 /**
  * Implement a rudimentary rate limiting system,
  * we can't use User::pingLImiter() because stewards
  * have the "noratelimit" userright
  *
  * Hardcoded to allow 1 merge per 60 seconds
  *
  * @return bool true if we should let the user proceed
  */
 private function checkRateLimit()
 {
     $cache = wfGetCache(CACHE_ANYTHING);
     $key = 'centralauth:usermerge:' . md5($this->getUser()->getName());
     $found = $cache->get($key);
     if ($found === false) {
         $cache->set($key, true, 60);
         return true;
     } else {
         return false;
     }
 }
 protected function setUp()
 {
     parent::setUp();
     $conf = array(__DIR__ . '/data/ParentGroups.yaml');
     global $wgHooks;
     $this->setMwGlobals(array('wgHooks' => $wgHooks, 'wgTranslateGroupFiles' => $conf, 'wgTranslateTranslationServices' => array()));
     $wgHooks['TranslatePostInitGroups'] = array('MessageGroups::getConfiguredGroups');
     $mg = MessageGroups::singleton();
     $mg->setCache(wfGetCache('hash'));
     $mg->recache();
     MessageIndex::setInstance(new HashMessageIndex());
     MessageIndex::singleton()->rebuild();
 }
 protected function setUp()
 {
     parent::setUp();
     global $wgHooks, $wgTranslateTranslationServices, $wgTranslateTestTTMServer;
     $this->setMwGlobals(array('wgHooks' => $wgHooks, 'wgTranslateTranslationServices' => array()));
     $wgTranslateTranslationServices['TTMServer'] = $wgTranslateTestTTMServer;
     $wgHooks['TranslatePostInitGroups'] = array(array($this, 'addGroups'));
     $mg = MessageGroups::singleton();
     $mg->setCache(wfGetCache('hash'));
     $mg->recache();
     MessageIndex::setInstance(new HashMessageIndex());
     MessageIndex::singleton()->rebuild();
 }
 function __construct()
 {
     $this->cache = wfGetCache(CACHE_ANYTHING);
     // if (HuijiPrefix::hasPrefix($prefix)){
     // 	$this->mPrefix = $prefix;
     // } else {
     // 	$this->mPrefix = '';
     // }
     // $this->cache = wfGetCache( CACHE_ANYTHING );
     // $this->loadFromRow();
     // $siteCache = self::getSiteCache();
     // $siteCache->set($this->mPrefix, $this);
 }
 protected function setUp()
 {
     parent::setUp();
     global $wgHooks;
     $this->setMwGlobals(array('wgHooks' => $wgHooks, 'wgEnablePageTranslation' => true, 'wgTranslateTranslationServices' => array()));
     TranslateHooks::setupTranslate();
     $wgHooks['TranslatePostInitGroups'] = array('MessageGroups::getTranslatablePages');
     $mg = MessageGroups::singleton();
     $mg->setCache(wfGetCache('hash'));
     $mg->recache();
     MessageIndex::setInstance(new HashMessageIndex());
     MessageIndex::singleton()->rebuild();
 }
 public static function updateCache()
 {
     global $wgFlaggedRevsStatsAge;
     $rNamespaces = FlaggedRevs::getReviewNamespaces();
     if (empty($rNamespaces)) {
         return;
         // no SQL errors please :)
     }
     // Set key to limit duplicate updates...
     $dbCache = wfGetCache(CACHE_DB);
     $keySQL = wfMemcKey('flaggedrevs', 'statsUpdating');
     $dbCache->set($keySQL, '1', $wgFlaggedRevsStatsAge);
     // Get total, reviewed, and synced page count for each namespace
     list($ns_total, $ns_reviewed, $ns_synced) = self::getPerNamespaceTotals();
     // Getting mean pending edit time
     // @TODO: percentiles?
     $avePET = self::getMeanPendingEditTime();
     # Get wait (till review) time samples for anon edits...
     $reviewData = self::getEditReviewTimes($dbCache, 'anons');
     $dbw = wfGetDB(DB_MASTER);
     // The timestamp to identify this whole batch of data
     $encDataTimestamp = $dbw->timestamp();
     $dataSet = array();
     $dataSet[] = array('frs_stat_key' => 'reviewLag-sampleStartTimestamp', 'frs_stat_val' => $reviewData['sampleStartTS'], 'frs_timestamp' => $encDataTimestamp);
     $dataSet[] = array('frs_stat_key' => 'reviewLag-sampleEndTimestamp', 'frs_stat_val' => $reviewData['sampleEndTS'], 'frs_timestamp' => $encDataTimestamp);
     // All-namespace percentiles...
     foreach ($reviewData['percTable'] as $percentile => $seconds) {
         $dataSet[] = array('frs_stat_key' => 'reviewLag-percentile:' . (int) $percentile, 'frs_stat_val' => $seconds, 'frs_timestamp' => $encDataTimestamp);
     }
     // Sample size...
     $dataSet[] = array('frs_stat_key' => 'reviewLag-sampleSize', 'frs_stat_val' => $reviewData['sampleSize'], 'frs_timestamp' => $encDataTimestamp);
     // All-namespace ave/med review lag & ave pending lag stats...
     $dataSet[] = array('frs_stat_key' => 'reviewLag-average', 'frs_stat_val' => $reviewData['average'], 'frs_timestamp' => $encDataTimestamp);
     $dataSet[] = array('frs_stat_key' => 'reviewLag-median', 'frs_stat_val' => $reviewData['median'], 'frs_timestamp' => $encDataTimestamp);
     $dataSet[] = array('frs_stat_key' => 'pendingLag-average', 'frs_stat_val' => $avePET, 'frs_timestamp' => $encDataTimestamp);
     // Per-namespace total/reviewed/synced stats...
     foreach ($rNamespaces as $namespace) {
         $dataSet[] = array('frs_stat_key' => 'totalPages-NS:' . (int) $namespace, 'frs_stat_val' => isset($ns_total[$namespace]) ? $ns_total[$namespace] : 0, 'frs_timestamp' => $encDataTimestamp);
         $dataSet[] = array('frs_stat_key' => 'reviewedPages-NS:' . (int) $namespace, 'frs_stat_val' => isset($ns_reviewed[$namespace]) ? $ns_reviewed[$namespace] : 0, 'frs_timestamp' => $encDataTimestamp);
         $dataSet[] = array('frs_stat_key' => 'syncedPages-NS:' . (int) $namespace, 'frs_stat_val' => isset($ns_synced[$namespace]) ? $ns_synced[$namespace] : 0, 'frs_timestamp' => $encDataTimestamp);
     }
     // Save the data...
     $dbw->begin();
     $dbw->insert('flaggedrevs_statistics', $dataSet, __FUNCTION__, array('IGNORE'));
     $dbw->commit();
     // Stats are now up to date!
     $key = wfMemcKey('flaggedrevs', 'statsUpdated');
     $dbCache->set($key, '1', $wgFlaggedRevsStatsAge);
     $dbCache->delete($keySQL);
 }
Exemple #18
0
 /**
  * @param array $params
  * @throws MWException
  */
 protected function __construct(array $params)
 {
     $this->wiki = $params['wiki'];
     $this->type = $params['type'];
     $this->claimTTL = isset($params['claimTTL']) ? $params['claimTTL'] : 0;
     $this->maxTries = isset($params['maxTries']) ? $params['maxTries'] : 3;
     if (isset($params['order']) && $params['order'] !== 'any') {
         $this->order = $params['order'];
     } else {
         $this->order = $this->optimalOrder();
     }
     if (!in_array($this->order, $this->supportedOrders())) {
         throw new MWException(__CLASS__ . " does not support '{$this->order}' order.");
     }
     $this->dupCache = wfGetCache(CACHE_ANYTHING);
     $this->aggr = isset($params['aggregator']) ? $params['aggregator'] : new JobQueueAggregatorNull(array());
 }
 function run()
 {
     // Initialization
     $title = $this->title;
     // Other stuff
     $user = $this->getUser();
     $summary = $this->getSummary();
     $base = $this->getBase();
     $doer = User::newFromName($this->getPerformer());
     PageTranslationHooks::$allowTargetEdit = true;
     $error = '';
     $wikipage = new WikiPage($title);
     $ok = $wikipage->doDeleteArticle($summary, false, 0, true, $error, $user);
     if (!$ok) {
         $params = array('target' => $base, 'error' => $ok);
         $type = $this->getFull() ? 'deletefnok' : 'deletelnok';
         $entry = new ManualLogEntry('pagetranslation', $type);
         $entry->setPerformer($doer);
         $entry->setTarget($title);
         $entry->setParameters($params);
         $logid = $entry->insert();
         $entry->publish($logid);
     }
     PageTranslationHooks::$allowTargetEdit = false;
     $cache = wfGetCache(CACHE_DB);
     $pages = (array) $cache->get(wfMemcKey('pt-base', $base));
     $lastitem = array_pop($pages);
     if ($title->getPrefixedText() === $lastitem) {
         $cache->delete(wfMemcKey('pt-base', $base));
         $type = $this->getFull() ? 'deletefok' : 'deletelok';
         $entry = new ManualLogEntry('pagetranslation', $type);
         $entry->setPerformer($doer);
         $entry->setTarget(Title::newFromText($base));
         $logid = $entry->insert();
         $entry->publish($logid);
         $tpage = TranslatablePage::newFromTitle($title);
         $tpage->getTranslationPercentages(true);
         foreach ($tpage->getTranslationPages() as $page) {
             $page->invalidateCache();
         }
         $title->invalidateCache();
     }
     return true;
 }
Exemple #20
0
	/**
	 * @param $params array
	 */
	protected function __construct( array $params ) {
		$this->wiki = $params['wiki'];
		$this->type = $params['type'];
		$this->claimTTL = isset( $params['claimTTL'] ) ? $params['claimTTL'] : 0;
		$this->maxTries = isset( $params['maxTries'] ) ? $params['maxTries'] : 3;
		if ( isset( $params['order'] ) && $params['order'] !== 'any' ) {
			$this->order = $params['order'];
		} else {
			$this->order = $this->optimalOrder();
		}
		if ( !in_array( $this->order, $this->supportedOrders() ) ) {
			throw new MWException( __CLASS__ . " does not support '{$this->order}' order." );
		}
		$this->checkDelay = !empty( $params['checkDelay'] );
		if ( $this->checkDelay && !$this->supportsDelayedJobs() ) {
			throw new MWException( __CLASS__ . " does not support delayed jobs." );
		}
		$this->dupCache = wfGetCache( CACHE_ANYTHING );
	}
 public function __construct()
 {
     $this->cache = wfGetCache(CACHE_ACCEL);
 }
 /**
  * @param BagOStuff $memCached A cache instance. If none, fall back to CACHE_NONE.
  * @param bool $useDB
  * @param int $expiry Lifetime for cache. @see $mExpiry.
  */
 function __construct($memCached, $useDB, $expiry)
 {
     global $wgUseLocalMessageCache;
     if (!$memCached) {
         $memCached = wfGetCache(CACHE_NONE);
     }
     $this->mMemc = $memCached;
     $this->mDisable = !$useDB;
     $this->mExpiry = $expiry;
     if ($wgUseLocalMessageCache) {
         $this->localCache = ObjectCache::newAccelerator(CACHE_NONE);
     } else {
         $this->localCache = wfGetCache(CACHE_NONE);
     }
     $this->wanCache = ObjectCache::getMainWANInstance();
 }
Exemple #23
0
/** Get the cache object used by the parser cache */
function &wfGetParserCacheStorage()
{
    global $wgParserCacheType;
    $ret =& wfGetCache($wgParserCacheType);
    return $ret;
}
 /**
  * Validate a given script file; if valid returns the original source.
  * If invalid, returns replacement JS source that throws an exception.
  *
  * @param string $fileName
  * @param string $contents
  * @return string JS with the original, or a replacement error
  */
 protected function validateScriptFile($fileName, $contents)
 {
     global $wgResourceLoaderValidateJS;
     if ($wgResourceLoaderValidateJS) {
         // Try for cache hit
         // Use CACHE_ANYTHING since filtering is very slow compared to DB queries
         $key = wfMemcKey('resourceloader', 'jsparse', self::$parseCacheVersion, md5($contents));
         $cache = wfGetCache(CACHE_ANYTHING);
         $cacheEntry = $cache->get($key);
         if (is_string($cacheEntry)) {
             return $cacheEntry;
         }
         $parser = self::javaScriptParser();
         try {
             $parser->parse($contents, $fileName, 1);
             $result = $contents;
         } catch (Exception $e) {
             // We'll save this to cache to avoid having to validate broken JS over and over...
             $err = $e->getMessage();
             $result = "throw new Error(" . Xml::encodeJsVar("JavaScript parse error: {$err}") . ");";
         }
         $cache->set($key, $result);
         return $result;
     } else {
         return $contents;
     }
 }
Exemple #25
0
 /**
  * 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 array $options For back-compat, can also be the boolean value for "cacheReport". Keys:
  *  - (bool) cache: Whether to allow caching this data. Default: true.
  *  - (bool) cacheReport: Whether to include the "cache key" report comment. Default: false.
  * @return string Filtered data, or a comment containing an error message
  */
 public function filter($filter, $data, $options = array())
 {
     // Back-compat
     if (is_bool($options)) {
         $options = array('cacheReport' => $options);
     }
     // Defaults
     $options += array('cache' => true, 'cacheReport' => false);
     $stats = RequestContext::getMain()->getStats();
     // Don't filter empty content
     if (trim($data) === '') {
         return $data;
     }
     if (!in_array($filter, array('minify-js', 'minify-css'))) {
         $this->logger->warning('Invalid filter {filter}', array('filter' => $filter));
         return $data;
     }
     if (!$options['cache']) {
         $result = self::applyFilter($filter, $data, $this->config);
     } else {
         $key = wfGlobalCacheKey('resourceloader', 'filter', $filter, self::$filterCacheVersion, md5($data));
         $cache = wfGetCache(wfIsHHVM() ? CACHE_ACCEL : CACHE_ANYTHING);
         $cacheEntry = $cache->get($key);
         if (is_string($cacheEntry)) {
             $stats->increment("resourceloader_cache.{$filter}.hit");
             return $cacheEntry;
         }
         $result = '';
         try {
             $statStart = microtime(true);
             $result = self::applyFilter($filter, $data, $this->config);
             $statTiming = microtime(true) - $statStart;
             $stats->increment("resourceloader_cache.{$filter}.miss");
             $stats->timing("resourceloader_cache.{$filter}.timing", 1000 * $statTiming);
             if ($options['cacheReport']) {
                 $result .= "\n/* cache key: {$key} */";
             }
             // Set a TTL since HHVM's APC doesn't have any limitation or eviction logic.
             $cache->set($key, $result, 24 * 3600);
         } catch (Exception $e) {
             MWExceptionHandler::logException($e);
             $this->logger->warning('Minification failed: {exception}', array('exception' => $e));
             $this->errors[] = self::formatExceptionNoComment($e);
         }
     }
     return $result;
 }
Exemple #26
0
 protected function initChild()
 {
     global $wgMemc, $wgMainCacheType;
     $wgMemc = wfGetCache($wgMainCacheType);
     $this->children = null;
     pcntl_signal(SIGTERM, SIG_DFL);
 }
 /**
  * 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;
 }
Exemple #28
0
 /**
  * Runs 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 $filter String: Name of filter to run
  * @param $data String: Text to filter, such as JavaScript or CSS text
  * @return String: Filtered data, or a comment containing an error message
  */
 protected function filter($filter, $data)
 {
     global $wgResourceLoaderMinifierStatementsOnOwnLine, $wgResourceLoaderMinifierMaxLineLength;
     wfProfileIn(__METHOD__);
     // 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'))) {
         wfProfileOut(__METHOD__);
         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)) {
         wfProfileOut(__METHOD__);
         return $cacheEntry;
     }
     $result = '';
     // Run the filter - we've already verified one of these will work
     try {
         switch ($filter) {
             case 'minify-js':
                 $result = JavaScriptMinifier::minify($data, $wgResourceLoaderMinifierStatementsOnOwnLine, $wgResourceLoaderMinifierMaxLineLength);
                 $result .= "\n/* cache key: {$key} */";
                 break;
             case 'minify-css':
                 $result = CSSMin::minify($data);
                 $result .= "\n/* cache key: {$key} */";
                 break;
         }
         // Save filtered text to Memcached
         $cache->set($key, $result);
     } catch (Exception $exception) {
         // Return exception as a comment
         $result = $this->makeComment($exception->__toString());
     }
     wfProfileOut(__METHOD__);
     return $result;
 }
Exemple #29
0
 function getFirstLetterData()
 {
     if ($this->firstLetterData !== null) {
         return $this->firstLetterData;
     }
     $cache = wfGetCache(CACHE_ANYTHING);
     $cacheKey = wfMemcKey('first-letters', $this->locale, $this->digitTransformLanguage->getCode(), self::getICUVersion());
     $cacheEntry = $cache->get($cacheKey);
     if ($cacheEntry && isset($cacheEntry['version']) && $cacheEntry['version'] == self::FIRST_LETTER_VERSION) {
         $this->firstLetterData = $cacheEntry;
         return $this->firstLetterData;
     }
     // Generate data from serialized data file
     if (isset(self::$tailoringFirstLetters[$this->locale])) {
         $letters = wfGetPrecompiledData("first-letters-root.ser");
         // Append additional characters
         $letters = array_merge($letters, self::$tailoringFirstLetters[$this->locale]);
         // Remove unnecessary ones, if any
         if (isset(self::$tailoringFirstLetters['-' . $this->locale])) {
             $letters = array_diff($letters, self::$tailoringFirstLetters['-' . $this->locale]);
         }
         // Apply digit transforms
         $digits = array('0', '1', '2', '3', '4', '5', '6', '7', '8', '9');
         $letters = array_diff($letters, $digits);
         foreach ($digits as $digit) {
             $letters[] = $this->digitTransformLanguage->formatNum($digit, true);
         }
     } else {
         $letters = wfGetPrecompiledData("first-letters-{$this->locale}.ser");
         if ($letters === false) {
             throw new MWException("MediaWiki does not support ICU locale " . "\"{$this->locale}\"");
         }
     }
     /* Sort the letters.
      *
      * It's impossible to have the precompiled data file properly sorted,
      * because the sort order changes depending on ICU version. If the
      * array is not properly sorted, the binary search will return random
      * results.
      *
      * We also take this opportunity to remove primary collisions.
      */
     $letterMap = array();
     foreach ($letters as $letter) {
         $key = $this->getPrimarySortKey($letter);
         if (isset($letterMap[$key])) {
             // Primary collision
             // Keep whichever one sorts first in the main collator
             if ($this->mainCollator->compare($letter, $letterMap[$key]) < 0) {
                 $letterMap[$key] = $letter;
             }
         } else {
             $letterMap[$key] = $letter;
         }
     }
     ksort($letterMap, SORT_STRING);
     /* Remove duplicate prefixes. Basically if something has a sortkey
      * which is a prefix of some other sortkey, then it is an
      * expansion and probably should not be considered a section
      * header.
      *
      * For example 'þ' is sometimes sorted as if it is the letters
      * 'th'. Other times it is its own primary element. Another
      * example is '₨'. Sometimes its a currency symbol. Sometimes it
      * is an 'R' followed by an 's'.
      *
      * Additionally an expanded element should always sort directly
      * after its first element due to they way sortkeys work.
      *
      * UCA sortkey elements are of variable length but no collation
      * element should be a prefix of some other element, so I think
      * this is safe. See:
      * - https://ssl.icu-project.org/repos/icu/icuhtml/trunk/design/collation/ICU_collation_design.htm
      * - http://site.icu-project.org/design/collation/uca-weight-allocation
      *
      * Additionally, there is something called primary compression to
      * worry about. Basically, if you have two primary elements that
      * are more than one byte and both start with the same byte then
      * the first byte is dropped on the second primary. Additionally
      * either \x03 or \xFF may be added to mean that the next primary
      * does not start with the first byte of the first primary.
      *
      * This shouldn't matter much, as the first primary is not
      * changed, and that is what we are comparing against.
      *
      * tl;dr: This makes some assumptions about how icu implements
      * collations. It seems incredibly unlikely these assumptions
      * will change, but nonetheless they are assumptions.
      */
     $prev = false;
     $duplicatePrefixes = array();
     foreach ($letterMap as $key => $value) {
         // Remove terminator byte. Otherwise the prefix
         // comparison will get hung up on that.
         $trimmedKey = rtrim($key, "");
         if ($prev === false || $prev === '') {
             $prev = $trimmedKey;
             // We don't yet have a collation element
             // to compare against, so continue.
             continue;
         }
         // Due to the fact the array is sorted, we only have
         // to compare with the element directly previous
         // to the current element (skipping expansions).
         // An element "X" will always sort directly
         // before "XZ" (Unless we have "XY", but we
         // do not update $prev in that case).
         if (substr($trimmedKey, 0, strlen($prev)) === $prev) {
             $duplicatePrefixes[] = $key;
             // If this is an expansion, we don't want to
             // compare the next element to this element,
             // but to what is currently $prev
             continue;
         }
         $prev = $trimmedKey;
     }
     foreach ($duplicatePrefixes as $badKey) {
         wfDebug("Removing '{$letterMap[$badKey]}' from first letters.\n");
         unset($letterMap[$badKey]);
         // This code assumes that unsetting does not change sort order.
     }
     $data = array('chars' => array_values($letterMap), 'keys' => array_keys($letterMap), 'version' => self::FIRST_LETTER_VERSION);
     // Reduce memory usage before caching
     unset($letterMap);
     // Save to cache
     $this->firstLetterData = $data;
     $cache->set($cacheKey, $data, $cache::TTL_WEEK);
     return $data;
 }
Exemple #30
0
 /**
  * Runs 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 $filter String: Name of filter to run
  * @param $data String: Text to filter, such as JavaScript or CSS text
  * @return String: Filtered data, or a comment containing an error message
  */
 protected function filter($filter, $data)
 {
     global $wgResourceLoaderMinifierStatementsOnOwnLine, $wgResourceLoaderMinifierMaxLineLength;
     wfProfileIn(__METHOD__);
     // 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'))) {
         wfProfileOut(__METHOD__);
         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)) {
         wfProfileOut(__METHOD__);
         return $cacheEntry;
     }
     $result = '';
     // Run the filter - we've already verified one of these will work
     try {
         switch ($filter) {
             case 'minify-js':
                 // Wikia - change begin - @author: wladek
                 global $wgResourceLoaderJavascriptMinifier;
                 $minifierCallback = 'JavaScriptMinifier::minify';
                 if (!empty($wgResourceLoaderJavascriptMinifier)) {
                     $minifierCallback = $wgResourceLoaderJavascriptMinifier;
                 }
                 if (!is_callable($minifierCallback)) {
                     throw new MWException('ResourceLoader invalid javascript minifier: ' . $minifierCallback);
                 }
                 $result = call_user_func($minifierCallback, $data, $wgResourceLoaderMinifierStatementsOnOwnLine, $wgResourceLoaderMinifierMaxLineLength);
                 // Wikia - change end
                 $result .= "\n\n/* cache key: {$key} */\n";
                 break;
             case 'minify-css':
                 // Wikia - change begin - @author: wladek
                 global $wgResourceLoaderCssMinifier;
                 $minifierCallback = 'CSSMin::minify';
                 if (!empty($wgResourceLoaderCssMinifier)) {
                     $minifierCallback = $wgResourceLoaderCssMinifier;
                 }
                 if (!is_callable($minifierCallback)) {
                     throw new MWException('ResourceLoader invalid css minifier: ' . $minifierCallback);
                 }
                 $result = call_user_func($minifierCallback, $data);
                 // Wikia - change end
                 $result .= "\n\n/* cache key: {$key} */\n";
                 break;
         }
         // Save filtered text to Memcached
         $cache->set($key, $result);
     } catch (Exception $exception) {
         // Return exception as a comment
         $result = $this->formatException($exception);
     }
     wfProfileOut(__METHOD__);
     return $result;
 }