コード例 #1
0
 /**
  * @todo Document
  * @param array|string $modules One or more module names
  * @param string $only ResourceLoaderModule TYPE_ class constant
  * @param bool $useESI
  * @param array $extraQuery Array with extra query parameters to add to each
  *   request. array( param => value ).
  * @param bool $loadCall If true, output an (asynchronous) mw.loader.load()
  *   call rather than a "<script src='...'>" tag.
  * @return string The html "<script>", "<link>" and "<style>" tags
  */
 public function makeResourceLoaderLink($modules, $only, $useESI = false, array $extraQuery = array(), $loadCall = false)
 {
     $modules = (array) $modules;
     $links = array('html' => '', 'states' => array());
     if (!count($modules)) {
         return $links;
     }
     if (count($modules) > 1) {
         // Remove duplicate module requests
         $modules = array_unique($modules);
         // Sort module names so requests are more uniform
         sort($modules);
         if (ResourceLoader::inDebugMode()) {
             // Recursively call us for every item
             foreach ($modules as $name) {
                 $link = $this->makeResourceLoaderLink($name, $only, $useESI);
                 $links['html'] .= $link['html'];
                 $links['states'] += $link['states'];
             }
             return $links;
         }
     }
     if (!is_null($this->mTarget)) {
         $extraQuery['target'] = $this->mTarget;
     }
     // Create keyed-by-source and then keyed-by-group list of module objects from modules list
     $sortedModules = array();
     $resourceLoader = $this->getResourceLoader();
     $resourceLoaderUseESI = $this->getConfig()->get('ResourceLoaderUseESI');
     foreach ($modules as $name) {
         $module = $resourceLoader->getModule($name);
         # Check that we're allowed to include this module on this page
         if (!$module || $module->getOrigin() > $this->getAllowedModules(ResourceLoaderModule::TYPE_SCRIPTS) && $only == ResourceLoaderModule::TYPE_SCRIPTS || $module->getOrigin() > $this->getAllowedModules(ResourceLoaderModule::TYPE_STYLES) && $only == ResourceLoaderModule::TYPE_STYLES || $module->getOrigin() > $this->getAllowedModules(ResourceLoaderModule::TYPE_COMBINED) && $only == ResourceLoaderModule::TYPE_COMBINED || $this->mTarget && !in_array($this->mTarget, $module->getTargets())) {
             continue;
         }
         $sortedModules[$module->getSource()][$module->getGroup()][$name] = $module;
     }
     foreach ($sortedModules as $source => $groups) {
         foreach ($groups as $group => $grpModules) {
             // Special handling for user-specific groups
             $user = null;
             if (($group === 'user' || $group === 'private') && $this->getUser()->isLoggedIn()) {
                 $user = $this->getUser()->getName();
             }
             // Create a fake request based on the one we are about to make so modules return
             // correct timestamp and emptiness data
             $query = ResourceLoader::makeLoaderQuery(array(), $this->getLanguage()->getCode(), $this->getSkin()->getSkinName(), $user, null, ResourceLoader::inDebugMode(), $only === ResourceLoaderModule::TYPE_COMBINED ? null : $only, $this->isPrintable(), $this->getRequest()->getBool('handheld'), $extraQuery);
             $context = new ResourceLoaderContext($resourceLoader, new FauxRequest($query));
             // Extract modules that know they're empty and see if we have one or more
             // raw modules
             $isRaw = false;
             foreach ($grpModules as $key => $module) {
                 // Inline empty modules: since they're empty, just mark them as 'ready' (bug 46857)
                 // If we're only getting the styles, we don't need to do anything for empty modules.
                 if ($module->isKnownEmpty($context)) {
                     unset($grpModules[$key]);
                     if ($only !== ResourceLoaderModule::TYPE_STYLES) {
                         $links['states'][$key] = 'ready';
                     }
                 }
                 $isRaw |= $module->isRaw();
             }
             // If there are no non-empty modules, skip this group
             if (count($grpModules) === 0) {
                 continue;
             }
             // Inline private modules. These can't be loaded through load.php for security
             // reasons, see bug 34907. Note that these modules should be loaded from
             // getHeadScripts() before the first loader call. Otherwise other modules can't
             // properly use them as dependencies (bug 30914)
             if ($group === 'private') {
                 if ($only == ResourceLoaderModule::TYPE_STYLES) {
                     $links['html'] .= Html::inlineStyle($resourceLoader->makeModuleResponse($context, $grpModules));
                 } else {
                     $links['html'] .= ResourceLoader::makeInlineScript($resourceLoader->makeModuleResponse($context, $grpModules));
                 }
                 $links['html'] .= "\n";
                 continue;
             }
             // Special handling for the user group; because users might change their stuff
             // on-wiki like user pages, or user preferences; we need to find the highest
             // timestamp of these user-changeable modules so we can ensure cache misses on change
             // This should NOT be done for the site group (bug 27564) because anons get that too
             // and we shouldn't be putting timestamps in Squid-cached HTML
             $version = null;
             if ($group === 'user') {
                 $query['version'] = $resourceLoader->getCombinedVersion($context, array_keys($grpModules));
             }
             $query['modules'] = ResourceLoader::makePackedModulesString(array_keys($grpModules));
             $moduleContext = new ResourceLoaderContext($resourceLoader, new FauxRequest($query));
             $url = $resourceLoader->createLoaderURL($source, $moduleContext, $extraQuery);
             if ($useESI && $resourceLoaderUseESI) {
                 $esi = Xml::element('esi:include', array('src' => $url));
                 if ($only == ResourceLoaderModule::TYPE_STYLES) {
                     $link = Html::inlineStyle($esi);
                 } else {
                     $link = Html::inlineScript($esi);
                 }
             } else {
                 // Automatically select style/script elements
                 if ($only === ResourceLoaderModule::TYPE_STYLES) {
                     $link = Html::linkedStyle($url);
                 } elseif ($loadCall) {
                     $link = ResourceLoader::makeInlineScript(Xml::encodeJsCall('mw.loader.load', array($url, 'text/javascript', true)));
                 } else {
                     $link = Html::linkedScript($url);
                     if (!$context->getRaw() && !$isRaw) {
                         // Wrap only=script / only=combined requests in a conditional as
                         // browsers not supported by the startup module would unconditionally
                         // execute this module. Otherwise users will get "ReferenceError: mw is
                         // undefined" or "jQuery is undefined" from e.g. a "site" module.
                         $link = ResourceLoader::makeInlineScript(Xml::encodeJsCall('document.write', array($link)));
                     }
                     // For modules requested directly in the html via <link> or <script>,
                     // tell mw.loader they are being loading to prevent duplicate requests.
                     foreach ($grpModules as $key => $module) {
                         // Don't output state=loading for the startup module..
                         if ($key !== 'startup') {
                             $links['states'][$key] = 'loading';
                         }
                     }
                 }
             }
             if ($group == 'noscript') {
                 $links['html'] .= Html::rawElement('noscript', array(), $link) . "\n";
             } else {
                 $links['html'] .= $link . "\n";
             }
         }
     }
     return $links;
 }
コード例 #2
0
ファイル: OutputPage.php プロジェクト: paladox/mediawiki
 private function getRlClientContext()
 {
     if (!$this->rlClientContext) {
         $query = ResourceLoader::makeLoaderQuery([], $this->getLanguage()->getCode(), $this->getSkin()->getSkinName(), $this->getUser()->isLoggedIn() ? $this->getUser()->getName() : null, null, ResourceLoader::inDebugMode(), null, $this->isPrintable(), $this->getRequest()->getBool('handheld'));
         $this->rlClientContext = new ResourceLoaderContext($this->getResourceLoader(), new FauxRequest($query));
     }
     return $this->rlClientContext;
 }
コード例 #3
0
function headScriptsStartupScript($outputPage, $scripts)
{
    $resourceLoader = $outputPage->getResourceLoader();
    $module = $resourceLoader->getModule('startup');
    $query = ResourceLoader::makeLoaderQuery(array(), $outputPage->getLanguage()->getCode(), $outputPage->getSkin()->getSkinName(), null, null, ResourceLoader::inDebugMode(), "scripts", $outputPage->isPrintable(), $outputPage->getRequest()->getBool('handheld'), array());
    $context = new ResourceLoaderContext($resourceLoader, new FauxRequest($query));
    $scripts = Html::inlineScript($resourceLoader->makeModuleResponse($context, array($module)));
    return true;
}
コード例 #4
0
ファイル: OutputPage.php プロジェクト: schwarer2006/wikia
 /**
  * TODO: Document
  * @param $modules Array/string with the module name(s)
  * @param $only String ResourceLoaderModule TYPE_ class constant
  * @param $useESI boolean
  * @param $extraQuery Array with extra query parameters to add to each request. array( param => value )
  * @param $loadCall boolean If true, output an (asynchronous) mw.loader.load() call rather than a <script src="..."> tag
  * @return string html <script> and <style> tags
  */
 protected function makeResourceLoaderLink($modules, $only, $useESI = false, array $extraQuery = array(), $loadCall = false)
 {
     global $wgResourceLoaderUseESI;
     if (!count($modules)) {
         return '';
     }
     if (count($modules) > 1) {
         // Remove duplicate module requests
         $modules = array_unique((array) $modules);
         // Sort module names so requests are more uniform
         sort($modules);
         if (ResourceLoader::inDebugMode()) {
             // Recursively call us for every item
             $links = '';
             foreach ($modules as $name) {
                 $links .= $this->makeResourceLoaderLink($name, $only, $useESI);
             }
             return $links;
         }
     }
     // Create keyed-by-group list of module objects from modules list
     $groups = array();
     $resourceLoader = $this->getResourceLoader();
     foreach ((array) $modules as $name) {
         $module = $resourceLoader->getModule($name);
         # Check that we're allowed to include this module on this page
         if (!$module || $module->getOrigin() > $this->getAllowedModules(ResourceLoaderModule::TYPE_SCRIPTS) && $only == ResourceLoaderModule::TYPE_SCRIPTS || $module->getOrigin() > $this->getAllowedModules(ResourceLoaderModule::TYPE_STYLES) && $only == ResourceLoaderModule::TYPE_STYLES) {
             continue;
         }
         $group = $module->getGroup();
         if (!isset($groups[$group])) {
             $groups[$group] = array();
         }
         $groups[$group][$name] = $module;
     }
     $links = '';
     foreach ($groups as $group => $modules) {
         // Special handling for user-specific groups
         $user = null;
         if (($group === 'user' || $group === 'private') && $this->getUser()->isLoggedIn()) {
             $user = $this->getUser()->getName();
         }
         // Create a fake request based on the one we are about to make so modules return
         // correct timestamp and emptiness data
         $query = ResourceLoader::makeLoaderQuery(array(), $this->getLanguage()->getCode(), $this->getSkin()->getSkinName(), $user, null, ResourceLoader::inDebugMode(), $only === ResourceLoaderModule::TYPE_COMBINED ? null : $only, $this->isPrintable(), $this->getRequest()->getBool('handheld'), $extraQuery);
         $context = new ResourceLoaderContext($resourceLoader, new FauxRequest($query));
         // Drop modules that know they're empty
         foreach ($modules as $key => $module) {
             if ($module->isKnownEmpty($context)) {
                 unset($modules[$key]);
             }
         }
         // If there are no modules left, skip this group
         if ($modules === array()) {
             continue;
         }
         // Inline private modules. These can't be loaded through load.php for security
         // reasons, see bug 34907. Note that these modules should be loaded from
         // getHeadScripts() before the first loader call. Otherwise other modules can't
         // properly use them as dependencies (bug 30914)
         if ($group === 'private') {
             if ($only == ResourceLoaderModule::TYPE_STYLES) {
                 $links .= Html::inlineStyle($resourceLoader->makeModuleResponse($context, $modules));
             } else {
                 $links .= Html::inlineScript(ResourceLoader::makeLoaderConditionalScript($resourceLoader->makeModuleResponse($context, $modules)));
             }
             $links .= "\n";
             continue;
         }
         // Special handling for the user group; because users might change their stuff
         // on-wiki like user pages, or user preferences; we need to find the highest
         // timestamp of these user-changable modules so we can ensure cache misses on change
         // This should NOT be done for the site group (bug 27564) because anons get that too
         // and we shouldn't be putting timestamps in Squid-cached HTML
         $version = null;
         if ($group === 'user') {
             // Get the maximum timestamp
             $timestamp = 1;
             foreach ($modules as $module) {
                 $timestamp = max($timestamp, $module->getModifiedTime($context));
             }
             // Add a version parameter so cache will break when things change
             $version = wfTimestamp(TS_ISO_8601_BASIC, $timestamp);
         }
         $url = ResourceLoader::makeLoaderURL(array_keys($modules), $this->getLanguage()->getCode(), $this->getSkin()->getSkinName(), $user, $version, ResourceLoader::inDebugMode(), $only === ResourceLoaderModule::TYPE_COMBINED ? null : $only, $this->isPrintable(), $this->getRequest()->getBool('handheld'), $extraQuery);
         if ($useESI && $wgResourceLoaderUseESI) {
             $esi = Xml::element('esi:include', array('src' => $url));
             if ($only == ResourceLoaderModule::TYPE_STYLES) {
                 $link = Html::inlineStyle($esi);
             } else {
                 $link = Html::inlineScript($esi);
             }
         } else {
             // Automatically select style/script elements
             if ($only === ResourceLoaderModule::TYPE_STYLES) {
                 $link = Html::linkedStyle($url);
             } else {
                 if ($loadCall) {
                     $link = Html::inlineScript(ResourceLoader::makeLoaderConditionalScript(Xml::encodeJsCall('mw.loader.load', array($url, 'text/javascript', true))));
                 } else {
                     $link = Html::linkedScript($url);
                 }
             }
         }
         if ($group == 'noscript') {
             $links .= Html::rawElement('noscript', array(), $link) . "\n";
         } else {
             $links .= $link . "\n";
         }
     }
     return $links;
 }