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

419 lines
15 KiB
PHP
Executable File

<?php
namespace Modules\AffiliatesAdmin\Controllers;
use App\Controllers\BaseAdminController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Modules\AffiliatesAdmin\Models\Affiliate;
use Modules\AffiliatesAdmin\Models\AffiliateCommission;
use Modules\AffiliatesAdmin\Models\AffiliateBanner;
use Modules\AffiliatesAdmin\Models\AffiliateClick;
use Modules\Auth\Models\User;
class AffiliatesAdminController extends BaseAdminController
{
/**
* Check if user has permission.
*
* @param string $permission
* @return void
*/
protected function checkPermission(string $permission)
{
$user = $this->getCurrentUser();
if (!$user || !$user->hasPermission($permission)) {
$this->addFlash('error', 'Você não tem permissão para acessar esta área.');
$this->redirect('admin/dashboard')->send();
exit;
}
}
/**
* Display a listing of the affiliates.
*
* @param Request $request
* @return Response
*/
public function index(Request $request): Response
{
$this->checkPermission('affiliatesadmin.view');
$affiliates = Affiliate::all();
return $this->renderAdminView('@affiliatesadmin/index.twig', ['affiliates' => $affiliates]);
}
/**
* Show the form for creating a new affiliate.
*
* @param Request $request
* @return Response
*/
public function create(Request $request): Response
{
$this->checkPermission('affiliatesadmin.manage');
return $this->renderAdminView('@affiliatesadmin/form.twig');
}
/**
* Store a newly created affiliate in storage.
*
* @param Request $request
* @return Response
*/
public function store(Request $request): Response
{
$this->checkPermission('affiliatesadmin.manage');
$data = $request->request->all();
if (empty($data['affiliates_name']) || empty($data['affiliates_email'])) {
$this->addFlash('error', __('affiliatesadmin.validation_name_email_required'));
return $this->redirect('/admin/affiliatesadmin/create');
}
if (!filter_var($data['affiliates_email'], FILTER_VALIDATE_EMAIL)) {
$this->addFlash('error', __('affiliatesadmin.validation_invalid_email'));
return $this->redirect('/admin/affiliatesadmin/create');
}
if (Affiliate::where('affiliates_email', $data['affiliates_email'])->exists()) {
$this->addFlash('error', __('affiliatesadmin.validation_email_exists'));
return $this->redirect('/admin/affiliatesadmin/create');
}
// Check if user already exists in the system
$existingUser = User::where('users_email', $data['affiliates_email'])->first();
if (!$existingUser && empty($data['password'])) {
$this->addFlash('error', 'A senha é obrigatória para criar um novo usuário no sistema.');
return $this->redirect('/admin/affiliatesadmin/create');
}
// Create the Affiliate record
Affiliate::create($data);
if ($existingUser) {
// Only change role if user is a standard 'user'
// Prevent downgrading admins or super_admins
if (in_array($existingUser->users_role, ['user', ''])) {
$existingUser->users_role = 'member';
$existingUser->save();
$this->addFlash('success', __('affiliatesadmin.affiliate_created_successfully') . ' O usuário existente foi promovido para "member".');
} else {
$this->addFlash('success', __('affiliatesadmin.affiliate_created_successfully') . ' O usuário existente manteve seu nível de acesso privilegiado: ' . $existingUser->users_role);
}
} else {
// Create a new System User
$user = new User();
$user->users_name = $data['affiliates_name'];
$user->users_email = $data['affiliates_email'];
$user->users_password = password_hash($data['password'], PASSWORD_DEFAULT);
$user->users_role = 'member';
$user->users_status = 'active';
$user->save();
$this->addFlash('success', __('affiliatesadmin.affiliate_created_successfully') . ' Um novo usuário com nível "member" foi criado.');
}
return $this->redirect('/admin/affiliatesadmin');
}
/**
* Display the specified affiliate.
*
* @param Request $request
* @param int $id
* @return Response
*/
public function show(Request $request, int $id): Response
{
$this->checkPermission('affiliatesadmin.view');
$affiliate = Affiliate::findOrFail($id);
return $this->renderAdminView('@affiliatesadmin/show.twig', ['affiliate' => $affiliate]);
}
/**
* Show the form for editing the specified affiliate.
*
* @param Request $request
* @param int $id
* @return Response
*/
public function edit(Request $request, int $id): Response
{
$this->checkPermission('affiliatesadmin.manage');
$affiliate = Affiliate::findOrFail($id);
return $this->renderAdminView('@affiliatesadmin/form.twig', ['affiliate' => $affiliate]);
}
/**
* Update the specified affiliate in storage.
*
* @param Request $request
* @param int $id
* @return Response
*/
public function update(Request $request, int $id): Response
{
$this->checkPermission('affiliatesadmin.manage');
$affiliate = Affiliate::findOrFail($id);
$data = $request->request->all();
if (empty($data['affiliates_name']) || empty($data['affiliates_email'])) {
$this->addFlash('error', __('affiliatesadmin.validation_name_email_required'));
return $this->redirect('/admin/affiliatesadmin/' . $id . '/edit');
}
if (!filter_var($data['affiliates_email'], FILTER_VALIDATE_EMAIL)) {
$this->addFlash('error', __('affiliatesadmin.validation_invalid_email'));
return $this->redirect('/admin/affiliatesadmin/' . $id . '/edit');
}
if (Affiliate::where('affiliates_email', $data['affiliates_email'])->where('affiliates_id', '!=', $id)->exists()) {
$this->addFlash('error', __('affiliatesadmin.validation_email_exists'));
return $this->redirect('/admin/affiliatesadmin/' . $id . '/edit');
}
$affiliate->update($data);
$this->addFlash('success', __('affiliatesadmin.affiliate_updated_successfully'));
return $this->redirect('/admin/affiliatesadmin');
}
/**
* Remove the specified affiliate from storage.
*
* @param Request $request
* @param int $id
* @return Response
*/
public function destroy(Request $request, int $id): Response
{
$this->checkPermission('affiliatesadmin.manage');
Affiliate::destroy($id);
$this->addFlash('success', __('affiliatesadmin.affiliate_deleted_successfully'));
return $this->redirect('/admin/affiliatesadmin');
}
/**
* Display a listing of commissions.
*
* @param Request $request
* @return Response
*/
public function commissions(Request $request): Response
{
$this->checkPermission('affiliatesadmin.view_commissions');
$commissions = AffiliateCommission::all();
return $this->renderAdminView('@affiliatesadmin/commissions.twig', ['commissions' => $commissions]);
}
/**
* Approve a commission.
*
* @param Request $request
* @param int $id
* @return Response
*/
public function approveCommission(Request $request, int $id): Response
{
$this->checkPermission('affiliatesadmin.manage_commissions');
$commission = AffiliateCommission::findOrFail($id);
$commission->affiliate_commissions_status = 'approved';
$commission->save();
$this->addFlash('success', __('affiliatesadmin.commission_approved_successfully'));
return $this->redirect('/admin/affiliatesadmin/commissions');
}
/**
* Reject a commission.
*
* @param Request $request
* @param int $id
* @return Response
*/
public function rejectCommission(Request $request, int $id): Response
{
$this->checkPermission('affiliatesadmin.manage_commissions');
$commission = AffiliateCommission::findOrFail($id);
$commission->affiliate_commissions_status = 'rejected';
$commission->save();
$this->addFlash('success', __('affiliatesadmin.commission_rejected_successfully'));
return $this->redirect('/admin/affiliatesadmin/commissions');
}
/**
* Display a listing of banners.
*
* @param Request $request
* @return Response
*/
public function banners(Request $request): Response
{
$this->checkPermission('affiliatesadmin.view_banners');
$banners = AffiliateBanner::all();
return $this->renderAdminView('@affiliatesadmin/banners.twig', ['banners' => $banners]);
}
/**
* Show the form for creating a new banner.
*
* @param Request $request
* @return Response
*/
public function createBanner(Request $request): Response
{
$this->checkPermission('affiliatesadmin.manage_banners');
return $this->renderAdminView('@affiliatesadmin/banner-form.twig');
}
/**
* Store a newly created banner in storage.
*
* @param Request $request
* @return Response
*/
public function storeBanner(Request $request): Response
{
$this->checkPermission('affiliatesadmin.manage_banners');
$data = $request->request->all();
if (empty($data['affiliate_banners_name']) || empty($data['affiliate_banners_target_url'])) {
$this->addFlash('error', __('affiliatesadmin.validation_banner_fields_required'));
return $this->redirect('/admin/affiliatesadmin/banners/create');
}
if ($request->files->has('banner_file')) {
$file = $request->files->get('banner_file');
if ($file && $file->isValid()) {
$data['affiliate_banners_image_url'] = $this->handleBannerUpload($file);
}
}
if (empty($data['affiliate_banners_image_url'])) {
$this->addFlash('error', 'O arquivo de imagem do banner é obrigatório.');
return $this->redirect('/admin/affiliatesadmin/banners/create');
}
AffiliateBanner::create($data);
$this->addFlash('success', __('affiliatesadmin.banner_created_successfully'));
return $this->redirect('/admin/affiliatesadmin/banners');
}
/**
* Show the form for editing the specified banner.
*
* @param Request $request
* @param int $id
* @return Response
*/
public function editBanner(Request $request, int $id): Response
{
$banner = AffiliateBanner::findOrFail($id);
return $this->renderAdminView('@affiliatesadmin/banner-form.twig', ['banner' => $banner]);
}
/**
* Update the specified banner in storage.
*
* @param Request $request
* @param int $id
* @return Response
*/
public function updateBanner(Request $request, int $id): Response
{
$banner = AffiliateBanner::findOrFail($id);
$data = $request->request->all();
if (empty($data['affiliate_banners_name']) || empty($data['affiliate_banners_target_url'])) {
$this->addFlash('error', __('affiliatesadmin.validation_banner_fields_required'));
return $this->redirect('/admin/affiliatesadmin/banners/' . $id . '/edit');
}
if ($request->files->has('banner_file')) {
$file = $request->files->get('banner_file');
if ($file && $file->isValid()) {
// Delete old file if exists
if ($banner->affiliate_banners_image_url) {
$oldPath = dirname(__DIR__, 4) . '/storage/uploads/affiliatesadmin/' . $banner->affiliate_banners_image_url;
if (file_exists($oldPath) && is_file($oldPath)) {
unlink($oldPath);
}
}
$data['affiliate_banners_image_url'] = $this->handleBannerUpload($file);
}
}
$banner->update($data);
$this->addFlash('success', __('affiliatesadmin.banner_updated_successfully'));
return $this->redirect('/admin/affiliatesadmin/banners');
}
/**
* Handle banner image upload.
*
* @param \Symfony\Component\HttpFoundation\File\UploadedFile $file
* @return string|null
*/
private function handleBannerUpload($file): ?string
{
$uploadDir = dirname(__DIR__, 4) . '/storage/uploads/affiliatesadmin';
if (!is_dir($uploadDir)) {
if (!mkdir($uploadDir, 0777, true)) {
return null;
}
}
$filename = uniqid('banner_') . '.' . $file->guessExtension();
$file->move($uploadDir, $filename);
// Store ONLY the filename in the database
// The view will prepend /storage/uploads/affiliatesadmin/
return $filename;
}
/**
* Remove the specified banner from storage.
*
* @param Request $request
* @param int $id
* @return Response
*/
public function destroyBanner(Request $request, int $id): Response
{
$banner = AffiliateBanner::findOrFail($id);
if ($banner->affiliate_banners_image_url) {
$path = dirname(__DIR__, 4) . '/storage/uploads/affiliatesadmin/' . $banner->affiliate_banners_image_url;
if (file_exists($path) && is_file($path)) {
unlink($path);
}
}
AffiliateBanner::destroy($id);
$this->addFlash('success', __('affiliatesadmin.banner_deleted_successfully'));
return $this->redirect('/admin/affiliatesadmin/banners');
}
/**
* Display affiliate statistics.
*
* @param Request $request
* @return Response
*/
public function statistics(Request $request): Response
{
$this->checkPermission('affiliatesadmin.view_statistics');
$stats = [
'total_affiliates' => Affiliate::count(),
'total_commissions_approved' => AffiliateCommission::where('affiliate_commissions_status', 'approved')->sum('affiliate_commissions_amount'),
'total_clicks' => AffiliateClick::count(),
'conversion_rate' => 0,
];
if ($stats['total_clicks'] > 0) {
$approvedCount = AffiliateCommission::where('affiliate_commissions_status', 'approved')->count();
$stats['conversion_rate'] = round(($approvedCount / $stats['total_clicks']) * 100, 2);
}
return $this->renderAdminView('@affiliatesadmin/statistics.twig', [
'stats' => $stats
]);
}
}