<?php
namespace App\EventSubscriber\User;
use App\Exception\NotFoundException;
use Symfony\Contracts\Translation\TranslatorInterface;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
use Symfony\Component\HttpKernel\Event\ViewEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use ApiPlatform\Core\EventListener\EventPriorities;
use Symfony\Component\Validator\Validator\ValidatorInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\Form\FormFactoryInterface;
use App\Repository\App\VendorRepository;
use App\Repository\App\ScheduleRepository;
use App\Repository\App\RoleRepository;
use App\Repository\App\LocationRepository;
use App\Repository\App\CompanyRepository;
use App\Repository\App\UserRepository;
use App\Repository\App\CategoryRepository;
use App\Repository\App\Task\WorkerBudgetRepository;
use App\Entity\App\Category;
use App\Exception\InvalidArgumentException;
use App\Exception\UserException;
use App\Services\VendorService;
use App\Services\UserService;
use App\Entity\App\User;
use App\Entity\App\Role;
use App\Entity\App\Schedule;
use App\Entity\App\Location;
use App\Entity\App\Company;
use App\Form\ScheduleType;
final class UserPostValidateSubscriber implements EventSubscriberInterface
{
private $tokenStorage;
private $authorizationChecker;
private $factory;
private $validator;
private $userService;
private $vendorService;
private $roleRepository;
private $vendorRepository;
private $scheduleRepository;
private $locationRepository;
private $companyRepository;
private $categoryRepository;
private $userRepository;
private $workerBudgetRepository;
private $translator;
public function __construct(
TokenStorageInterface $tokenStorage,
AuthorizationCheckerInterface $checker,
FormFactoryInterface $factory,
ValidatorInterface $validator,
UserService $userService,
VendorService $vendorService,
VendorRepository $vendorRepository,
RoleRepository $roleRepository,
ScheduleRepository $scheduleRepository,
LocationRepository $locationRepository,
CompanyRepository $companyRepository,
CategoryRepository $categoryRepository,
UserRepository $userRepository,
WorkerBudgetRepository $workerBudgetRepository,
TranslatorInterface $translator
) {
$this->tokenStorage = $tokenStorage;
$this->authorizationChecker = $checker;
$this->factory = $factory;
$this->validator = $validator;
$this->userService = $userService;
$this->vendorService = $vendorService;
$this->roleRepository = $roleRepository;
$this->vendorRepository = $vendorRepository;
$this->scheduleRepository = $scheduleRepository;
$this->locationRepository = $locationRepository;
$this->companyRepository = $companyRepository;
$this->categoryRepository = $categoryRepository;
$this->userRepository = $userRepository;
$this->workerBudgetRepository = $workerBudgetRepository;
$this->translator = $translator;
}
/**
* {@inheritdoc}
*/
public static function getSubscribedEvents() {
return [
KernelEvents::VIEW => ['prepareUserData', EventPriorities::POST_VALIDATE]
];
}
/**
* @param ViewEvent $event
* @throws InvalidArgumentException
* @throws NotFoundException
* @throws UserException
*/
public function prepareUserData(ViewEvent $event) {
$user = $event->getControllerResult();
$method = $event->getRequest()->getMethod();
$request = $event->getRequest();
if (!($user instanceof User) ||
(Request::METHOD_POST !== $method && Request::METHOD_PUT !== $method))
return;
$mediaContent = $user->getMediaContent();
if ($mediaContent !== null && $mediaContent !== 0)
$this->userService->addMediaContent($user, $mediaContent);
$content = $request->getContent();
$data = json_decode($content, true);
$vendor = null;
if (isset($data['vendor'])) {
$vendor = $this->vendorRepository->find($data['vendor']);
}
if ($vendor && isset($data['company']) && !is_null($data['company'])) {
$company = $this->companyRepository->find($data['company']);
if (!$company instanceof Company) {
throw new UserException(
$this->translator->trans(
'entity not found',
['%entity%' => 'company', '%entityId%' => $data['company']]
)
);
}
if ($company->getVendor() !== $vendor) {
throw new InvalidArgumentException(
$this->translator->trans('vendor.validate.does_not_belongs',
[
'%entity%' => $this->translator->trans('company'),
'%vendorName%' => $vendor->getName()
]
)
);
}
}
if (isset($data['email']) && isset($data['phoneNumber']) && empty($user->getEmail()) && empty($user->getPhoneNumber())) {
throw new InvalidArgumentException(
$this->translator->trans(
'field not must be null',
['%field%' => 'email & phoneNumber']
)
);
}
$this->userRepository->disableSoftDeleteable();
if (isset($data['phoneNumber']) && !is_null($data['phoneNumber'])) {
$phone = $data['phoneNumber'];
if (isset($data['phonePrefix']) && !is_null($data['phonePrefix'])) {
$phone = str_replace([' ', '+', '-', '(', ')', '-'], '', $data['phonePrefix'].$data['phoneNumber']);
}
$getUser = $this->userRepository->findOneBy(['username' => $phone]);
if ($getUser instanceof User && $user !== $getUser) {
throw new UserException(
$this->translator->trans(
'field already taken with value',
[
'%field1%' => 'phoneNumber',
'%field2%' => 'username',
'%value%' => $data['phoneNumber']
]
)
);
}
$getUser = $this->userRepository->findOneBy(['email' => $phone]);
if ($getUser instanceof User && $user !== $getUser) {
throw new UserException(
$this->translator->trans(
'field already taken with value',
[
'%field1%' => 'phoneNumber',
'%field2%' => 'email',
'%value%' => $data['phoneNumber']
]
)
);
}
}
if (isset($data['email']) && !is_null($data['email'])) {
$getUser = $this->userRepository->findOneBy(['username' => $data['email']]);
if ($getUser instanceof User && $user !== $getUser) {
throw new UserException(
$this->translator->trans(
'field already taken with value',
[
'%field1%' => 'email',
'%field2%' => ' username',
'%value%' => $data['email']
]
)
);
}
$getUser = $this->userRepository->findOneBy(['phoneNumber' => $data['email']]);
if ($getUser instanceof User && $user !== $getUser) {
throw new UserException(
$this->translator->trans(
'field already taken with value',
[
'%field1%' => 'email',
'%field2%' => 'phoneNumber',
'%value%' => $data['email']
]
)
);
}
$getUser = $this->userRepository->findOneBy(['phonePrefixAndPhone' => $data['email']]);
if ($getUser instanceof User && $user !== $getUser) {
throw new UserException(
$this->translator->trans(
'field already taken with value',
[
'%field1%' => 'email',
'%field2%' => 'phonePrefixAndPhone',
'%value%' => $data['email']
]
)
);
}
}
if (isset($data['username']) && !is_null($data['username'])) {
$getUser = $this->userRepository->findOneBy(['phoneNumber' => $data['username']]);
if ($getUser instanceof User && $user !== $getUser) {
throw new UserException(
$this->translator->trans(
'field already taken with value',
[
'%field1%' => 'username',
'%field2%' => 'phoneNumber',
'%value%' => $data['username']
]
)
);
}
$getUser = $this->userRepository->findOneBy(['phonePrefixAndPhone' => $data['username']]);
if ($getUser instanceof User && $user !== $getUser) {
throw new UserException(
$this->translator->trans(
'field already taken with value',
[
'%field1%' => 'username',
'%field2%' => 'phonePrefixAndPhone',
'%value%' => $data['email']
]
)
);
}
$getUser = $this->userRepository->findOneBy(['email' => $data['username']]);
if ($getUser instanceof User && $user !== $getUser) {
throw new UserException(
$this->translator->trans(
'field already taken with value',
[
'%field1%' => 'username',
'%field2%' => 'email',
'%value%' => $data['username']
]
)
);
}
}
if ($vendor && isset($data['roles'])) {
$rolesObject = [];
$rolesName = [];
foreach ($data['roles'] as $role) {
$entityId = null;
if (is_string($role)) {
$entityId = $role;
$role = $this->roleRepository->findOneBy(['name' => $role]);
} else if(is_array($role) && isset($role['id'])) {
$entityId = $role['id'];
$role = $this->roleRepository->find($role['id']);
}
if (!$role instanceof Role) {
throw new NotFoundException(
$this->translator->trans('general.validate.not_exists',
[
'%entityName%' => $this->translator->trans('role.title'),
'%entityId%' => $entityId
]
)
);
}
if ($role->getName() == Role::ROLE_SUPERADMIN) {
throw new UserException(
$this->translator->trans('role not allowed', ['%role%' => $role->getName()])
);
}
$rolesObject[] = $role;
$rolesName[] = $role->getName();
}
if (Request::METHOD_PUT === $method) {
$vendorStaff = $this->vendorService->getVendorStaff(null, $user, $vendor);
$oldRoles = $vendorStaff->getRoles();
$roleOperator = $this->roleRepository->findOneBy(['name' => Role::ROLE_OPERATOR]);
$roleTaskmaster = $this->roleRepository->findOneBy(['name' => Role::ROLE_TASKMASTER]);
if (in_array($roleOperator, $oldRoles) &&
!in_array(Role::ROLE_OPERATOR, $rolesName)
) {
$workerBudgets = $this->workerBudgetRepository->findBy(
[
'vendorStaff' => $vendorStaff,
'role' => $roleOperator
]
);
if (count($workerBudgets) > 0) {
throw new InvalidArgumentException(
$this->translator->trans(
'user is active as an role',
[
'%role%' => $this->translator->trans(Role::ROLE_OPERATOR)
]
)
);
}
}
if (in_array($roleTaskmaster, $oldRoles) &&
!in_array(Role::ROLE_TASKMASTER, $rolesName)
) {
$workerBudgets = $this->workerBudgetRepository->findBy(
[
'vendorStaff' => $vendorStaff,
'role' => $roleTaskmaster
]
);
if (count($workerBudgets) > 0) {
throw new InvalidArgumentException(
$this->translator->trans(
'user is active as an role',
[
'%role%' => $this->translator->trans(Role::ROLE_TASKMASTER)
]
)
);
}
}
}
} else {
if (Request::METHOD_POST === $method) {
throw new InvalidArgumentException(
$this->translator->trans('role.field_validate.required')
);
}
}
if ($vendor && isset($data['locations'])) {
foreach ($data['locations'] as $locationId) {
$location = $this->locationRepository->find($locationId);
if (!$location instanceof Location) {
throw new NotFoundException(
$this->translator->trans('general.validate.not_exists',
[
'%entityName%' => $this->translator->trans('location.title'),
'%entityId%' => $locationId
]
)
);
}
if ($location->getVendor() !== $vendor) {
throw new InvalidArgumentException(
$this->translator->trans('vendor.validate.does_not_belongs',
[
'%entity%' => $this->translator->trans('location.title'),
'%vendorName%' => $vendor->getName()
]
)
);
}
}
}
if ($vendor && isset($data['categories'])) {
foreach ($data['categories'] as $categoryId) {
$category = $this->categoryRepository->find($categoryId);
if (!$category instanceof Category) {
throw new NotFoundException(
$this->translator->trans('general.validate.not_exists',
[
'%entityName%' => $this->translator->trans('category.title'),
'%entityId%' => $categoryId
]
)
);
}
if ($category->getVendor() !== $vendor) {
throw new InvalidArgumentException(
$this->translator->trans('vendor.validate.does_not_belongs',
[
'%entity%' => $this->translator->trans('category.title'),
'%vendorName%' => $vendor->getName()
]
)
);
}
if ($category->getType() !== Category::TYPE_USER) {
throw new InvalidArgumentException(
$this->translator->trans('category.validate.type_not_allowed',
[
'%type%' => $category->getType(),
'%typeAllowed%' => Category::TYPE_USER
]
)
);
}
}
}
if ($vendor && isset($data['costPerHour'])) {
if (is_null($data['costPerHour'])) {
throw new InvalidArgumentException(
$this->translator->trans(
'field not must be null',
['%field%' => 'costPerHour']
)
);
}
if (!is_numeric($data['costPerHour'])) {
throw new InvalidArgumentException(
$this->translator->trans(
'field must be numeric',
['%field%' => 'costPerHour']
)
);
}
}
/*
if ($vendor && isset($data['schedules']) && is_array($data['schedules'])) {
foreach ($data['schedules'] as $scheduleRequest) {
$schedule = new Schedule();
$form = $this->factory->create(ScheduleType::class, $schedule);
$request->request->replace($scheduleRequest);
$form->handleRequest($request);
if($form->isSubmitted() && !$form->isValid())
throw new ValidationException($this->validator->validate($schedule));
if (isset($scheduleRequest['id']) && is_integer($scheduleRequest['id'])) {
$getSchedule = $this->scheduleRepository->find($scheduleRequest['id']);
if ($getSchedule == null) {
throw new UserException(
$this->translator->trans(
'entity not found',
[
'%entity%' => $this->translator->trans('schedule'),
'%entityId%' => $scheduleRequest['id']
]
)
);
}
$vendorStaff = $this->vendorService->findOrCreateVendorStaff($vendor, $user);
if ($getSchedule->getVendorStaff() !== $vendorStaff) {
throw new InvalidArgumentException(
$this->translator->trans(
'entity does not belong to the user',
[
'%entity%' => $this->translator->trans('schedule'),
'%entityId%' => $scheduleRequest['id']
]
)
);
}
}
}
}
*/
}
}