Your IP : 216.73.216.224


Current Path : /var/www/html/libraries/noboss/src/Form/Field/
Upload File :
Current File : /var/www/html/libraries/noboss/src/Form/Field/NbModalModulesField.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\Form\Field;

use Joomla\CMS\Form\Field\ListField;
use Joomla\CMS\Factory;
use Joomla\Database\DatabaseInterface;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Uri\Uri;
use Joomla\CMS\HTML\HTMLHelper;
use Noboss\Library\Util\NbLoadextensionAssetsUtil;

// phpcs:disable PSR1.Files.SideEffects
\defined('_JEXEC') or die;
// phpcs:enable PSR1.Files.SideEffects

// Carrega select com posicoes de modulo permitindo abrir em modal para edicao
// Código inspirado no plugin 'FormFieldEBModules' (plugins\engagebox\module\form\fields\ebmodules.php)

// TODO: a partir do Joomla 5.0.0, o Joomla passou a usar o campo 'ModalSelectField' para abrir modais de edicao de artigos, categorias, etc. No futuro, podemos migrar este campo para estender o 'ModalSelectField' igual field administrator\components\com_content\src\Field\Modal\ArticleField.php faz (https://magazine.joomla.org/all-issues/january-2024/creating-a-custom-form-field-type-in-joomla-5-using-the-modal-select-example)
class NbModalModulesField extends ListField {

    protected $options = array();
    protected $limit;

    protected function getOptions() {
        // Merge any additional options in the XML definition.
        $options = array_merge(parent::getOptions(), $this->options);
        
        return $options;

    }

    protected function getModules($limit = null){
        $db	= Factory::getContainer()->get(DatabaseInterface::class);
        $query =  $db->getQuery(true);
        $query->select("id, CONCAT(title, ' (id: ', id, ')') AS title, module, position, published");
        $query->from('#__modules AS m');
        $query->where("m.client_id = 0");
        // $query->where("published IN ('0', '1')");

        // Definido parametro 'extension': limita exibicao somente do modulo mencionado
        if(isset($this->element['extension'])){
            $query->where("m.module = " . $db->quote($this->element['extension']));
        }

        // Limita numero de exibicoes
        if(!empty($limit)){
            $query->setLimit("{$limit}");
            // Ordena priorizando a exibicao dos modulos da no boss
            $query->order("module like 'mod_noboss%' DESC, module like 'mod_nb%' DESC, published DESC, module, ordering");
        }else{
            // Ordena priorizando os ids mais recentes
            $query->order("id desc, published DESC, module, ordering");
        }

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

        // Set the query
        $db->setQuery($query);

        // Dados nao encontrados
        if (!($modules = $db->loadObjectList())) {
            return false;
        }

        return $modules;
    }

    protected function getInput() {
        // Obtem os modulos do site
        $modules = $this->getModules();

        // Limite maximo a exibir definido no xml
        if(!empty($this->element['limit'])){
            $this->limit = (int)$this->element['limit'];
        }
        // Limite nao definido: forca um limite
        else{
            $this->limit = 2000;
        }

        // Existe mais modulos que o limite: repete pesquisa trazendo apenas os modulos mais recentes dentro do limite
        if(!empty($modules) && (count($modules) > $this->limit)){
            // Obtem os modulos do site
            $modules = $this->getModules($this->limit);
        }

        // Percorre resultados para montar opcoes do select
        foreach($modules as $module){
            $title = $module->title;

            // Nao definido parametro 'extension': acrescenta junto ao nome do modulo o nome da extensao
            if(!isset($this->element['extension'])){
                $title .=  ' (' . $module->module . ')';
            }

            if($module->published == '-2'){
                $title .= Text::_('LIB_NOBOSS_FIELD_NOBOSSMODULES_NOT_TRASHED');
            }

            if($module->published == '0'){
                $title .= Text::_('LIB_NOBOSS_FIELD_NOBOSSMODULES_NOT_PUBLISHED');
            }

            $this->options[] = HTMLHelper::_('select.option', $module->id, $title);
        }

        $app = Factory::getApplication();
        $wa = $app->getDocument()->getWebAssetManager();

        $wa->registerAndUseStyle('nobossmodalmodules', Uri::root()."libraries/noboss/src/Form/Field/assets/stylesheets/css/nobossmodalmodules.min.css");
        $wa->registerAndUseScript('nobossmodalmodules', Uri::root()."libraries/noboss/src/Form/Field/assets/js/min/nobossmodalmodules.min.js");

        // Definido parametro 'extension'
        if(isset($this->element['extension'])){
            // Obtem dados da extensao na tabela do joomla
            $extensionData = $this->getExtensionsData($this->element['extension']);

            if(!empty($extensionData)){
                // Carrega arquivo .sys de traducao da extensao
                $assetsObject = new NbLoadextensionAssetsUtil($extensionData->element);
                $extensionPath = $assetsObject->getDirectoryExtension();
                $lang = Factory::getApplication()->getLanguage();
                $lang->load($extensionData->element. '.sys', $extensionPath);

                // Obtem nome da extensao a partir do arquivo de traducao
                $extensionName = Text::_($extensionData->name);
            }
        }

        $modalNameEdit = 'modaledit_' . $this->id;
       
        // Options da modal de edicao (nao passamos a url da modal pq isso manipulamos via JS por conta da variacao do ID de modulo selecionado)
        $optionsEdit = array(
            'title'       => (!empty($extensionName) ? $extensionName . ': ' : '') . Text::_('LIB_NOBOSS_FIELD_NOBOSSMODULES_TITLE_EDIT_MODULE'),
            'url'         => '#',
            'backdrop'    => 'static',
            'keyboard'    => false,
            'closeButton' => true,
            // 'height'      => '700px', // 400px
            // 'width'       => '800px', // 800px
            'bodyHeight'  => 90, // 70
            'modalWidth'  => 90, // 80
            'footer'      => '<button type="button" class="btn btn-danger" data-id="' . $modalNameEdit . '" data-id-select="' . $this->id . '" data-type="cancel">' . Text::_('JLIB_HTML_BEHAVIOR_CLOSE') . '</button>'
                        . '<button type="button" class="btn btn-success" data-id="' . $modalNameEdit . '" data-id-select="' . $this->id . '" data-type="save">' . Text::_('JSAVE') . '</button>'
                        . '<button type="button" class="btn btn-success" data-id="' . $modalNameEdit . '" data-id-select="' . $this->id . '" data-type="apply">' . Text::_('JAPPLY') . '</button>',
        );

        // Renderiza a modal de edicao
        echo '<div class="nobossmodalmodules__modal nobossmodalmodules__modal-edit">'.HTMLHelper::_('bootstrap.renderModal', $modalNameEdit, $optionsEdit).'</div>';

        $linkPreview = '';
        $displayBtnsEdit = '';
        $displayBtnNew = '';

        // Nao possui valor vindo do banco
        if(empty($this->value)){
            $displayBtnsEdit = 'none';
            $displayBtnNew = 'inline-block';
        }
        else{
            $displayBtnsEdit = 'inline-block';
            $displayBtnNew = 'none';
            $linkPreview = Uri::root()."index.php?option=com_nobossajax&load-head=1&module-id={$this->value}";
        }   

        // Dtml do botao de edicao
        $htmlButtons = '<button class="btn btn-primary nb-module-btn-edit" id="'.$this->id.'_edit" name="'.$this->name.'_edit" data-bs-toggle="modal" type="button" data-bs-target="#'.$modalNameEdit.'" style="display:'.$displayBtnsEdit.';"><span class="icon-edit" aria-hidden="true"></span> ' . Text::_('LIB_NOBOSS_FIELD_NOBOSSMODULES_BUTTON_EDIT_MODULE') . '</button>';

        // Html do botao de preview
        $htmlButtons .= '<a class="btn btn-secondary nb-module-btn-preview" href="'.$linkPreview.'" target="_blank" style="display:'.$displayBtnsEdit.';"> ' . Text::_('LIB_NOBOSS_FIELD_NOBOSSMODULES_BUTTON_PREVIEW_MODULE') . '</a>';

        // Definido parametro 'extension': exibe opcao de criar modulo que seja da extensao especificada
        if(isset($this->element['extension']) && !empty($extensionData)){
            $modalNameNew = 'modalnew_' . $this->id;

            // Options da modal de new
            $optionsNew = array(
                'title'       => $extensionName . ': ' . Text::_('LIB_NOBOSS_FIELD_NOBOSSMODULES_TITLE_NEW_MODULE'),
                'url'         => '#',
                'backdrop'    => 'static',
                'keyboard'    => false,
                'closeButton' => true,               
                // 'height'      => '700px', // 400px
                // 'width'       => '800px', // 800px
                'bodyHeight'  => 90, // 70
                'modalWidth'  => 90, // 80
                'footer'      => '<button type="button" class="btn btn-danger" data-id="' . $modalNameNew . '" data-id-select="' . $this->id . '" data-type="cancel">' . Text::_('JLIB_HTML_BEHAVIOR_CLOSE') . '</button>'
                        . '<button type="button" class="btn btn-success" data-id="' . $modalNameNew . '" data-id-select="' . $this->id . '" data-type="save">' . Text::_('JSAVE') . '</button>'
                        . '<button type="button" class="btn btn-success" data-id="' . $modalNameNew . '" data-id-select="' . $this->id . '" data-type="apply">' . Text::_('JAPPLY') . '</button>',
            );


            // Renderiza a modal de novo modulo
            echo '<div class="nobossmodalmodules__modal nobossmodalmodules__modal-new">'.HTMLHelper::_('bootstrap.renderModal', $modalNameNew, $optionsNew).'</div>';

            // Html do botao de novo modulo
            $htmlButtons .= '<button class="btn btn-success nb-module-btn-new" id="'.$this->id.'_new" name="'.$this->name.'_new" data-bs-toggle="modal" type="button" data-bs-target="#'.$modalNameNew.'" style="display:'.$displayBtnNew.';" data-extension-id="'.$extensionData->extension_id.'" ><span class="icon-new" aria-hidden="true"></span> ' . Text::_('LIB_NOBOSS_FIELD_NOBOSSMODULES_BUTTON_NEW_MODULE') . '</button>';
        }

        // Usando preg_match para capturar a ultima  ocorrencia de colchetes
        preg_match_all('/\[(.*?)\]/', $this->formControl, $matches);
        
        // Existe uma ultima ocorrencia de [] no name do field (campo esta sendo chamado talvez em subform)
        if (!empty($matches[1])) {
            // Alias para replace via JS de name / id quando utilizado em subform
            $aliasReplace = end($matches[1]);
        }
        else{
            $aliasReplace = '';
        }

        // Retorna input parent (field list) e mais os botoes
        return "<div class='nobossmodalmodules__field' data-alias-replace='{$aliasReplace}'>".parent::getInput().$htmlButtons."</div>";
    }

    protected function getExtensionsData($element){
        $db	= Factory::getContainer()->get(DatabaseInterface::class);

        $query =  $db->getQuery(true);
        $query->select('*');
        $query->from('#__extensions');
        $query->where("element = " . $db->quote($element));

        $db->setQuery($query);

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

        return $db->loadObject();
    }
}