add upload file to support ticket
This commit is contained in:
parent
b935fdf6b2
commit
4c5908c5c8
|
@ -8,6 +8,7 @@ parameters:
|
|||
archiveTempMediaDir: '%kernel.project_dir%/../hesabixArchive/temp'
|
||||
avatarDir: '%kernel.project_dir%/../hesabixArchive/avatars'
|
||||
sealDir: '%kernel.project_dir%/../hesabixArchive/seal'
|
||||
SupportFilesDir: '%kernel.project_dir%/../hesabixArchive/support'
|
||||
services:
|
||||
# default configuration for services in *this* file
|
||||
_defaults:
|
||||
|
|
|
@ -5,6 +5,7 @@ namespace App\Controller;
|
|||
use App\Entity\Settings;
|
||||
use App\Entity\Support;
|
||||
use App\Entity\User;
|
||||
use App\Service\Access;
|
||||
use App\Service\Explore;
|
||||
use App\Service\Extractor;
|
||||
use App\Service\Jdate;
|
||||
|
@ -14,205 +15,284 @@ use App\Service\registryMGR;
|
|||
use App\Service\SMS;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\BinaryFileResponse;
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\HttpFoundation\ResponseHeaderBag;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
use Symfony\Component\Serializer\SerializerInterface;
|
||||
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
|
||||
|
||||
class SupportController extends AbstractController
|
||||
{
|
||||
// ثابتها برای مدیریت خطاها
|
||||
private const ERROR_TICKET_NOT_FOUND = ['error' => 1, 'message' => 'تیکت یافت نشد.'];
|
||||
private const ERROR_NO_FILE = ['error' => 2, 'message' => 'فایلی برای این تیکت وجود ندارد.'];
|
||||
private const ERROR_FILE_NOT_FOUND = ['error' => 3, 'message' => 'فایل در سرور یافت نشد.'];
|
||||
private const ERROR_ACCESS_DENIED = ['error' => 4, 'message' => 'شما اجازه دسترسی به این فایل را ندارید.'];
|
||||
private const ERROR_INVALID_PARAMS = ['error' => 999, 'message' => 'تمام موارد لازم را وارد کنید.'];
|
||||
|
||||
/**
|
||||
* function to generate random strings
|
||||
* @param int $length number of characters in the generated string
|
||||
* @return string a new string is created with random characters of the desired length
|
||||
* Generate a random string
|
||||
*/
|
||||
private function RandomString($length = 32)
|
||||
private function randomString(int $length = 32): string
|
||||
{
|
||||
return substr(str_shuffle(str_repeat($x = '23456789ABCDEFGHJKLMNPQRSTUVWXYZ', ceil($length / strlen($x)))), 1, $length);
|
||||
return substr(str_shuffle(str_repeat('23456789ABCDEFGHJKLMNPQRSTUVWXYZ', ceil($length / 32))), 1, $length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch ticket by ID and check ownership
|
||||
*/
|
||||
private function getTicket(EntityManagerInterface $entityManager, string $id, bool $checkOwnership = false): ?Support
|
||||
{
|
||||
$ticket = $entityManager->getRepository(Support::class)->find($id);
|
||||
if (!$ticket || ($checkOwnership && $ticket->getSubmitter() !== $this->getUser())) {
|
||||
return null;
|
||||
}
|
||||
return $ticket;
|
||||
}
|
||||
|
||||
#[Route('/api/admin/support/list', name: 'app_admin_support_list')]
|
||||
public function app_admin_support_list(Extractor $extractor, EntityManagerInterface $entityManager): JsonResponse
|
||||
{
|
||||
$items = $entityManager->getRepository(Support::class)->findBy(['main' => 0], ['id' => 'DESC']);
|
||||
$res = [];
|
||||
foreach ($items as $item) {
|
||||
$res[] = Explore::ExploreSupportTicket($item, $this->getUser());
|
||||
}
|
||||
$res = array_map(fn($item) => Explore::ExploreSupportTicket($item, $this->getUser()), $items);
|
||||
return $this->json($extractor->operationSuccess($res));
|
||||
}
|
||||
|
||||
#[Route('/api/admin/support/view/{id}', name: 'app_admin_support_view')]
|
||||
public function app_admin_support_view(Extractor $extractor, Jdate $jdate, EntityManagerInterface $entityManager, string $id = ''): JsonResponse
|
||||
public function app_admin_support_view(Extractor $extractor, EntityManagerInterface $entityManager, string $id): JsonResponse
|
||||
{
|
||||
$item = $entityManager->getRepository(Support::class)->find($id);
|
||||
if (!$item)
|
||||
$item = $this->getTicket($entityManager, $id);
|
||||
if (!$item) {
|
||||
throw $this->createNotFoundException();
|
||||
$replays = $entityManager->getRepository(Support::class)->findBy(['main' => $item->getId()]);
|
||||
$res = [];
|
||||
foreach ($replays as $replay) {
|
||||
if ($replay->getSubmitter() == $this->getUser())
|
||||
$replay->setState(1);
|
||||
else
|
||||
$replay->setState(0);
|
||||
$res[] = Explore::ExploreSupportTicket($replay, $this->getUser());
|
||||
}
|
||||
return $this->json(
|
||||
$extractor->operationSuccess([
|
||||
'item' => Explore::ExploreSupportTicket($item, $this->getUser()),
|
||||
'replays' => $res
|
||||
])
|
||||
);
|
||||
}
|
||||
#[Route('/api/admin/support/mod/{id}', name: 'app_admin_support_mod')]
|
||||
public function app_admin_support_mod(registryMGR $registryMGR, SMS $SMS, Request $request, EntityManagerInterface $entityManager, Notification $notifi, string $id = ''): JsonResponse
|
||||
{
|
||||
$params = [];
|
||||
if ($content = $request->getContent()) {
|
||||
$params = json_decode($content, true);
|
||||
}
|
||||
|
||||
$item = $entityManager->getRepository(Support::class)->find($id);
|
||||
if (!$item)
|
||||
$this->createNotFoundException();
|
||||
if (array_key_exists('body', $params)) {
|
||||
$support = new Support();
|
||||
$support->setDateSubmit(time());
|
||||
$support->setTitle('0');
|
||||
$support->setBody($params['body']);
|
||||
$support->setState('0');
|
||||
$support->setMain($item->getId());
|
||||
$support->setSubmitter($this->getUser());
|
||||
$entityManager->persist($support);
|
||||
$entityManager->flush();
|
||||
$item->setState('پاسخ داده شده');
|
||||
$entityManager->persist($support);
|
||||
$entityManager->flush();
|
||||
//send sms to customer
|
||||
if ($item->getSubmitter()->getMobile()) {
|
||||
$SMS->send(
|
||||
[$item->getId()],
|
||||
$registryMGR->get('sms', 'ticketReplay'),
|
||||
$item->getSubmitter()->getMobile()
|
||||
);
|
||||
}
|
||||
//send notification to user
|
||||
$settings = $entityManager->getRepository(Settings::class)->findAll()[0];
|
||||
$url = '/profile/support-view/' . $item->getId();
|
||||
$notifi->insert("به درخواست پشتیبانی پاسخ داده شد", $url, null, $item->getSubmitter());
|
||||
return $this->json([
|
||||
'error' => 0,
|
||||
'message' => 'successful'
|
||||
]);
|
||||
$replays = $entityManager->getRepository(Support::class)->findBy(['main' => $item->getId()]);
|
||||
$res = array_map(function ($replay) {
|
||||
$replay->setState($replay->getSubmitter() === $this->getUser() ? 1 : 0);
|
||||
return Explore::ExploreSupportTicket($replay, $this->getUser());
|
||||
}, $replays);
|
||||
|
||||
return $this->json($extractor->operationSuccess([
|
||||
'item' => Explore::ExploreSupportTicket($item, $this->getUser()),
|
||||
'replays' => $res
|
||||
]));
|
||||
}
|
||||
|
||||
#[Route('/api/admin/support/mod/{id}', name: 'app_admin_support_mod')]
|
||||
public function app_admin_support_mod(registryMGR $registryMGR, SMS $SMS, Request $request, EntityManagerInterface $entityManager, Notification $notifi, string $id): JsonResponse
|
||||
{
|
||||
$params = $request->getPayload()->all();
|
||||
$item = $this->getTicket($entityManager, $id);
|
||||
if (!$item) {
|
||||
throw $this->createNotFoundException();
|
||||
}
|
||||
|
||||
if (!isset($params['body'])) {
|
||||
return $this->json(self::ERROR_INVALID_PARAMS);
|
||||
}
|
||||
|
||||
$support = new Support();
|
||||
$support->setDateSubmit(time())
|
||||
->setTitle('0')
|
||||
->setBody($params['body'])
|
||||
->setState('0')
|
||||
->setMain($item->getId())
|
||||
->setSubmitter($this->getUser());
|
||||
|
||||
// ذخیره موقت برای گرفتن ID
|
||||
$entityManager->persist($support);
|
||||
$entityManager->flush();
|
||||
|
||||
// مدیریت فایل با متد handleFileUpload
|
||||
$fileName = $this->handleFileUpload($request, $this->getParameter('SupportFilesDir'), $support->getId());
|
||||
if ($fileName) {
|
||||
$support->setFileName($fileName);
|
||||
}
|
||||
|
||||
$entityManager->persist($support);
|
||||
$item->setState('پاسخ داده شده');
|
||||
$entityManager->persist($item);
|
||||
$entityManager->flush();
|
||||
|
||||
// بررسی سوئیچ ارسال SMS
|
||||
$sendSms = filter_var($params['sendSms'] ?? true, FILTER_VALIDATE_BOOLEAN); // پیشفرض true
|
||||
if ($sendSms && ($mobile = $item->getSubmitter()->getMobile())) {
|
||||
$SMS->send([$item->getId()], $registryMGR->get('sms', 'ticketReplay'), $mobile);
|
||||
}
|
||||
|
||||
$settings = $entityManager->getRepository(Settings::class)->findAll()[0];
|
||||
$notifi->insert("به درخواست پشتیبانی پاسخ داده شد", "/profile/support-view/{$item->getId()}", null, $item->getSubmitter());
|
||||
|
||||
return $this->json([
|
||||
'error' => 999,
|
||||
'message' => 'تمام موارد لازم را وارد کنید.'
|
||||
'error' => 0,
|
||||
'message' => 'successful',
|
||||
'file' => $fileName
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle file upload and return filename
|
||||
*/
|
||||
private function handleFileUpload(Request $request, string $uploadDirectory, int $ticketId): ?string
|
||||
{
|
||||
if (!file_exists($uploadDirectory)) {
|
||||
mkdir($uploadDirectory, 0777, true);
|
||||
}
|
||||
|
||||
$files = $request->files->get('files');
|
||||
if ($files && !empty($files)) {
|
||||
$file = $files[0]; // فقط اولین فایل
|
||||
$extension = $file->getClientOriginalExtension();
|
||||
$fileName = $ticketId . '.' . $extension;
|
||||
$file->move($uploadDirectory, $fileName);
|
||||
return $fileName;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
#[Route('/api/support/list', name: 'app_support_list')]
|
||||
public function app_support_list(Jdate $jdate, EntityManagerInterface $entityManager): JsonResponse
|
||||
{
|
||||
$items = $entityManager->getRepository(Support::class)->findBy(
|
||||
[
|
||||
'submitter' => $this->getUser(),
|
||||
'main' => 0
|
||||
],
|
||||
[
|
||||
'id' => 'DESC'
|
||||
]
|
||||
['submitter' => $this->getUser(), 'main' => 0],
|
||||
['id' => 'DESC']
|
||||
);
|
||||
|
||||
foreach ($items as $item) {
|
||||
$item->setDateSubmit($jdate->jdate('Y/n/d', $item->getDateSubmit()));
|
||||
}
|
||||
|
||||
return $this->json($items);
|
||||
}
|
||||
|
||||
#[Route('/api/support/mod/{id}', name: 'app_support_mod')]
|
||||
public function app_support_mod(registryMGR $registryMGR, SMS $SMS, Request $request, EntityManagerInterface $entityManager, string $id = ''): JsonResponse
|
||||
{
|
||||
$params = [];
|
||||
if ($content = $request->getContent()) {
|
||||
$params = json_decode($content, true);
|
||||
$params = $request->getPayload()->all();
|
||||
$uploadDirectory = $this->getParameter('SupportFilesDir');
|
||||
if (!file_exists($uploadDirectory)) {
|
||||
mkdir($uploadDirectory, 0777, true);
|
||||
}
|
||||
if ($id == '') {
|
||||
if (array_key_exists('title', $params) && array_key_exists('body', $params)) {
|
||||
$item = new Support();
|
||||
$item->setBody($params['body']);
|
||||
$item->setTitle($params['title']);
|
||||
$item->setDateSubmit(time());
|
||||
$item->setSubmitter($this->getUser());
|
||||
$item->setMain(0);
|
||||
$item->setCode($this->RandomString(8));
|
||||
$item->setState('در حال پیگیری');
|
||||
$entityManager->persist($item);
|
||||
$entityManager->flush();
|
||||
//send sms to manager
|
||||
$SMS->send(
|
||||
[$item->getId()],
|
||||
$registryMGR->get('sms', 'ticketRec'),
|
||||
$registryMGR->get('ticket', 'managerMobile')
|
||||
);
|
||||
|
||||
return $this->json([
|
||||
'error' => 0,
|
||||
'message' => 'ok',
|
||||
'url' => $item->getId()
|
||||
]);
|
||||
if ($id === '') {
|
||||
if (!isset($params['title'], $params['body'])) {
|
||||
return $this->json(self::ERROR_INVALID_PARAMS);
|
||||
}
|
||||
} else {
|
||||
if (array_key_exists('body', $params)) {
|
||||
$item = new Support();
|
||||
$upper = $entityManager->getRepository(Support::class)->find($id);
|
||||
if ($upper)
|
||||
$item->setMain($upper->getid());
|
||||
|
||||
$item->setBody($params['body']);
|
||||
$item->setTitle($upper->getTitle());
|
||||
$item->setDateSubmit(time());
|
||||
$item->setSubmitter($this->getUser());
|
||||
$item->setState('در حال پیگیری');
|
||||
$entityManager->persist($item);
|
||||
$entityManager->flush();
|
||||
$upper->setState('در حال پیگیری');
|
||||
$entityManager->persist($upper);
|
||||
$entityManager->flush();
|
||||
//send sms to manager
|
||||
$SMS->send(
|
||||
[$item->getId()],
|
||||
$registryMGR->get('sms', 'ticketRec'),
|
||||
$registryMGR->get('ticket', 'managerMobile')
|
||||
);
|
||||
return $this->json([
|
||||
'error' => 0,
|
||||
'message' => 'ok',
|
||||
'url' => $item->getId()
|
||||
]);
|
||||
$item = new Support();
|
||||
$item->setBody($params['body'])
|
||||
->setTitle($params['title'])
|
||||
->setDateSubmit(time())
|
||||
->setSubmitter($this->getUser())
|
||||
->setMain(0)
|
||||
->setCode($this->randomString(8))
|
||||
->setState('در حال پیگیری');
|
||||
|
||||
$entityManager->persist($item);
|
||||
$entityManager->flush();
|
||||
|
||||
$fileName = $this->handleFileUpload($request, $uploadDirectory, $item->getId());
|
||||
if ($fileName) {
|
||||
$item->setFileName($fileName);
|
||||
}
|
||||
|
||||
$entityManager->persist($item);
|
||||
$entityManager->flush();
|
||||
|
||||
$SMS->send([$item->getId()], $registryMGR->get('sms', 'ticketRec'), $registryMGR->get('ticket', 'managerMobile'));
|
||||
|
||||
return $this->json([
|
||||
'error' => 0,
|
||||
'message' => 'ok',
|
||||
'url' => $item->getId(),
|
||||
'files' => $fileName
|
||||
]);
|
||||
}
|
||||
|
||||
if (!isset($params['body'])) {
|
||||
return $this->json(self::ERROR_INVALID_PARAMS);
|
||||
}
|
||||
|
||||
$upper = $this->getTicket($entityManager, $id);
|
||||
if (!$upper) {
|
||||
return $this->json(self::ERROR_TICKET_NOT_FOUND);
|
||||
}
|
||||
|
||||
$item = new Support();
|
||||
$item->setMain($upper->getId())
|
||||
->setBody($params['body'])
|
||||
->setTitle($upper->getTitle())
|
||||
->setDateSubmit(time())
|
||||
->setSubmitter($this->getUser())
|
||||
->setState('در حال پیگیری');
|
||||
|
||||
$entityManager->persist($item);
|
||||
$entityManager->flush();
|
||||
|
||||
$fileName = $this->handleFileUpload($request, $uploadDirectory, $item->getId());
|
||||
if ($fileName) {
|
||||
$item->setFileName($fileName);
|
||||
}
|
||||
|
||||
$entityManager->persist($item);
|
||||
$upper->setState('در حال پیگیری');
|
||||
$entityManager->persist($upper);
|
||||
$entityManager->flush();
|
||||
|
||||
$SMS->send([$item->getId()], $registryMGR->get('sms', 'ticketRec'), $registryMGR->get('ticket', 'managerMobile'));
|
||||
|
||||
return $this->json([
|
||||
'error' => 999,
|
||||
'message' => 'تمام موارد لازم را وارد کنید.'
|
||||
'error' => 0,
|
||||
'message' => 'ok',
|
||||
'url' => $item->getId(),
|
||||
'files' => $fileName
|
||||
]);
|
||||
}
|
||||
|
||||
#[Route('/api/support/view/{id}', name: 'app_support_view')]
|
||||
public function app_support_view(Jdate $jdate, EntityManagerInterface $entityManager, string $id = ''): JsonResponse
|
||||
public function app_support_view(EntityManagerInterface $entityManager, string $id): JsonResponse
|
||||
{
|
||||
$item = $entityManager->getRepository(Support::class)->find($id);
|
||||
if (!$item)
|
||||
throw $this->createNotFoundException();
|
||||
if ($item->getSubmitter() != $this->getUser())
|
||||
$item = $this->getTicket($entityManager, $id, true);
|
||||
if (!$item) {
|
||||
throw $this->createAccessDeniedException();
|
||||
$replays = $entityManager->getRepository(Support::class)->findBy(['main' => $item->getId()]);
|
||||
$replaysArray = [];
|
||||
foreach ($replays as $replay) {
|
||||
$replaysArray[] = Explore::ExploreSupportTicket($replay, $this->getUser());
|
||||
}
|
||||
|
||||
$replays = $entityManager->getRepository(Support::class)->findBy(['main' => $item->getId()]);
|
||||
$replaysArray = array_map(fn($replay) => Explore::ExploreSupportTicket($replay, $this->getUser()), $replays);
|
||||
|
||||
return $this->json([
|
||||
'item' => Explore::ExploreSupportTicket($item, $this->getUser()),
|
||||
'replays' => $replaysArray
|
||||
]);
|
||||
}
|
||||
|
||||
#[Route('/api/support/download/file/{id}', name: 'app_support_download_file')]
|
||||
public function app_support_download_file(EntityManagerInterface $entityManager, string $id): Response
|
||||
{
|
||||
$ticket = $this->getTicket($entityManager, $id);
|
||||
if (!$ticket) {
|
||||
return $this->json(self::ERROR_TICKET_NOT_FOUND, 404);
|
||||
}
|
||||
|
||||
$currentUser = $this->getUser();
|
||||
if (!$currentUser || (!$this->isGranted('ROLE_ADMIN') && $ticket->getSubmitter() !== $currentUser)) {
|
||||
return $this->json(self::ERROR_ACCESS_DENIED, 403);
|
||||
}
|
||||
|
||||
$fileName = $ticket->getFileName();
|
||||
if (!$fileName) {
|
||||
return $this->json(self::ERROR_NO_FILE, 404);
|
||||
}
|
||||
|
||||
$filePath = $this->getParameter('SupportFilesDir') . '/' . $fileName;
|
||||
if (!file_exists($filePath)) {
|
||||
return $this->json(self::ERROR_FILE_NOT_FOUND, 404);
|
||||
}
|
||||
|
||||
return new BinaryFileResponse($filePath, 200, [
|
||||
'Content-Disposition' => ResponseHeaderBag::DISPOSITION_ATTACHMENT . '; filename="' . $fileName . '"'
|
||||
]);
|
||||
}
|
||||
}
|
|
@ -38,6 +38,9 @@ class Support
|
|||
#[ORM\Column(length: 255, nullable: true)]
|
||||
private ?string $code = null;
|
||||
|
||||
#[ORM\Column(length: 255, nullable: true)]
|
||||
private ?string $fileName = null;
|
||||
|
||||
public function getId(): ?int
|
||||
{
|
||||
return $this->id;
|
||||
|
@ -126,4 +129,16 @@ class Support
|
|||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getFileName(): ?string
|
||||
{
|
||||
return $this->fileName;
|
||||
}
|
||||
|
||||
public function setFileName(?string $fileName): static
|
||||
{
|
||||
$this->fileName = $fileName;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -564,6 +564,7 @@ class Explore
|
|||
$res['submitter'] = self::ExploreUser($support->getSubmitter());
|
||||
$res['main'] = $support->getMain();
|
||||
$res['owner'] = true;
|
||||
$res['fileName'] = $support->getFileName();
|
||||
if ($user->getId() != $support->getSubmitter()->getId()) {
|
||||
$res['owner'] = false;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue