[ Index ]

PHP Cross Reference of Joomla 4.2.2 documentation

title

Body

[close]

/libraries/src/Document/Renderer/Html/ -> ScriptsRenderer.php (source)

   1  <?php
   2  
   3  /**
   4   * Joomla! Content Management System
   5   *
   6   * @copyright   (C) 2005 Open Source Matters, Inc. <https://www.joomla.org>
   7   * @license     GNU General Public License version 2 or later; see LICENSE
   8   */
   9  
  10  namespace Joomla\CMS\Document\Renderer\Html;
  11  
  12  use Joomla\CMS\Document\DocumentRenderer;
  13  use Joomla\CMS\WebAsset\WebAssetItemInterface;
  14  
  15  // phpcs:disable PSR1.Files.SideEffects
  16  \defined('JPATH_PLATFORM') or die;
  17  // phpcs:enable PSR1.Files.SideEffects
  18  
  19  /**
  20   * JDocument head renderer
  21   *
  22   * @since  4.0.0
  23   */
  24  class ScriptsRenderer extends DocumentRenderer
  25  {
  26      /**
  27       * List of already rendered src
  28       *
  29       * @var array
  30       *
  31       * @since   4.0.0
  32       */
  33      private $renderedSrc = [];
  34  
  35      /**
  36       * Renders the document script tags and returns the results as a string
  37       *
  38       * @param   string  $head     (unused)
  39       * @param   array   $params   Associative array of values
  40       * @param   string  $content  The script
  41       *
  42       * @return  string  The output of the script
  43       *
  44       * @since   4.0.0
  45       */
  46      public function render($head, $params = array(), $content = null)
  47      {
  48          // Get line endings
  49          $lnEnd        = $this->_doc->_getLineEnd();
  50          $tab          = $this->_doc->_getTab();
  51          $buffer       = '';
  52          $wam          = $this->_doc->getWebAssetManager();
  53          $assets       = $wam->getAssets('script', true);
  54  
  55          // Get a list of inline assets and their relation with regular assets
  56          $inlineAssets   = $wam->filterOutInlineAssets($assets);
  57          $inlineRelation = $wam->getInlineRelation($inlineAssets);
  58  
  59          // Merge with existing scripts, for rendering
  60          $assets = array_merge(array_values($assets), $this->_doc->_scripts);
  61  
  62          // Generate script file links
  63          foreach ($assets as $key => $item) {
  64              // Check whether we have an Asset instance, or old array with attributes
  65              $asset = $item instanceof WebAssetItemInterface ? $item : null;
  66  
  67              // Add src attribute for non Asset item
  68              if (!$asset) {
  69                  $item['src'] = $key;
  70              }
  71  
  72              // Check for inline content "before"
  73              if ($asset && !empty($inlineRelation[$asset->getName()]['before'])) {
  74                  foreach ($inlineRelation[$asset->getName()]['before'] as $itemBefore) {
  75                      $buffer .= $this->renderInlineElement($itemBefore);
  76  
  77                      // Remove this item from inline queue
  78                      unset($inlineAssets[$itemBefore->getName()]);
  79                  }
  80              }
  81  
  82              $buffer .= $this->renderElement($item);
  83  
  84              // Check for inline content "after"
  85              if ($asset && !empty($inlineRelation[$asset->getName()]['after'])) {
  86                  foreach ($inlineRelation[$asset->getName()]['after'] as $itemBefore) {
  87                      $buffer .= $this->renderInlineElement($itemBefore);
  88  
  89                      // Remove this item from inline queue
  90                      unset($inlineAssets[$itemBefore->getName()]);
  91                  }
  92              }
  93          }
  94  
  95          // Generate script declarations for assets
  96          foreach ($inlineAssets as $item) {
  97              $buffer .= $this->renderInlineElement($item);
  98          }
  99  
 100          // Generate script declarations for old scripts
 101          foreach ($this->_doc->_script as $type => $contents) {
 102              // Test for B.C. in case someone still store script declarations as single string
 103              if (\is_string($contents)) {
 104                  $contents = [$contents];
 105              }
 106  
 107              foreach ($contents as $content) {
 108                  $buffer .= $this->renderInlineElement(
 109                      [
 110                          'type' => $type,
 111                          'content' => $content,
 112                      ]
 113                  );
 114              }
 115          }
 116  
 117          // Output the custom tags - array_unique makes sure that we don't output the same tags twice
 118          foreach (array_unique($this->_doc->_custom) as $custom) {
 119              $buffer .= $tab . $custom . $lnEnd;
 120          }
 121  
 122          return ltrim($buffer, $tab);
 123      }
 124  
 125      /**
 126       * Renders the element
 127       *
 128       * @param   WebAssetItemInterface|array  $item  The element
 129       *
 130       * @return  string  The resulting string
 131       *
 132       * @since   4.0.0
 133       */
 134      private function renderElement($item): string
 135      {
 136          $buffer = '';
 137          $asset  = $item instanceof WebAssetItemInterface ? $item : null;
 138          $src    = $asset ? $asset->getUri() : ($item['src'] ?? '');
 139  
 140          // Make sure we have a src, and it not already rendered
 141          if (!$src || !empty($this->renderedSrc[$src]) || ($asset && $asset->getOption('webcomponent'))) {
 142              return '';
 143          }
 144  
 145          $lnEnd        = $this->_doc->_getLineEnd();
 146          $tab          = $this->_doc->_getTab();
 147          $mediaVersion = $this->_doc->getMediaVersion();
 148  
 149          // Get the attributes and other options
 150          if ($asset) {
 151              $attribs     = $asset->getAttributes();
 152              $version     = $asset->getVersion();
 153              $conditional = $asset->getOption('conditional');
 154  
 155              // Add an asset info for debugging
 156              if (JDEBUG) {
 157                  $attribs['data-asset-name'] = $asset->getName();
 158  
 159                  if ($asset->getDependencies()) {
 160                      $attribs['data-asset-dependencies'] = implode(',', $asset->getDependencies());
 161                  }
 162              }
 163          } else {
 164              $attribs     = $item;
 165              $version     = isset($attribs['options']['version']) ? $attribs['options']['version'] : '';
 166              $conditional = !empty($attribs['options']['conditional']) ? $attribs['options']['conditional'] : null;
 167          }
 168  
 169          // Add "nonce" attribute if exist
 170          if ($this->_doc->cspNonce && !is_null($this->_doc->cspNonce)) {
 171              $attribs['nonce'] = $this->_doc->cspNonce;
 172          }
 173  
 174          // To prevent double rendering
 175          $this->renderedSrc[$src] = true;
 176  
 177          // Check if script uses media version.
 178          if ($version && strpos($src, '?') === false && ($mediaVersion || $version !== 'auto')) {
 179              $src .= '?' . ($version === 'auto' ? $mediaVersion : $version);
 180          }
 181  
 182          $buffer .= $tab;
 183  
 184          // This is for IE conditional statements support.
 185          if (!\is_null($conditional)) {
 186              $buffer .= '<!--[if ' . $conditional . ']>';
 187          }
 188  
 189          // Render the element with attributes
 190          $buffer .= '<script src="' . htmlspecialchars($src) . '"';
 191          $buffer .= $this->renderAttributes($attribs);
 192          $buffer .= '></script>';
 193  
 194          // This is for IE conditional statements support.
 195          if (!\is_null($conditional)) {
 196              $buffer .= '<![endif]-->';
 197          }
 198  
 199          $buffer .= $lnEnd;
 200  
 201          return $buffer;
 202      }
 203  
 204      /**
 205       * Renders the inline element
 206       *
 207       * @param   WebAssetItemInterface|array  $item  The element
 208       *
 209       * @return  string  The resulting string
 210       *
 211       * @since   4.0.0
 212       */
 213      private function renderInlineElement($item): string
 214      {
 215          $buffer = '';
 216          $lnEnd  = $this->_doc->_getLineEnd();
 217          $tab    = $this->_doc->_getTab();
 218  
 219          if ($item instanceof WebAssetItemInterface) {
 220              $attribs = $item->getAttributes();
 221              $content = $item->getOption('content');
 222          } else {
 223              $attribs = $item;
 224              $content = $item['content'] ?? '';
 225  
 226              unset($attribs['content']);
 227          }
 228  
 229          // Do not produce empty elements
 230          if (!$content) {
 231              return '';
 232          }
 233  
 234          // Add "nonce" attribute if exist
 235          if ($this->_doc->cspNonce && !is_null($this->_doc->cspNonce)) {
 236              $attribs['nonce'] = $this->_doc->cspNonce;
 237          }
 238  
 239          $buffer .= $tab . '<script';
 240          $buffer .= $this->renderAttributes($attribs);
 241          $buffer .= '>';
 242  
 243          // This is for full XHTML support.
 244          if ($this->_doc->_mime !== 'text/html') {
 245              $buffer .= $tab . $tab . '//<![CDATA[' . $lnEnd;
 246          }
 247  
 248          $buffer .= $content;
 249  
 250          // See above note
 251          if ($this->_doc->_mime !== 'text/html') {
 252              $buffer .= $tab . $tab . '//]]>' . $lnEnd;
 253          }
 254  
 255          $buffer .= '</script>' . $lnEnd;
 256  
 257          return $buffer;
 258      }
 259  
 260      /**
 261       * Renders the element attributes
 262       *
 263       * @param   array  $attributes  The element attributes
 264       *
 265       * @return  string  The attributes string
 266       *
 267       * @since   4.0.0
 268       */
 269      private function renderAttributes(array $attributes): string
 270      {
 271          $buffer = '';
 272  
 273          $defaultJsMimes         = array('text/javascript', 'application/javascript', 'text/x-javascript', 'application/x-javascript');
 274          $html5NoValueAttributes = array('defer', 'async', 'nomodule');
 275  
 276          foreach ($attributes as $attrib => $value) {
 277              // Don't add the 'options' attribute. This attribute is for internal use (version, conditional, etc).
 278              if ($attrib === 'options' || $attrib === 'src') {
 279                  continue;
 280              }
 281  
 282              // Don't add type attribute if document is HTML5 and it's a default mime type. 'mime' is for B/C.
 283              if (\in_array($attrib, array('type', 'mime')) && $this->_doc->isHtml5() && \in_array($value, $defaultJsMimes)) {
 284                  continue;
 285              }
 286  
 287              // B/C: If defer and async is false or empty don't render the attribute. Also skip if value is bool:false.
 288              if (\in_array($attrib, array('defer', 'async')) && !$value || $value === false) {
 289                  continue;
 290              }
 291  
 292              // NoValue attribute, if it have bool:true
 293              $isNoValueAttrib = $value === true || \in_array($attrib, $html5NoValueAttributes);
 294  
 295              // Don't add type attribute if document is HTML5 and it's a default mime type. 'mime' is for B/C.
 296              if ($attrib === 'mime') {
 297                  $attrib = 'type';
 298              } elseif ($isNoValueAttrib) {
 299                  // NoValue attribute in non HTML5 should contain a value, set it equal to attribute name.
 300                  $value = $attrib;
 301              }
 302  
 303              // Add attribute to script tag output.
 304              $buffer .= ' ' . htmlspecialchars($attrib, ENT_COMPAT, 'UTF-8');
 305  
 306              if (!($this->_doc->isHtml5() && $isNoValueAttrib)) {
 307                  // Json encode value if it's an array.
 308                  $value = !is_scalar($value) ? json_encode($value) : $value;
 309  
 310                  $buffer .= '="' . htmlspecialchars($value, ENT_COMPAT, 'UTF-8') . '"';
 311              }
 312          }
 313  
 314          return $buffer;
 315      }
 316  }


Generated: Wed Sep 7 05:41:13 2022 Chilli.vc Blog - For Webmaster,Blog-Writer,System Admin and Domainer