| Current Path : /var/www/html/libraries/noboss/src/Util/ |
| Current File : /var/www/html/libraries/noboss/src/Util/NbLoadextensionAssetsUtil.php |
<?php
/**
* @package No Boss Extensions
* @subpackage No Boss Library
* @author No Boss Technology <contact@nobosstechnology.com>
* @copyright Copyright (C) 2026 No Boss Technology. All rights reserved.
* @license GNU Lesser General Public License version 3 or later; see <https://www.gnu.org/licenses/lgpl-3.0.en.html>
*/
namespace Noboss\Library\Util;
use Joomla\CMS\Factory;
use Joomla\Database\DatabaseInterface;
use Joomla\CMS\Uri\Uri;
// phpcs:disable PSR1.Files.SideEffects
\defined('_JEXEC') or die;
// phpcs:enable PSR1.Files.SideEffects
class NbLoadextensionAssetsUtil {
// Variavel que armazena o nome da extensao com prefixo
var $extensionName = '';
// Variavel que armazena o diretorio da extensao
var $directoryExtension = '';
// Variavel que armazena o prefixo da extensao para códigos inline
var $prefixCode = '';
var $extensionsVersion = '';
/**
* Metodo construtor
*
* @param string $extensionName nome da extensao (ex: mod_nobossbanners)
* @param string $prefixCode prefixo da extensao para codigos inline (opcional)
*/
public function __construct($extensionName, $prefixCode = ''){
// Seta o nome da extensao
$this->extensionName = $extensionName;
// Seta o prefixo da extensao
$this->prefixCode = $prefixCode;
// Seta a versao da extensao
$this->extensionsVersion = self::getExtensionVersion($extensionName);
}
/**
* Obtem a versao da extensao (registrada em banco)
*
* @param string $extensionName nome da extensao (ex: mod_nobossbanners)
*
* @return mixed String com versao ou false, caso nao encontrado
*/
public static function getExtensionVersion($extensionName){
$db = Factory::getContainer()->get(DatabaseInterface::class);
$query = $db->getQuery(true);
$query->select('manifest_cache')->from($db->quoteName('#__extensions'))->where('element = "' . $extensionName . '"');
$db->setQuery($query);
$result = $db->loadResult();
if(!$result){
return false;
}
$manifest = json_decode($result, true);
if(empty($manifest) || empty($manifest['version'])){
return false;
}
return $manifest['version'];
}
/**
* Carrega arquivo e codigos inline JS
*
* @param boolean $loadFile flag para informar se arquivo da extensao deve ser carregado
* @param array $optionsInlineCode dados de codigos a serem inseridos inline (opcional) - principais valores: 'prefix' e 'code'
* @param boolean $loadJquery flag para informar se a biblioteca jquery deve ser adicionada
* @param boolean $loadBaseNameUrl flag para declarar ou nao a variavel baseNameUrl
* @param boolean $admin flag para declarar se esta carregando na area admin
* @param boolean $fileName nome do arquivo (informar somente qnd nao for o nome da extensao mesmo)
*
* @return void
*/
public function loadJs($loadFile = true, $optionsInlineCode = array(), $loadJquery = true, $loadBaseNameUrl = true, $admin = false, $fileName = ''){
$app = Factory::getApplication();
$wa = $app->getDocument()->getWebAssetManager();
// Defindo para chamar a variavel 'baseNameUrl'
if ($loadBaseNameUrl){
// Define variavel JS 'basenameUrl' caso ja nao esteja definido
$wa->addInline("script", "var baseNameUrl = '".Uri::root()."';", array('name' => 'baseNameUrl'));
// Define variavel JS 'majorVersionJoomla' (versao macro do Joomla. ex: '4') caso ja nao esteja definido
$wa->addInline("script", "var majorVersionJoomla = '".substr(JVERSION, 0, 1)."';", array('name' => 'majorVersionJoomla'));
// Define variavel JS 'completeVersionJoomla' (versao completa do Joomla. ex: '4.0.1') caso ja nao esteja definido
$wa->addInline("script", "var completeVersionJoomla = '".JVERSION."';", array('name' => 'completeVersionJoomla'));
}
// Setado para carregar jquery
if ($loadJquery){
// Carrega framework jquery adicionado pelo Joomla
$wa->useScript('jquery');
}
// Setado para carregar o arquivo de JS da extensao
if ($loadFile){
// Se nome do arquivo nao foi definido, coloca nome da extensao
if(empty($fileName)){
$fileName = $this->extensionName;
}
if ($fileName == ''){
return false;
}
// Obtem o diretorio da extensao desde o diretorio raiz do site
if ($this->getDirectoryExtension()){
// Monta a url do arquivo a ser adicionado
$urlFile = $this->directoryExtension . "assets/".(($admin) ? 'admin' : 'site')."/js/{$fileName}.min.js";
// Verifica se arquivo existe
if(is_file(JPATH_ROOT. "/". (($admin) ? 'administrator/' : '') . $urlFile)){
// Adiciona a versao da extensao no final da url para controle de cache
if(!empty($this->extensionsVersion)){
$urlFile .= "?v={$this->extensionsVersion}";
}
// Adiciona os scripts e/ou css pertencentes a extensao
$wa->registerAndUseScript($this->directoryExtension.'_'.$fileName, Uri::base() . $urlFile, array(), array('defer' => 'defer'));
}
}
}
if(empty($optionsInlineCode)){
$optionsInlineCode = array();
}
// Prefixo nao informado como parametro: obtem o definido na classe
$optionsInlineCode['prefix'] = !empty($optionsInlineCode['prefix'])?: $this->prefixCode;
// Ha codigo inline a ser inserido
if (!empty($optionsInlineCode['code'])){
// Definido prefixo da extensao
if (!empty($optionsInlineCode['prefix'])){
// Atualiza codigo adicionando prefixo
$optionsInlineCode['code'] = $this->addContextInJs($optionsInlineCode['code'], $optionsInlineCode['prefix']);
}
// Adiciona codigo inline na pagina
$wa->addInlineScript($optionsInlineCode['code']);
}
// Extensao admin: aproveita e carrega JS para corrigir valores default de alguns campos
if($admin){
$wa->registerAndUseScript('defaultvalues', Uri::root().'libraries/noboss/assets/util/js/min/defaultvalues.min.js');
$wa->addInlineScript('util.fixDefaultValues();');
}
}
/**
* Carrega arquivo e codigos inline CSS
*
* @param boolean $loadFile flag para informar se arquivo da extensao deve ser carregado
* @param array $optionsInlineCode dados de codigos a serem inseridos inline (opcional) - principais valores: 'prefix' e 'code'
* @param boolean $admin flag para declarar se esta carregando na area admin
* @param boolean $fileName nome do arquivo (informar somente qnd nao for o nome da extensao mesmo)
*
* @return void
*/
public function loadCss($loadFile = true, $optionsInlineCode = array(), $admin = false, $fileName = ''){
$app = Factory::getApplication();
$wa = $app->getDocument()->getWebAssetManager();
// Setado para carregar o arquivo de CSS da extensao
if ($loadFile){
// Se nome do arquivo nao foi definido, coloca nome da extensao
if(empty($fileName)){
$fileName = $this->extensionName;
}
if ($fileName == ''){
return false;
}
// Obtem o diretorio da extensao desde o diretorio raiz do site
if ($this->getDirectoryExtension()){
// Monta a url do arquivo a ser adicionado
$urlFile = $this->directoryExtension . "assets/".(($admin) ? 'admin' : 'site')."/css/{$fileName}.min.css";
// Verifica se arquivo existe
if(is_file(JPATH_ROOT. "/". (($admin) ? 'administrator/' : '') . $urlFile)){
// Adiciona a versao da extensao no final da url para controle de cache
if(!empty($this->extensionsVersion)){
$urlFile .= "?v={$this->extensionsVersion}";
}
// Adiciona o arquivo CSS
$wa->registerAndUseStyle($this->directoryExtension.'_load', Uri::base() . $urlFile);
}
}
}
// Ha codigo inline a ser inserido
if (!empty($optionsInlineCode) && !empty($this->prefixCode) && !empty($optionsInlineCode['code'])){
// Insere codigo inline, caso esteja definido
$this->addStyleWithPrefix($optionsInlineCode['code'], $this->prefixCode);
}
if(empty($optionsInlineCode)){
$optionsInlineCode = array();
}
// Prefixo nao informado como parametro: obtem o definido na classe
$optionsInlineCode['prefix'] = !empty($optionsInlineCode['prefix'])?: $this->prefixCode;
// Ha codigo inline a ser inserido
if (!empty($optionsInlineCode['code'])){
// Definido prefixo da extensao
if (!empty($optionsInlineCode['prefix'])){
// Adiciona codigo na pagina incluindo prefixo
$this->addStyleWithPrefix($optionsInlineCode['code'], $optionsInlineCode['prefix']);
}else{
// Adiciona codigo inline na pagina sem prefixos
$wa->addInlineStyle($optionsInlineCode['code']);
}
}
}
/**
* Adiciona uma declaracao de estilo colocando prefixo da extensao
*
* @param String $code Código CSS
* @param String $prefix Prefixo a ser adicionado (opcional)
*
* @return void
*/
public function addStyleWithPrefix($code, $prefix = ''){
// Prefixo nao informado como parametro: obtem o definido na classe
if (empty($prefix)){
$prefix = $this->prefixCode;
}
$app = Factory::getApplication();
$wa = $app->getDocument()->getWebAssetManager();
// Ha codigo inline a ser inserido
if ($code && $prefix != ''){
// Atualiza codigo com prefixo informado
if ($code = $this->addPrefixInCss($code, $prefix)){
// Adiciona codigo inline na pagina
$wa->addInlineStyle($code);
}
}
else{
return false;
}
}
/**
* Carrega arquivo css para uma familia de icones especificada
*
* @param string $aliasFamily alias da familiar a ser adicionada
*
* @return mixed Adiciona arquivo em caso de sucesso ou retorna false em caso de erro
*/
public static function loadFamilyIcons($aliasFamily){
$app = Factory::getApplication();
$wa = $app->getDocument()->getWebAssetManager();
// Verifica familia solicitada para definir a url
// OBS: todas as familias sao servidas localmente (libraries/noboss/assets/plugins/stylesheets)
// para compatibilidade com sites que aplicam Content Security Policy ('style-src'/'font-src'
// restritivos) e para evitar dependencia de CDNs (LGPD/GDPR — cookies de origem externa)
$base = Uri::root()."libraries/noboss/assets/plugins/stylesheets/css/";
switch($aliasFamily){
case 'font-awesome':
$url = $base."font-awesome-4.7.min.css?v=4.7.0";
break;
case 'font-awesome-v6':
$url = $base."font-awesome.css?v=6.7.2";
break;
case 'material-icons':
$url = $base."material-icons.css?v=145";
break;
case 'material-design':
$url = $base."material-symbols-outlined.css?v=332";
break;
case 'simple-line':
$url = $base."simple-line-icons.min.css?v=2.5.5";
break;
case 'linear-icons':
$url = $base."linearicons.min.css?v=1.0.0";
break;
default:
$url = "";
break;
}
// Adiciona url do arquivo css
if ($url != ''){
$wa->registerAndUseStyle($aliasFamily.'_icons', $url, ['version' => '']);
return;
}
return false;
}
/**
* Alias da familia de icones a partir do valor salvo em arrows_icon.
*
* @param string $arrowsIcon Valor com placeholder DIRECTION (ex.: fa-solid fa-chevron-DIRECTION)
*
* @return string|false
*/
public static function getArrowsIconFamilyAlias(string $arrowsIcon)
{
if ($arrowsIcon === '') {
return false;
}
if (str_contains($arrowsIcon, 'fa-')) {
return 'font-awesome-v6';
}
if (str_contains($arrowsIcon, 'icon-')) {
return 'simple-line';
}
if (str_contains($arrowsIcon, 'lnr')) {
return 'linear-icons';
}
if (str_contains($arrowsIcon, '_')) {
return 'material-design';
}
return false;
}
/**
* Resolve classes e conteudo (ligature) das setas esquerda/direita.
*
* @param string $arrowsIcon Valor salvo no parametro arrows_icon
*
* @return array{class_left:string,class_right:string,content_left:string,content_right:string,family:string|false}
*/
public static function resolveArrowsIcon(string $arrowsIcon): array
{
$empty = [
'family' => false,
'class_left' => '',
'class_right' => '',
'content_left' => '',
'content_right' => '',
];
if ($arrowsIcon === '') {
return $empty;
}
if (str_contains($arrowsIcon, 'fa-')) {
return [
'family' => 'font-awesome-v6',
'class_left' => 'fa ' . str_replace('DIRECTION', 'left', $arrowsIcon),
'class_right' => 'fa ' . str_replace('DIRECTION', 'right', $arrowsIcon),
'content_left' => '',
'content_right' => '',
];
}
if (str_contains($arrowsIcon, 'icon-')) {
return [
'family' => 'simple-line',
'class_left' => str_replace('DIRECTION', 'left', $arrowsIcon),
'class_right' => str_replace('DIRECTION', 'right', $arrowsIcon),
'content_left' => '',
'content_right' => '',
];
}
if (str_contains($arrowsIcon, 'lnr')) {
return [
'family' => 'linear-icons',
'class_left' => str_replace('DIRECTION', 'left', $arrowsIcon),
'class_right' => str_replace('DIRECTION', 'right', $arrowsIcon),
'content_left' => '',
'content_right' => '',
];
}
if (str_contains($arrowsIcon, '_')) {
if ($arrowsIcon === 'arrow_back_ios') {
return [
'family' => 'material-design',
'class_left' => 'material-symbols-outlined',
'class_right' => 'material-symbols-outlined',
'content_left' => 'arrow_back_ios',
'content_right' => 'arrow_forward_ios',
];
}
if (str_contains($arrowsIcon, 'DIRECTION')) {
return [
'family' => 'material-design',
'class_left' => 'material-symbols-outlined',
'class_right' => 'material-symbols-outlined',
'content_left' => str_replace('DIRECTION', 'left', $arrowsIcon),
'content_right' => str_replace('DIRECTION', 'right', $arrowsIcon),
];
}
}
return $empty;
}
/**
* Carrega CSS das familias necessarias para um ou mais valores de arrows_icon.
*
* @param string ...$arrowsIconValues Valores de arrows_icon / arrows_icon_mobile
*
* @return void
*/
public static function loadArrowsIconFamilies(string ...$arrowsIconValues): void
{
$loaded = [];
foreach ($arrowsIconValues as $arrowsIcon) {
if (!is_string($arrowsIcon) || $arrowsIcon === '') {
continue;
}
$family = self::getArrowsIconFamilyAlias($arrowsIcon);
if ($family === false || isset($loaded[$family])) {
continue;
}
self::loadFamilyIcons($family);
$loaded[$family] = true;
}
}
/**
* Adiciona o contexto da extensao nos blocos de JS
*
* @param String $code Código JS
* @param String $prefix Prefixo (contexto) a ser adicionado
*
* @return mixed Codigo com conexto adicionado ou false em caso de erro ou falta de informacoes
*/
private function addContextInJs($code, $prefix){
// Dados nao informados ou em branco
if (empty($code) || empty($prefix)){
return false;
}
// adiciona declaracao de $ como jQuery no codigo
$code = "var $ = jQuery;\n" . $code;
// Classe utilizada no elemento HTML mais externo da extensao
$outerClass = '.' . substr($this->extensionName, 4);
// regex para seletores usando 'jQuery' ou '$' com aspas duplas ou simples
$pattern = '/(\$|jQuery)(\(\s*)(\'|\")(.*?)(\'|\")(\s*\))/';
// para cada padrao encontrado no codigo, executa um callback
$code = preg_replace_callback(
$pattern,
function($found) use ($outerClass, $prefix){
// separa os seletores informados em itens de array
$selectors = explode(" ", $found[4]);
// verifica se o ultimo seletor é igual a classe mais externa da extensao
if(end($selectors) == $outerClass){
// subtitui os seletores informados para o module-id da extensao
return str_replace($found[4], $prefix, $found[0]);
}
// verifica se algum dos seletores eh a classe da ext
elseif(in_array($outerClass, $selectors)){
// regex para pegar todos os seletores ate a classe da ext
$r = '/(?<=\\\'|\\")(.*?'.$outerClass.')+\s/';
// remove ocorrencias do padrao $r e adiciona o contexto da section da ext como parametro do seletor
$temp = str_replace($found[6], ", '{$prefix}')", $found[0]);
return (!empty($temp)) ? preg_replace($r, '', $temp) : '';
}
// se o padrao encontrado nao atender as condicoes acima, retorna sem nenhum tratamento
else{
return $found[0];
}
},
$code
);
// retorna o codigo tratado com os contextos adicionados
return $code;
}
/**
* Adiciona um prefixo em todos os blocos de CSS
*
* @param String $code Código CSS
* @param String $prefix Prefixo a ser adicionado (opcional)
*
* @return mixed Codigo com prefixo adicionado ou false em caso de erro ou falta de informacoes
*/
private function addPrefixInCss($code, $prefix = ''){
// Prefixo nao informado como parametro: obtem o definido na classe
if (empty($prefix)){
$prefix = $this->prefixCode;
}
// Classe externa utilizada no elemento HTML mais externo da extensao
$outerClass = substr($this->extensionName, 4);
// Dados nao informados ou em branco
if ($code == '' || $prefix == ''){
return false;
}
// divide os trechos de css pelo }
$parts = explode('}', $code);
// Percorre cada trecho
foreach ($parts as &$part) {
$part = trim($part);
// Verifica se não é um trecho vazio
if (empty($part)) continue;
// Valida a existiencia de um @media e evita que seja colocado prefixo nele
$mediaPart = '';
if ($part[0] == "@") {
// Separa o media
$tmp = explode('{', $part);
// Guarda em uma variavel temporaia
$mediaPart = $tmp[0];
// remove a posição do array
unset($tmp[0]);
$part = implode('{', $tmp);
}
// Substitui as vírgulas dentro de parentesis por ## para que o prefixer não de errado em casos como rgba(0,0,0,0)
$part = preg_replace_callback("|\((.*)\)|",
function ($s) {
return str_replace(",", "##", $s[0]);
},
$part);
// Separa as subpartes por virgula
$subParts = explode(',', $part);
// Adiciona o prefixo para cada subtrecho
foreach ($subParts as &$subPart) {
// caso possua classes
if(!empty($subPart)){
// Pega os seletores
$subPart = trim($subPart);
$outerClassWithDot = '.'.$outerClass;
// Posicao da classe do modulo nos seletores
$outerClassPosition = strpos($outerClassWithDot, $subPart);
$outerClassLength = strlen($outerClassWithDot);
// Pega o primeiro char depois da classe do modulo
$firstCharAfterOuterClass = substr($subPart, $outerClassPosition + $outerClassLength, 1);
/*
* O proximo caracter apos a classe principal eh '.' (ex: .nobossfaq.container{...}) OU;
* O proximo caracter apos a classe principal eh ':' (ex: .nobossfaq:not(...){...}) OU;
* O proximo caracter apos a classe principal eh ' ' (ex: .nobossfaq .container{...}) OU;
* O proximo caracter apos a classe principal eh '{' (ex: .nobossfaq{...}) OU;
*/
if ($firstCharAfterOuterClass === '.'
|| $firstCharAfterOuterClass === ':'
|| $firstCharAfterOuterClass === ' '
|| $firstCharAfterOuterClass === '{'
){
/* Significa que a primeira classe seletora eh a classe do modulo, ou seja, o mesmo elemento que
possui o module id, entao eles precisam ficar juntos */
$subPart = $prefix . $subPart;
}
else{
/* A primeira classe entao nao eh a mesma que a classe do modulo e o seletor
externo passa a ser o id do modulo */
$subPart = $prefix . ' ' . $subPart;
}
}
}
// Remonta o trecho
$part = implode(', ', $subParts);
// Dá replace de volta nos ## dentro de parenteses para vírgula
$part = str_replace('##', ',', $part);
// Readiciona a tag @media
if(!empty($mediaPart)){
$part = $mediaPart.'{'.$part;
}
}
// Remonta a string de css
return trim(implode("}\n", $parts));
}
/**
* Obtem o diretorio de uma extensao a partir do nome
*
* @param boolean $admin Flag para informar se extensao eh admin ou site
*
* @return mixed String com o diretorio ou false caso o tipo de extensao nao seja identificada
*/
public function getDirectoryExtension($admin = ''){
// Se variavel nao for setada pelo usuario pega informacao do acesso do usuario
/* if ($admin == ''){
@NBTODO: desenvolver forma de saber se deve carregar o caminho do diretorio no administrator ou do site (o metodo abaixo nao funciona)
$app = Factory::getApplication();
$admin = $app->isClient('admin');
}*/
// Caminho base
$basePath = ($admin) ? JPATH_ADMINISTRATOR : JPATH_SITE;
// Obtem o prefixo da extensao para localizar diretorio
$extensionPrefix = substr($this->extensionName, 0, 3);
// Monta diretorio da extensao conforme o tipo
switch ($extensionPrefix) {
// Extensao eh um modulo
case 'mod':
$directoryExtension = "modules/{$this->extensionName}/";
break;
// Extensao eh um componente
case 'com':
$directoryExtension = "components/{$this->extensionName}/";
break;
// Extensao eh uma library
case 'lib':
$directoryExtension = "libraries/".substr($this->extensionName, 4)."/";
break;
// Tipo de extensao nao identificada
default:
return false;
break;
}
$this->directoryExtension = $directoryExtension;
// Monta caminho do diretorio completo
$directoryExtension = "{$basePath}/{$directoryExtension}";
return $directoryExtension;
}
/**
* Carrega na pagina arquivos codigos inline de CSS (nao funciona nas requicoes feitas para viewraw pq nestes casos nao existe a funcao getHeadData que usamos)
*
* @param Boolean $addViaJs Informa se o codigo deve ser adicionado via JS (se for informado false, retorna html com as chamadas a serem exibidas na pagina
*
* @return mixed void ou string com html a ser exibido
*/
public static function addCss($addViaJs = false){
$doc = Factory::getApplication()->getDocument();
$app = Factory::getApplication();
$wa = $app->getDocument()->getWebAssetManager();
$dataHead = array();
// Obtem dados do head apenas se o documento suportar (não funciona em requisições AJAX com RawDocument)
if (method_exists($doc, 'getHeadData')) {
$dataHead = $doc->getHeadData();
}
$stylesUrls = array();
$stylesInline = '';
// Existem url de scripts (formato J3, mas que ainda funciona no J4)
if(!empty($dataHead['styleSheets'])){
$stylesUrls = array_keys($dataHead['styleSheets']);
}
// Existem scripts inline (formato J3, mas que ainda funciona no J4)
if(!empty($dataHead['style']['text/css'])){
$stylesInline = $dataHead['style']['text/css'];
// No J4 vem como array e convertemos para string para ficar igual ao J3
if(is_array($stylesInline)){
$stylesInline = implode(' ', $stylesInline);
}
}
// Obtem assets de estilo registrados
$styleAssets = $wa->getAssets('style', true);
// Existem scripts definidos no formato novo do J4 (inline e url)
if (!empty($styleAssets)){
$stylesUrlsJ4 = array();
$stylesInlineJ4 = '';
// Percorre todos styles
foreach ($styleAssets as $assetName => $asset) {
$options = $asset->getOptions();
// Eh inline
if(!empty($options['inline']) && $options['inline']){
// Concatena conteudo inline
$stylesInlineJ4 .= $options['content'];
}
// Eh url
else{
// Armazena url em posicao do array
$stylesUrlsJ4[] = $asset->getUri();
}
}
// Concatena conteudo inline do formato novo com antigo
$stylesInline = trim("{$stylesInlineJ4} {$stylesInline}");
// Concatena urls do formato novo com antigo
$stylesUrls = array_merge($stylesUrlsJ4, $stylesUrls);
}
// Forca margin 0 no body
$stylesInline .= ' body{ margin: 0; }';
// Adiciona arquivos e inline via JS na pagina
if($addViaJs){
// Adiciona arquivos CSS via JS apenas se houver URLs
if(!empty($stylesUrls)){
?>
<script>
var stylesFiles = [
<?php foreach($stylesUrls as $url){
echo json_encode($url) . ",";
} ?>
];
stylesFiles.forEach(function(styleFile) {
if (!document.querySelector('link[href="' + styleFile + '"]')) {
var link = document.createElement('link');
link.rel = 'stylesheet';
link.type = 'text/css';
link.href = styleFile;
document.head.appendChild(link);
}
});
</script>
<?php
}
// Adiciona estilos inline via JS
if(!empty($stylesInline)){
$escapedStyles = json_encode($stylesInline);
echo "<script>document.head.insertAdjacentHTML('beforeend', '<style>' + {$escapedStyles} + '</style>');</script>";
}
}
// Requisicao normal inserindo arquivos via PHP
else{
// faz a chamada dos arquivos css na pagina
foreach($stylesUrls as $url){
echo "<link href={$url} rel='stylesheet' type='text/css'>";
}
// Adiciona estilos inline via PHP
echo "<style>{$stylesInline}</style>";
}
return '';
}
/**
* Carrega na pagina arquivos codigos inline de JS (nao funciona nas requicoes feitas para viewraw pq nestes casos nao existe a funcao getHeadData que usamos)
*
* @param Boolean $addViaJs Informa se o codigo deve ser adicionado via JS (se for informado false, retorna html com as chamadas a serem exibidas na pagina
*
* @return mixed void ou string com html a ser exibido
*/
public static function addJs($addViaJs = false){
$doc = Factory::getApplication()->getDocument();
$app = Factory::getApplication();
$wa = $app->getDocument()->getWebAssetManager();
$dataHead = array();
// Obtem dados do head apenas se o documento suportar (não funciona em requisições AJAX com RawDocument)
if (method_exists($doc, 'getHeadData')) {
$dataHead = $doc->getHeadData();
}
$scriptsUrls = array();
$scriptsInline = '';
// Obtem assets de estilo registrados
$scriptAssets = $wa->getAssets('script', true);
// Existem scripts definidos no formato novo do J4 (inline e url)
if (!empty($scriptAssets)){
if (method_exists($doc, 'getScriptOptions')) {
// Carrega na pagina os options que poderao ser acessados posteriormente pelo Joomla usando a funcao Joomla.getOptions
$scriptOptions = $doc->getScriptOptions();
if ($scriptOptions){
$prettyPrint = (JDEBUG && \defined('JSON_PRETTY_PRINT') ? JSON_PRETTY_PRINT : false);
$jsonOptions = json_encode($scriptOptions, $prettyPrint);
$jsonOptions = $jsonOptions ? $jsonOptions : '{}';
echo '<script type="application/json" class="joomla-script-options new">'.$jsonOptions.'</script>';
}
}
// Percorre todos scripts
foreach ($scriptAssets as $asset){
$options = $asset->getOptions();
// Eh inline
if(!empty($options['inline']) && $options['inline']){
// Concatena conteudo inline
$scriptsInline .= $options['content'];
}
// Eh url
else{
$attributes = $asset->getattributes();
$script = new \stdClass();
$script->url = $asset->getUri();
if(!empty($version = $asset->getVersion())){
$script->url .= "?{$version}";
}
// Eh do type 'module'
if ((!empty($attributes['type'])) && ($attributes['type'] == 'module')){
$script->module = 'type="module"';
}
else{
$script->module = '';
}
// Eh defer
if (!empty($attributes['defer'])){
$script->defer = 'defer';
}
else{
$script->defer = '';
}
$scriptsUrls[] = $script;
}
}
// Faz com que o Joomla renderize os options inseridos na pagina
$scriptsInline .= " if(typeof Joomla !== 'undefined'){ Joomla.loadOptions(); } ";
}
// Existem url de scripts (formato J3, mas que ainda funciona no J4)
if(!empty($dataHead['scripts'])){
foreach ($dataHead['scripts'] as $key => $value) {
$script = new \stdClass();
$script->url = $key;
$script->module = '';
$script->defer = '';
$scriptsUrls[] = $script;
}
}
// Existem scripts inline
if(!empty($dataHead['script'])){
if(!empty($dataHead['script']['text/javascript'])){
// No J4 vem como array e convertemos para string para ficar igual ao J3
if(is_array($dataHead['script']['text/javascript'])){
$scriptsInline .= implode(' ', $dataHead['script']['text/javascript']);
}
else{
$scriptsInline .= $dataHead['script']['text/javascript'];
}
}
// TODO: versoes mto antigas eh possivel que venha em string assim
else{
$scriptsInline .= $dataHead['script'];
}
}
$scriptsInline = trim($scriptsInline);
// Adiciona arquivos e inline via JS na pagina
if($addViaJs){
?>
<script>
var scripts = [
<?php foreach($scriptsUrls as $script){
// TODO: neste formato nao estamos colocando o $script->module e $script->defer
echo "'{$script->url}',";
} ?>
];
var queue = scripts.map(function (script) {
if (jQuery("script[src*='" + script.slice(-30) + "']").length === 0) {
var fileJsTemp = document.createElement('script');
fileJsTemp.src = script;
document.head.appendChild(fileJsTemp);
}
});
// Todos arquivos terminaram de serem carregados
jQuery.when.apply(null, queue).done(function () {
<?php echo $scriptsInline; ?>
});
</script>
<?php
}
// Requisicao normal: insere todos JS via PHP
else{
// Adiciona na pagina os codiso JS inline
echo "<script>{$scriptsInline}</script>";
// faz a chamada dos arquivos na pagina
foreach($scriptsUrls as $script){
echo "<script src='{$script->url}' {$script->module} {$script->defer}></script>";
}
}
return '';
}
}