コード例 #1
0
 /**
  * Build html output from an array of links from makeResourceLoaderLink.
  * @param array $links
  * @return string HTML
  */
 protected static function getHtmlFromLoaderLinks(array $links)
 {
     $html = '';
     $states = array();
     foreach ($links as $link) {
         if (!is_array($link)) {
             $html .= $link;
         } else {
             $html .= $link['html'];
             $states += $link['states'];
         }
     }
     if (count($states)) {
         $html = ResourceLoader::makeInlineScript(ResourceLoader::makeLoaderStateScript($states)) . "\n" . $html;
     }
     return $html;
 }
コード例 #2
0
 /**
  * Build html output from an array of links from makeResourceLoaderLink.
  * @param array $links
  * @return string HTML
  */
 protected static function getHtmlFromLoaderLinks(array $links)
 {
     $html = array();
     $states = array();
     foreach ($links as $link) {
         if (!is_array($link)) {
             $html[] = $link;
         } else {
             $html = array_merge($html, $link['html']);
             $states += $link['states'];
         }
     }
     // Filter out empty values
     $html = array_filter($html, 'strlen');
     if (count($states)) {
         array_unshift($html, ResourceLoader::makeInlineScript(ResourceLoader::makeLoaderStateScript($states)));
     }
     return WrappedString::join("\n", $html);
 }
コード例 #3
0
 function outputInlineScript($moduleList)
 {
     $o = "";
     $modules = array();
     $resolvedModuleDependencyList = $this->getModuleDependencyList($moduleList);
     // "Fake" the request headers as ResourceLoaderContext derives it's data for module resolving from them
     $_GET['only'] = NULL;
     $_GET['modules'] = ResourceLoader::makePackedModulesString($resolvedModuleDependencyList);
     $fauxRequest = new WebRequest();
     $resourceLoader = new MwEmbedResourceLoader();
     foreach ($resolvedModuleDependencyList as $moduleName) {
         $modules[$moduleName] = $resourceLoader->getModule($moduleName);
     }
     $s = $resourceLoader->makeModuleResponse(new MwEmbedResourceLoaderContext($resourceLoader, $fauxRequest), $modules, array());
     $o .= 'window.inlineScript = true;';
     $o .= $s;
     $o .= ResourceLoader::makeLoaderStateScript(array_fill_keys($resolvedModuleDependencyList, 'ready'));
     return $o;
 }
コード例 #4
0
 /**
  * BeforePageDisplay hook handler.
  * @param $out OutputPage
  */
 public static function beforePageDisplay($out)
 {
     global $wgUser;
     wfProfileIn(__METHOD__);
     $gadgets = Gadget::loadList();
     if (!$gadgets) {
         wfProfileOut(__METHOD__);
         return true;
     }
     $lb = new LinkBatch();
     $lb->setCaller(__METHOD__);
     $pages = array();
     $stylesModules = array();
     foreach ($gadgets as $gadget) {
         if ($gadget->isEnabled($wgUser) && $gadget->isAllowed($wgUser)) {
             if ($gadget->hasModule()) {
                 $out->addModules($gadget->getModuleName());
             }
             if ($gadget->hasStylesModule()) {
                 $stylesModules[] = $gadget->getStylesModuleName();
             }
             foreach ($gadget->getLegacyScripts() as $page) {
                 $lb->add(NS_MEDIAWIKI, $page);
                 $pages[] = $page;
             }
         }
     }
     if (count($stylesModules)) {
         $out->addHeadItem('ext.gadget', $out->makeResourceLoaderLink($stylesModules, ResourceLoaderModule::TYPE_STYLES) . Html::inlineScript(ResourceLoader::makeLoaderConditionalScript(ResourceLoader::makeLoaderStateScript(array_fill_keys($stylesModules, 'ready')))));
     }
     $lb->execute(__METHOD__);
     $done = array();
     foreach ($pages as $page) {
         if (isset($done[$page])) {
             continue;
         }
         $done[$page] = true;
         self::applyScript($page, $out);
     }
     wfProfileOut(__METHOD__);
     return true;
 }
コード例 #5
0
 /**
  * The order of elements in the head is as follows:
  * - Inline scripts.
  * - Stylesheets.
  * - Async external script-src.
  *
  * Reasons:
  * - Script execution may be blocked on preceeding stylesheets.
  * - Async scripts are not blocked on stylesheets.
  * - Inline scripts can't be asynchronous.
  * - For styles, earlier is better.
  *
  * @return string|WrappedStringList HTML
  */
 public function getHeadHtml()
 {
     $data = $this->getData();
     $chunks = [];
     // Change "client-nojs" class to client-js. This allows easy toggling of UI components.
     // This happens synchronously on every page view to avoid flashes of wrong content.
     // See also #getDocumentAttributes() and /resources/src/startup.js.
     $chunks[] = Html::inlineScript('document.documentElement.className = document.documentElement.className' . '.replace( /(^|\\s)client-nojs(\\s|$)/, "$1client-js$2" );');
     // Inline RLQ: Set page variables
     if ($this->config) {
         $chunks[] = ResourceLoader::makeInlineScript(ResourceLoader::makeConfigSetScript($this->config));
     }
     // Inline RLQ: Initial module states
     $states = array_merge($this->exemptStates, $data['states']);
     if ($states) {
         $chunks[] = ResourceLoader::makeInlineScript(ResourceLoader::makeLoaderStateScript($states));
     }
     // Inline RLQ: Embedded modules
     if ($data['embed']['general']['top']) {
         $chunks[] = $this->getLoad($data['embed']['general']['top'], ResourceLoaderModule::TYPE_COMBINED);
     }
     // Inline RLQ: Load general modules
     if ($data['general']['top']) {
         $chunks[] = ResourceLoader::makeInlineScript(Xml::encodeJsCall('mw.loader.load', [$data['general']['top']]));
     }
     // Inline RLQ: Load only=scripts
     if ($data['scripts']['top']) {
         $chunks[] = $this->getLoad($data['scripts']['top'], ResourceLoaderModule::TYPE_SCRIPTS);
     }
     // External stylesheets
     if ($data['styles']) {
         $chunks[] = $this->getLoad($data['styles'], ResourceLoaderModule::TYPE_STYLES);
     }
     // Inline stylesheets (embedded only=styles)
     if ($data['embed']['styles']) {
         $chunks[] = $this->getLoad($data['embed']['styles'], ResourceLoaderModule::TYPE_STYLES);
     }
     // Async scripts. Once the startup is loaded, inline RLQ scripts will run.
     // Pass-through a custom target from OutputPage (T143066).
     $startupQuery = $this->target ? ['target' => $this->target] : [];
     $chunks[] = $this->getLoad('startup', ResourceLoaderModule::TYPE_SCRIPTS, $startupQuery);
     return WrappedStringList::join("\n", $chunks);
 }
コード例 #6
0
 /**
  * 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 $inHead boolean If true, this HTML goes into the "<head>", if false it goes into the "<body>"
  * @return string
  */
 function getScriptsForBottomQueue($inHead)
 {
     global $wgUseSiteJs, $wgAllowUserJs;
     // Script and Messages "only" requests marked for bottom inclusion
     // If we're in the <head>, use load() calls rather than <script src="..."> tags
     // Messages should go first
     $scripts = $this->makeResourceLoaderLink($this->getModuleMessages(true, 'bottom'), ResourceLoaderModule::TYPE_MESSAGES, false, array(), $inHead);
     $scripts .= $this->makeResourceLoaderLink($this->getModuleScripts(true, 'bottom'), ResourceLoaderModule::TYPE_SCRIPTS, 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) {
         $scripts .= Html::inlineScript(ResourceLoader::makeLoaderConditionalScript(Xml::encodeJsCall('mw.loader.load', array($modules, null, true))));
     }
     // Legacy Scripts
     $scripts .= "\n" . $this->mScripts;
     $defaultModules = array();
     // Add site JS if enabled
     if ($wgUseSiteJs) {
         $scripts .= $this->makeResourceLoaderLink('site', ResourceLoaderModule::TYPE_SCRIPTS, false, array(), $inHead);
         $defaultModules['site'] = 'loading';
     } else {
         // The wiki is configured to not allow a site module.
         $defaultModules['site'] = 'missing';
     }
     // Add user JS if enabled
     if ($wgAllowUserJs) {
         if ($this->getUser()->isLoggedIn()) {
             if ($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)
                 $scripts .= $this->makeResourceLoaderLink('user', ResourceLoaderModule::TYPE_SCRIPTS, false, array('excludepage' => $this->getTitle()->getPrefixedDBkey()), $inHead);
                 // Load the previewed JS
                 $scripts .= 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.
                 $scripts .= $this->makeResourceLoaderLink('user', ResourceLoaderModule::TYPE_SCRIPTS, false, array(), $inHead);
             }
             $defaultModules['user'] = '******';
         } else {
             // Non-logged-in users have no user module. Treat it as empty and 'ready' to avoid
             // blocking default gadgets that might depend on it. Although arguably default-enabled
             // gadgets should not depend on the user module, it's harmless and less error-prone to
             // handle this case.
             $defaultModules['user'] = '******';
         }
     } else {
         // User JS disabled
         $defaultModules['user'] = '******';
     }
     // Group JS is only enabled if site JS is enabled.
     if ($wgUseSiteJs) {
         if ($this->getUser()->isLoggedIn()) {
             $scripts .= $this->makeResourceLoaderLink('user.groups', ResourceLoaderModule::TYPE_COMBINED, false, array(), $inHead);
             $defaultModules['user.groups'] = 'loading';
         } else {
             // Non-logged-in users have no user.groups module. Treat it as empty and 'ready' to
             // avoid blocking gadgets that might depend upon the module.
             $defaultModules['user.groups'] = 'ready';
         }
     } else {
         // Site (and group JS) disabled
         $defaultModules['user.groups'] = 'missing';
     }
     $loaderInit = '';
     if ($inHead) {
         // We generate loader calls anyway, so no need to fix the client-side loader's state to 'loading'.
         foreach ($defaultModules as $m => $state) {
             if ($state == 'loading') {
                 unset($defaultModules[$m]);
             }
         }
     }
     if (count($defaultModules) > 0) {
         $loaderInit = Html::inlineScript(ResourceLoader::makeLoaderConditionalScript(ResourceLoader::makeLoaderStateScript($defaultModules))) . "\n";
     }
     return $loaderInit . $scripts;
 }