<?php
namespace App\Security\Athena;
use App\Entity\Apollon\BTag;
use App\Entity\Apollon\EditorialContent;
use App\Entity\Apollon\NewsBlog;
use App\Entity\Apollon\NewsBlogCategory;
use App\Entity\Apollon\TipSheet;
use App\Entity\Apollon\Website;
use App\Entity\Apollon\WebsiteInstance;
use App\Entity\Apollon\WebsitePage;
use App\Entity\Apollon\WebsiteTemplate;
use App\Entity\Asclepios\Audit;
use App\Entity\Asclepios\Clinic;
use App\Entity\Asclepios\ClinicEmployee;
use App\Entity\Asclepios\ClinicEmployeeClinic;
use App\Entity\Asclepios\Customer;
use App\Entity\Asclepios\Holiday;
use App\Entity\Asclepios\Order;
use App\Entity\Asclepios\Price;
use App\Entity\Asclepios\PriceCategory;
use App\Entity\Asclepios\PricePlan;
use App\Entity\Asclepios\Service;
use App\Entity\Asclepios\Subscription;
use App\Entity\Asclepios\VetNews;
use App\Entity\Athena\User;
use App\Service\Asclepios\ClinicService;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Authorization\Voter\Voter;
use Symfony\Component\Security\Core\Security;
class GlobalVoter extends Voter
{
private ClinicService $clinicService;
private EntityManagerInterface $entityManager;
private Security $security;
public function __construct(EntityManagerInterface $entityManager, Security $security, ClinicService $clinicService)
{
$this->clinicService = $clinicService;
$this->entityManager = $entityManager;
$this->security = $security;
}
protected function supports(string $attribute, $subject): bool
{
if ($attribute !== 'ACCESS') {
return false;
}
if (!in_array(get_class($subject), [
Audit::class,
BTag::class,
Clinic::class,
ClinicEmployee::class,
Customer::class,
EditorialContent::class,
Holiday::class,
NewsBlog::class,
Order::class,
Price::class,
PricePlan::class,
Service::class,
Subscription::class,
Website::class,
WebsitePage::class,
])) {
return false;
}
return true;
}
protected function voteOnAttribute(string $attribute, $subject, TokenInterface $token): bool
{
$user = $token->getUser();
if (!$user instanceof User) {
return false;
}
if ($this->security->isGranted('ROLE_SALESMAN')) {
return true;
}
if (
$this->security->isGranted('ROLE_LABO') &&
get_class($subject) === BTag::class
) {
while ($subject->getParent()) {
$subject = $subject->getParent();
}
if (($vetNews = $this->entityManager->getRepository(VetNews::class)->findOneByContent($subject)) &&
$vetNews->getAuthor() === $this->security->getUser()
) {
return true;
}
}
if (
$this->security->isGranted('ROLE_WRITER') &&
get_class($subject) === NewsBlog::class &&
$subject->getUser() === $user
) {
return true;
}
if (
$this->security->isGranted('ROLE_WRITER') &&
get_class($subject) === BTag::class
) {
while ($subject->getParent()) {
$subject = $subject->getParent();
}
if (($newsBlog = $this->entityManager->getRepository(NewsBlog::class)->findOneByContent($subject)) &&
$newsBlog->getUser() === $user
) {
return true;
}
}
if ($clinics = $this->getClinicBySubject($subject)) {
foreach ($clinics as $clinic) {
foreach ($this->entityManager->getRepository(ClinicEmployeeClinic::class)->findByClinic($clinic) as $employee) {
if ($employee->getClinicEmployee()?->getUser()?->getId() == $user->getId()) {
return true;
}
}
foreach ($user->getFranchise()?->getClinics() ?? [] as $franchisedClinic) {
if ($clinic->getId() === $franchisedClinic->getId()) {
return true;
}
}
}
}
return false;
}
private function getClinicBySubject($subject): array
{
$result = [];
switch (get_class($subject)) {
case BTag::class:
while ($subject->getParent()) {
$subject = $subject->getParent();
}
if (
(
($template = $this->entityManager->getRepository(WebsiteTemplate::class)->findOneByHeader($subject)) ||
($template = $this->entityManager->getRepository(WebsiteTemplate::class)->findOneByMain($subject)) ||
($template = $this->entityManager->getRepository(WebsiteTemplate::class)->findOneByAside($subject)) ||
($template = $this->entityManager->getRepository(WebsiteTemplate::class)->findOneByFooter($subject))
) &&
($website = $this->entityManager->getRepository(Website::class)->findOneByTemplate($template)) &&
$website->getClinic()
) {
$result[] = $website->getClinic();
}
if (
($newsBlog = $this->entityManager->getRepository(NewsBlog::class)->findOneByContent($subject)) &&
$newsBlog->getClinic()
) {
$result[] = $newsBlog->getClinic();
}
if (
($tipSheet = $this->entityManager->getRepository(TipSheet::class)->findOneByContent($subject)) &&
$tipSheet->getClinic()
) {
$result[] = $tipSheet->getClinic();
}
if (
($editorialContent = $this->entityManager->getRepository(EditorialContent::class)->findOneByContent($subject)) &&
$editorialContent->getClinic()
) {
$result[] = $editorialContent->getClinic();
}
break;
case Clinic::class:
$result[] = $subject;
break;
case ClinicEmployee::class:
foreach ($subject->getClinicEmployeeClinics() as $clinicEmployeeClinic) {
if ($clinicEmployeeClinic->getClinic()) {
$result[] = $clinicEmployeeClinic->getClinic();
}
}
break;
case Audit::class:
case Customer::class:
case EditorialContent::class:
case Holiday::class:
case NewsBlog::class:
case Order::class:
case Price::class:
case PriceCategory::class:
case Service::class:
case Website::class:
if ($subject->getClinic()) {
$result[] = $subject->getClinic();
}
break;
case PricePlan::class:
if ($clinic = $this->entityManager->getRepository(Clinic::class)->findOneByPricePlan($subject)) {
$result[] = $clinic;
}
break;
case Subscription::class:
if ($subject->getCustomer()?->getClinic()) {
$result[] = $subject->getCustomer()?->getClinic();
}
break;
case WebsitePage::class:
if (
($instance = $this->entityManager->getRepository(WebsiteInstance::class)->findOneByTemplate($subject->getWebsiteTemplate())) &&
$instance->getShowcase()?->getClinic()
) {
$result[] = $instance->getShowcase()?->getClinic();
}
break;
}
return $result;
}
}