<?php
/**
* Created by PhpStorm.
* User: SUSAN MEDINA
* Date: 21/03/2019
* Time: 12:34 PM
*/
namespace App\EventSubscriber\Task;
use ApiPlatform\Core\EventListener\EventPriorities;
use App\Entity\App\Task\TaskStatusLog;
use App\Entity\App\Task\WorkerBudget;
use App\Entity\App\Ticket\Ticket;
use App\Entity\App\User;
use App\Services\VendorService;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\Event\ViewEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\Validator\Validator\ValidatorInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Form\FormFactoryInterface;
use Symfony\Contracts\Translation\TranslatorInterface;
use App\Exception\InvalidArgumentException;
use App\Exception\NotFoundException;
use App\Repository\App\MaintenanceElementRepository;
use App\Repository\App\VendorStaffRepository;
use App\Repository\App\MediaObjectRepository;
use App\Repository\App\ResourceRepository;
use App\Repository\App\RoleRepository;
use App\Repository\App\ScheduleRepository;
use App\Repository\App\Task\WorkerBudgetRepository;
use App\Entity\App\Task\Task;
use App\Entity\App\Role;
use App\Entity\App\VendorStaff;
use App\Entity\App\MediaObject;
use App\Entity\App\ResourceAndTool;
use App\Entity\App\Category;
use App\Services\UtilsService;
class TaskPostValidateSubscriber implements EventSubscriberInterface
{
private $translator;
private $tokenStorage;
private $factory;
private $validator;
private $request;
private $roleRepository;
private $vendorStaffRepository;
private $mediaObjectRepository;
private $elementRepository;
private $resourceRepository;
private $scheduleRepository;
private $workerBudgetRepository;
private $utilsService;
private $vendorService;
private $locale;
public function __construct(
TranslatorInterface $translator,
FormFactoryInterface $factory,
ValidatorInterface $validator,
RoleRepository $roleRepository,
VendorStaffRepository $vendorStaffRepository,
MediaObjectRepository $mediaObjectRepository,
MaintenanceElementRepository $elementRepository,
WorkerBudgetRepository $workerBudgetRepository,
ResourceRepository $resourceRepository,
ScheduleRepository $scheduleRepository,
TokenStorageInterface $tokenStorage,
UtilsService $utilsService,
VendorService $vendorService
){
$this->translator = $translator;
$this->tokenStorage = $tokenStorage;
$this->factory = $factory;
$this->validator = $validator;
$this->roleRepository = $roleRepository;
$this->vendorStaffRepository = $vendorStaffRepository;
$this->mediaObjectRepository = $mediaObjectRepository;
$this->elementRepository = $elementRepository;
$this->resourceRepository = $resourceRepository;
$this->scheduleRepository = $scheduleRepository;
$this->workerBudgetRepository = $workerBudgetRepository;
$this->utilsService = $utilsService;
$this->vendorService = $vendorService;
}
/**
* @param ViewEvent $event
* @throws \Exception
*/
public function onKernelView(ViewEvent $event)
{
if ($this->utilsService->isAPublicRequest($event)) {
return;
}
$task = $event->getControllerResult();
$this->request = $event->getRequest();
$method = $this->request->getMethod();
$this->locale = $this->request->getLocale();
if (!($task instanceof Task) ||
(Request::METHOD_POST !== $method && Request::METHOD_PUT !== $method)
) {
return;
}
$content = $this->request->getContent();
$params = json_decode($content, true);
$this->validateRequiredFields($task, $params, $event, $method);
return;
}
/**
* @param Task $task
* @param array $params
* @param ViewEvent $event
* @param string $method
* @throws InvalidArgumentException
* @throws NotFoundException
*/
protected function validateRequiredFields(Task $task, array $params, ViewEvent $event, string $method)
{
$ticket = $task->getTicket();
$vendor = $ticket->getVendor();
$locale = $this->locale;
if ($task->getCategory() && $task->getCategory()->getVendor() !== $vendor) {
$this->response(
$event,
$this->translator->trans('vendor.validate.does_not_belongs',
[
'%entity%' => $this->translator->trans('category.title', [], null, $locale),
'%vendorName%' => $vendor->getName()
]
));
}
if ($task->getCategory() && $task->getCategory()->getType() !== Category::TYPE_TASK) {
$this->response(
$event,
$this->translator->trans(
'category.validate.type_not_allowed',
[
'%type%' => $task->getCategory()->getType(),
'%typeAllowed%' => Category::TYPE_TASK
],
null,
$locale
)
);
}
if ($task->getLocation() && $task->getLocation()->getVendor() !== $vendor) {
$this->response(
$event,
$this->translator->trans(
'vendor.validate.does_not_belongs',
[
'%entity%' => $this->translator->trans('location.title'),
'%vendorName%' => $vendor->getName()
],
null,
$locale
)
);
}
if ($task->getDateStart() && $task->getDateEnd()) {
$dateStart = $task->getDateStart()->format('Y-m-d');
$dateEnd = $task->getDateEnd()->format('Y-m-d');
if ($dateStart > $dateEnd) {
$this->response(
$event,
$this->translator->trans(
'general.validate.date_must_be_greater',
[
'%field%' => 'dateEnd',
'%dateCompare%' => 'dateStart'
],
null,
$locale
)
);
}
}
$authorizationManager = false;
$userCurrent = $this->tokenStorage->getToken()->getUser();
if($userCurrent instanceof User) {
$locale = $userCurrent->getLocale();
$vendor = $task->getTicket()->getVendor();
if ($this->vendorService->isUserRoleInToVendor(
$vendor,
$userCurrent,
[Role::ROLE_ADMIN, Role::ROLE_TASKMASTER]
)) {
$authorizationManager = true;
}
}
if ($authorizationManager && isset($params['workerBudgets']) && is_array($params['workerBudgets'])) {
$roleOperator = $this->roleRepository->findOneBy(['name' => Role::ROLE_OPERATOR]);
if ($method === Request::METHOD_PUT) {
$getWorkerBudgets = $this->workerBudgetRepository->findByTask($task);
} else {
$getWorkerBudgets = [];
}
$workerBudgetArray = [];
foreach ($params['workerBudgets'] as &$wb) {
if (isset($wb['role']) && $wb['role'] === $roleOperator->getId()) {
$workerBudgetArray[] = [
'role' => $wb['role'],
'vendorStaff' => $wb['vendorStaff']
];
}
}
foreach ($getWorkerBudgets as $workerBudget) {
if ($workerBudget instanceof WorkerBudget) {
$workerBudgetFormat = [
'role' => $workerBudget->getRole()->getId(),
'vendorStaff' => $workerBudget->getVendorStaff()->getId()
];
if ($workerBudget->getRole() === $roleOperator &&
!in_array($workerBudgetFormat, $workerBudgetArray)
) {
if ($ticket->getType()->getStage() === Ticket::STAGE_WORK_ORDER &&
$workerBudget->getTaskStatusLogs()->last() &&
!in_array(
$workerBudget->getTaskStatusLogs()->last()->getState(),
[
TaskStatusLog::STATUS_TASK_IN_PROCESS,
TaskStatusLog::STATUS_TASK_CANCELLED
]
)) {
$this->response(
$event,
$this->translator->trans(
'operator has already started their task',
[
'%user%' => $workerBudget->getVendorStaff()->getUser()->getFullName()
],
null,
$locale
)
);
}
}
}
}
foreach ($params['workerBudgets'] as $workerBudgetRequest) {
if (isset($workerBudgetRequest['role'])) {
$role = $this->roleRepository->find($workerBudgetRequest['role']);
if (!$role instanceof Role) {
$this->response(
$event,
$this->translator->trans(
'general.validate.not_exists',
[
'%entityName%' => $this->translator->trans('role.title', [], null, $locale),
'%entityId%' => $workerBudgetRequest['role']
],
null,
$locale
),
Response::HTTP_NOT_FOUND
);
}
$vendorStaff = $this->vendorStaffRepository->find($workerBudgetRequest['vendorStaff']);
if (!$vendorStaff instanceof VendorStaff) {
throw new NotFoundException(
$this->translator->trans(
'general.validate.not_exists',
[
'%entityName%' => 'vendorStaff',
'%entityId%' => $workerBudgetRequest['vendorStaff']
]
)
);
}
if ($vendorStaff->getVendor() !== $vendor) {
throw new InvalidArgumentException(
$this->translator->trans(
'vendor.validate.does_not_belongs',
[
'%entity%' => 'vendorStaff '.$vendorStaff->getId(),
'%vendorName%' => $vendor->getName()
]
)
);
}
if (!in_array($role, $vendorStaff->getRoles())) {
throw new InvalidArgumentException(
$this->translator->trans(
'user with vendorStaff, has not been assigned the role',
[
'%user%' => $vendorStaff->getUser()->getFullName(),
'%vendorStaff%' => $workerBudgetRequest['vendorStaff'],
'%role%' => $this->translator->trans($role->getName())
]
)
);
}
}
}
}
if($authorizationManager && isset($params['mediaContent']) &&
is_array($params['mediaContent']) &&
count($params['mediaContent']) > 0
){
foreach ($task->getMediaContent() as $mediaId){
$media = $this->mediaObjectRepository->find($mediaId);
if (!$media instanceof MediaObject) {
$this->response(
$event,
$this->translator->trans(
'general.validate.not_exists',
[
'%entityName%' => $this->translator->trans('mediaObject.name'),
'%entityId%' => $mediaId
]
),
Response::HTTP_NOT_FOUND
);
}
if ($media->getTask() !== null && $media->getTask() !== $task) {
$this->response(
$event,
$this->translator->trans(
'mediaObject.validate.does_not_belongs',
[
'%mediaId%' => $mediaId,
'%entity%' => $this->translator->trans('task.name')
],
null,
$locale
)
);
}
if ($media->getType() !== MediaObject::TYPE_TASK) {
$this->response(
$event,
$this->translator->trans(
'mediaObject.validate.type_not_allowed',
[
'%mediaId%' => $mediaId,
'%mediaType%' => $media->getType(),
'%mediaTypeAvailable%' => MediaObject::TYPE_TASK
],
null,
$locale
)
);
}
}
}
if(isset($params['maintenanceElements']) &&
is_array($params['maintenanceElements']) &&
count($params['maintenanceElements']) > 0
){
foreach ($params['maintenanceElements'] as $field) {
if (isset($field['id'])) {
$maintenanceElement = $this->elementRepository->find($field['id']);
if ($maintenanceElement->getVendor() !== $vendor) {
$this->response(
$event,
$this->translator->trans(
'vendor.validate.does_not_belongs',
[
'%entity%' => $this->translator->trans('maintenanceElement.title'),
'%vendorName%' => $vendor->getName()
],
null,
$locale
)
);
}
}
}
}
if(isset($params['resources']) &&
is_array($params['resources']) &&
count($params['resources']) > 0
){
foreach ($params['resources'] as $field) {
if (isset($field['id'])) {
$resource = $this->resourceRepository->find($field['id']);
if (!$resource instanceof ResourceAndTool) {
$this->response(
$event,
$this->translator->trans('general.validate.not_exists',
[
'%entityName%' => $this->translator->trans('resource.title'),
'%entityId%' => $field['id']
],
null,
$locale
),
Response::HTTP_NOT_FOUND
);
}
if ($resource->getVendor() !== $vendor) {
$this->response(
$event,
$this->translator->trans('vendor.validate.does_not_belongs',
[
'%entity%' => $this->translator->trans('resource.title'),
'%vendorName%' => $vendor->getName()
],
null,
$locale
)
);
}
}
if (!isset($field['quantity'])) {
$this->response(
$event,
$this->translator->trans(
'field required in entity',
[
'%field%' => 'quantity',
'%entityId%' => $field['id'],
'%entity%' => 'resources'
],
null,
$locale
)
);
}
if (!is_numeric($field['quantity'])) {
$this->response(
$event,
$this->translator->trans(
'field is numeric in entity',
[
'%field%' => 'quantity',
'%entityId%' => $field['id'],
'%entity%' => 'resources'
],
null,
$locale
)
);
}
}
}
}
/**
* @param ViewEvent $event
* @param $message
* @param int $code
*/
protected function response(ViewEvent $event, $message, $code = Response::HTTP_NOT_ACCEPTABLE)
{
$response = new Response();
$response->setContent(json_encode(['detail' => $message]));
$response->setStatusCode($code);
$event->setResponse($response);
return;
}
public static function getSubscribedEvents()
{
return [
KernelEvents::VIEW => ['onKernelView', EventPriorities::POST_VALIDATE]
];
}
}