| Current Path : /var/www/html/administrator/manifests/packages/noboss/ |
| Current File : /var/www/html/administrator/manifests/packages/noboss/script.package.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>
* @todo: Esse arquivo ainda é usado no pacote de instalação do Joomla 3, mantendo compatibilidade com Joomla 3, 4, 5 e 6.
*/
// phpcs:disable PSR1.Files.SideEffects
\defined('_JEXEC') or die;
// phpcs:enable PSR1.Files.SideEffects
// Define Joomla version compatibility
define('NB_JOOMLA3', defined('JVERSION') && version_compare(JVERSION, '4.0', '<'));
/**
* Script de instalação dos pacotes (usado na library e todos pacotes mais externos)
* - Esse script normalmente é executado após o script de instalacao do pacote
*
* - Formatos para retornar mensagens de erro / warning:
* // Mensagem de erro (fundo vermelho), sem interromper a instalacao
* Factory::getApplication()->enqueueMessage(Text::_("Aqui mensagem"), 'Error');
*
* // Mensagem de warning (fundo amarelo), sem interromper a instalacao
* Factory::getApplication()->enqueueMessage(Text::_("Aqui mensagem"), 'Warning');
*
* // Mensagem de warning (fundo amarelo), interrompendo a instalacao (Joomla tb exibe mensagem de erro da instalacao)
* throw new RuntimeException(Text::_("Aqui mensagem"));
* return false;
*
*
* - Exemplos de usos do $parent que é recebido como parametro nas funções:
* // Obter nova versao recem instalada
* $parent->get('manifest')->version;
*
* // Obter alias da extensao (Ex: 'mod_nobosscalendar)
* $parent->manifest->name;
*
* // Redirecionar usuario apos a instalacao (interessante usar no metodo install na instalacao de componentes nossos para redirecionar o usuario para a pagina principal do componente apos a instalacao)
* $parent->getParent()->setRedirectURL('index.php?option=com_helloworld');*
*
*
* - Sobre uso de constantes de tradução
* - Se você deseja que as KEYs desses idiomas sejam usadas na primeira instalação do componente, o arquivo de idioma .sys.ini deve ser armazenado na pasta do componente (admin/language/en-GB/en-GB.com_helloworld.sys.ini)
* - Quando ja temos a library instalada, podemos forcar o carregamento do idioma da library e usar as constantes dela
*/
class pkg_NobossInstallerScript{
/**
* Evento executado antes de qualquer outro no processo de instalacao / update
* - Esse é o momento que a instalacao / update pode ser cancelado
* - Essa funcao eh executada antes da preflight do script de instalacao de cada extensao do pacote
*
* @param string $type Tipo de intalações (install, update, discover_install)
* @param Installer $parent Classe que chama esse metodo (pode acessar funcoes dela)
*
* @return boolean true caso deva ser instalada, false para cancelar a instalação
*/
function preflight($type, $parent){
if($type == 'uninstall'){
return;
}
// Verifica permissoes dos diretorios necessarios para instalacao
if(!$this->checkDirectoryPermissions($parent)){
return false;
}
// Instala cada extensao localizada no diretorio 'packages' do zip
$this->installPackageExtras($parent);
return true;
}
/**
* Metodo executado após o término da instalação / update
*
* @param string $type Tipo de intalações (install, update, discover_install)
* @param Installer $parent Classe que chama esse metodo (pode acessar funcoes dela)
*/
function postflight($type, $parent){
if($type == 'uninstall'){
return;
}
$db = NB_JOOMLA3 ? JFactory::getDbo() : \Joomla\CMS\Factory::getContainer()->get(\Joomla\Database\DatabaseInterface::class);
$newPackageId = 0;
$zipFiles = NB_JOOMLA3 ? JFolder::files(__DIR__, '.*\.zip$') : \Joomla\Filesystem\Folder::files(__DIR__, '.*\.zip$');
// Pega o arquivo
$zipFile = reset($zipFiles);
// Verifica se foi registrado o pacote no banco de dados
if(substr($zipFile, 0, 3) == 'pkg'){
$element = explode('.', $zipFile);
$element = $element[0];
$query = $db->getQuery(true);
$query->select("a.extension_id")
->from("#__extensions as a")
->where("a.element = '{$element}'");
$db->setQuery($query);
$newPackageId = $db->loadResult();
}
// Atualiza as extensões para não estarem relacionadas ao pacote
$query = $db->getQuery(true);
$query->update("#__extensions as a, (SELECT b.extension_id FROM #__extensions as b WHERE b.element = 'pkg_noboss') as b")
->set("a.package_id = '{$newPackageId}'")
->where("a.package_id = b.extension_id");
$db->setQuery($query);
$result = $db->execute();
// Deleta a linha do pacote no banco
$query = $db->getQuery(true);
$query->delete('#__extensions')
->where("element = 'pkg_noboss'");
$db->setQuery($query);
$result = $db->execute();
// TODO: colocado aqui em 27/03/24 pq nao estava mais executando no script de instalacao da library
$this->installLayoutsFolder();
}
/**
* Metodo executado apos a instalacao
* - Aqui podemos exibir textos fora de notices / warnings utilizanco 'echo' ou html direto
*
* @param Installer $parent Classe que chama esse metodo (pode acessar funcoes dela)
*/
function install($parent) {
// Exibe mensagem personalizada de sucesso com dicas e propagandas da No Boss
echo '<br>'. (NB_JOOMLA3 ? JText::_('SCRIPT_INSTALLATION_SUCCESS') : \Joomla\CMS\Language\Text::_('SCRIPT_INSTALLATION_SUCCESS')) .'<br><br>';
}
/**
* Metodo executado apos a atualizacao
* - OBS: aqui nao pega warning ou 'echo'
*
* @param Installer $parent Classe que chama esse metodo (pode acessar funcoes dela)
*/
function update($parent) {
}
/**
* Metodo que verifica permissoes de escrita nos diretorios necessarios
*
* @param Installer $parent Classe que chama esse metodo (pode acessar funcoes dela)
*/
function checkDirectoryPermissions($parent){
// Eh instalacao somente da library
//if (in_array('noboss.zip', (array) $parent->get('manifest')->files)){
// Diretorios que precisam permissao de escrita / remocao
$writingDirs = array();
$writingDirs[] = '/libraries/';
$writingDirs[] = '/layouts/';
$writingDirs[] = '/layouts/noboss/';
$writingDirs[] = '/modules/';
$writingDirs[] = '/components/';
$writingDirs[] = '/administrator/components/';
$writingDirs[] = '/plugins/system/';
// Array que ira armazenar diretorios que faltam permissao
$errorDirs = array();
// Percorre cada diretorio
foreach ($writingDirs as $dir){
// Diretorio existe e nao possui permissoes suficientes (conforme regras do Joomla)
if (NB_JOOMLA3) {
if ((is_dir(JPATH_SITE.$dir)) && (!is_writable(JPATH_SITE.$dir))){
// Adiciona diretorio no array dos que possuem erro de permissao
$errorDirs[] = $dir;
}
} else {
if ((is_dir(JPATH_SITE.$dir)) && (!\Joomla\Filesystem\Path::canChmod(JPATH_SITE.$dir))){
// Adiciona diretorio no array dos que possuem erro de permissao
$errorDirs[] = $dir;
}
}
}
// Pelo menos um diretorio nao possui permissao de escrita
if(!empty($errorDirs)){
// Mensagem a ser exibida para o usuario, informando junto os diretorios sem permissao
$message = NB_JOOMLA3 ? JText::sprintf('SCRIPT_INSTALLATION_LACK_PERMISSION_REST_CONTENT', "'".implode("', '", $errorDirs)."'") : \Joomla\CMS\Language\Text::sprintf('SCRIPT_INSTALLATION_LACK_PERMISSION_REST_CONTENT', "'".implode("', '", $errorDirs)."'");
// Verifica se algum dos diretorios com erro sao de 'layouts' ou 'libraries'
// $result = array_filter($errorDirs, function($el) {
// return ((strpos($el, 'layouts') || (strpos($el, 'libraries'))) !== false);
// });
// Seta mensagem de aviso sem impedir que instalacao prossiga (alguns casos eh alarme falso)
if (NB_JOOMLA3) {
JFactory::getApplication()->enqueueMessage($message, 'Warning');
} else {
\Joomla\CMS\Factory::getApplication()->enqueueMessage($message, 'Warning');
}
}
return true;
}
/**
* Metodo que instala as extensoes localizadas na pasta 'packages'
*
* @param Installer $parent Classe que chama esse metodo (pode acessar funcoes dela)
*/
private function installPackageExtras($parent){
if(!is_dir(__DIR__ . '/packages')){
return;
}
// Obtem extensoes
$packages = NB_JOOMLA3 ? JFolder::folders(__DIR__ . '/packages') : \Joomla\Filesystem\Folder::folders(__DIR__ . '/packages');
// Percorre cada extensao do pacote
foreach ($packages as $extension){
try{
// Cria novo installer e define o banco de dados para compatibilidade
$tmpInstaller = NB_JOOMLA3 ? new JInstaller() : new \Joomla\CMS\Installer\Installer;
if (!NB_JOOMLA3) {
$tmpInstaller->setDatabase(\Joomla\CMS\Factory::getContainer()->get(\Joomla\Database\DatabaseInterface::class));
}
$tmpInstaller->setPath('source', __DIR__ . '/packages/' . $extension);
$tmpInstaller->findManifest();
$manifest = $tmpInstaller->getPath('manifest');
$manifestPath = NB_JOOMLA3 ? JPath::clean($manifest) : \Joomla\Filesystem\Path::clean($manifest);
$element = preg_replace('/\.xml/', '', basename($manifestPath));
$manifest = $tmpInstaller->getManifest();
// Ajusta o element de acordo com o tipo de extensão
if($manifest['type'] == 'component'){
if (strpos($element, 'com_') !== 0){
$element = 'com_' . $element;
}
} else if ($manifest['type'] == 'plugin'){
// if (strpos($element, 'plg_') !== 0){
// $element = 'plg_' . $element;
// }
} else if ($manifest['type'] == 'package'){
if (strpos($element, 'pkg_') !== 0){
$element = 'pkg_' . $element;
}
} else if ($manifest['type'] == 'module'){
if (strpos($element, 'mod_') !== 0){
$element = 'mod_' . $element;
}
}
else if ($manifest['type'] == 'library'){
}
// Obtem dados da extensao no banco (caso ela ja exista instalada)
$extensionDataBase = $this->getExtensionByElement($element, $manifest['type']);
// Extensao ja existe instalada (update)
if(!empty($extensionDataBase)){
$extensionDataBase = json_decode($extensionDataBase->manifest_cache);
$installResult = false;
if(!empty($manifest)){
// Versao do zip eh maior que versao instalada: realiza nova instalacao (update)
if(version_compare($manifest->version, $extensionDataBase->version, '>')){
// Executa a instalação da extensao
$installResult = $tmpInstaller->install(__DIR__ . '/packages/' . $extension);
}
}
}
// Extensao ainda nao existe (nova instalacao)
else {
// Executa a instalação da extensao
$installResult = $tmpInstaller->install(__DIR__ . '/packages/' . $extension);
// Erro ao instalar
if(!$installResult){
// Seta Warning para exibir na tela
if (NB_JOOMLA3) {
JFactory::getApplication()->enqueueMessage(JText::sprintf('SCRIPT_INSTALLATION_EXTRA_ERROR_NO_INSTALLED', $extension), 'Warning');
} else {
\Joomla\CMS\Factory::getApplication()->enqueueMessage(\Joomla\CMS\Language\Text::sprintf('SCRIPT_INSTALLATION_EXTRA_ERROR_NO_INSTALLED', $extension), 'Warning');
}
}
}
} catch (\Exception $e){
$error = $e->getMessage();
// Seta Warning para exibir na tela
if (NB_JOOMLA3) {
JFactory::getApplication()->enqueueMessage(JText::sprintf('SCRIPT_INSTALLATION_EXTRA_ERROR_EXCEPTION', $extension . ' - ' . $error), 'Warning');
} else {
\Joomla\CMS\Factory::getApplication()->enqueueMessage(\Joomla\CMS\Language\Text::sprintf('SCRIPT_INSTALLATION_EXTRA_ERROR_EXCEPTION', $extension . ' - ' . $error), 'Warning');
}
}
}
}
/**
* Metodo que obtem dados da extensao no banco (caso ela ja exista instalada)
*
* @param Installer $parent Classe que chama esse metodo (pode acessar funcoes dela)
*/
function getExtensionByElement($element, $type){
$db = NB_JOOMLA3 ? JFactory::getDbo() : \Joomla\CMS\Factory::getContainer()->get(\Joomla\Database\DatabaseInterface::class);
$query = $db->getQuery(true);
$query->select('*')
->from('#__extensions')
->where("element = '{$element}'");
if(!empty($type)){
$query->where("type = '{$type}'");
}
$db->setQuery($query, 0, 1);
$result = $db->loadObject();
return $result;
}
/**
* Metodo que move a pasta 'layouts/noboss' para o local correto no Joomla (na instalacao vem dentro da library)
*/
public function installLayoutsFolder(){
$dirLayoutLibrary = JPATH_ROOT.'/libraries/noboss/src/layouts/';
$dirLayout = JPATH_ROOT.'/layouts/noboss/';
// Confirma se a pasta layouts esta criada dentro da library
if(is_dir($dirLayoutLibrary)){
try{
// Copia pasta layouts da library da no boss para a pasta layouts correta
if (NB_JOOMLA3) {
JFolder::copy($dirLayoutLibrary, $dirLayout, '', true, true);
} else {
\Joomla\Filesystem\Folder::copy($dirLayoutLibrary, $dirLayout, '', true, true);
}
// Altera permissao da pasta layouts inserida no site do usuario
@chmod($dirLayout, 0775);
if(is_dir($dirLayoutLibrary)){
// Remove a pasta layouts da library com funcao recursiva robusta
$this->removeDirectory($dirLayoutLibrary);
}
} catch (\Exception $e){
// Seta Warning para exibir na tela
if (NB_JOOMLA3) {
JFactory::getApplication()->enqueueMessage('Could not manage layouts directory: ' . $e->getMessage(), 'Warning');
} else {
\Joomla\CMS\Factory::getApplication()->enqueueMessage('Could not manage layouts directory: ' . $e->getMessage(), 'Warning');
}
}
}
}
/**
* Remove um diretório e todo o seu conteúdo recursivamente
*
* @param string $dir Caminho absoluto para o diretório a ser removido
* @return bool Retorna true se removido com sucesso, false caso contrário
*/
private function removeDirectory($dir) {
if (!is_dir($dir)) {
return false;
}
$items = @scandir($dir);
if ($items === false) {
return false;
}
foreach ($items as $item) {
if ($item == '.' || $item == '..') {
continue;
}
$path = $dir . DIRECTORY_SEPARATOR . $item;
// Tenta alterar permissao antes de remover
@chmod($path, 0777);
if (is_dir($path)) {
$this->removeDirectory($path);
} else {
@unlink($path);
}
}
// Tenta alterar permissao do diretorio antes de remover
@chmod($dir, 0777);
return @rmdir($dir);
}
}