[ Index ] |
PHP Cross Reference of Joomla 4.2.2 documentation |
[Summary view] [Print] [Text view]
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 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Wed Sep 7 05:41:13 2022 | Chilli.vc Blog - For Webmaster,Blog-Writer,System Admin and Domainer |