Files
2026-09-01 10:46:29 -03:00

280 lines
8.8 KiB
PHP
Executable File

<?php
/**
* SysCMS - Content Management System
*
* Copyright (c) 2026 Marco Costa
* All rights reserved.
*
* Author: Marco Costa
* Email: contato@syspanel.com.br
* Project: SysCMS
*
* This software is licensed, not sold.
* Permission is granted to use this software
* subject to the terms of the SysCMS Commercial License.
*
* Redistribution, sublicensing, resale, or
* disclosure of this software, in whole or in part,
* is strictly prohibited without prior written permission.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND.
*/
namespace Modules\GlobalLists\Controllers;
use App\Controllers\BaseAdminController;
use Modules\GlobalLists\Models\State;
use Modules\GlobalLists\Models\City;
use Modules\GlobalLists\Models\Activity;
use Modules\GlobalLists\Models\Country;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
/**
* Class GlobalListsController
*
* Controller for managing global lists (States, Cities, Activities).
*
* @package Modules\GlobalLists\Controllers
*/
class GlobalListsController extends BaseAdminController
{
/**
* Display the lists dashboard.
*
* @return Response
*/
public function index(): Response
{
$countriesCount = Country::count();
$statesCount = State::count();
$citiesCount = City::count();
$activitiesCount = Activity::count();
$countries = Country::all()->sortBy(function ($country) {
return $country->name;
});
$activities = Activity::all()->sortBy(function ($activity) {
return $activity->name;
});
return $this->renderAdminView('@globallists/admin/index.twig', [
'countriesCount' => $countriesCount,
'statesCount' => $statesCount,
'citiesCount' => $citiesCount,
'activitiesCount' => $activitiesCount,
'countries' => $countries,
'activities' => $activities,
'title' => 'Gerenciamento de Listas Globais'
]);
}
/**
* List all activities.
*
* @return Response
*/
public function activitiesIndex(): Response
{
$activities = Activity::orderBy('activities_id')->get();
return $this->renderAdminView('@globallists/admin/activities.twig', [
'activities' => $activities,
'title' => 'Gerenciar Atividades',
'current_locale' => \Kernel\Translator::getLocale() ?: 'pt_BR'
]);
}
/**
* Save an activity.
*
* @param Request $request
* @return Response
*/
public function activitySave(Request $request): Response
{
$id = $request->request->get('activities_id');
$name = $request->request->get('activities_name');
$type = $request->request->get('activities_type');
$locale = \Kernel\Translator::getLocale() ?: 'pt_BR';
if ($id) {
$activity = Activity::find($id);
if ($activity) {
$names = $activity->activities_name;
if (!is_array($names)) {
$names = ['pt_BR' => $names];
}
$names[$locale] = $name;
$activity->update([
'activities_name' => $names,
'activities_type' => $type,
'activities_slug' => $this->slugify($name)
]);
}
} else {
Activity::create([
'activities_name' => [$locale => $name],
'activities_type' => $type,
'activities_slug' => $this->slugify($name)
]);
}
return $this->redirect('/admin/globallists/activities');
}
/**
* Delete an activity.
*
* @param int $id
* @return Response
*/
public function activityDelete(int $id): Response
{
Activity::where('activities_id', $id)->delete();
return $this->redirect('/admin/globallists/activities');
}
/**
* API: Get cities by state.
*
* @param Request $request
* @param string $stateId
* @return Response
*/
public function apiGetCities(Request $request, string $stateId): Response
{
try {
$cities = City::where('cities_state_id', $stateId)
->orderBy('cities_name')
->get();
$data = $cities->map(function ($city) {
return [
'id' => $city->cities_id,
'name' => (string) $city->cities_name
];
})->values()->all();
return new Response(json_encode($data, JSON_UNESCAPED_UNICODE | JSON_THROW_ON_ERROR), 200, ['Content-Type' => 'application/json']);
} catch (\Throwable $e) {
return new Response(json_encode(['error' => $e->getMessage()]), 500, ['Content-Type' => 'application/json']);
}
}
/**
* API: Get states by country.
*
* @param Request $request
* @param string $countryId
* @return Response
*/
public function apiGetStates(Request $request, string $countryId): Response
{
try {
$states = State::where('states_country_id', $countryId)
->orderBy('states_name')
->get();
$data = $states->map(function ($state) {
return [
'id' => $state->states_id,
'name' => $state->states_name . ' (' . $state->states_uf . ')'
];
})->values()->all();
return new Response(json_encode($data, JSON_UNESCAPED_UNICODE | JSON_THROW_ON_ERROR), 200, ['Content-Type' => 'application/json']);
} catch (\Throwable $e) {
return new Response(json_encode(['error' => $e->getMessage()]), 500, ['Content-Type' => 'application/json']);
}
}
/**
* API: Search activities.
*
* @param Request $request
* @return Response
*/
public function apiSearchActivities(Request $request): Response
{
$query = $request->query->get('q');
$locale = \Kernel\Translator::getLocale() ?: 'pt_BR';
// Search in the current locale JSON key
$activities = Activity::where('activities_name->' . $locale, 'LIKE', "%{$query}%")
->orWhere('activities_name->pt_BR', 'LIKE', "%{$query}%") // Fallback search in pt_BR
->limit(20)
->get();
// Map to include the translated name
$results = $activities->map(function ($activity) {
return [
'activities_id' => $activity->activities_id,
'activities_name' => $activity->name // Uses the accessor we added
];
});
return new Response(json_encode($results, JSON_UNESCAPED_UNICODE | JSON_THROW_ON_ERROR), 200, ['Content-Type' => 'application/json']);
}
/**
* API: Lookup location by IBGE code or UF/City name.
*
* @param Request $request
* @return Response
*/
public function apiLookupLocation(Request $request): Response
{
$ibge = $request->query->get('ibge');
$uf = $request->query->get('uf');
$cityName = $request->query->get('city');
if ($ibge) {
$city = City::where('cities_ibge_code', $ibge)->first();
if ($city) {
return new Response(json_encode([
'city_id' => $city->cities_id,
'state_id' => $city->cities_state_id
], JSON_UNESCAPED_UNICODE | JSON_THROW_ON_ERROR), 200, ['Content-Type' => 'application/json']);
}
}
if ($uf && $cityName) {
$state = State::where('states_uf', $uf)->first();
if ($state) {
$city = City::where('cities_state_id', $state->states_id)
->where('cities_name', $cityName)
->first();
if ($city) {
return new Response(json_encode([
'city_id' => $city->cities_id,
'state_id' => $state->states_id
], JSON_UNESCAPED_UNICODE | JSON_THROW_ON_ERROR), 200, ['Content-Type' => 'application/json']);
}
}
}
return new Response(json_encode(['error' => 'Location not found'], JSON_UNESCAPED_UNICODE | JSON_THROW_ON_ERROR), 404, ['Content-Type' => 'application/json']);
}
/**
* Simple slugify helper.
*/
protected function slugify($text)
{
$text = preg_replace('~[^\pL\d]+~u', '-', $text);
$text = iconv('utf-8', 'us-ascii//TRANSLIT', $text);
$text = preg_replace('~[^-\w]+~', '', $text);
$text = trim($text, '-');
$text = preg_replace('~-+~', '-', $text);
$text = strtolower($text);
if (empty($text)) {
return 'n-a';
}
return $text;
}
}