First Commit
This commit is contained in:
@@ -0,0 +1,279 @@
|
||||
<?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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user