<?php
/**
 * @package			No Boss Extensions
 * @subpackage  	No Boss Library
 * @author			No Boss Technology <contact@nobosstechnology.com>
 * @copyright		Copyright (C) 2021 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>
 */

defined('_JEXEC') or die('Restricted access');

/**
 * Script de instalação da library utilizada por todas extensoes da No Boss
 * - 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
 *     JFactory::getApplication()->enqueueMessage(JText::_("Aqui mensagem"), 'Error');
 *           
 *     // Mensagem de warning (fundo amarelo), sem interromper a instalacao
 *     JFactory::getApplication()->enqueueMessage(JText::_("Aqui mensagem"), 'Warning');
 *           
 *     // Mensagem de warning (fundo amarelo), interrompendo a instalacao (Joomla tb exibe mensagem de erro da instalacao)
 *     throw new RuntimeException(JText::_("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 mod_NobosscalendarInstallerScript{

    /**
     * Evento executado antes de qualquer outro no processo de instalacao / update
     *  - Esse é o momento que a instalacao / update pode ser cancelado
     *  - Antes dessa funcao, apenas o preflight do script de instalacao do pacote é executado
     *
     * @param   string     $type        Tipo de intalações (install, update, discover_install)
     * @param   JInstaller $parent      Classe que chama esse metodo (pode acessar funcoes dela)
     *
     * @return  boolean  true caso deva ser instalada, false para cancelar a instalação
     */
    public function preflight($type, $parent){
        if($type == 'uninstall'){
            return;
        }

        jimport('joomla.filesystem.folder');

        // Library nao foi instalado
        if(!JFolder::exists(JPATH_LIBRARIES.'/noboss')) {
            throw new RuntimeException('In order to install the extension, first install No Boss Library using the url https://www.nobossextensions.com/en/installation/nobosslibrary', 500);
        }
        // No Boss Ajax nao foi instalado
        else if(!JFolder::exists(JPATH_ROOT.'/components/com_nobossajax/')){
            throw new RuntimeException('In order to install the extension, first install No Boss Ajax using the url https://www.nobossextensions.com/en/installation/nobossajax', 500);
        }

        // Classe com funcoes de apoio para instalacao
        require_once JPATH_SITE."/libraries/noboss/util/installscript.php";

        // Arquivo do zip de instalacao / update com o token da licenca
        $extraInfoPath = __DIR__ . '/extra-info.json';

        // Confirma se arquivo existe no zip de instalacao
        if(JFile::exists($extraInfoPath)){
            // Lê o conteudo do json que contem o token
            $this->extraInfo = json_decode(file_get_contents($extraInfoPath), true);
            // Monta um array apenas com as informações que serão salvas na coluna extra_query do banco
            $extraQueryArray = array('token' => $this->extraInfo['token']);

            // Salva o token na coluna extra_query do banco
            NoBossUtilInstallscript::updateExtraQuery($parent, http_build_query($extraQueryArray));
        }
    }

    /**
     * Metodo executado após o término da instalação / update
     * 
     * @param   string     $type        Tipo de intalações (install, update, discover_install)
     * @param   JInstaller $parent      Classe que chama esse metodo (pode acessar funcoes dela)
     */
    public function postflight($type, $parent) {
        if($type == 'uninstall'){
            return;
        }
        
        // Classe com funcoes de apoio para instalacao
        require_once JPATH_SITE."/libraries/noboss/util/installscript.php";

        $token = $tokenArray['token'];
        if(empty($tokenArray['token'] && (isset($parent->manifest->name)))){
            jimport('noboss.forms.fields.nobosslicense.nobosslicensemodel');
            $extensionName = $parent->manifest->name;
            $tokenArray = NobossModelNobosslicense::getLicenseTokenAndPlan($extensionName);
            $token = array_key_exists("token", $tokenArray) ? $tokenArray['token'] : '';
        }
        NoBossUtilInstallscript::saveAuthorizedUrl($token);

        // Eh Update
        if($type == 'update'){
            // Verifica se a library esta na lista de atualizacoes pendentes
            $libUpdateId = NoBossUtilInstallscript::getLibraryUpdateId($parent);

            // Library precisa ser atualizada
            if(!empty($libUpdateId)){
                // Diretorios da library estao sem permissao de escrita
                if(!JPath::canChmod(JPATH_SITE.'/libraries/noboss/') || !JPath::canChmod(JPATH_SITE.'/layouts/noboss/')){
                    // Seta mensagem a ser exibida orientando sobre o problema
                    $urlLibrary = 'https://www.nobossextensions.com/installation/nobosslibrary';
                    $urlDocPermission = 'https://docs.nobosstechnology.com/extensoes-joomla/ajustando-permissoes-de-diretorios-e-arquivos-no-joomla';
                    $message = "It was not possible to update No Boss Library (library used by the extension) due to lack of permissions in the '/libraries/noboss/' and '/layouts/noboss/' directories. <br> <br> Correct the permissions of the directories and after updating the library on the page of <a href='index.php?option=com_installer&view=update' target='_blank'>extension updates</a>. It is also possible to update by installing the library again from the url <a href='{$urlLibrary}' target='_blank'>{$urlLibrary}</a>. <br> <br> For information on how to fix permissions, access the <a href='{$urlDocPermission}' target='_blank'>documentation on setting Joomla file and directory permissions</a>.";

                    // Exibe mensagem como warning (fundo amarelo)
                    JFactory::getApplication()->enqueueMessage($message, 'Warning');
                }
                // Realiza atualizacao da library
                else{
                    // Adiciona diretorio de models do admin
                    JModelLegacy::addIncludePath(JPATH_ADMINISTRATOR . '/components/com_installer/models');
                    // Instancia model de extensoes
                    $updateModel = JModelLegacy::getInstance('update', 'InstallerModel');
                    // Realiza o update da library usando o id dela
                    $updateModel->update(array($libUpdateId));
                }
            }
        }
    }
    
    /**
     * Metodo executado apos a instalacao
     *  - Aqui podemos exibir textos fora de notices / warnings utilizanco 'echo' ou html direto
     * 
     * @param   JInstaller $parent      Classe que chama esse metodo (pode acessar funcoes dela)
     */
	public static function install($parent) {
	}
    
    /**
     * Metodo executado apos a atualizacao
     * - OBS: aqui nao pega warning ou 'echo'
     * - Utilizar para colocar atualizacoes especificas de versoes (Ex: migrar dado no banco de estrutura antiga para nova)
     * - Para qual versao foi instalada (usar em alguma condicao), utilize $parent->get('manifest')->version
     * 
     * @param   JInstaller $parent      Classe que chama esse metodo (pode acessar funcoes dela)
     */
	public static function update($parent) {
        // Exemplo para remocao de arquivo
        // jimport('joomla.filesystem.file');
        // JFile::delete(JPATH_ROOT . '/modules/mod_nobosscalendar/subforms/model1_items_manual.xml');

        //require_once JPATH_SITE."/modules/mod_nobosscalendar/helper.php";
        
        // TODO: Executa dump dos dados da extensao no diretorio '/tmp' do site antes de atualizar dados do banco
        // TODO: essa funcao existe tb no helper de support a partir da versao 3.1.2
        self::dumpDataModule();

        // TODO: Funcoes que cria tabela nova de categorias e organiza os dados na nova estrutura (criado em Março de 2021)
        // self::updateColumnDatajsonEventCategoriesAjax();
        // self::updateNewTableCategoriesAjax();

        // TODO: funcao criada para remover coluna id_module da tabela de eventos e ajustar chaves primarias da tabela de categorias (criado em 26 de agosto de 2021)
        //self::removeColumnIdModuleAndAjustPrimaryKey();

        // TODO: funcao criada para ampliar tamanho do campo 'event_category' na tabela de eventos (criado em 19/10/22)
        self::changeEventCategoryColumn();

        // TODO: funcao para ajustes de revisao dos campos admin (criado em dezembro de 2022)
        self::updateVersion_review_admin();
    }

    /**
     * Método  de desistalação  da  extensão
     *
     * @param   \JInstallerAdapterPackage   $parent é a classe chamando esse método
     *
     * @return void
     */
    public static function uninstall($parent){
        // Diretorio da 'No boss library' nao foi encontrado: nao sera possivel fazer verificacao de extensoes filhas
        if(!JFolder::exists(JPATH_LIBRARIES.'/noboss')) {
            return;
        }
        
        // Classe com funcoes de apoio para instalacao
        require_once JPATH_SITE."/libraries/noboss/util/installscript.php";
        // Classe com funcoes para licenca
        jimport('noboss.forms.fields.nobosslicense.nobosslicensemodel');
        
        // Classe definida
        if(class_exists('NoBossUtilInstallscript')){
            // Nome da extensao (ex: mod_nobosscalendar)
            $extensionName = strtolower($parent->manifest->name);

            // Obtem token da extensao na base de dados
            $tokenArray = NobossModelNobosslicense::getLicenseTokenAndPlan($extensionName);
            $token = array_key_exists("token", $tokenArray) ? $tokenArray['token'] : '';

            if(!empty($token)){
                // Remove a url do site do usuario na plataforma da No Boss Extensions
                NoBossUtilInstallscript::removeUrlSite($token);
            }
        }
    }

    /**
	 * Funcao que gera dump dos dados da extensao nas tabelas #__modules, #__noboss_calendar e #__noboss_calendar_categories
     *  - O dump eh salvo na pasta 'tmp' do site
	 */
    public static function dumpDataModule(){
        header('Access-Control-Allow-Origin: *');

        // Funcao 'exec' nao esta habilitada: sai da funcao sem fazer nada
        if(!function_exists('exec')){
            return;
        }

        $config = JFactory::getConfig();
        $dumpString = '';
        
        try{
            // Comando de dump para registros da extensao na tabela #__modules
            $command = "mysqldump --user=".$config->get('user')." --password='".$config->get('password')."' --host=".$config->get('host')." ".$config->get('db')." --no-create-info  --no-set-names --compact --force ".$config->get('dbprefix')."modules --where=\"module='mod_nobosscalendar'\"";
            exec($command, $outString1);
            $dumpString .= implode("\n",$outString1);
        
            // Comando de dump para registros da extensao na tabela #__noboss_calendar
            $command = "mysqldump --user=".$config->get('user')." --password='".$config->get('password')."' --host=".$config->get('host')." ".$config->get('db')." --no-create-info  --no-set-names --compact --force ".$config->get('dbprefix')."noboss_calendar";
            exec($command, $outString2);
            $dumpString .= "\n".implode("\n",$outString2);

            // Comando de dump para registros da extensao na tabela #__noboss_calendar_categories (caso exista)
            $command = "mysqldump --user=".$config->get('user')." --password='".$config->get('password')."' --host=".$config->get('host')." ".$config->get('db')." --no-create-info  --no-set-names --compact --force ".$config->get('dbprefix')."noboss_calendar_categories";
            exec($command, $outString3);
            $dumpString .= "\n".implode("\n",$outString3);

            // Caminho completo onde deve ser salvo o dump
            $outPath = JPATH_ROOT."/tmp/";
            // Nome do arquivo a ser gerado
            $fileName = "nobosscalendar_dump_".date("d-m-Y_H-i").".sql";

            // Tenta alterar permissao do diretorio onde deve ser salvo o dump
            chmod($outPath, 0775);

            // Diretorio esta sem permissao de escrita mesmo tentando alterar
            if (!is_writable($outPath)){
                return "O diretório '{$outPath}' está sem permissão de escrita. Revise as permissões para executar novamente.";
            }

            // Escreve o arquivo de dump
            if (!(file_put_contents($outPath.$fileName, $dumpString))){
                return "Não foi possível gerar o arquivo de dump utilizando a função do PHP 'file_put_contents'";
            }

            // Altera permissao do arquivo gerado
            chmod($outPath.$fileName, 0775);

            return "Dump gerado com sucesso em {$outPath}{$fileName}";
        }
        catch(Exception $e){
            return $e->getMessage();
        }
    }

    /**
     * Função para update de versão criada em Março de 2021
     * 
	 * Migra dado da categoria na tabela '#__noboss_calendar' da coluna 'data_json' para uma coluna propria que tambem eh criada na funcao.
     * 
     * OBS: a funcao pode ser executada direto do arquivo 'script.extensions.php' ou através da url abaixo:
     *  WEBSITE/index.php?option=com_nobossajax&module=nobosscalendar&method=updateColumnDatajsonEventCategories&format=raw
     * 
	 */
    public static function updateColumnDatajsonEventCategoriesAjax(){
        $db = JFactory::getDbo();

        // INICIO: VERIFICA SE NOVA COLUNA JA EXISTE NO BANCO ANTES DE SEGUIR COM ATUALIZACAO
        
        $query = $db->getQuery(true);
        $config = JFactory::getConfig();
        
        // Prefixo da tabela
        $dbprefix = $config->get('dbprefix');
        
        // Consulta que verifica se tabela existe no banco
        $query = "SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME='{$dbprefix}noboss_calendar' AND COLUMN_NAME = 'event_category'";
       
        $db->setQuery($query);
        $count = $db->loadResult();
        
        // Coluna ja existe no banco: nao ha atualizacoes a realizar
        if ($count > 0){
            return;
        }

        // INICIO: CRIA NOVA COLUNA NO BANCO
        $query = $db->getQuery(true);
        
        $query = "ALTER TABLE  `#__noboss_calendar` ADD COLUMN `event_category` varchar(80) DEFAULT '' AFTER `id_calendar`;";
        $db->setQuery($query);
        $db->execute();

        // INICIO: MIGRA VALOR DO CAMPO PARA COLUNA PROPRIA

        $query = $db->getQuery(true);

        $query
        ->select("id_event, data_json, id_calendar")
        ->from('#__noboss_calendar')
        ->where("input_type = 'manual'");

        // Seta query
        $db->setQuery($query);
        
        //echo str_replace('#__', 'ext_', $query); exit;

        try{
            $events = $db->loadObjectList();

            if(count($events) > 0){
                // Percorre cada modulo a ser atualizado
                foreach ($events as $event) {
                    $params = json_decode($event->data_json);

                    // Obtem valor do id da categoria para salvar em base propria
                    $idCategorie = $params->event_category;

                    // Categoria esta definida e nao eh 'feriado'
                    if(($idCategorie != 'none') && ($idCategorie != 'holidays')){
                        // // Evento nao possui id de modulo
                        // if(empty($event->id_module)){
                        //     // Busca id do modulo para concatenar com categoria
                        //     $query = $db->getQuery(true);
                        //     $query
                        //     ->select("id")
                        //     ->from('#__modules')
                        //     ->where("module = 'mod_nobosscalendar'")
                        //     ->where("params like '%\"id\":\"{$idCategorie}%'")
                        //     ->where("params like '%\"id_calendar\":\"{$event->id_calendar}%'");
                        //     $db->setQuery($query, 0, 1);
                        //     $event->id_module = $db->loadResult();
                        // }

                        if(!empty($event->id_calendar)){
                            $idCategorie = $idCategorie.'_'.$event->id_calendar;
                        }
                    }

                    unset($params->event_category);

                    // Codifica novamente para salvar
                    $params = json_encode($params);

    
                    $query = $db->getQuery(true);

                    // Realiza update no banco
                    $query->update($db->quoteName('#__noboss_calendar'))
                            ->set($db->quoteName('event_category') . ' = ' . $db->quote($idCategorie))
                            ->set($db->quoteName('data_json') . ' = ' . $db->quote($params))
                            ->where("id_event = '{$event->id_event}'");

                    //echo str_replace('#__', 'ext_', $query); exit;

                    // Seta query
                    $db->setQuery($query);
                    $db->execute();

                }

            }
        }
        catch(Exception $e){
            throw new Exception('Erro migrar o id de categoria dos eventos para coluna propria');
        }

        // Aproveita funcao para alterar formato que datas especificas sao salvar no banco (era '__/__/__' e virou '__-__-__')
        $query = $db->getQuery(true);
        $query->update($db->quoteName('#__noboss_calendar'))->set($db->quoteName('specific_dates') . " = REPLACE(specific_dates,'\\\/','-')");
        $db->setQuery($query);
        $db->execute();
        $query = $db->getQuery(true);
        $query->update($db->quoteName('#__noboss_calendar'))->set($db->quoteName('specific_dates') . " = REPLACE(specific_dates,'\\\-','-')");
        $db->setQuery($query);
        $db->execute();
    }

    /**
     * Função para update de versão criada em Março de 2021
     * 
	 * Cria a tabela '#__noboss_calendar_categories' migrando os dados que ficavam nos params do módulo para a tabela.
     * Também reorganiza os id's das categorias na tabela '#__noboss_calendar'
     * 
	 */
    public static function updateNewTableCategoriesAjax(){
        $db = JFactory::getDbo();
        $query = $db->getQuery(true);
        $config = JFactory::getConfig();
        
        // Prefixo da tabela
        $dbprefix = $config->get('dbprefix');
        
        try{
            // Consulta que verifica se tabela existe no banco
            $query = "SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME='{$dbprefix}noboss_calendar_categories'";
            
            $db->setQuery($query);
            $count = $db->loadResult();
            
            // Coluna ja existe no banco: nao ha atualizacoes a realizar
            if ($count > 0){
                return;
            }
            
            $db->transactionStart();

            // INICIO: CRIA TABELA
            $query = $db->getQuery(true);
            $query = "CREATE TABLE IF NOT EXISTS `#__noboss_calendar_categories` (
                `id_categorie` varchar(80) NOT NULL,
                `id_calendar` varchar(20) DEFAULT '',
                `legend` varchar(255) DEFAULT '',
                `category_color` varchar(40) DEFAULT '',
                `show_in_legends` tinyint DEFAULT '1',
                `input_type` varchar(30) DEFAULT 'manual',
                PRIMARY KEY (`id_categorie`),
                UNIQUE KEY `id_categorie` (`id_categorie`)
            ) DEFAULT CHARSET=utf8;";
            $db->setQuery($query);
            $db->execute();

            // INICIO: MIGRA CATEGORIAS PARA TABELA PROPRIA

            // Busca todos registros de modulos do calendario
            $query = $db->getQuery(true);
            $query
            ->select("id, params")
            ->from('#__modules')
            ->where("module = 'mod_nobosscalendar'");

            // Seta query
            $db->setQuery($query);
            
            //echo str_replace('#__', 'ext_', $query); exit;

            $modules = $db->loadObjectList();

            if(count($modules) > 0){
                // Percorre cada modulo a ser atualizado
                foreach ($modules as $module) {
                    $params = json_decode($module->params);
                    
                    // echo '<pre>';
                    // var_dump($params);
                    // exit;

                    // Se nao existe param de categorias, pula fora
                    if(empty($params->categories)){
                        continue;
                    }
             
                    // Percorre as categorias para salvar na tabela propria
                    foreach ($params->categories as $categorie) {
                        // Verifica se ja existe categoria salva com mesmo 'id_Calendar' e 'legend'
                        $query = "SELECT id_categorie FROM #__noboss_calendar_categories WHERE id_calendar='{$params->id_calendar}' AND legend = '{$categorie->legend}'";
                        $db->setQuery($query);
                        $verifyCat = $db->loadResult();

                        // Adiciona o ID do modulo no id da categoria para evitar duplicacao
                        $categorie->id = $categorie->id.'_'.$module->id;

                        // Ja existe no banco categoria com mesmo nome e mesmo id_calendar
                        if (!empty($verifyCat)){
                            // A categoria nao possui mesmo ID
                            if($categorie->id != $verifyCat){
                                // Atualiza eventos que possuem a categoria atual pela que esta salva no banco
                                $query = $db->getQuery(true);
                                $query->update($db->quoteName('#__noboss_calendar'))
                                        ->set($db->quoteName('event_category') . ' = ' . $db->quote($verifyCat))
                                        ->where("event_category = '{$categorie->id}'");
                                $db->setQuery($query);
                                $db->execute();
                            }
                        }
                        // Ainda nao existe no banco: insere
                        else{
                            // Confirma se nao existe categoria com mesmo id para nao dar erro
                            $query = "SELECT id_categorie FROM #__noboss_calendar_categories WHERE id_categorie='{$categorie->id}'";
                            $db->setQuery($query);

                            // Nao existe categoria no banco
                            if(empty($db->loadResult())){
                                $query = $db->getQuery(true);
                                $columns = array('id_categorie', 'id_calendar', 'legend', 'category_color', 'show_in_legends');
                                $values = array($db->quote($categorie->id), $db->quote($params->id_calendar), $db->quote($categorie->legend), $db->quote($categorie->category_color), $db->quote($categorie->show_in_legends));

                                
                                // Realiza insert no banco
                                $query->insert($db->quoteName('#__noboss_calendar_categories'))
                                ->columns($db->quoteName($columns))
                                ->values(implode(',', $values));
                                
                                //echo str_replace('#__', 'ext_', $query); exit;

                                // Seta query
                                $db->setQuery($query);
                                $db->execute();
                            }
                        }
                    }

                    // Renove categorias da tabela params
                    unset($params->categories);

                    // Converte para json de volta os parametros para salvar no banco
                    $params = json_encode($params);
    
                    $query = $db->getQuery(true);

                    // Realiza update no banco
                    $query->update($db->quoteName('#__modules'))
                            ->set($db->quoteName('params') . ' = ' . $db->quote($params))
                            ->where("id = '{$module->id}'");

                    //echo str_replace('#__', 'ext_', $query); exit;

                    // Seta query
                    $db->setQuery($query);
                    $db->execute();
                }
            }

            $db->transactionCommit();
        }
        catch(Exception $e){
            $db->transactionRollback();

            throw new Exception('Erro ao tentar criar nova tabela de categorias. Detalhes: '.$e->getMessage());
        }
    }

    /**
     * Função para remover coluna id_module da tabela de eventos e ajustar chaves primarias da tabela de categorias (criado em 26 de agosto de 2021)
	 */
    /*public static function removeColumnIdModuleAndAjustPrimaryKey(){
        $db = JFactory::getDbo();
        $query = $db->getQuery(true);
        $config = JFactory::getConfig();
        
        // Prefixo da tabela
        $dbprefix = $config->get('dbprefix');

        // Consulta que verifica se coluna id_module ainda existe na tabela
        $query = "SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME='{$dbprefix}noboss_calendar' AND COLUMN_NAME = 'id_module'";
        
        $db->setQuery($query);
        $count = $db->loadResult();
        
        // Coluna ja foi removida: nao ha atualizacoes a realizar
        if ($count == 0){
            return;
        }
        
        $db->transactionStart();

        // Remove coluna id_module da tabela de eventos
        $query = "ALTER TABLE  `#__noboss_calendar` DROP COLUMN `id_module`;";
        $db->setQuery($query);
        $db->execute();

        // Altera chaves primarias da tabela de categorias
        $query = "ALTER TABLE `#__noboss_calendar_categories` DROP INDEX `id_categorie`, DROP PRIMARY KEY, ADD PRIMARY KEY (`id_categorie`,`id_calendar`);";
        $db->setQuery($query);
        $db->execute();

        $db->transactionCommit();
    }*/

    /**
     * Funcao para ampliar tamanho do campo 'event_category' na tabela de eventos criada em Outubro de 2022
     * 
	 */
    public static function changeEventCategoryColumn(){
        $db = JFactory::getDbo();
        $query = $db->getQuery(true);
        $config = JFactory::getConfig();
        
        // Prefixo da tabela
        $dbprefix = $config->get('dbprefix');

        $db->transactionStart();

        // Altera a coluna event_category de varchar para mediumtext
        $query = "ALTER TABLE `#__noboss_calendar` MODIFY event_category mediumtext;";
        $db->setQuery($query);
        $db->execute();

        // Altera a coluna id_categorie aumentando largura de 80 para 150
        $query = "ALTER TABLE `#__noboss_calendar_categories` MODIFY id_categorie varchar(150) NOT NULL;";
        $db->setQuery($query);
        $db->execute();


        $db->transactionCommit();
    }

    /*
        TODO: funcao temporaria para ajustes de revisao dos campos admin
                * Criado em Dezembro de 2022
    */
    public static function updateVersion_review_admin(){
        jimport('joomla.filesystem.file');
        JFile::delete(JPATH_ROOT . '/modules/mod_nobosscalendar/modals/model1_external_area_customization.xml');
        JFile::delete(JPATH_ROOT . '/modules/mod_nobosscalendar/modals/model2_external_area_customization.xml');
        JFile::delete(JPATH_ROOT . '/modules/mod_nobosscalendar/modals/model3_external_area_customization.xml');
        JFile::delete(JPATH_ROOT . '/modules/mod_nobosscalendar/modals/model1_items_customization.xml');
        JFile::delete(JPATH_ROOT . '/modules/mod_nobosscalendar/modals/model2_items_customization.xml');
        JFile::delete(JPATH_ROOT . '/modules/mod_nobosscalendar/modals/model3_items_customization.xml');
        JFile::delete(JPATH_ROOT . '/modules/mod_nobosscalendar/modals/modal_customization.xml');

        $db = JFactory::getDBO();
        $query = $db->getQuery(true);

        $query
        ->select("id, params")
        ->from('#__modules')
        ->where("module = 'mod_nobosscalendar'");

        // Seta query
		$db->setQuery($query);
		
		//echo str_replace('#__', 'ext_', $query); exit;

        try{
            $modules = $db->loadObjectList();

            if(count($modules) > 0){
                // Percorre cada modulo a ser atualizado
                foreach ($modules as $module) {
                    $params = json_decode($module->params);

                    // echo '<pre>';
                    // var_dump($params); exit;

                    // TODO: Pula atualizacao de modulo pq ja foi atualizado (gatilho para saber se deve ou nao ser atualizado)
                    if(!empty($params->external_area)){
                        continue;
                    }

                    // Obtem dados do tema
                    $themeData = json_decode($params->theme);
                    
                    // Tema nao definido: pula
                    if(empty($themeData)){
                        continue;
                    }

                    // TODO: mudanca do alias da modal de area externa - INICIO

                    // Monta nome da modal de area externa no formato antigo
                    $themeAliasExternal = $themeData->theme."_external_area_customization";

                    // Migra alias da area externa para novo modelo (era, por exemplo, 'model1_external_area_customization' e agora eh sempre 'external_area')
                    $params->external_area = $params->{$themeAliasExternal};
                    
                    // Remove referencia antiga
                    unset($params->{$themeAliasExternal});

                    // TODO: mudanca do alias da modal de area externa - FIM


                    // TODO: mudanca do valor do campo de setas E TAMBEM NOME DO FIELD - INICIO
                   
                    // monta nome da modal de calendario
                    $themeAliasCalendar = $themeData->theme."_items_customization";

                    // Extrai dados da modal de personalizacao
                    $valuesEditModal = json_decode($params->{$themeAliasCalendar});
                    
                    // Faz substituicao de icone de setas
                    if(isset($valuesEditModal->arrows_icon)){
                        switch ($valuesEditModal->arrows_icon) {
                            case "fa-chevron-circle":
                            case "fa-arrow-circle":
                            case "fa-arrow-circle-o":
                                $valuesEditModal->arrows_icon = "fa-solid fa-circle-chevron-DIRECTION";
                            break;
                                        
                            case "fa-angle":
                            case "fa-chevron":
                                $valuesEditModal->arrows_icon = "fa-solid fa-chevron-DIRECTION";
                                break;
                                
                            case "fa-angle-double":
                                $valuesEditModal->arrows_icon = "fa-solid fa-angles-DIRECTION";
                            break;

                            case "fa-arrow":
                                $valuesEditModal->arrows_icon = "fa-solid fa-arrow-DIRECTION";
                            break;
                            
                            case "fa-caret-square-o":
                                $valuesEditModal->arrows_icon = "fa-solid fa-square-caret-DIRECTION";
                            break;

                            case "fa-long-arrow":
                                $valuesEditModal->arrows_icon = "fa-solid fa-arrow-DIRECTION-long";
                                break;
                            }
                        }
    
                        // echo '<pre>';
                        // var_dump($valuesEditModal);
                        // exit;

                        // Armazena dados de volta da modal a salvar ja no novo nome
                        $params->layout_calendar = json_encode($valuesEditModal);
                        
                        // Remove referencia antiga
                        unset($params->{$themeAliasCalendar});
                        
                        // TODO: mudanca do valor do campo de setas - FIM
                        
                        // Converte para json de volta os parametros para salvar no banco
                    $params = json_encode($params);
    
                    $query = $db->getQuery(true);

                    // Realiza update no banco
                    $query->update($db->quoteName('#__modules'))
                            ->set($db->quoteName('params') . ' = ' . $db->quote($params))
                            ->where("id = '{$module->id}'");

                    //echo str_replace('#__', 'ext_', $query); exit;

                    // Seta query
                    $db->setQuery($query);
                    $db->execute();

                }

            }
        }
        catch(Exception $e){
			throw new Exception('Erro ao tentar converter os registros da versao antiga para nova');
        }
    }
}
