diff --git a/libraries/joomla/document/renderer/html/head.php b/libraries/joomla/document/renderer/html/head.php index 3d6f747b0192a..9409d41cf4317 100644 --- a/libraries/joomla/document/renderer/html/head.php +++ b/libraries/joomla/document/renderer/html/head.php @@ -63,16 +63,78 @@ public function fetchHead($document) $app->triggerEvent('onBeforeCompileHead'); // Get line endings - $lnEnd = $document->_getLineEnd(); - $tab = $document->_getTab(); - $tagEnd = ' />'; - $buffer = ''; - $mediaVersion = $document->getMediaVersion(); + $lnEnd = $document->_getLineEnd(); + + // Get the meta tags (also base, title, etc.) + $buffer = $this->fetchMetaTags($document); + + // Get (non-stylesheet) link tags if any + if (!empty($document->_links)) + { + $buffer = array_merge($buffer, $this->fetchLinkTags($document)); + } + + // Get the stylesheets + if (!empty($document->_styleSheets)) + { + $buffer = array_merge($buffer, $this->fetchStyleSheets($document)); + } + + // Get the style declarations + if (!empty($document->_style)) + { + $buffer = array_merge($buffer, $this->fetchStyleDeclarations($document)); + } + + // Get script options + $scriptOptions = $document->getScriptOptions(); + + if (!empty($scriptOptions)) + { + $buffer = array_merge($buffer, $this->fetchScriptOptions($document)); + } + + // Get scripts (loaded as external files) + if (!empty($document->_scripts)) + { + $buffer = array_merge($buffer, $this->fetchScripts($document)); + } + + // Get script declarations + if (!empty($document->_script)) + { + $buffer = array_merge($buffer, $this->fetchScriptDeclarations($document)); + } + + // Get custom tags + if (!empty($document->_custom)) + { + $buffer = array_merge($buffer, $this->fetchCustomTags($document)); + } + + return implode($lnEnd, $buffer); + } + + /** + * Gets the meta, title, and base tags as an array. + * + * @param JDocumentHtml $document The document for which the head will be created + * + * @return array The tags + * + * @since __DEPLOY_VERSION__ + */ + protected function fetchMetaTags($document) + { + $tab = $document->_getTab(); + $isHtml5 = $document->isHtml5(); + $tagEnd = $isHtml5 ? '>' : '/>'; + $buffer = array(); // Generate charset when using HTML5 (should happen first) - if ($document->isHtml5()) + if ($isHtml5) { - $buffer .= $tab . '' . $lnEnd; + $buffer[] = $tab . '' . $lnEnd; + $buffer[] = $tab . ' $content) { - if ($type == 'http-equiv' && !($document->isHtml5() && $name == 'content-type')) - { - $buffer .= $tab . '' . $lnEnd; - } - elseif ($type != 'http-equiv' && !empty($content)) + // Html5 doesn't need content-type and we don't need empty meta tags + if (($isHtml5 && $type == 'http-equiv' && $name == 'content-type') || empty($content)) { - $buffer .= $tab . '' . $lnEnd; + continue; } + + $buffer[] = $tab . '' . $lnEnd; + $buffer[] = $tab . '' . $lnEnd; + $buffer[] = $tab . '' . htmlspecialchars($document->getTitle(), ENT_COMPAT, 'UTF-8') . '' . $lnEnd; + $buffer[] = $tab . '' . htmlspecialchars($document->getTitle(), ENT_COMPAT, 'UTF-8') . ''; + + return $buffer; + } + + /** + * Gets the (non-stylesheet) link tags as an array. + * + * @param JDocumentHtml $document The document for which the head will be created + * + * @return array The tags + * + * @since __DEPLOY_VERSION__ + */ + protected function fetchLinkTags($document) + { + $tab = $document->_getTab(); + $isHtml5 = $document->isHtml5(); + $tagEnd = $isHtml5 ? '>' : '/>'; + $buffer = array(); // Generate link declarations foreach ($document->_links as $link => $linkAtrr) { - $buffer .= $tab . '_getTab(); + $isHtml5 = $document->isHtml5(); + $mediaVersion = $document->getMediaVersion(); + $tagEnd = $isHtml5 ? ' >' : ' />'; + $buffer = array(); + $defaultCssMimes = array('text/css'); // Generate stylesheet links foreach ($document->_styleSheets as $src => $attribs) { - // Check if stylesheet uses IE conditional statements. - $conditional = isset($attribs['options']) && isset($attribs['options']['conditional']) ? $attribs['options']['conditional'] : null; + $conditional = null; + $attr = array('rel="stylesheet"'); - // Check if script uses media version. - if (isset($attribs['options']['version']) && $attribs['options']['version'] && strpos($src, '?') === false - && ($mediaVersion || $attribs['options']['version'] !== 'auto')) + if (isset($attribs['mime']) && (!$isHtml5 || !in_array($attribs['mime'], $defaultCssMimes))) { - $src .= '?' . ($attribs['options']['version'] === 'auto' ? $mediaVersion : $attribs['options']['version']); + $attr[] = 'type="' . $attribs['mime'] . '"'; } - $buffer .= $tab; - - // This is for IE conditional statements support. - if (!is_null($conditional)) + if (isset($attribs['options']) && is_array($attribs['options'])) { - $buffer .= ''; + $attr[] = 'media="' . $attribs['media'] . '"'; + } + + if (isset($attribs['attribs']) && is_array($attribs['attribs']) && !empty($attribs['attribs'])) + { + $attr[] = ArrayHelper::toString($attribs['attribs']); } - $buffer .= $lnEnd; + $buffer[] = $tab . '_getTab(); + $buffer = array(); + + $defaultCssMimes = array('text/css'); + // Generate stylesheet declarations foreach ($document->_style as $type => $content) { - $buffer .= $tab . 'isHtml5() || !in_array($type, $defaultCssMimes))) { - $buffer .= ' type="' . $type . '"'; + $openTag .= ' type="' . $type . '"'; } - $buffer .= '>' . $lnEnd; + $openTag .= '>'; + + $buffer[] = $openTag; // This is for full XHTML support. if ($document->_mime != 'text/html') { - $buffer .= $tab . $tab . '/*_mime != 'text/html') { - $buffer .= $tab . $tab . '/*]]>*/' . $lnEnd; + $buffer[] = $tab . $tab . '/*]]>*/'; } - $buffer .= $tab . '' . $lnEnd; + $buffer[] = $tab . ''; } - // Generate scripts options - $scriptOptions = $document->getScriptOptions(); - - if (!empty($scriptOptions)) - { - $buffer .= $tab . '' . $lnEnd; - } + /** + * Gets the external file loading script tags as an array. + * + * @param JDocumentHtml $document The document for which the head will be created + * + * @return array The tags + * + * @since __DEPLOY_VERSION__ + */ + protected function fetchScripts($document) + { + $tab = $document->_getTab(); + $isHtml5 = $document->isHtml5(); + $buffer = array(); $defaultJsMimes = array('text/javascript', 'application/javascript', 'text/x-javascript', 'application/x-javascript'); $html5NoValueAttributes = array('defer', 'async'); + $mediaVersion = $document->getMediaVersion(); // Generate script file links foreach ($document->_scripts as $src => $attribs) { - // Check if script uses IE conditional statements. - $conditional = isset($attribs['options']) && isset($attribs['options']['conditional']) ? $attribs['options']['conditional'] : null; - // Check if script uses media version. if (isset($attribs['options']['version']) && $attribs['options']['version'] && strpos($src, '?') === false && ($mediaVersion || $attribs['options']['version'] !== 'auto')) @@ -259,15 +359,7 @@ public function fetchHead($document) $src .= '?' . ($attribs['options']['version'] === 'auto' ? $mediaVersion : $attribs['options']['version']); } - $buffer .= $tab; - - // This is for IE conditional statements support. - if (!is_null($conditional)) - { - $buffer .= ''; - } + $buffer[] = $tab . + (is_null($conditional) ? '' : ''); + } + + return $buffer; + } - $buffer .= $lnEnd; + /** + * Gets a script tag containing the Joomla options storage. + * + * @param JDocumentHtml $document The document for which the head will be created + * + * @return array The tags + * + * @since __DEPLOY_VERSION__ + */ + protected function fetchScriptOptions($document) + { + // Generate scripts options + $scriptOptions = $document->getScriptOptions(); + + if (empty($scriptOptions)) + { + return array(); } + $tab = $document->_getTab(); + + $prettyPrint = (JDEBUG && defined('JSON_PRETTY_PRINT') ? JSON_PRETTY_PRINT : false); + $jsonOptions = json_encode($scriptOptions, $prettyPrint); + $jsonOptions = $jsonOptions ? $jsonOptions : '{}'; + + $buffer = $tab . + ''; + + return array($buffer); + } + + /** + * Gets a script tag containing javascript declarations as an array. + * + * @param JDocumentHtml $document The document for which the head will be created + * + * @return array The tags + * + * @since __DEPLOY_VERSION__ + */ + protected function fetchScriptDeclarations($document) + { + $tab = $document->_getTab(); + $isHtml5 = $document->isHtml5(); + $buffer = array(); + + $defaultJsMimes = array('text/javascript', 'application/javascript', 'text/x-javascript', 'application/x-javascript'); + // Generate script declarations foreach ($document->_script as $type => $content) { - $buffer .= $tab . 'isHtml5() || !in_array($type, $defaultJsMimes))) + if (!is_null($type) && (!$isHtml5 || !in_array($type, $defaultJsMimes))) { - $buffer .= ' type="' . $type . '"'; + $openTag .= ' type="' . $type . '"'; } - $buffer .= '>' . $lnEnd; + $openTag .= '>'; + + $buffer[] = $openTag; // This is for full XHTML support. if ($document->_mime != 'text/html') { - $buffer .= $tab . $tab . '//_mime != 'text/html') { - $buffer .= $tab . $tab . '//]]>' . $lnEnd; + $buffer[] = $tab . $tab . '//]]>'; } - $buffer .= $tab . '' . $lnEnd; + $buffer[] = $tab . ''; } + return $buffer; + } + + /** + * Gets the custom tags as an array. + * + * @param JDocumentHtml $document The document for which the head will be created + * + * @return array The tags + * + * @since __DEPLOY_VERSION__ + */ + protected function fetchCustomTags($document) + { + $tab = $document->_getTab(); + $buffer = array(); + // Output the custom tags - array_unique makes sure that we don't output the same tags twice foreach (array_unique($document->_custom) as $custom) { - $buffer .= $tab . $custom . $lnEnd; + $buffer[] = $tab . $custom; } return ltrim($buffer, $tab);