public function getLanguage()
 {
     if ($this->language === self::INHERIT_VALUE) {
         return $this->context->getLanguage();
     }
     return $this->language;
 }
 public function getLanguage()
 {
     if (!is_null($this->language)) {
         return $this->language;
     } else {
         return $this->context->getLanguage();
     }
 }
 /**
  * @param ResourceLoaderContext $context
  * @return array
  */
 protected function getConfigSettings($context)
 {
     $hash = $context->getHash();
     if (isset($this->configVars[$hash])) {
         return $this->configVars[$hash];
     }
     global $wgContLang;
     $mainPage = Title::newMainPage();
     /**
      * Namespace related preparation
      * - wgNamespaceIds: Key-value pairs of all localized, canonical and aliases for namespaces.
      * - wgCaseSensitiveNamespaces: Array of namespaces that are case-sensitive.
      */
     $namespaceIds = $wgContLang->getNamespaceIds();
     $caseSensitiveNamespaces = array();
     foreach (MWNamespace::getCanonicalNamespaces() as $index => $name) {
         $namespaceIds[$wgContLang->lc($name)] = $index;
         if (!MWNamespace::isCapitalized($index)) {
             $caseSensitiveNamespaces[] = $index;
         }
     }
     $conf = $this->getConfig();
     // Build list of variables
     $vars = array('wgLoadScript' => wfScript('load'), 'debug' => $context->getDebug(), 'skin' => $context->getSkin(), 'stylepath' => $conf->get('StylePath'), 'wgUrlProtocols' => wfUrlProtocols(), 'wgArticlePath' => $conf->get('ArticlePath'), 'wgScriptPath' => $conf->get('ScriptPath'), 'wgScriptExtension' => $conf->get('ScriptExtension'), 'wgScript' => wfScript(), 'wgSearchType' => $conf->get('SearchType'), 'wgVariantArticlePath' => $conf->get('VariantArticlePath'), 'wgActionPaths' => (object) $conf->get('ActionPaths'), 'wgServer' => $conf->get('Server'), 'wgServerName' => $conf->get('ServerName'), 'wgUserLanguage' => $context->getLanguage(), 'wgContentLanguage' => $wgContLang->getCode(), 'wgTranslateNumerals' => $conf->get('TranslateNumerals'), 'wgVersion' => $conf->get('Version'), 'wgEnableAPI' => $conf->get('EnableAPI'), 'wgEnableWriteAPI' => $conf->get('EnableWriteAPI'), 'wgMainPageTitle' => $mainPage->getPrefixedText(), 'wgFormattedNamespaces' => $wgContLang->getFormattedNamespaces(), 'wgNamespaceIds' => $namespaceIds, 'wgContentNamespaces' => MWNamespace::getContentNamespaces(), 'wgSiteName' => $conf->get('Sitename'), 'wgDBname' => $conf->get('DBname'), 'wgAvailableSkins' => Skin::getSkinNames(), 'wgExtensionAssetsPath' => $conf->get('ExtensionAssetsPath'), 'wgCookiePrefix' => $conf->get('CookiePrefix'), 'wgCookieDomain' => $conf->get('CookieDomain'), 'wgCookiePath' => $conf->get('CookiePath'), 'wgCookieExpiration' => $conf->get('CookieExpiration'), 'wgResourceLoaderMaxQueryLength' => $conf->get('ResourceLoaderMaxQueryLength'), 'wgCaseSensitiveNamespaces' => $caseSensitiveNamespaces, 'wgLegalTitleChars' => Title::convertByteClassToUnicodeClass(Title::legalChars()), 'wgResourceLoaderStorageVersion' => $conf->get('ResourceLoaderStorageVersion'), 'wgResourceLoaderStorageEnabled' => $conf->get('ResourceLoaderStorageEnabled'));
     Hooks::run('ResourceLoaderGetConfigVars', array(&$vars));
     $this->configVars[$hash] = $vars;
     return $this->configVars[$hash];
 }
 /**
  * @param ResourceLoaderContext $context
  * @return array
  */
 protected function getConfig($context)
 {
     $hash = $context->getHash();
     if (isset($this->configVars[$hash])) {
         return $this->configVars[$hash];
     }
     global $wgLoadScript, $wgScript, $wgStylePath, $wgScriptExtension, $wgArticlePath, $wgScriptPath, $wgServer, $wgContLang, $wgVariantArticlePath, $wgActionPaths, $wgVersion, $wgEnableAPI, $wgEnableWriteAPI, $wgDBname, $wgSitename, $wgFileExtensions, $wgExtensionAssetsPath, $wgCookiePrefix, $wgResourceLoaderMaxQueryLength, $wgResourceLoaderStorageEnabled, $wgResourceLoaderStorageVersion, $wgSearchType;
     $mainPage = Title::newMainPage();
     /**
      * Namespace related preparation
      * - wgNamespaceIds: Key-value pairs of all localized, canonical and aliases for namespaces.
      * - wgCaseSensitiveNamespaces: Array of namespaces that are case-sensitive.
      */
     $namespaceIds = $wgContLang->getNamespaceIds();
     $caseSensitiveNamespaces = array();
     foreach (MWNamespace::getCanonicalNamespaces() as $index => $name) {
         $namespaceIds[$wgContLang->lc($name)] = $index;
         if (!MWNamespace::isCapitalized($index)) {
             $caseSensitiveNamespaces[] = $index;
         }
     }
     // Build list of variables
     $vars = array('wgLoadScript' => $wgLoadScript, 'debug' => $context->getDebug(), 'skin' => $context->getSkin(), 'stylepath' => $wgStylePath, 'wgUrlProtocols' => wfUrlProtocols(), 'wgArticlePath' => $wgArticlePath, 'wgScriptPath' => $wgScriptPath, 'wgScriptExtension' => $wgScriptExtension, 'wgScript' => $wgScript, 'wgSearchType' => $wgSearchType, 'wgVariantArticlePath' => $wgVariantArticlePath, 'wgActionPaths' => (object) $wgActionPaths, 'wgServer' => $wgServer, 'wgUserLanguage' => $context->getLanguage(), 'wgContentLanguage' => $wgContLang->getCode(), 'wgVersion' => $wgVersion, 'wgEnableAPI' => $wgEnableAPI, 'wgEnableWriteAPI' => $wgEnableWriteAPI, 'wgMainPageTitle' => $mainPage->getPrefixedText(), 'wgFormattedNamespaces' => $wgContLang->getFormattedNamespaces(), 'wgNamespaceIds' => $namespaceIds, 'wgContentNamespaces' => MWNamespace::getContentNamespaces(), 'wgSiteName' => $wgSitename, 'wgFileExtensions' => array_values(array_unique($wgFileExtensions)), 'wgDBname' => $wgDBname, 'wgFileCanRotate' => BitmapHandler::canRotate(), 'wgAvailableSkins' => Skin::getSkinNames(), 'wgExtensionAssetsPath' => $wgExtensionAssetsPath, 'wgCookiePrefix' => $wgCookiePrefix, 'wgResourceLoaderMaxQueryLength' => $wgResourceLoaderMaxQueryLength, 'wgCaseSensitiveNamespaces' => $caseSensitiveNamespaces, 'wgLegalTitleChars' => Title::convertByteClassToUnicodeClass(Title::legalChars()), 'wgResourceLoaderStorageVersion' => $wgResourceLoaderStorageVersion, 'wgResourceLoaderStorageEnabled' => $wgResourceLoaderStorageEnabled);
     wfRunHooks('ResourceLoaderGetConfigVars', array(&$vars));
     $this->configVars[$hash] = $vars;
     return $this->configVars[$hash];
 }
 /**
  * Get language-specific LESS variables for this module.
  *
  * @return array
  */
 private function getLessVars(ResourceLoaderContext $context)
 {
     $language = Language::factory($context->getLanguage());
     // This is very conveniently formatted and we can pass it right through
     $vars = $language->getImageFiles();
     // less.php tries to be helpful and parse our variables as LESS source code
     foreach ($vars as $key => &$value) {
         $value = CSSMin::serializeStringValue($value);
     }
     return $vars;
 }
 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 testTypicalRequest()
 {
     $ctx = new ResourceLoaderContext($this->getResourceLoader(), new FauxRequest(['debug' => 'false', 'lang' => 'zh', 'modules' => 'foo|foo.quux,baz,bar|baz.quux', 'only' => 'styles', 'skin' => 'fallback']));
     // Request parameters
     $this->assertEquals($ctx->getModules(), ['foo', 'foo.quux', 'foo.baz', 'foo.bar', 'baz.quux']);
     $this->assertEquals(false, $ctx->getDebug());
     $this->assertEquals('zh', $ctx->getLanguage());
     $this->assertEquals('styles', $ctx->getOnly());
     $this->assertEquals('fallback', $ctx->getSkin());
     $this->assertEquals(null, $ctx->getUser());
     // Misc
     $this->assertEquals('ltr', $ctx->getDirection());
     $this->assertEquals('zh|fallback|||styles|||||', $ctx->getHash());
 }
 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()) . ');';
 }
 /**
  * @param ResourceLoaderContext $context
  * @return array
  */
 protected function getConfigSettings($context)
 {
     $hash = $context->getHash();
     if (isset($this->configVars[$hash])) {
         return $this->configVars[$hash];
     }
     global $wgContLang;
     $conf = $this->getConfig();
     // We can't use Title::newMainPage() if 'mainpage' is in
     // $wgForceUIMsgAsContentMsg because that will try to use the session
     // user's language and we have no session user. This does the
     // equivalent but falling back to our ResourceLoaderContext language
     // instead.
     $mainPage = Title::newFromText($context->msg('mainpage')->inContentLanguage()->text());
     if (!$mainPage) {
         $mainPage = Title::newFromText('Main Page');
     }
     /**
      * Namespace related preparation
      * - wgNamespaceIds: Key-value pairs of all localized, canonical and aliases for namespaces.
      * - wgCaseSensitiveNamespaces: Array of namespaces that are case-sensitive.
      */
     $namespaceIds = $wgContLang->getNamespaceIds();
     $caseSensitiveNamespaces = [];
     foreach (MWNamespace::getCanonicalNamespaces() as $index => $name) {
         $namespaceIds[$wgContLang->lc($name)] = $index;
         if (!MWNamespace::isCapitalized($index)) {
             $caseSensitiveNamespaces[] = $index;
         }
     }
     $illegalFileChars = $conf->get('IllegalFileChars');
     // Build list of variables
     $vars = ['wgLoadScript' => wfScript('load'), 'debug' => $context->getDebug(), 'skin' => $context->getSkin(), 'stylepath' => $conf->get('StylePath'), 'wgUrlProtocols' => wfUrlProtocols(), 'wgArticlePath' => $conf->get('ArticlePath'), 'wgScriptPath' => $conf->get('ScriptPath'), 'wgScriptExtension' => '.php', 'wgScript' => wfScript(), 'wgSearchType' => $conf->get('SearchType'), 'wgVariantArticlePath' => $conf->get('VariantArticlePath'), 'wgActionPaths' => (object) $conf->get('ActionPaths'), 'wgServer' => $conf->get('Server'), 'wgServerName' => $conf->get('ServerName'), 'wgUserLanguage' => $context->getLanguage(), 'wgContentLanguage' => $wgContLang->getCode(), 'wgTranslateNumerals' => $conf->get('TranslateNumerals'), 'wgVersion' => $conf->get('Version'), 'wgEnableAPI' => $conf->get('EnableAPI'), 'wgEnableWriteAPI' => $conf->get('EnableWriteAPI'), 'wgMainPageTitle' => $mainPage->getPrefixedText(), 'wgFormattedNamespaces' => $wgContLang->getFormattedNamespaces(), 'wgNamespaceIds' => $namespaceIds, 'wgContentNamespaces' => MWNamespace::getContentNamespaces(), 'wgSiteName' => $conf->get('Sitename'), 'wgDBname' => $conf->get('DBname'), 'wgExtraSignatureNamespaces' => $conf->get('ExtraSignatureNamespaces'), 'wgAvailableSkins' => Skin::getSkinNames(), 'wgExtensionAssetsPath' => $conf->get('ExtensionAssetsPath'), 'wgCookiePrefix' => $conf->get('CookiePrefix'), 'wgCookieDomain' => $conf->get('CookieDomain'), 'wgCookiePath' => $conf->get('CookiePath'), 'wgCookieExpiration' => $conf->get('CookieExpiration'), 'wgResourceLoaderMaxQueryLength' => $conf->get('ResourceLoaderMaxQueryLength'), 'wgCaseSensitiveNamespaces' => $caseSensitiveNamespaces, 'wgLegalTitleChars' => Title::convertByteClassToUnicodeClass(Title::legalChars()), 'wgIllegalFileChars' => Title::convertByteClassToUnicodeClass($illegalFileChars), 'wgResourceLoaderStorageVersion' => $conf->get('ResourceLoaderStorageVersion'), 'wgResourceLoaderStorageEnabled' => $conf->get('ResourceLoaderStorageEnabled'), 'wgResourceLoaderLegacyModules' => self::getLegacyModules(), 'wgForeignUploadTargets' => $conf->get('ForeignUploadTargets'), 'wgEnableUploads' => $conf->get('EnableUploads')];
     Hooks::run('ResourceLoaderGetConfigVars', [&$vars]);
     $this->configVars[$hash] = $vars;
     return $this->configVars[$hash];
 }
Пример #10
0
 /**
  * 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));
 }
 /**
  * Get the load.php URL that will produce this image.
  *
  * @param ResourceLoaderContext $context Any context
  * @param string $script URL to load.php
  * @param string|null $variant Variant to get the URL for
  * @param string $format Format to get the URL for, 'original' or 'rasterized'
  * @return string
  */
 public function getUrl(ResourceLoaderContext $context, $script, $variant, $format)
 {
     $query = array('modules' => $this->getModule(), 'image' => $this->getName(), 'variant' => $variant, 'format' => $format, 'lang' => $context->getLanguage(), 'version' => $context->getVersion());
     return wfExpandUrl(wfAppendQuery($script, $query), PROTO_RELATIVE);
 }
Пример #12
0
 /**
  * Generate code for a response.
  *
  * @param $context ResourceLoaderContext Context in which to generate a response
  * @param array $modules List of module objects keyed by module name
  * @param array $missing List of requested module names that are unregistered (optional)
  * @return string Response data
  */
 public function makeModuleResponse(ResourceLoaderContext $context, array $modules, array $missing = array())
 {
     $out = '';
     $exceptions = '';
     $states = array();
     if (!count($modules) && !count($missing)) {
         return "/* This file is the Web entry point for MediaWiki's ResourceLoader:\n   <https://www.mediawiki.org/wiki/ResourceLoader>. In this request,\n   no modules were requested. Max made me put this here. */";
     }
     wfProfileIn(__METHOD__);
     // Pre-fetch blobs
     if ($context->shouldIncludeMessages()) {
         try {
             $blobs = MessageBlobStore::get($this, $modules, $context->getLanguage());
         } catch (Exception $e) {
             MWExceptionHandler::logException($e);
             wfDebugLog('resourceloader', __METHOD__ . ": pre-fetching blobs from MessageBlobStore failed: {$e}");
             $this->hasErrors = true;
             // Add exception to the output as a comment
             $exceptions .= self::formatException($e);
         }
     } else {
         $blobs = array();
     }
     foreach ($missing as $name) {
         $states[$name] = 'missing';
     }
     // Generate output
     $isRaw = false;
     foreach ($modules as $name => $module) {
         /**
          * @var $module ResourceLoaderModule
          */
         wfProfileIn(__METHOD__ . '-' . $name);
         try {
             $scripts = '';
             if ($context->shouldIncludeScripts()) {
                 // If we are in debug mode, we'll want to return an array of URLs if possible
                 // However, we can't do this if the module doesn't support it
                 // We also can't do this if there is an only= parameter, because we have to give
                 // the module a way to return a load.php URL without causing an infinite loop
                 if ($context->getDebug() && !$context->getOnly() && $module->supportsURLLoading()) {
                     $scripts = $module->getScriptURLsForDebug($context);
                 } else {
                     $scripts = $module->getScript($context);
                     // rtrim() because there are usually a few line breaks after the last ';'.
                     // A new line at EOF, a new line added by ResourceLoaderFileModule::readScriptFiles, etc.
                     if (is_string($scripts) && strlen($scripts) && substr(rtrim($scripts), -1) !== ';') {
                         // Append semicolon to prevent weird bugs caused by files not
                         // terminating their statements right (bug 27054)
                         $scripts .= ";\n";
                     }
                 }
             }
             // Styles
             $styles = array();
             if ($context->shouldIncludeStyles()) {
                 // Don't create empty stylesheets like array( '' => '' ) for modules
                 // that don't *have* any stylesheets (bug 38024).
                 $stylePairs = $module->getStyles($context);
                 if (count($stylePairs)) {
                     // If we are in debug mode without &only= set, we'll want to return an array of URLs
                     // See comment near shouldIncludeScripts() for more details
                     if ($context->getDebug() && !$context->getOnly() && $module->supportsURLLoading()) {
                         $styles = array('url' => $module->getStyleURLsForDebug($context));
                     } else {
                         // Minify CSS before embedding in mw.loader.implement call
                         // (unless in debug mode)
                         if (!$context->getDebug()) {
                             foreach ($stylePairs as $media => $style) {
                                 // Can be either a string or an array of strings.
                                 if (is_array($style)) {
                                     $stylePairs[$media] = array();
                                     foreach ($style as $cssText) {
                                         if (is_string($cssText)) {
                                             $stylePairs[$media][] = $this->filter('minify-css', $cssText);
                                         }
                                     }
                                 } elseif (is_string($style)) {
                                     $stylePairs[$media] = $this->filter('minify-css', $style);
                                 }
                             }
                         }
                         // Wrap styles into @media groups as needed and flatten into a numerical array
                         $styles = array('css' => self::makeCombinedStyles($stylePairs));
                     }
                 }
             }
             // Messages
             $messagesBlob = isset($blobs[$name]) ? $blobs[$name] : '{}';
             // Append output
             switch ($context->getOnly()) {
                 case 'scripts':
                     if (is_string($scripts)) {
                         // Load scripts raw...
                         $out .= $scripts;
                     } elseif (is_array($scripts)) {
                         // ...except when $scripts is an array of URLs
                         $out .= self::makeLoaderImplementScript($name, $scripts, array(), array());
                     }
                     break;
                 case 'styles':
                     // We no longer seperate into media, they are all combined now with
                     // custom media type groups into @media .. {} sections as part of the css string.
                     // Module returns either an empty array or a numerical array with css strings.
                     $out .= isset($styles['css']) ? implode('', $styles['css']) : '';
                     break;
                 case 'messages':
                     $out .= self::makeMessageSetScript(new XmlJsCode($messagesBlob));
                     break;
                 default:
                     $out .= self::makeLoaderImplementScript($name, $scripts, $styles, new XmlJsCode($messagesBlob));
                     break;
             }
         } catch (Exception $e) {
             MWExceptionHandler::logException($e);
             wfDebugLog('resourceloader', __METHOD__ . ": generating module package failed: {$e}");
             $this->hasErrors = true;
             // Add exception to the output as a comment
             $exceptions .= self::formatException($e);
             // Respond to client with error-state instead of module implementation
             $states[$name] = 'error';
             unset($modules[$name]);
         }
         $isRaw |= $module->isRaw();
         wfProfileOut(__METHOD__ . '-' . $name);
     }
     // Update module states
     if ($context->shouldIncludeScripts() && !$context->getRaw() && !$isRaw) {
         if (count($modules) && $context->getOnly() === 'scripts') {
             // Set the state of modules loaded as only scripts to ready as
             // they don't have an mw.loader.implement wrapper that sets the state
             foreach ($modules as $name => $module) {
                 $states[$name] = 'ready';
             }
         }
         // Set the state of modules we didn't respond to with mw.loader.implement
         if (count($states)) {
             $out .= self::makeLoaderStateScript($states);
         }
     }
     if (!$context->getDebug()) {
         if ($context->getOnly() === 'styles') {
             $out = $this->filter('minify-css', $out);
         } else {
             $out = $this->filter('minify-js', $out);
         }
     }
     wfProfileOut(__METHOD__);
     return $exceptions . $out;
 }
Пример #13
0
 /**
  * Generates code for a response
  *
  * @param $context ResourceLoaderContext: Context in which to generate a response
  * @param $modules Array: List of module objects keyed by module name
  * @param $missing Array: List of unavailable modules (optional)
  * @return String: Response data
  */
 public function makeModuleResponse(ResourceLoaderContext $context, array $modules, $missing = array())
 {
     $out = '';
     $exceptions = '';
     if ($modules === array() && $missing === array()) {
         return '/* No modules requested. Max made me put this here */';
     }
     wfProfileIn(__METHOD__);
     // Pre-fetch blobs
     if ($context->shouldIncludeMessages()) {
         try {
             $blobs = MessageBlobStore::get($this, $modules, $context->getLanguage());
         } catch (Exception $e) {
             // Add exception to the output as a comment
             $exceptions .= $this->formatException($e);
         }
     } else {
         $blobs = array();
     }
     // Generate output
     foreach ($modules as $name => $module) {
         /**
          * @var $module ResourceLoaderModule
          */
         wfProfileIn(__METHOD__ . '-' . $name);
         try {
             $scripts = '';
             if ($context->shouldIncludeScripts()) {
                 // If we are in debug mode, we'll want to return an array of URLs if possible
                 // However, we can't do this if the module doesn't support it
                 // We also can't do this if there is an only= parameter, because we have to give
                 // the module a way to return a load.php URL without causing an infinite loop
                 if ($context->getDebug() && !$context->getOnly() && $module->supportsURLLoading()) {
                     $scripts = $module->getScriptURLsForDebug($context);
                 } else {
                     $scripts = $module->getScript($context);
                     if (is_string($scripts)) {
                         // bug 27054: Append semicolon to prevent weird bugs
                         // caused by files not terminating their statements right
                         $scripts .= ";\n";
                     }
                 }
             }
             // Styles
             $styles = array();
             if ($context->shouldIncludeStyles()) {
                 // If we are in debug mode, we'll want to return an array of URLs
                 // See comment near shouldIncludeScripts() for more details
                 if ($context->getDebug() && !$context->getOnly() && $module->supportsURLLoading()) {
                     $styles = $module->getStyleURLsForDebug($context);
                 } else {
                     $styles = $module->getStyles($context);
                 }
             }
             // Messages
             $messagesBlob = isset($blobs[$name]) ? $blobs[$name] : '{}';
             // Append output
             switch ($context->getOnly()) {
                 case 'scripts':
                     if (is_string($scripts)) {
                         // Load scripts raw...
                         $out .= $scripts;
                     } elseif (is_array($scripts)) {
                         // ...except when $scripts is an array of URLs
                         $out .= self::makeLoaderImplementScript($name, $scripts, array(), array());
                     }
                     break;
                 case 'styles':
                     $out .= self::makeCombinedStyles($styles);
                     break;
                 case 'messages':
                     $out .= self::makeMessageSetScript(new XmlJsCode($messagesBlob));
                     break;
                 default:
                     // Minify CSS before embedding in mw.loader.implement call
                     // (unless in debug mode)
                     if (!$context->getDebug()) {
                         foreach ($styles as $media => $style) {
                             if (is_string($style)) {
                                 $styles[$media] = $this->filter('minify-css', $style);
                             }
                         }
                     }
                     $out .= self::makeLoaderImplementScript($name, $scripts, $styles, new XmlJsCode($messagesBlob));
                     break;
             }
         } catch (Exception $e) {
             // Add exception to the output as a comment
             $exceptions .= $this->formatException($e);
             // Register module as missing
             $missing[] = $name;
             unset($modules[$name]);
         }
         wfProfileOut(__METHOD__ . '-' . $name);
     }
     // Update module states
     if ($context->shouldIncludeScripts()) {
         // Set the state of modules loaded as only scripts to ready
         if (count($modules) && $context->getOnly() === 'scripts' && !isset($modules['startup'])) {
             $out .= self::makeLoaderStateScript(array_fill_keys(array_keys($modules), 'ready'));
         }
         // Set the state of modules which were requested but unavailable as missing
         if (is_array($missing) && count($missing)) {
             $out .= self::makeLoaderStateScript(array_fill_keys($missing, 'missing'));
         }
     }
     if (!$context->getDebug()) {
         if ($context->getOnly() === 'styles') {
             $out = $this->filter('minify-css', $out);
         } else {
             $out = $this->filter('minify-js', $out);
         }
     }
     wfProfileOut(__METHOD__);
     return $exceptions . $out;
 }
Пример #14
0
 /**
  * Generates code for a response
  *
  * @param $context ResourceLoaderContext: Context in which to generate a response
  * @param $modules Array: List of module objects keyed by module name
  * @param $missing Array: List of unavailable modules (optional)
  * @return String: Response data
  */
 public function makeModuleResponse(ResourceLoaderContext $context, array $modules, $missing = array())
 {
     $out = '';
     $exceptions = '';
     if ($modules === array() && $missing === array()) {
         return '/* No modules requested. Max made me put this here */';
     }
     wfProfileIn(__METHOD__);
     // Pre-fetch blobs
     if ($context->shouldIncludeMessages()) {
         try {
             $blobs = MessageBlobStore::get($this, $modules, $context->getLanguage());
         } catch (Exception $e) {
             // Add exception to the output as a comment
             $exceptions .= $this->makeComment($e->__toString());
         }
     } else {
         $blobs = array();
     }
     // Generate output
     $isRaw = false;
     foreach ($modules as $name => $module) {
         /**
          * @var $module ResourceLoaderModule
          */
         wfProfileIn(__METHOD__ . '-' . $name);
         try {
             $scripts = '';
             if ($context->shouldIncludeScripts()) {
                 // If we are in debug mode, we'll want to return an array of URLs if possible
                 // However, we can't do this if the module doesn't support it
                 // We also can't do this if there is an only= parameter, because we have to give
                 // the module a way to return a load.php URL without causing an infinite loop
                 if ($context->getDebug() && !$context->getOnly() && $module->supportsURLLoading()) {
                     $scripts = $module->getScriptURLsForDebug($context);
                 } else {
                     $scripts = $module->getScript($context);
                     if (is_string($scripts) && strlen($scripts) && substr($scripts, -1) !== ';') {
                         // bug 27054: Append semicolon to prevent weird bugs
                         // caused by files not terminating their statements right
                         $scripts .= ";\n";
                     }
                 }
             }
             // Styles
             $styles = array();
             if ($context->shouldIncludeStyles()) {
                 // Don't create empty stylesheets like array( '' => '' ) for modules
                 // that don't *have* any stylesheets (bug 38024).
                 $stylePairs = $module->getStyles($context);
                 if (count($stylePairs)) {
                     // If we are in debug mode without &only= set, we'll want to return an array of URLs
                     // See comment near shouldIncludeScripts() for more details
                     if ($context->getDebug() && !$context->getOnly() && $module->supportsURLLoading()) {
                         $styles = array('url' => $module->getStyleURLsForDebug($context));
                     } else {
                         // Minify CSS before embedding in mw.loader.implement call
                         // (unless in debug mode)
                         if (!$context->getDebug()) {
                             foreach ($stylePairs as $media => $style) {
                                 // Can be either a string or an array of strings.
                                 if (is_array($style)) {
                                     $stylePairs[$media] = array();
                                     foreach ($style as $cssText) {
                                         if (is_string($cssText)) {
                                             $stylePairs[$media][] = $this->filter('minify-css', $cssText);
                                         }
                                     }
                                 } elseif (is_string($style)) {
                                     $stylePairs[$media] = $this->filter('minify-css', $style);
                                 }
                             }
                         }
                         // Wrap styles into @media groups as needed and flatten into a numerical array
                         $styles = array('css' => self::makeCombinedStyles($stylePairs));
                     }
                 }
             }
             // Messages
             $messagesBlob = isset($blobs[$name]) ? $blobs[$name] : '{}';
             // Append output
             switch ($context->getOnly()) {
                 case 'scripts':
                     if (is_string($scripts)) {
                         // Load scripts raw...
                         $out .= $scripts;
                     } elseif (is_array($scripts)) {
                         // ...except when $scripts is an array of URLs
                         $out .= self::makeLoaderImplementScript($name, $scripts, array(), array());
                     }
                     break;
                 case 'styles':
                     // We no longer seperate into media, they are all combined now with
                     // custom media type groups into @media .. {} sections as part of the css string.
                     // Module returns either an empty array or a numerical array with css strings.
                     $out .= isset($styles['css']) ? implode('', $styles['css']) : '';
                     break;
                 case 'messages':
                     $out .= self::makeMessageSetScript(new XmlJsCode($messagesBlob));
                     break;
                 default:
                     $out .= self::makeLoaderImplementScript($name, $scripts, $styles, new XmlJsCode($messagesBlob));
                     break;
             }
         } catch (Exception $e) {
             // Add exception to the output as a comment
             $exceptions .= $this->makeComment($e->__toString());
             // Register module as missing
             $missing[] = $name;
             unset($modules[$name]);
         }
         $isRaw |= $module->isRaw();
         wfProfileOut(__METHOD__ . '-' . $name);
     }
     // Update module states
     if ($context->shouldIncludeScripts() && !$context->getRaw() && !$isRaw) {
         // Set the state of modules loaded as only scripts to ready
         if (count($modules) && $context->getOnly() === 'scripts') {
             $out .= self::makeLoaderStateScript(array_fill_keys(array_keys($modules), 'ready'));
         }
         // Set the state of modules which were requested but unavailable as missing
         if (is_array($missing) && count($missing)) {
             $out .= self::makeLoaderStateScript(array_fill_keys($missing, 'missing'));
         }
     }
     if (!$context->getDebug()) {
         if ($context->getOnly() === 'styles') {
             $out = $this->filter('minify-css', $out);
         } else {
             $out = $this->filter('minify-js', $out);
         }
     }
     wfProfileOut(__METHOD__);
     return $exceptions . $out;
 }
 /**
  * @param $context ResourceLoaderContext
  * @return string: Hash
  */
 public function getModifiedHash(ResourceLoaderContext $context)
 {
     $this->language = Language::factory($context->getLanguage());
     return md5(serialize($this->getData()));
 }
 /**
  * Gets a list of file paths for all scripts in this module, in order of propper execution.
  *
  * @param $context ResourceLoaderContext: Context
  * @return Array: List of file paths
  */
 protected function getScriptFiles(ResourceLoaderContext $context)
 {
     $files = array_merge($this->scripts, self::tryForKey($this->languageScripts, $context->getLanguage()), self::tryForKey($this->skinScripts, $context->getSkin(), 'default'));
     if ($context->getDebug()) {
         $files = array_merge($files, $this->debugScripts);
     }
     return array_unique($files);
 }
 public function getScript(ResourceLoaderContext $context)
 {
     global $IP, $wgLoadScript;
     $out = file_get_contents("{$IP}/resources/startup.js");
     if ($context->getOnly() === 'scripts') {
         // Build load query for jquery and mediawiki modules
         $query = array('modules' => implode('|', array('jquery', 'mediawiki')), 'only' => 'scripts', 'lang' => $context->getLanguage(), 'skin' => $context->getSkin(), 'debug' => $context->getDebug() ? 'true' : 'false', 'version' => wfTimestamp(TS_ISO_8601_BASIC, round(max($context->getResourceLoader()->getModule('jquery')->getModifiedTime($context), $context->getResourceLoader()->getModule('mediawiki')->getModifiedTime($context)), -2)));
         // Ensure uniform query order
         ksort($query);
         // Startup function
         $configuration = $this->getConfig($context);
         $registrations = self::getModuleRegistrations($context);
         $out .= "var startUp = function() {\n" . "\t{$registrations}\n" . "\t" . Xml::encodeJsCall('mediaWiki.config.set', array($configuration)) . "};\n";
         // Conditional script injection
         $scriptTag = Html::linkedScript($wgLoadScript . '?' . wfArrayToCGI($query));
         $out .= "if ( isCompatible() ) {\n" . "\t" . Xml::encodeJsCall('document.write', array($scriptTag)) . "}\n" . "delete isCompatible;";
     }
     return $out;
 }
 /**
  * Get the load URL of the startup modules.
  *
  * This is a helper for getScript(), but can also be called standalone, such
  * as when generating an AppCache manifest.
  *
  * @param ResourceLoaderContext $context
  * @return string
  */
 public static function getStartupModulesUrl(ResourceLoaderContext $context)
 {
     $rl = $context->getResourceLoader();
     $moduleNames = self::getStartupModules();
     $query = ['modules' => ResourceLoader::makePackedModulesString($moduleNames), 'only' => 'scripts', 'lang' => $context->getLanguage(), 'skin' => $context->getSkin(), 'debug' => $context->getDebug() ? 'true' : 'false', 'version' => $rl->getCombinedVersion($context, $moduleNames)];
     // Ensure uniform query order
     ksort($query);
     return wfAppendQuery(wfScript('load'), $query);
 }
Пример #19
0
 /**
  * Set in-object cache for file dependencies.
  *
  * This is used to retrieve data in batches. See ResourceLoader::preloadModuleInfo().
  * To save the data, use saveFileDependencies().
  *
  * @param string $skin Skin name
  * @param array $deps Array of file names
  */
 public function setFileDependencies(ResourceLoaderContext $context, $files)
 {
     $vary = $context->getSkin() . '|' . $context->getLanguage();
     $this->fileDeps[$vary] = $files;
 }
Пример #20
0
 /**
  * Get the load.php URL that will produce this image.
  *
  * @param ResourceLoaderContext $context Any context
  * @param string $script URL to load.php
  * @param string|null $variant Variant to get the URL for
  * @param string $format Format to get the URL for, 'original' or 'rasterized'
  * @return string
  */
 public function getUrl(ResourceLoaderContext $context, $script, $variant, $format)
 {
     $query = ['modules' => $this->getModule(), 'image' => $this->getName(), 'variant' => $variant, 'format' => $format, 'lang' => $context->getLanguage(), 'version' => $context->getVersion()];
     return wfAppendQuery($script, $query);
 }
Пример #21
0
 /**
  * Generates code for a response
  * 
  * @param $context ResourceLoaderContext: Context in which to generate a response
  * @param $modules Array: List of module objects keyed by module name
  * @param $missing Array: List of unavailable modules (optional)
  * @return String: Response data
  */
 public function makeModuleResponse(ResourceLoaderContext $context, array $modules, $missing = array())
 {
     $out = '';
     $exceptions = '';
     if ($modules === array() && $missing === array()) {
         return '/* No modules requested. Max made me put this here */';
     }
     wfProfileIn(__METHOD__);
     // Pre-fetch blobs
     if ($context->shouldIncludeMessages()) {
         try {
             $blobs = MessageBlobStore::get($this, $modules, $context->getLanguage());
         } catch (Exception $e) {
             // Add exception to the output as a comment
             $exceptions .= "/*\n{$e->__toString()}\n*/\n";
         }
     } else {
         $blobs = array();
     }
     // Generate output
     foreach ($modules as $name => $module) {
         wfProfileIn(__METHOD__ . '-' . $name);
         try {
             // Scripts
             $scripts = '';
             if ($context->shouldIncludeScripts()) {
                 // bug 27054: Append semicolon to prevent weird bugs
                 // caused by files not terminating their statements right
                 $scripts .= $module->getScript($context) . ";\n";
             }
             // Styles
             $styles = array();
             if ($context->shouldIncludeStyles()) {
                 $styles = $module->getStyles($context);
             }
             // Messages
             $messagesBlob = isset($blobs[$name]) ? $blobs[$name] : '{}';
             // Append output
             switch ($context->getOnly()) {
                 case 'scripts':
                     $out .= $scripts;
                     break;
                 case 'styles':
                     $out .= self::makeCombinedStyles($styles);
                     break;
                 case 'messages':
                     $out .= self::makeMessageSetScript(new XmlJsCode($messagesBlob));
                     break;
                 default:
                     // Minify CSS before embedding in mediaWiki.loader.implement call
                     // (unless in debug mode)
                     if (!$context->getDebug()) {
                         foreach ($styles as $media => $style) {
                             $styles[$media] = $this->filter('minify-css', $style);
                         }
                     }
                     $out .= self::makeLoaderImplementScript($name, $scripts, $styles, new XmlJsCode($messagesBlob));
                     break;
             }
         } catch (Exception $e) {
             // Add exception to the output as a comment
             $exceptions .= "/*\n{$e->__toString()}\n*/\n";
             // Register module as missing
             $missing[] = $name;
             unset($modules[$name]);
         }
         wfProfileOut(__METHOD__ . '-' . $name);
     }
     // Update module states
     if ($context->shouldIncludeScripts()) {
         // Set the state of modules loaded as only scripts to ready
         if (count($modules) && $context->getOnly() === 'scripts' && !isset($modules['startup'])) {
             $out .= self::makeLoaderStateScript(array_fill_keys(array_keys($modules), 'ready'));
         }
         // Set the state of modules which were requested but unavailable as missing
         if (is_array($missing) && count($missing)) {
             $out .= self::makeLoaderStateScript(array_fill_keys($missing, 'missing'));
         }
     }
     if (!$context->getDebug()) {
         if ($context->getOnly() === 'styles') {
             $out = $this->filter('minify-css', $out);
         } else {
             $out = $this->filter('minify-js', $out);
         }
     }
     wfProfileOut(__METHOD__);
     return $exceptions . $out;
 }
 /**
  * @param ResourceLoaderContext $context
  * @return string JavaScript code
  */
 public function getScript(ResourceLoaderContext $context)
 {
     return Xml::encodeJsCall('mw.language.setData', [$context->getLanguage(), $this->getData($context)], ResourceLoader::inDebugMode());
 }
Пример #23
0
 /**
  * Get the hash of the message blob.
  *
  * @since 1.27
  * @param ResourceLoaderContext $context
  * @return string|null JSON blob or null if module has no messages
  */
 protected function getMessageBlob(ResourceLoaderContext $context)
 {
     if (!$this->getMessages()) {
         // Don't bother consulting MessageBlobStore
         return null;
     }
     // Message blobs may only vary language, not by context keys
     $lang = $context->getLanguage();
     if (!isset($this->msgBlobs[$lang])) {
         $this->getLogger()->warning('Message blob for {module} should have been preloaded', ['module' => $this->getName()]);
         $store = $context->getResourceLoader()->getMessageBlobStore();
         $this->msgBlobs[$lang] = $store->getBlob($this, $lang);
     }
     return $this->msgBlobs[$lang];
 }
Пример #24
0
 /**
  * Helper for createLoaderURL()
  *
  * @since 1.24
  * @see makeLoaderQuery
  * @param ResourceLoaderContext $context
  * @param array $extraQuery
  * @return array
  */
 public static function createLoaderQuery(ResourceLoaderContext $context, $extraQuery = array())
 {
     return self::makeLoaderQuery($context->getModules(), $context->getLanguage(), $context->getSkin(), $context->getUser(), $context->getVersion(), $context->getDebug(), $context->getOnly(), $context->getRequest()->getBool('printable'), $context->getRequest()->getBool('handheld'), $extraQuery);
 }
 /**
  * @param $context ResourceLoaderContext
  * @return string JavaScript code
  */
 public function getScript(ResourceLoaderContext $context)
 {
     return Xml::encodeJsCall('mw.language.setData', array($context->getLanguage(), 'languageNames', $this->getData($context)));
 }
Пример #26
0
 /**
  * Get the last modified timestamp of this module.
  * 
  * Last modified timestamps are calculated from the highest last modified 
  * timestamp of this module's constituent files as well as the files it 
  * depends on. This function is context-sensitive, only performing 
  * calculations on files relevant to the given language, skin and debug 
  * mode.
  * 
  * @param $context ResourceLoaderContext: Context in which to calculate 
  *     the modified time
  * @return Integer: UNIX timestamp
  * @see ResourceLoaderModule::getFileDependencies
  */
 public function getModifiedTime(ResourceLoaderContext $context)
 {
     if (isset($this->modifiedTime[$context->getHash()])) {
         return $this->modifiedTime[$context->getHash()];
     }
     wfProfileIn(__METHOD__);
     $files = array();
     // Flatten style files into $files
     $styles = self::collateFilePathListByOption($this->styles, 'media', 'all');
     foreach ($styles as $styleFiles) {
         $files = array_merge($files, $styleFiles);
     }
     $skinFiles = self::tryForKey(self::collateFilePathListByOption($this->skinStyles, 'media', 'all'), $context->getSkin(), 'default');
     foreach ($skinFiles as $styleFiles) {
         $files = array_merge($files, $styleFiles);
     }
     // Final merge, this should result in a master list of dependent files
     $files = array_merge($files, $this->scripts, $context->getDebug() ? $this->debugScripts : array(), self::tryForKey($this->languageScripts, $context->getLanguage()), self::tryForKey($this->skinScripts, $context->getSkin(), 'default'), $this->loaderScripts);
     $files = array_map(array($this, 'getLocalPath'), $files);
     // File deps need to be treated separately because they're already prefixed
     $files = array_merge($files, $this->getFileDependencies($context->getSkin()));
     // If a module is nothing but a list of dependencies, we need to avoid
     // giving max() an empty array
     if (count($files) === 0) {
         wfProfileOut(__METHOD__);
         return $this->modifiedTime[$context->getHash()] = 1;
     }
     wfProfileIn(__METHOD__ . '-filemtime');
     $filesMtime = max(array_map('filemtime', $files));
     wfProfileOut(__METHOD__ . '-filemtime');
     $this->modifiedTime[$context->getHash()] = max($filesMtime, $this->getMsgBlobMtime($context->getLanguage()));
     wfProfileOut(__METHOD__);
     return $this->modifiedTime[$context->getHash()];
 }
 /**
  * @param $context ResourceLoaderContext
  * @return array|int|Mixed
  */
 public function getModifiedTime(ResourceLoaderContext $context)
 {
     $this->language = Language::factory($context->getLanguage());
     $cache = wfGetCache(CACHE_ANYTHING);
     $key = wfMemcKey('resourceloader', 'langdatamodule', 'changeinfo');
     $data = $this->getData();
     $hash = md5(serialize($data));
     $result = $cache->get($key);
     if (is_array($result) && $result['hash'] === $hash) {
         return $result['timestamp'];
     }
     $timestamp = wfTimestamp();
     $cache->set($key, array('hash' => $hash, 'timestamp' => $timestamp));
     return $timestamp;
 }