[ Index ]

PHP Cross Reference of Joomla 4.2.2 documentation

title

Body

[close]

/libraries/src/Document/Renderer/Html/ -> StylesRenderer.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 styles renderer
  21   *
  22   * @since  4.0.0
  23   */
  24  class StylesRenderer 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 stylesheets and style 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          $tab          = $this->_doc->_getTab();
  49          $buffer       = '';
  50          $wam          = $this->_doc->getWebAssetManager();
  51          $assets       = $wam->getAssets('style', true);
  52  
  53          // Get a list of inline assets and their relation with regular assets
  54          $inlineAssets   = $wam->filterOutInlineAssets($assets);
  55          $inlineRelation = $wam->getInlineRelation($inlineAssets);
  56  
  57          // Merge with existing styleSheets, for rendering
  58          $assets = array_merge(array_values($assets), $this->_doc->_styleSheets);
  59  
  60          // Generate stylesheet links
  61          foreach ($assets as $key => $item) {
  62              $asset = $item instanceof WebAssetItemInterface ? $item : null;
  63  
  64              // Add href attribute for non Asset item
  65              if (!$asset) {
  66                  $item['href'] = $key;
  67              }
  68  
  69              // Check for inline content "before"
  70              if ($asset && !empty($inlineRelation[$asset->getName()]['before'])) {
  71                  foreach ($inlineRelation[$asset->getName()]['before'] as $itemBefore) {
  72                      $buffer .= $this->renderInlineElement($itemBefore);
  73  
  74                      // Remove this item from inline queue
  75                      unset($inlineAssets[$itemBefore->getName()]);
  76                  }
  77              }
  78  
  79              $buffer .= $this->renderElement($item);
  80  
  81              // Check for inline content "after"
  82              if ($asset && !empty($inlineRelation[$asset->getName()]['after'])) {
  83                  foreach ($inlineRelation[$asset->getName()]['after'] as $itemBefore) {
  84                      $buffer .= $this->renderInlineElement($itemBefore);
  85  
  86                      // Remove this item from inline queue
  87                      unset($inlineAssets[$itemBefore->getName()]);
  88                  }
  89              }
  90          }
  91  
  92          // Generate script declarations for assets
  93          foreach ($inlineAssets as $item) {
  94              $buffer .= $this->renderInlineElement($item);
  95          }
  96  
  97          // Generate stylesheet declarations
  98          foreach ($this->_doc->_style as $type => $contents) {
  99              // Test for B.C. in case someone still store stylesheet declarations as single string
 100              if (\is_string($contents)) {
 101                  $contents = [$contents];
 102              }
 103  
 104              foreach ($contents as $content) {
 105                  $buffer .= $this->renderInlineElement(
 106                      [
 107                          'type' => $type,
 108                          'content' => $content,
 109                      ]
 110                  );
 111              }
 112          }
 113  
 114          return ltrim($buffer, $tab);
 115      }
 116  
 117      /**
 118       * Renders the element
 119       *
 120       * @param   WebAssetItemInterface|array  $item  The element
 121       *
 122       * @return  string  The resulting string
 123       *
 124       * @since   4.0.0
 125       */
 126      private function renderElement($item): string
 127      {
 128          $buffer = '';
 129          $asset  = $item instanceof WebAssetItemInterface ? $item : null;
 130          $src    = $asset ? $asset->getUri() : ($item['href'] ?? '');
 131  
 132          // Make sure we have a src, and it not already rendered
 133          if (!$src || !empty($this->renderedSrc[$src])) {
 134              return '';
 135          }
 136  
 137          $lnEnd        = $this->_doc->_getLineEnd();
 138          $tab          = $this->_doc->_getTab();
 139          $mediaVersion = $this->_doc->getMediaVersion();
 140  
 141          // Get the attributes and other options
 142          if ($asset) {
 143              $attribs     = $asset->getAttributes();
 144              $version     = $asset->getVersion();
 145              $conditional = $asset->getOption('conditional');
 146  
 147              // Add an asset info for debugging
 148              if (JDEBUG) {
 149                  $attribs['data-asset-name'] = $asset->getName();
 150  
 151                  if ($asset->getDependencies()) {
 152                      $attribs['data-asset-dependencies'] = implode(',', $asset->getDependencies());
 153                  }
 154              }
 155          } else {
 156              $attribs     = $item;
 157              $version     = isset($attribs['options']['version']) ? $attribs['options']['version'] : '';
 158              $conditional = !empty($attribs['options']['conditional']) ? $attribs['options']['conditional'] : null;
 159          }
 160  
 161          // Add "nonce" attribute if exist
 162          if ($this->_doc->cspNonce && !is_null($this->_doc->cspNonce)) {
 163              $attribs['nonce'] = $this->_doc->cspNonce;
 164          }
 165  
 166          // To prevent double rendering
 167          $this->renderedSrc[$src] = true;
 168  
 169          // Check if script uses media version.
 170          if ($version && strpos($src, '?') === false && ($mediaVersion || $version !== 'auto')) {
 171              $src .= '?' . ($version === 'auto' ? $mediaVersion : $version);
 172          }
 173  
 174          $buffer .= $tab;
 175  
 176          // This is for IE conditional statements support.
 177          if (!\is_null($conditional)) {
 178              $buffer .= '<!--[if ' . $conditional . ']>';
 179          }
 180  
 181          $relation = isset($attribs['rel']) ? $attribs['rel'] : 'stylesheet';
 182  
 183          if (isset($attribs['rel'])) {
 184              unset($attribs['rel']);
 185          }
 186  
 187          // Render the element with attributes
 188          $buffer .= '<link href="' . htmlspecialchars($src) . '" rel="' . $relation . '"';
 189          $buffer .= $this->renderAttributes($attribs);
 190          $buffer .= ' />';
 191  
 192          if ($relation === 'lazy-stylesheet') {
 193              $buffer .= '<noscript><link href="' . htmlspecialchars($src) . '" rel="stylesheet" /></noscript>';
 194          }
 195  
 196          // This is for IE conditional statements support.
 197          if (!\is_null($conditional)) {
 198              $buffer .= '<![endif]-->';
 199          }
 200  
 201          $buffer .= $lnEnd;
 202  
 203          return $buffer;
 204      }
 205  
 206      /**
 207       * Renders the inline element
 208       *
 209       * @param   WebAssetItemInterface|array  $item  The element
 210       *
 211       * @return  string  The resulting string
 212       *
 213       * @since   4.0.0
 214       */
 215      private function renderInlineElement($item): string
 216      {
 217          $buffer = '';
 218          $lnEnd  = $this->_doc->_getLineEnd();
 219          $tab    = $this->_doc->_getTab();
 220  
 221          if ($item instanceof WebAssetItemInterface) {
 222              $attribs = $item->getAttributes();
 223              $content = $item->getOption('content');
 224          } else {
 225              $attribs = $item;
 226              $content = $item['content'] ?? '';
 227  
 228              unset($attribs['content']);
 229          }
 230  
 231          // Do not produce empty elements
 232          if (!$content) {
 233              return '';
 234          }
 235  
 236          // Add "nonce" attribute if exist
 237          if ($this->_doc->cspNonce && !is_null($this->_doc->cspNonce)) {
 238              $attribs['nonce'] = $this->_doc->cspNonce;
 239          }
 240  
 241          $buffer .= $tab . '<style';
 242          $buffer .= $this->renderAttributes($attribs);
 243          $buffer .= '>';
 244  
 245          // This is for full XHTML support.
 246          if ($this->_doc->_mime !== 'text/html') {
 247              $buffer .= $tab . $tab . '/*<![CDATA[*/' . $lnEnd;
 248          }
 249  
 250          $buffer .= $content;
 251  
 252          // See above note
 253          if ($this->_doc->_mime !== 'text/html') {
 254              $buffer .= $tab . $tab . '/*]]>*/' . $lnEnd;
 255          }
 256  
 257          $buffer .= '</style>' . $lnEnd;
 258  
 259          return $buffer;
 260      }
 261  
 262      /**
 263       * Renders the element attributes
 264       *
 265       * @param   array  $attributes  The element attributes
 266       *
 267       * @return  string  The attributes string
 268       *
 269       * @since   4.0.0
 270       */
 271      private function renderAttributes(array $attributes): string
 272      {
 273          $buffer = '';
 274  
 275          $defaultCssMimes = array('text/css');
 276  
 277          foreach ($attributes as $attrib => $value) {
 278              // Don't add the 'options' attribute. This attribute is for internal use (version, conditional, etc).
 279              if ($attrib === 'options' || $attrib === 'href') {
 280                  continue;
 281              }
 282  
 283              // Don't add type attribute if document is HTML5 and it's a default mime type. 'mime' is for B/C.
 284              if (\in_array($attrib, array('type', 'mime')) && $this->_doc->isHtml5() && \in_array($value, $defaultCssMimes)) {
 285                  continue;
 286              }
 287  
 288              // Skip the attribute if value is bool:false.
 289              if ($value === false) {
 290                  continue;
 291              }
 292  
 293              // NoValue attribute, if it have bool:true
 294              $isNoValueAttrib = $value === true;
 295  
 296              // Don't add type attribute if document is HTML5 and it's a default mime type. 'mime' is for B/C.
 297              if ($attrib === 'mime') {
 298                  $attrib = 'type';
 299              } elseif ($isNoValueAttrib) {
 300                  // NoValue attribute in non HTML5 should contain a value, set it equal to attribute name.
 301                  $value = $attrib;
 302              }
 303  
 304              // Add attribute to script tag output.
 305              $buffer .= ' ' . htmlspecialchars($attrib, ENT_COMPAT, 'UTF-8');
 306  
 307              if (!($this->_doc->isHtml5() && $isNoValueAttrib)) {
 308                  // Json encode value if it's an array.
 309                  $value = !is_scalar($value) ? json_encode($value) : $value;
 310  
 311                  $buffer .= '="' . htmlspecialchars($value, ENT_COMPAT, 'UTF-8') . '"';
 312              }
 313          }
 314  
 315          return $buffer;
 316      }
 317  }


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