First Commit
This commit is contained in:
@@ -0,0 +1,493 @@
|
||||
<?php
|
||||
|
||||
namespace Modules\Configindex\Controllers;
|
||||
|
||||
use App\Controllers\BaseAdminController;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\HttpFoundation\RedirectResponse;
|
||||
use Modules\Configindex\Models\ConfigPage;
|
||||
|
||||
class ConfigIndexController extends BaseAdminController
|
||||
{
|
||||
/**
|
||||
* List pages to configure
|
||||
*/
|
||||
public function index(Request $request): Response
|
||||
{
|
||||
$user = $this->getCurrentUser();
|
||||
if (!$user) {
|
||||
return new RedirectResponse(url('login'));
|
||||
}
|
||||
|
||||
$theme = $request->query->get('theme', \Kernel\View::getActiveTheme() ?? 'default');
|
||||
|
||||
$pagesKeys = $this->getPagesKeys($theme);
|
||||
$pages = [];
|
||||
foreach ($pagesKeys as $key) {
|
||||
$pages[$key] = ucfirst($key);
|
||||
}
|
||||
|
||||
$themesDir = dirname(dirname(dirname(dirname(__DIR__)))) . '/themes';
|
||||
$availableThemes = ['default' => 'Default'];
|
||||
if (is_dir($themesDir)) {
|
||||
$folders = array_diff(scandir($themesDir), ['.', '..']);
|
||||
foreach ($folders as $folder) {
|
||||
if (is_dir($themesDir . '/' . $folder)) {
|
||||
$availableThemes[$folder] = ucfirst($folder);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $this->renderAdminView('configindex/views/admin/index.twig', [
|
||||
'title' => __('configindex.title'),
|
||||
'pages' => $pages,
|
||||
'currentTheme' => $theme,
|
||||
'availableThemes' => $availableThemes
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Show create form
|
||||
*/
|
||||
public function create(Request $request): Response
|
||||
{
|
||||
$user = $this->getCurrentUser();
|
||||
if (!$user) {
|
||||
return new RedirectResponse(url('login'));
|
||||
}
|
||||
|
||||
return $this->renderAdminView('configindex/views/admin/create.twig', [
|
||||
'title' => 'Nova Página Index'
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Store new page
|
||||
*/
|
||||
public function store(Request $request): Response
|
||||
{
|
||||
$user = $this->getCurrentUser();
|
||||
if (!$user) {
|
||||
return new RedirectResponse(url('login'));
|
||||
}
|
||||
|
||||
$key = $request->request->get('key');
|
||||
if (!$key) {
|
||||
return new RedirectResponse(url('admin/configindex/create?error=missing_key'));
|
||||
}
|
||||
|
||||
// Sanitiza a chave (slug)
|
||||
$key = strtolower(preg_replace('/[^a-zA-Z0-9_-]/', '', $key));
|
||||
|
||||
$busId = $user->users_bus_id ?? 1;
|
||||
|
||||
// Verifica se já existe
|
||||
$existing = ConfigPage::getByKey($key, $busId);
|
||||
if ($existing) {
|
||||
return new RedirectResponse(url('admin/configindex/create?error=already_exists'));
|
||||
}
|
||||
|
||||
// Cria o registro no banco
|
||||
$page = new ConfigPage();
|
||||
$page->config_index_bus_id = $busId;
|
||||
$page->config_index_key = $key;
|
||||
$page->config_index_title = ucfirst($key);
|
||||
$page->config_index_show_public_nav = true;
|
||||
$page->config_index_show_dashboard_nav = true;
|
||||
$page->save();
|
||||
|
||||
// Cria o arquivo físico se não existir
|
||||
$viewsPath = dirname(__DIR__, 3) . '/index/views';
|
||||
$templatePath = $viewsPath . '/' . $key . '.twig';
|
||||
|
||||
if (!is_dir($viewsPath)) {
|
||||
mkdir($viewsPath, 0755, true);
|
||||
}
|
||||
|
||||
if (!is_file($templatePath)) {
|
||||
$defaultContent = "{% extends '@index/layout.twig' %}\n\n{% block content %}\n<div class=\"container my-5\">\n <h1>{{ __('index." . $key . ".title') }}</h1>\n <p>{{ __('index." . $key . ".description') }}</p>\n</div>\n{% endblock %}\n";
|
||||
file_put_contents($templatePath, $defaultContent);
|
||||
}
|
||||
|
||||
// Cria arquivos de tradução padrão
|
||||
$localesPath = dirname(__DIR__, 3) . '/index/locales';
|
||||
$languages = ['pt_BR', 'en_US', 'es_ES', 'de_DE', 'fr_FR'];
|
||||
|
||||
foreach ($languages as $lang) {
|
||||
$savePath = $localesPath . '/' . $lang . '/index.json';
|
||||
if (!is_dir(dirname($savePath))) {
|
||||
mkdir(dirname($savePath), 0755, true);
|
||||
}
|
||||
|
||||
$base = [];
|
||||
if (is_file($savePath)) {
|
||||
$base = json_decode(file_get_contents($savePath), true) ?: [];
|
||||
}
|
||||
|
||||
if (!isset($base[$key])) {
|
||||
$base[$key] = [
|
||||
'title' => ucfirst($key),
|
||||
'description' => 'Conteúdo da página ' . $key
|
||||
];
|
||||
file_put_contents($savePath, json_encode($base, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE));
|
||||
}
|
||||
}
|
||||
|
||||
return new RedirectResponse(url('admin/configindex/' . $key . '/edit?success=created'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all valid page keys for a theme
|
||||
*/
|
||||
private function getPagesKeys(string $themeSlug): array
|
||||
{
|
||||
$keys = [];
|
||||
$baseDir = dirname(dirname(dirname(dirname(__DIR__))));
|
||||
|
||||
// 1. Coleta do módulo index (Padrão do Sistema)
|
||||
$indexViewsPath = $baseDir . '/modules/index/views';
|
||||
if (is_dir($indexViewsPath)) {
|
||||
$files = glob($indexViewsPath . '/*.{twig,php}', GLOB_BRACE);
|
||||
foreach ($files as $file) {
|
||||
$filename = pathinfo($file, PATHINFO_FILENAME);
|
||||
if ($filename !== 'layout') {
|
||||
$keys[] = $filename;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 2. Coleta do Tema (Se houver overrides de módulos)
|
||||
$themeModuleViewsPath = $baseDir . '/themes/' . $themeSlug . '/modules/index/views';
|
||||
if (is_dir($themeModuleViewsPath)) {
|
||||
$files = glob($themeModuleViewsPath . '/*.{twig,php}', GLOB_BRACE);
|
||||
foreach ($files as $file) {
|
||||
$filename = pathinfo($file, PATHINFO_FILENAME);
|
||||
if ($filename !== 'layout') {
|
||||
$keys[] = $filename;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 3. Coleta do Tema (Views genéricas na raiz do tema ou subpasta views)
|
||||
$themeRootViews = [
|
||||
$baseDir . '/themes/' . $themeSlug,
|
||||
$baseDir . '/themes/' . $themeSlug . '/views'
|
||||
];
|
||||
foreach ($themeRootViews as $path) {
|
||||
if (is_dir($path)) {
|
||||
$files = glob($path . '/*.{twig,php}', GLOB_BRACE);
|
||||
foreach ($files as $file) {
|
||||
$filename = pathinfo($file, PATHINFO_FILENAME);
|
||||
// Ignorar arquivos de sistema e layouts
|
||||
if (!in_array($filename, ['layout', 'header', 'footer', 'sidebar'])) {
|
||||
$keys[] = $filename;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($keys)) {
|
||||
$keys = ['index', 'about', 'contact', 'services'];
|
||||
}
|
||||
|
||||
return array_unique($keys);
|
||||
}
|
||||
|
||||
/**
|
||||
* Show edit form
|
||||
*/
|
||||
public function edit(Request $request, string $key): Response
|
||||
{
|
||||
$user = $this->getCurrentUser();
|
||||
if (!$user) {
|
||||
return new RedirectResponse(url('login'));
|
||||
}
|
||||
|
||||
$theme = $request->query->get('theme', \Kernel\View::getActiveTheme() ?? 'default');
|
||||
$busId = $user->users_bus_id ?? 1;
|
||||
$page = ConfigPage::getByKey($key, $busId);
|
||||
|
||||
$templateCode = null;
|
||||
$baseDir = dirname(dirname(dirname(dirname(__DIR__))));
|
||||
|
||||
// Prioridade de busca do arquivo para edição:
|
||||
// 1. Override do módulo no tema selecionado
|
||||
$paths = [
|
||||
$baseDir . '/themes/' . $theme . '/modules/index/views/' . $key . '.twig',
|
||||
$baseDir . '/themes/' . $theme . '/modules/index/views/' . $key . '.php',
|
||||
$baseDir . '/themes/' . $theme . '/' . $key . '.twig',
|
||||
$baseDir . '/themes/' . $theme . '/' . $key . '.php',
|
||||
$baseDir . '/themes/' . $theme . '/views/' . $key . '.twig',
|
||||
$baseDir . '/themes/' . $theme . '/views/' . $key . '.php',
|
||||
$baseDir . '/modules/index/views/' . $key . '.twig',
|
||||
$baseDir . '/modules/index/views/' . $key . '.php',
|
||||
];
|
||||
|
||||
$foundPath = null;
|
||||
foreach ($paths as $path) {
|
||||
if (is_file($path)) {
|
||||
$templateCode = file_get_contents($path);
|
||||
$foundPath = $path;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$languagesMap = [];
|
||||
|
||||
// Locais de tradução: Módulo index + Tema selecionado
|
||||
$localesPaths = [
|
||||
$baseDir . '/modules/index/locales',
|
||||
$baseDir . '/themes/' . $theme . '/locales'
|
||||
];
|
||||
|
||||
foreach ($localesPaths as $base) {
|
||||
if (is_dir($base)) {
|
||||
foreach (glob($base . '/*', GLOB_ONLYDIR) as $dir) {
|
||||
$languagesMap[basename($dir)] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$languages = array_keys($languagesMap);
|
||||
if (empty($languages)) {
|
||||
$languages = ['pt_BR', 'en_US', 'es_ES', 'de_DE', 'fr_FR'];
|
||||
}
|
||||
sort($languages);
|
||||
|
||||
$validKeys = $this->getPagesKeys($theme);
|
||||
|
||||
$translationsIndexSection = [];
|
||||
foreach ($languages as $lang) {
|
||||
$langData = [];
|
||||
|
||||
foreach ($localesPaths as $base) {
|
||||
$path = $base . '/' . $lang . '/index.json';
|
||||
if (is_file($path)) {
|
||||
$decoded = json_decode(file_get_contents($path), true);
|
||||
if (is_array($decoded)) {
|
||||
$langData = array_merge($langData, $decoded);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($key === 'index') {
|
||||
$indexData = [];
|
||||
foreach ($langData as $k => $v) {
|
||||
if (!in_array($k, $validKeys) || $k === 'index') {
|
||||
$indexData[$k] = $v;
|
||||
}
|
||||
}
|
||||
$translationsIndexSection[$lang] = json_encode($indexData, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
|
||||
} elseif (isset($langData[$key])) {
|
||||
$translationsIndexSection[$lang] = json_encode($langData[$key], JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
|
||||
} else {
|
||||
$translationsIndexSection[$lang] = json_encode(new \stdClass(), JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
|
||||
}
|
||||
}
|
||||
|
||||
return $this->renderAdminView('configindex/views/admin/edit.twig', [
|
||||
'title' => __('configindex.edit_title', ['page' => ucfirst($key)]),
|
||||
'page_key' => $key,
|
||||
'page_data' => $page,
|
||||
'template_code' => $templateCode,
|
||||
'languages' => $languages,
|
||||
'translations_index_section' => $translationsIndexSection,
|
||||
'currentTheme' => $theme,
|
||||
'foundPath' => $foundPath,
|
||||
'base_path' => $baseDir
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update page content
|
||||
*/
|
||||
public function update(Request $request, string $key): Response
|
||||
{
|
||||
try {
|
||||
$user = $this->getCurrentUser();
|
||||
if (!$user) {
|
||||
return new RedirectResponse(url('login'));
|
||||
}
|
||||
|
||||
$busId = $user->users_bus_id ?? 1;
|
||||
|
||||
$data = $request->request->all();
|
||||
|
||||
$page = ConfigPage::getByKey($key, $busId);
|
||||
|
||||
if (!$page) {
|
||||
$page = new ConfigPage();
|
||||
$page->config_index_bus_id = $busId;
|
||||
$page->config_index_key = $key;
|
||||
$page->config_index_title = ucfirst($key);
|
||||
$page->config_index_meta_title = '';
|
||||
$page->config_index_meta_description = '';
|
||||
}
|
||||
|
||||
if (isset($data['content'])) {
|
||||
$page->config_index_content = $data['content'];
|
||||
}
|
||||
$page->config_index_show_public_nav = !empty($data['config_index_show_public_nav']);
|
||||
$page->config_index_show_dashboard_nav = !empty($data['config_index_show_dashboard_nav']);
|
||||
|
||||
$page->save();
|
||||
|
||||
$codeToWrite = $data['content'] ?? ($data['template_code'] ?? null);
|
||||
if ($codeToWrite !== null) {
|
||||
$theme = $request->query->get('theme', \Kernel\View::getActiveTheme() ?? 'default');
|
||||
$baseDir = dirname(dirname(dirname(dirname(__DIR__))));
|
||||
|
||||
// Determina o caminho de salvamento baseado no tema
|
||||
if ($theme === 'default') {
|
||||
$templatePath = $baseDir . '/modules/index/views/' . $key . '.twig';
|
||||
// Fallback para .php se já existir
|
||||
if (!is_file($templatePath) && is_file(str_replace('.twig', '.php', $templatePath))) {
|
||||
$templatePath = str_replace('.twig', '.php', $templatePath);
|
||||
}
|
||||
} else {
|
||||
// Para temas, salvamos no override do módulo dentro do tema
|
||||
$templatePath = $baseDir . '/themes/' . $theme . '/modules/index/views/' . $key . '.twig';
|
||||
}
|
||||
|
||||
$viewsDir = dirname($templatePath);
|
||||
if (!is_dir($viewsDir)) {
|
||||
mkdir($viewsDir, 0755, true);
|
||||
}
|
||||
file_put_contents($templatePath, $codeToWrite);
|
||||
}
|
||||
|
||||
// Update translations
|
||||
$translations = $request->request->all('translations_index_section');
|
||||
if (is_array($translations)) {
|
||||
$theme = $request->query->get('theme', \Kernel\View::getActiveTheme() ?? 'default');
|
||||
$baseDir = dirname(dirname(dirname(dirname(__DIR__))));
|
||||
|
||||
// Salva no local apropriado (Módulo ou Tema)
|
||||
if ($theme === 'default') {
|
||||
$localesBase = $baseDir . '/modules/index/locales';
|
||||
} else {
|
||||
$localesBase = $baseDir . '/themes/' . $theme . '/locales';
|
||||
}
|
||||
|
||||
foreach ($translations as $lang => $json) {
|
||||
if ($json !== null && $json !== '') {
|
||||
$section = json_decode($json, true);
|
||||
if (is_array($section)) {
|
||||
$savePath = $localesBase . '/' . $lang . '/index.json';
|
||||
if (!is_dir(dirname($savePath))) {
|
||||
mkdir(dirname($savePath), 0755, true);
|
||||
}
|
||||
|
||||
$base = [];
|
||||
if (is_file($savePath)) {
|
||||
$base = json_decode(file_get_contents($savePath), true) ?: [];
|
||||
}
|
||||
|
||||
if ($key === 'index') {
|
||||
// Mescla chaves soltas na raiz, preservando outras páginas
|
||||
$newBase = $section;
|
||||
foreach ($base as $k => $v) {
|
||||
if (is_array($v) && $k !== 'index' && $k !== 'layout' && $k !== 'menu') {
|
||||
$newBase[$k] = $v;
|
||||
}
|
||||
}
|
||||
$base = $newBase;
|
||||
} else {
|
||||
// Salva na seção da página
|
||||
$base[$key] = $section;
|
||||
}
|
||||
|
||||
file_put_contents($savePath, json_encode($base, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
\Kernel\Translator::setLocale(\Kernel\Translator::getLocale());
|
||||
} catch (\Throwable $e) {
|
||||
}
|
||||
|
||||
$theme = $request->query->get('theme', \Kernel\View::getActiveTheme() ?? 'default');
|
||||
return new RedirectResponse(url('admin/configindex/' . $key . '/edit?theme=' . $theme . '&success=updated'));
|
||||
} catch (\Exception $e) {
|
||||
error_log("Error in ConfigIndexController::update: " . $e->getMessage());
|
||||
return new Response("Internal Server Error: " . $e->getMessage(), 500);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggle page visibility status
|
||||
*/
|
||||
public function toggleStatus(Request $request, string $key): Response
|
||||
{
|
||||
$user = $this->getCurrentUser();
|
||||
if (!$user) {
|
||||
return new RedirectResponse(url('login'));
|
||||
}
|
||||
|
||||
$busId = $user->users_bus_id ?? 1;
|
||||
$page = ConfigPage::getByKey($key, $busId);
|
||||
|
||||
if ($page) {
|
||||
$page->config_index_show_public_nav = !$page->config_index_show_public_nav;
|
||||
$page->save();
|
||||
}
|
||||
|
||||
return new RedirectResponse(url('admin/configindex?success=status_updated'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete page and associated files
|
||||
*/
|
||||
public function destroy(Request $request, string $key): Response
|
||||
{
|
||||
$user = $this->getCurrentUser();
|
||||
if (!$user) {
|
||||
return new RedirectResponse(url('login'));
|
||||
}
|
||||
|
||||
// Não permitir excluir a home (index)
|
||||
if ($key === 'index') {
|
||||
return new RedirectResponse(url('admin/configindex?error=cannot_delete_home'));
|
||||
}
|
||||
|
||||
$busId = $user->users_bus_id ?? 1;
|
||||
$page = ConfigPage::getByKey($key, $busId);
|
||||
|
||||
if ($page) {
|
||||
$page->delete();
|
||||
}
|
||||
|
||||
// Remover arquivos físicos (.twig)
|
||||
$viewsPath = dirname(__DIR__, 3) . '/index/views';
|
||||
$templatePath = $viewsPath . '/' . $key . '.twig';
|
||||
if (is_file($templatePath)) {
|
||||
unlink($templatePath);
|
||||
}
|
||||
|
||||
// Remover de .php se existir
|
||||
$phpPath = $viewsPath . '/' . $key . '.php';
|
||||
if (is_file($phpPath)) {
|
||||
unlink($phpPath);
|
||||
}
|
||||
|
||||
// Remover traduções dos arquivos index.json
|
||||
$localesPath = dirname(__DIR__, 3) . '/index/locales';
|
||||
$languages = ['pt_BR', 'en_US', 'es_ES', 'de_DE', 'fr_FR'];
|
||||
|
||||
foreach ($languages as $lang) {
|
||||
$savePath = $localesPath . '/' . $lang . '/index.json';
|
||||
if (is_file($savePath)) {
|
||||
$base = json_decode(file_get_contents($savePath), true) ?: [];
|
||||
if (isset($base[$key])) {
|
||||
unset($base[$key]);
|
||||
file_put_contents($savePath, json_encode($base, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new RedirectResponse(url('admin/configindex?success=deleted'));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user