public function __construct(WebRequest $request) { parent::__construct($request); global $IP; if (strpos($this->mOid, '..') !== false) { throw new Exception('File path must not contain \'..\'.'); } if (endsWith($this->mOid, '.js', false)) { $this->mContentType = AssetsManager::TYPE_JS; } else { if (endsWith($this->mOid, '.css', false)) { $this->mContentType = AssetsManager::TYPE_CSS; } else { throw new Exception('Requested file must be .css or .js.'); } } $filePath = $IP . '/' . $this->mOid; if (file_exists($filePath)) { $this->mContent = file_get_contents($filePath); } else { $requestDetails = AssetsManager::getRequestDetails(); Wikia::log(__METHOD__, false, "file '{$filePath}' doesn't exist ({$requestDetails})", true); throw new Exception('File does not exist'); } }
public function getContent() { wfProfileIn(__METHOD__); $processingTimeStart = null; if ($this->mForceProfile) { $processingTimeStart = microtime(true); } $hash = wfAssetManagerGetSASShash($this->mOid); $paramsHash = md5(urldecode(http_build_query($this->mParams, '', ' '))); $cacheId = "/Sass-{$paramsHash}-{$hash}-" . self::CACHE_VERSION; $memc = F::App()->wg->Memc; $cachedContent = $memc->get($cacheId); if ($cachedContent) { $this->mContent = $cachedContent; } else { $this->processContent(); // This is the final pass on contents which, among other things, performs minification parent::getContent($processingTimeStart); // Prevent cache poisoning if we are serving sass from preview server if (getHostPrefix() == null && !$this->mForceProfile) { $memc->set($cacheId, $this->mContent); } } wfProfileOut(__METHOD__); return $this->mContent; }
public function __construct(WebRequest $request) { parent::__construct($request); global $IP, $wgUser; $ac = new AssetsConfig(); $assets = $ac->resolve($this->mOid, true, !isset($this->mParams['minify']) || $this->mParams['minify'] == true, $this->mParams); $this->mContentType = $ac->getGroupType($this->mOid); foreach ($assets as $asset) { // reference to a file to be fetched by the browser from external server (BugId:9522) if (substr($asset, 0, 10) == '#external_') { // do nothing } else { if (Http::isValidURI($asset)) { $params = array(); $url = parse_url($asset); if (isset($url['query'])) { parse_str($url['query'], $params); } // Start checking the url to see if it is something we care about (BugId:30188) if (isset($params['action']) && $params['action'] == 'raw' && isset($params['gen']) && $params['gen'] == 'js') { //$this->mContent .= RequestContext::getMain()->getSkin()->generateUserJs(); // FIXME } else { if (isset($params['action']) && $params['action'] == 'raw' && isset($params['gen']) && $params['gen'] == 'css') { //$this->mContent .= RequestContext::getMain()->getSkin()->generateUserStylesheet(); // FIXME } else { //Debug added on May 4, 2012 to inquire external requests spikes $start = microtime(true); $this->mContent .= HTTP::get($asset); $totalTime = microtime(true) - $start; if ($totalTime >= 1) { Wikia::log(__METHOD__, false, "oid: {$this->mOid}, totalTime: {$totalTime}, asset: {$asset}, referrer: {$_SERVER['HTTP_REFERER']}, entrypoint: {$_SERVER['HTTP_HOST']}{$_SERVER['REQUEST_URI']}", true); } } } } else { $this->mContent .= file_get_contents($IP . '/' . $asset); } } if ($this->mContentType == AssetsManager::TYPE_JS) { // add semicolon to separate concatenated files (BugId:20272) // but only for JS (BugId:20824) $this->mContent .= ";\n"; } } // For RTE only // TODO: add "filters" definitions to config.php if ($this->mOid == 'rte' || $this->mOid == 'eplrte' || $this->mOid == 'mini_editor_rte_js') { $this->mContent = preg_replace('#^.*@Packager\\.RemoveLine.*$#m', '', $this->mContent); $this->mContent = str_replace("", '', $this->mContent); } }
public function __construct(WebRequest $request) { parent::__construct($request); $groups = explode(',', $this->mOid); foreach ($groups as $groupName) { // fake request to a group $groupRequest = new WebRequest(); $groupRequest->setVal('type', 'group'); $groupRequest->setVal('oid', $groupName); $builder = new AssetsManagerGroupBuilder($groupRequest); $this->mContent .= "\n\n" . $builder->getContent(); $this->mContentType = $builder->getContentType(); } }
public function __construct(WebRequest $request) { parent::__construct($request); $files = explode(',', $this->mOid); foreach ($files as $file) { // fake single SASS file request $sassRequest = new WebRequest(); $sassRequest->setVal('type', 'sass'); $sassRequest->setVal('oid', $file); $builder = new AssetsManagerSassBuilder($sassRequest); $this->mContent .= "\n\n/* {$file} */\n" . $builder->getContent(); } $this->mContentType = AssetsManager::TYPE_CSS; }
public function getContent($processingTimeStart = null) { global $IP, $wgEnableSASSSourceMaps; wfProfileIn(__METHOD__); $processingTimeStart = null; if ($this->mForceProfile) { $processingTimeStart = microtime(true); } $memc = F::App()->wg->Memc; $this->mContent = null; $content = null; $sassService = null; $hasErrors = false; try { $sassService = SassService::newFromFile("{$IP}/{$this->mOid}"); $sassService->setSassVariables($this->mParams); $sassService->enableSourceMaps(!empty($wgEnableSASSSourceMaps)); $sassService->setFilters(SassService::FILTER_IMPORT_CSS | SassService::FILTER_CDN_REWRITE | SassService::FILTER_BASE64 | SassService::FILTER_JANUS); $cacheId = __CLASS__ . "-minified-" . $sassService->getCacheKey(); $content = $memc->get($cacheId); } catch (Exception $e) { $content = "/* {$e->getMessage()} */"; $hasErrors = true; } if ($content) { $this->mContent = $content; } else { // todo: add extra logging of AM request in case of any error try { $this->mContent = $sassService->getCss(false); } catch (Exception $e) { $this->mContent = $this->makeComment($e->getMessage()); $hasErrors = true; } // This is the final pass on contents which, among other things, performs minification parent::getContent($processingTimeStart); // Prevent cache poisoning if we are serving sass from preview server if (!empty($cacheId) && getHostPrefix() == null && !$this->mForceProfile && !$hasErrors) { $memc->set($cacheId, $this->mContent, WikiaResponse::CACHE_STANDARD); } } if ($hasErrors) { wfProfileOut(__METHOD__); throw new Exception($this->mContent); } wfProfileOut(__METHOD__); return $this->mContent; }
/** * Load an 'onerror' handler that forwards js errors to a log. * * @param array $vars * @param string $scripts * @return boolean * */ public static function onWikiaSkinTopScripts(&$vars, &$scripts) { global $wgDevelEnvironment, $wgIsGASpecialWiki, $wgEnableJavaScriptErrorLogging, $wgCacheBuster, $wgMemc; if (!$wgDevelEnvironment) { $onError = $wgIsGASpecialWiki || $wgEnableJavaScriptErrorLogging; $key = "wikialogger-top-script-{$onError}"; $loggingJs = $wgMemc->get($key); if (!$loggingJs) { $errorUrl = "//jserrorslog.wikia.com/"; $loggingJs = "\n\t\t\t\t\tfunction syslogReport(priority, message, context) {\n\t\t\t\t\t\tcontext = context || null;\n\t\t\t\t\t\tvar url = '{$errorUrl}',\n\t\t\t\t\t\t\ti = new Image(),\n\t\t\t\t\t\t\tdata = {\n\t\t\t\t\t\t\t\t'@message': message,\n\t\t\t\t\t\t\t\t'syslog_pri': priority\n\t\t\t\t\t\t\t};\n\n\t\t\t\t\t\tif (context) {\n\t\t\t\t\t\t\tdata['@context'] = context;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tdata['@fields'] = { server: document.cookie.match(/server.([A-Z]*).cache/)[1] };\n\t\t\t\t\t\t} catch (e) {}\n\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\ti.src = url+'l?'+JSON.stringify(data);\n\t\t\t\t\t\t} catch (e) {\n\t\t\t\t\t\t\ti.src = url+'e?'+e;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t"; if ($onError) { $loggingJs .= "\n\t\t\t\t\t\twindow.onerror = function(m, u, l) {\n\t\t\t\t\t\t\tif (Math.random() < 0.01) {\n\t\t\t\t\t\t\t\tsyslogReport(3, m, {'url': u, 'line': l}); // 3 is 'error'\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t}\n\t\t\t\t\t"; } $loggingJs = \AssetsManagerBaseBuilder::minifyJS($loggingJs); $wgMemc->set($key, $loggingJs, 60 * 60 * 24); } $scripts = "<script>{$loggingJs}</script>{$scripts}"; } return true; }
public static function getLiftiumOptionsScript() { wfProfileIn(__METHOD__); global $wgDBname, $wgTitle, $wgLang; // See Liftium.js for documentation on options $options = array(); $options['pubid'] = 999; $options['baseUrl'] = '/__varnish_liftium/'; $options['kv_wgDBname'] = $wgDBname; if (is_object($wgTitle)) { $options['kv_article_id'] = $wgTitle->getArticleID(); $options['kv_wpage'] = $wgTitle->getPartialURL(); } $cat = AdEngine::getCachedCategory(); $options['kv_Hub'] = $cat['name']; $options['kv_skin'] = RequestContext::getMain()->getSkin()->getSkinName(); $options['kv_user_lang'] = $wgLang->getCode(); $options['kv_cont_lang'] = $GLOBALS['wgLanguageCode']; $options['kv_isMainPage'] = WikiaPageType::isMainPage(); $options['kv_page_type'] = WikiaPageType::getPageType(); $options['geoUrl'] = "http://geoiplookup.wikia.com/"; if (!empty($wgDartCustomKeyValues)) { $options['kv_dart'] = $wgDartCustomKeyValues; } $options['kv_domain'] = $_SERVER['HTTP_HOST']; $js = "LiftiumOptions = " . json_encode($options) . ";\n"; if (WikiaPageType::isSearch() || !$wgTitle->getNamespace() == NS_SPECIAL && !BodyController::isEditPage()) { $js .= <<<EOT \t\t\t\tif ( !window.wgLoadAdDriverOnLiftiumInit && ( !window.Wikia.AbTest || !Wikia.AbTest.inTreatmentGroup( "AD_LOAD_TIMING", "ONLOAD" ) ) ) { \t\t\t\t\tLiftiumOptions['hasMoreCalls'] = true; \t\t\t\t\tLiftiumOptions['isCalledAfterOnload'] = true; \t\t\t\t\tLiftiumOptions['maxLoadDelay'] = 6000; \t\t\t\t} \t\t\t\telse { \t\t\t\t\tLiftiumOptions['autoInit'] = false; \t\t\t\t} EOT; } else { $js .= <<<EOT \t\t\t\tLiftiumOptions['hasMoreCalls'] = true; \t\t\t\tLiftiumOptions['isCalledAfterOnload'] = true; \t\t\t\tLiftiumOptions['maxLoadDelay'] = 6000; EOT; } $js = AssetsManagerBaseBuilder::minifyJs($js); $out = "\n<!-- Liftium options -->\n"; $out .= Html::inlineScript($js) . "\n"; wfProfileOut(__METHOD__); return $out; }
/** * Returns a string that contains minified javascript of a small function stub which will * spool any calls to WikiaTracker.trackEvent until the code is actually loaded for doing the tracking (at * which point the calls will be replayed). */ public static function getTrackerSpoolingJs() { global $wgCacheBuster, $wgMemc, $wgDevelEnvironment; wfProfileIn(__METHOD__); // This code will spool all of the calls (in the order they were called) and different code will replay them later. // The wikiatracker implememtation will be replaced directly as soon as the correct file will load. ob_start(); ?> window.WikiaTracker = window.WikiaTracker || { trackEvent: function(eventName, params, method){ wikiaTrackingSpool.push([eventName, params, method]); } }; <?php $jsString = ob_get_clean(); // We're embedding this in every page, so minify it. Minifying takes a while, so cache it in memcache (BugzId 43421). if (!empty($wgDevelEnvironment)) { $memcKey = wfMemcKey('tracker_spooling_js'); // cachebuster changes on every pageview in dev... this will cache on devboxes anyway. } else { $memcKey = wfMemcKey('tracker_spooling_js', $wgCacheBuster); } $cachedValue = $wgMemc->get($memcKey); if (!$cachedValue) { $jsString = AssetsManagerBaseBuilder::minifyJs($jsString); // This code doesn't look like it should change almost at all, so we give it a long duration (cachebuster also purges it because that's in the key). // Warning: Memcached expirations work strangely around the one-month boundary (if the duration is too long, it interprets it as a timestamp instead of a duration). $TWO_WEEKS = 60 * 60 * 24 * 14; // in seconds. $wgMemc->set($memcKey, $jsString, $TWO_WEEKS); } else { $jsString = $cachedValue; } wfProfileOut(__METHOD__); return $jsString; }