/** * @param ResourceLoader $resourceLoader * @param WebRequest $request */ public function __construct(ResourceLoader $resourceLoader, WebRequest $request) { $this->resourceLoader = $resourceLoader; $this->request = $request; $this->logger = $resourceLoader->getLogger(); // Future developers: Avoid use of getVal() in this class, which performs // expensive UTF normalisation by default. Use getRawVal() instead. // Values here are either one of a finite number of internal IDs, // or previously-stored user input (e.g. titles, user names) that were passed // to this endpoint by ResourceLoader itself from the canonical value. // Values do not come directly from user input and need not match. // List of modules $modules = $request->getRawVal('modules'); $this->modules = $modules ? self::expandModuleNames($modules) : []; // Various parameters $this->user = $request->getRawVal('user'); $this->debug = $request->getFuzzyBool('debug', $resourceLoader->getConfig()->get('ResourceLoaderDebug')); $this->only = $request->getRawVal('only', null); $this->version = $request->getRawVal('version', null); $this->raw = $request->getFuzzyBool('raw'); // Image requests $this->image = $request->getRawVal('image'); $this->variant = $request->getRawVal('variant'); $this->format = $request->getRawVal('format'); $this->skin = $request->getRawVal('skin'); $skinnames = Skin::getSkinNames(); // If no skin is specified, or we don't recognize the skin, use the default skin if (!$this->skin || !isset($skinnames[$this->skin])) { $this->skin = $resourceLoader->getConfig()->get('DefaultSkin'); } }
public function execute() { $result = false; $resourceLoader = new ResourceLoader(); foreach ($resourceLoader->getModuleNames() as $name) { /** @var ResourceLoaderFileModule $module */ $module = $resourceLoader->getModule($name); if (!$module || !$module instanceof ResourceLoaderFileModule) { continue; } $hadErrors = false; foreach ($module->getAllStyleFiles() as $file) { if ($module->getStyleSheetLang($file) !== 'less') { continue; } try { $compiler = ResourceLoader::getLessCompiler(); $compiler->compileFile($file); } catch (Exception $e) { if (!$hadErrors) { $this->error("Errors checking module {$name}:\n"); $hadErrors = true; } $this->error($e->getMessage() . "\n"); $result = true; } } } if (!$result) { $this->output("No errors found\n"); } else { die(1); } }
/** * @param ResourceLoader $resourceLoader * @param WebRequest $request */ public function __construct(ResourceLoader $resourceLoader, WebRequest $request) { $this->resourceLoader = $resourceLoader; $this->request = $request; // Interpret request // List of modules $modules = $request->getVal('modules'); $this->modules = $modules ? self::expandModuleNames($modules) : array(); // Various parameters $this->skin = $request->getVal('skin'); $this->user = $request->getVal('user'); $this->debug = $request->getFuzzyBool('debug', $resourceLoader->getConfig()->get('ResourceLoaderDebug')); $this->only = $request->getVal('only'); $this->version = $request->getVal('version'); $this->raw = $request->getFuzzyBool('raw'); // Image requests $this->image = $request->getVal('image'); $this->variant = $request->getVal('variant'); $this->format = $request->getVal('format'); $skinnames = Skin::getSkinNames(); // If no skin is specified, or we don't recognize the skin, use the default skin if (!$this->skin || !isset($skinnames[$this->skin])) { $this->skin = $resourceLoader->getConfig()->get('DefaultSkin'); } }
public function execute() { $dbw = wfGetDB(DB_MASTER); $rl = new ResourceLoader(ConfigFactory::getDefaultInstance()->makeConfig('main')); $moduleNames = $rl->getModuleNames(); $moduleList = implode(', ', array_map(array($dbw, 'addQuotes'), $moduleNames)); $limit = max(1, intval($this->getOption('batchsize', 500))); $this->output("Cleaning up module_deps table...\n"); $i = 1; $modDeps = $dbw->tableName('module_deps'); do { // $dbw->delete() doesn't support LIMIT :( $where = $moduleList ? "md_module NOT IN ({$moduleList})" : '1=1'; $dbw->query("DELETE FROM {$modDeps} WHERE {$where} LIMIT {$limit}", __METHOD__); $numRows = $dbw->affectedRows(); $this->output("Batch {$i}: {$numRows} rows\n"); $i++; wfWaitForSlaves(); } while ($numRows > 0); $this->output("done\n"); $this->output("Cleaning up msg_resource table...\n"); $i = 1; $mrRes = $dbw->tableName('msg_resource'); do { $where = $moduleList ? "mr_resource NOT IN ({$moduleList})" : '1=1'; $dbw->query("DELETE FROM {$mrRes} WHERE {$where} LIMIT {$limit}", __METHOD__); $numRows = $dbw->affectedRows(); $this->output("Batch {$i}: {$numRows} rows\n"); $i++; wfWaitForSlaves(); } while ($numRows > 0); $this->output("done\n"); }
/** * @param ResourceLoader $rl * @return bool */ public static function onResourceLoaderRegisterModules(ResourceLoader $rl) { $moduleDependencies = array('mediawiki.api', 'mediawiki.RegExp', 'mediawiki.Title', 'mediawiki.jqueryMsg', 'mediawiki.Uri', 'moment', 'jquery.jStorage', 'jquery.client', 'jquery.hidpi'); // If EventLogging is present, add the schema as a dependency. if (class_exists('ResourceLoaderSchemaModule')) { $moduleDependencies[] = "schema.Popups"; } $rl->register("ext.popups", array('scripts' => array('resources/ext.popups.core.js', 'resources/ext.popups.logger.js', 'resources/ext.popups.renderer.js', 'resources/ext.popups.renderer.article.js', 'resources/ext.popups.disablenavpop.js', 'resources/ext.popups.settings.js'), 'styles' => array('resources/ext.popups.core.less', 'resources/ext.popups.animation.less', 'resources/ext.popups.settings.less'), 'dependencies' => $moduleDependencies, 'messages' => array('popups-last-edited', "popups-settings-title", "popups-settings-description", "popups-settings-option-simple", "popups-settings-option-simple-description", "popups-settings-option-advanced", "popups-settings-option-advanced-description", "popups-settings-option-off", "popups-settings-option-off-description", "popups-settings-save", "popups-settings-cancel", "popups-settings-enable", "popups-settings-help", "popups-settings-help-ok", "popups-send-feedback"), 'remoteExtPath' => 'Popups', 'localBasePath' => __DIR__)); return true; }
public static function onResourceLoaderRegisterModules(ResourceLoader &$resourceLoader) { global $wgFlowEventLogging, $wgResourceModules; // Only if EventLogging in Flow is enabled & EventLogging exists if ($wgFlowEventLogging && class_exists('ResourceLoaderSchemaModule')) { $resourceLoader->register('schema.FlowReplies', array('class' => 'ResourceLoaderSchemaModule', 'schema' => 'FlowReplies', 'revision' => 10561344)); // Add as dependency to Flow JS $wgResourceModules['ext.flow']['dependencies'][] = 'schema.FlowReplies'; } return true; }
/** * ResourceLoaderRegisterModules hook * * Adds modules to ResourceLoader * * @param ResourceLoader $resourceLoader * @return bool */ public static function resourceLoaderRegisterModules(&$resourceLoader) { global $wgAPIModules; if (array_key_exists('titleblacklist', $wgAPIModules)) { self::$modules['ext.uploadWizard']['dependencies'][] = 'mediawiki.api.titleblacklist'; } if (class_exists('ResourceLoaderSchemaModule')) { self::$modules['ext.uploadWizard.events']['dependencies'] = array('ext.eventLogging', 'schema.UploadWizardTutorialActions', 'schema.UploadWizardUploadActions'); self::$modules['uw.EventFlowLogger']['dependencies'] += array('ext.eventLogging', 'schema.UploadWizardStep', 'schema.UploadWizardFlowEvent', 'schema.UploadWizardErrorFlowEvent', 'schema.UploadWizardExceptionFlowEvent', 'schema.UploadWizardUploadFlowEvent'); } foreach (self::$modules as $name => $resources) { $resourceLoader->register($name, $resources + array('localBasePath' => __DIR__, 'remoteExtPath' => 'UploadWizard')); } return true; }
public function testLessFileCompilation() { $thisString = $this->toString(); $this->assertTrue(is_string($this->file) && is_file($this->file) && is_readable($this->file), "{$thisString} must refer to a readable file"); $compiler = ResourceLoader::getLessCompiler(RequestContext::getMain()->getConfig()); $this->assertNotNull($compiler->compileFile($this->file)); }
private function getFileLocation($file) { $pathToFile = stripos($file, ".js") === false ? parent::getCSSPath() : parent::getJSPath(); //trim the first forward slash off, since PHP doesn't look at the file system the same way apache would from the HTML file. $currentFile = substr("{$pathToFile}{$file}", 1); return $currentFile; }
protected static function registerAssetsManagerGroups(ResourceLoader $resourceLoader) { if (empty(self::$assetsManagerGroups)) { return true; } $assetsConfig = new AssetsConfig(); foreach (self::$assetsManagerGroups as $moduleName => $groupName) { $type = $assetsConfig->getGroupType($groupName); $key = null; switch ($type) { case AssetsManager::TYPE_JS: $key = 'scripts'; break; case AssetsManager::TYPE_CSS: case AssetsManager::TYPE_SCSS: $key = 'styles'; break; } if (empty($key)) { // todo: log error continue; } $assets = $assetsConfig->resolve($groupName, false, false); foreach ($assets as $k => $v) { if (!preg_match('#^(extensions|resources|skins)/#', $v)) { unset($assets[$k]); } } $assets = array_values($assets); $module = array(); $module[$key] = $assets; $resourceLoader->register($moduleName, $module); } return true; }
/** * 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; }
/** * @group Slow * @slowExecutionTime 0.01651 ms * @dataProvider resourceLoaderModifyMaxAgeDataProvider * * @param $timestamp int timestamp in URL * @param $ttl int expected caching period */ public function testResourceLoaderModifyMaxAge($version, $ttl) { global $wgHooks; $resourceLoader = new ResourceLoader(); $resourceLoader->register('WikiaTestModule', array('class' => 'TestResourceLoaderModule')); $request = new WebRequest(); $request->setVal('modules', 'WikiaTestModule'); $request->setVal('version', join('-', $version)); // set up hooks $wgHooks['ResourceLoaderCacheControlHeaders'][] = 'ResourceLoaderTest::onResourceLoaderCacheControlHeaders'; ob_start(); $resourceLoader->respond(new ResourceLoaderContext($resourceLoader, $request)); ob_end_clean(); // hook ResourceLoaderHooks::onResourceLoaderModifyMaxAge was called // check modified caching period with expected one $this->assertEquals($ttl, self::$ttl, 'TTL should match expected value'); }
/** * Get all registered modules from ResouceLoader. */ protected static function getAllModules() { global $wgEnableJavaScriptTest; // Test existance of test suite files as well // (can't use setUp or setMwGlobals because providers are static) $org_wgEnableJavaScriptTest = $wgEnableJavaScriptTest; $wgEnableJavaScriptTest = true; // Initialize ResourceLoader $rl = new ResourceLoader(); $modules = array(); foreach ($rl->getModuleNames() as $moduleName) { $modules[$moduleName] = $rl->getModule($moduleName); } // Restore settings $wgEnableJavaScriptTest = $org_wgEnableJavaScriptTest; return array('modules' => $modules, 'resourceloader' => $rl, 'context' => new ResourceLoaderContext($rl, new FauxRequest())); }
public function test() { $loader = new ResourceLoader(); $definitions = new Definition($loader->load($this->source)); foreach ($definitions->getExpectations() as $definition) { if (null !== $definition['type']) { $actual = $loader->getType($definition['uri']); if ($actual !== $definition['type']) { throw new FailedExpectationException("Type mismatch for {$definition['uri']}. Got [{$actual}] but expected [{$definition['type']}]"); } } $expectation = new Expectation($definition['expected']); if (!$expectation->assert($loader->load($definition['uri']))) { throw new FailedExpectationException(implode("\n", $expectation->getMessages())); } } return true; }
/** * @param ResourceLoaderContext $context * @return array */ public function getStyles(ResourceLoaderContext $context) { $geshi = SyntaxHighlight_GeSHi::prepare('', $this->lang); if (!$geshi->error) { $css = SyntaxHighlight_GeSHi::getCSS($geshi); } else { $css = ResourceLoader::makeComment($geshi->error()); } return array('all' => $css); }
protected function setUp() { parent::setUp(); ResourceLoader::clearCache(); $globals = []; foreach (self::getSettings() as $key => $value) { $globals['wg' . $key] = $value; } $this->setMwGlobals($globals); }
public function __construct() { parent::__construct(); $resourceLoader = new ResourceLoader(); foreach ($resourceLoader->getModuleNames() as $name) { $module = $resourceLoader->getModule($name); if (!$module || !$module instanceof ResourceLoaderFileModule) { continue; } foreach ($module->getAllStyleFiles() as $styleFile) { // TODO (phuedx, 2014-03-19) The // ResourceLoaderFileModule class shouldn't // know how to get a file's extension. if ($module->getStyleSheetLang($styleFile) !== 'less') { continue; } $this->addTest(new LessFileCompilationTest($styleFile, $module)); } } }
public function testValidation() { $module = $this->makeModule(array('foo')); $rl = new ResourceLoader(); $rl->register($module->getName(), $module); $blobStore = $this->makeBlobStore(array('fetchMessage'), $rl); $blobStore->expects($this->once())->method('fetchMessage')->will($this->returnValueMap(array(array('foo', 'en', 'Hello')))); $blob = $blobStore->getBlob($module, 'en'); $this->assertEquals('{"foo":"Hello"}', $blob, 'Generated blob'); // Now, imagine a change to the module is deployed. The module now contains // message 'foo' and 'bar'. While updateMessage() was not called (since no // message values were changed) it should detect the change in list of // message keys. $module = $this->makeModule(array('foo', 'bar')); $rl = new ResourceLoader(); $rl->register($module->getName(), $module); $blobStore = $this->makeBlobStore(array('fetchMessage'), $rl); $blobStore->expects($this->exactly(2))->method('fetchMessage')->will($this->returnValueMap(array(array('foo', 'en', 'Hello'), array('bar', 'en', 'World')))); $blob = $blobStore->getBlob($module, 'en'); $this->assertEquals('{"foo":"Hello","bar":"World"}', $blob, 'Updated blob'); }
/** * @dataProvider lessProvider */ public function testLessFile($lessFile) { $cssFile = substr($lessFile, 0, -4) . 'css'; if (!file_exists($cssFile)) { $this->fail("No css file found to assert equal to {$lessFile}"); return; } $expect = file_get_contents($cssFile); $content = file_get_contents($lessFile); $result = ResourceLoader::getLessCompiler(RequestContext::getMain()->getConfig())->compile($content, $lessFile); $this->assertEquals($expect, $result); }
public function getScript(ResourceLoaderContext $context) { // Messages $msgInfo = $this->getMessageInfo(); $parsedMessages = array(); $messages = array(); foreach ($msgInfo['args'] as $msgKey => $msgArgs) { $parsedMessages[$msgKey] = call_user_func_array('wfMessage', $msgArgs)->inLanguage($context->getLanguage())->parse(); } foreach ($msgInfo['vals'] as $msgKey => $msgVal) { $messages[$msgKey] = $msgVal; } return 've.init.platform.addParsedMessages(' . FormatJson::encode($parsedMessages, ResourceLoader::inDebugMode()) . ');' . 've.init.platform.addMessages(' . FormatJson::encode($messages, ResourceLoader::inDebugMode()) . ');'; }
public function getScript(ResourceLoaderContext $context) { // Messages $msgInfo = $this->getMessageInfo(); $parsedMessages = array(); $messages = array(); foreach ($msgInfo['args'] as $msgKey => $msgArgs) { $parsedMessages[$msgKey] = call_user_func_array('wfMessage', $msgArgs)->inLanguage($context->getLanguage())->parse(); } foreach ($msgInfo['vals'] as $msgKey => $msgVal) { $messages[$msgKey] = $msgVal; } // Version information $language = Language::factory($context->getLanguage()); $hash = $this->getGitHeadHash(); $id = $hash ? substr($this->getGitHeadHash(), 0, 7) : false; $url = $this->gitInfo->getHeadViewUrl(); $date = $this->gitInfo->getHeadCommitDate(); $dateString = $date ? $language->timeanddate($date, true) : ''; return 've.init.platform.addParsedMessages(' . FormatJson::encode($parsedMessages, ResourceLoader::inDebugMode()) . ');' . 've.init.platform.addMessages(' . FormatJson::encode($messages, ResourceLoader::inDebugMode()) . ');' . 've.version = ' . FormatJson::encode(array('id' => $id, 'url' => $url, 'timestamp' => $date, 'dateString' => $dateString), ResourceLoader::inDebugMode()) . ';'; }
public function getContext(Title $title, $skinName) { $wrapper = new GlobalStateWrapper(['wgTitle' => $title]); $wg = F::app()->wg; return $wrapper->wrap(function () use($title, $wg, $skinName) { $wikiFactoryHub = WikiFactoryHub::getInstance(); $hubService = new HubService(); $adPageTypeService = new AdEngine2PageTypeService(); $wikiaPageType = new WikiaPageType(); $sevenOneMediaCombinedUrl = null; if (!empty($wg->AdDriverUseSevenOneMedia)) { // TODO: implicitly gets the skin from the context! $sevenOneMediaCombinedUrl = ResourceLoader::makeCustomURL($wg->Out, ['wikia.ext.adengine.sevenonemedia'], 'scripts'); } $monetizationServiceAds = null; if (!empty($wg->AdDriverUseMonetizationService) && !empty($wg->EnableMonetizationModuleExt)) { $monetizationServiceAds = F::app()->sendRequest('MonetizationModule', 'index')->getData()['data']; } $langCode = $title->getPageLanguage()->getCode(); return ['opts' => $this->filterOutEmptyItems(['adsInContent' => $wg->EnableAdsInContent, 'delayBtf' => $wg->AdDriverDelayBelowTheFold, 'enableAdsInMaps' => $wg->AdDriverEnableAdsInMaps, 'pageType' => $adPageTypeService->getPageType(), 'paidAssetDropConfig' => $wg->PaidAssetDropConfig, 'showAds' => $adPageTypeService->areAdsShowableOnPage(), 'trackSlotState' => $wg->AdDriverTrackState, 'usePostScribe' => $wg->Request->getBool('usepostscribe', false)]), 'targeting' => $this->filterOutEmptyItems(['enablePageCategories' => array_search($langCode, $wg->AdPageLevelCategoryLangs) !== false, 'pageArticleId' => $title->getArticleId(), 'pageIsArticle' => !!$title->getArticleId(), 'pageIsHub' => $wikiaPageType->isWikiaHub(), 'pageName' => $title->getPrefixedDBKey(), 'pageType' => $wikiaPageType->getPageType(), 'sevenOneMediaSub2Site' => $wg->AdDriverSevenOneMediaOverrideSub2Site, 'skin' => $skinName, 'wikiCategory' => $wikiFactoryHub->getCategoryShort($wg->CityId), 'wikiCustomKeyValues' => $wg->DartCustomKeyValues, 'wikiDbName' => $wg->DBname, 'wikiDirectedAtChildren' => $wg->WikiDirectedAtChildrenByFounder || $wg->WikiDirectedAtChildrenByStaff, 'wikiIsCorporate' => $wikiaPageType->isCorporatePage(), 'wikiIsTop1000' => $wg->AdDriverWikiIsTop1000, 'wikiLanguage' => $langCode, 'wikiVertical' => $hubService->getCategoryInfoForCity($wg->CityId)->cat_name]), 'providers' => $this->filterOutEmptyItems(['monetizationService' => $wg->AdDriverUseMonetizationService, 'monetizationServiceAds' => $monetizationServiceAds, 'sevenOneMedia' => $wg->AdDriverUseSevenOneMedia, 'sevenOneMediaCombinedUrl' => $sevenOneMediaCombinedUrl, 'taboola' => $wg->AdDriverUseTaboola]), 'slots' => $this->filterOutEmptyItems(['exitstitial' => $wg->EnableOutboundScreenExt, 'exitstitialRedirectDelay' => $wg->OutboundScreenRedirectDelay, 'invisibleHighImpact' => $wg->AdDriverEnableInvisibleHighImpactSlot]), 'forcedProvider' => $wg->AdDriverForcedProvider]; }); }
/** * @param $context ResourceLoaderContext * @return string */ public function getScript(ResourceLoaderContext $context) { global $IP, $wgLoadScript, $wgLegacyJavaScriptGlobals; $out = file_get_contents("{$IP}/resources/startup.js"); if ($context->getOnly() === 'scripts') { // The core modules: $modules = array('jquery', 'mediawiki'); wfRunHooks('ResourceLoaderGetStartupModules', array(&$modules)); // Get the latest version $version = 0; foreach ($modules as $moduleName) { $version = max($version, $context->getResourceLoader()->getModule($moduleName)->getModifiedTime($context)); } // Build load query for StartupModules $query = array('modules' => ResourceLoader::makePackedModulesString($modules), 'only' => 'scripts', 'lang' => $context->getLanguage(), 'skin' => $context->getSkin(), 'debug' => $context->getDebug() ? 'true' : 'false', 'version' => wfTimestamp(TS_ISO_8601_BASIC, $version)); // Ensure uniform query order ksort($query); // Startup function $configuration = $this->getConfig($context); $registrations = self::getModuleRegistrations($context); $out .= "var startUp = function() {\n" . "\tmw.config = new " . Xml::encodeJsCall('mw.Map', array($wgLegacyJavaScriptGlobals)) . "\n" . "\t{$registrations}\n" . "\t" . Xml::encodeJsCall('mw.config.set', array($configuration)) . "\t" . Xml::encodeJsCall('mw.loader.state', array(array('jquery' => 'ready'))) . "};\n"; // Conditional script injection // Wikia change - begin - @author: wladek // $scriptTag = Html::linkedScript( $wgLoadScript . '?' . wfArrayToCGI( $query ) ); // get jquery from CDN if we have wsl and getJqueryUrl loaded $scriptTagJquery = Xml::encodeJsVar(Html::linkedScript(ResourceLoader::makeLoaderURL($modules, $query['lang'], $query['skin'], null, $query['version'], $context->getDebug(), 'scripts'))); $scriptTagNoJquery = Xml::encodeJsVar(Html::linkedScript(ResourceLoader::makeLoaderURL(array('mediawiki'), $query['lang'], $query['skin'], null, $query['version'], $context->getDebug(), 'scripts'))); $scriptTag = <<<ENDSCRIPT ( (window.wsl && window.getJqueryUrl && window.wgJqueryUrl) ? (wsl.buildScript(window.getJqueryUrl()) + {$scriptTagNoJquery}) : ({$scriptTagJquery}) ) ENDSCRIPT; $scriptTag = new XmlJsCode($scriptTag); // Wikia change - end $out .= "if ( isCompatible() ) {\n" . "\t" . Xml::encodeJsCall('document.write', array($scriptTag)) . "}\n" . "delete isCompatible;"; } return $out; }
/** * @param $context ResourceLoaderContext * @return string */ public function getScript(ResourceLoaderContext $context) { return Xml::encodeJsCall('mw.user.tokens.set', array($this->contextUserTokens()), ResourceLoader::inDebugMode()); }
public function getTopScripts() { $scripts = ''; $vars = array('Wikia' => new stdClass(), 'wgJqueryUrl' => AssetsManager::getInstance()->getURL('jquery')); $this->wf->runHooks('WikiaSkinTopScripts', array(&$vars, &$scripts, $this)); $scriptModules = array(); $this->wf->runHooks('WikiaSkinTopModules', array(&$scriptModules, $this)); if (!empty($scriptModules)) { $scripts .= "<script>window.mw || ( window.mw = { loader: { state: function() {} } } );</script>"; $scripts .= ResourceLoader::makeCustomLink($this->wg->out, $scriptModules, 'scripts'); } return self::makeInlineVariablesScript($vars) . $scripts; }
/** * JS stuff to put at the 'bottom', which can either be the bottom of the * "<body>" or the bottom of the "<head>" depending on * $wgResourceLoaderExperimentalAsyncLoading: modules marked with position * 'bottom', legacy scripts ($this->mScripts), user preferences, site JS * and user JS. * * @param bool $inHead If true, this HTML goes into the "<head>", * if false it goes into the "<body>". * @return string */ function getScriptsForBottomQueue($inHead) { // Scripts "only" requests marked for bottom inclusion // If we're in the <head>, use load() calls rather than <script src="..."> tags $links = array(); $links[] = $this->makeResourceLoaderLink($this->getModuleScripts(true, 'bottom'), ResourceLoaderModule::TYPE_SCRIPTS, false, array(), $inHead); $links[] = $this->makeResourceLoaderLink($this->getModuleStyles(true, 'bottom'), ResourceLoaderModule::TYPE_STYLES, false, array(), $inHead); // Modules requests - let the client calculate dependencies and batch requests as it likes // Only load modules that have marked themselves for loading at the bottom $modules = $this->getModules(true, 'bottom'); if ($modules) { $links[] = ResourceLoader::makeInlineScript(Xml::encodeJsCall('mw.loader.load', array($modules, null, true))); } // Legacy Scripts $links[] = "\n" . $this->mScripts; // Add site JS if enabled $links[] = $this->makeResourceLoaderLink('site', ResourceLoaderModule::TYPE_SCRIPTS, false, array(), $inHead); // Add user JS if enabled if ($this->getConfig()->get('AllowUserJs') && $this->getUser()->isLoggedIn() && $this->getTitle() && $this->getTitle()->isJsSubpage() && $this->userCanPreview()) { # XXX: additional security check/prompt? // We're on a preview of a JS subpage // Exclude this page from the user module in case it's in there (bug 26283) $links[] = $this->makeResourceLoaderLink('user', ResourceLoaderModule::TYPE_SCRIPTS, false, array('excludepage' => $this->getTitle()->getPrefixedDBkey()), $inHead); // Load the previewed JS $links[] = Html::inlineScript("\n" . $this->getRequest()->getText('wpTextbox1') . "\n") . "\n"; // FIXME: If the user is previewing, say, ./vector.js, his ./common.js will be loaded // asynchronously and may arrive *after* the inline script here. So the previewed code // may execute before ./common.js runs. Normally, ./common.js runs before ./vector.js... } else { // Include the user module normally, i.e., raw to avoid it being wrapped in a closure. $links[] = $this->makeResourceLoaderLink('user', ResourceLoaderModule::TYPE_SCRIPTS, false, array(), $inHead); } // Group JS is only enabled if site JS is enabled. $links[] = $this->makeResourceLoaderLink('user.groups', ResourceLoaderModule::TYPE_COMBINED, false, array(), $inHead); return self::getHtmlFromLoaderLinks($links); }
/** * @param ResourceLoaderContext $context * @return string JavaScript code */ public function getScript(ResourceLoaderContext $context) { return Xml::encodeJsCall('mw.language.setSpecialCharacters', array($this->getData()), ResourceLoader::inDebugMode()); }
/** * JS stuff to put at the 'bottom', which goes at the bottom of the `<body>`. * These are modules marked with position 'bottom', legacy scripts ($this->mScripts), * site JS, and user JS. * * @param bool $unused Previously used to let this method change its output based * on whether it was called by getExternalHeadScripts() or getBottomScripts(). * @return string */ function getScriptsForBottomQueue($unused = null) { // Scripts "only" requests marked for bottom inclusion // If we're in the <head>, use load() calls rather than <script src="..."> tags $links = array(); $links[] = $this->makeResourceLoaderLink($this->getModuleScripts(true, 'bottom'), ResourceLoaderModule::TYPE_SCRIPTS); // Modules requests - let the client calculate dependencies and batch requests as it likes // Only load modules that have marked themselves for loading at the bottom $modules = $this->getModules(true, 'bottom'); if ($modules) { $links[] = ResourceLoader::makeInlineScript(Xml::encodeJsCall('mw.loader.load', array($modules))); } // Legacy Scripts $links[] = $this->mScripts; // Add user JS if enabled // This must use TYPE_COMBINED instead of only=scripts so that its request is handled by // mw.loader.implement() which ensures that execution is scheduled after the "site" module. if ($this->getConfig()->get('AllowUserJs') && $this->getUser()->isLoggedIn() && $this->getTitle() && $this->getTitle()->isJsSubpage() && $this->userCanPreview()) { // We're on a preview of a JS subpage. Exclude this page from the user module (T28283) // and include the draft contents as a raw script instead. $links[] = $this->makeResourceLoaderLink('user', ResourceLoaderModule::TYPE_COMBINED, array('excludepage' => $this->getTitle()->getPrefixedDBkey())); // Load the previewed JS $links[] = ResourceLoader::makeInlineScript(Xml::encodeJsCall('mw.loader.using', array(array('user', 'site'), new XmlJsCode('function () {' . Xml::encodeJsCall('$.globalEval', array($this->getRequest()->getText('wpTextbox1'))) . '}')))); // FIXME: If the user is previewing, say, ./vector.js, his ./common.js will be loaded // asynchronously and may arrive *after* the inline script here. So the previewed code // may execute before ./common.js runs. Normally, ./common.js runs before ./vector.js. // Similarly, when previewing ./common.js and the user module does arrive first, // it will arrive without common.js and the inline script runs after. // Thus running common after the excluded subpage. } else { // Include the user module normally, i.e., raw to avoid it being wrapped in a closure. $links[] = $this->makeResourceLoaderLink('user', ResourceLoaderModule::TYPE_COMBINED); } // Group JS is only enabled if site JS is enabled. $links[] = $this->makeResourceLoaderLink('user.groups', ResourceLoaderModule::TYPE_COMBINED); return self::getHtmlFromLoaderLinks($links); }
/** * Get global LESS variables. * * @param Config $config * @since 1.22 * @return array Map of variable names to string CSS values. */ public static function getLessVars(Config $config) { if (!self::$lessVars) { $lessVars = $config->get('ResourceLoaderLESSVars'); Hooks::run('ResourceLoaderGetLessVars', array(&$lessVars)); // Sort by key to ensure consistent hashing for cache lookups. ksort($lessVars); self::$lessVars = $lessVars; } return self::$lessVars; }
/** * Get the URL or URLs to load for this module's CSS in debug mode. * The default behavior is to return a load.php?only=styles URL for * the module, but file-based modules will want to override this to * load the files directly. See also getScriptURLsForDebug() * * @param $context ResourceLoaderContext: Context object * @return Array: array( mediaType => array( URL1, URL2, ... ), ... ) */ public function getStyleURLsForDebug(ResourceLoaderContext $context) { $url = ResourceLoader::makeLoaderURL(array($this->getName()), $context->getLanguage(), $context->getSkin(), $context->getUser(), $context->getVersion(), true, 'styles', $context->getRequest()->getBool('printable'), $context->getRequest()->getBool('handheld')); return array('all' => array($url)); }