280 lines
8.8 KiB
PHP
Executable File
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;
|
|
}
|
|
}
|