. */ namespace App\Services\Parts; use App\Entity\Parts\Category; use App\Entity\Parts\Footprint; use App\Entity\Parts\Manufacturer; use App\Entity\Parts\MeasurementUnit; use App\Entity\Parts\Part; use App\Repository\DBElementRepository; use App\Repository\PartRepository; use Doctrine\ORM\EntityManagerInterface; use InvalidArgumentException; use Symfony\Component\Security\Core\Exception\AccessDeniedException; use Symfony\Component\Security\Core\Security; final class PartsTableActionHandler { private EntityManagerInterface $entityManager; private Security $security; public function __construct(EntityManagerInterface $entityManager, Security $security) { $this->entityManager = $entityManager; $this->security = $security; } /** * Converts the given array to an array of Parts. * * @param string $ids a comma separated list of Part IDs * * @return Part[] */ public function idStringToArray(string $ids): array { $id_array = explode(',', $ids); /** @var PartRepository $repo */ $repo = $this->entityManager->getRepository(Part::class); return $repo->getElementsFromIDArray($id_array); } /** * @param Part[] $selected_parts */ public function handleAction(string $action, array $selected_parts, ?int $target_id): void { //Iterate over the parts and apply the action to it: foreach ($selected_parts as $part) { if (!$part instanceof Part) { throw new InvalidArgumentException('$selected_parts must be an array of Part elements!'); } //We modify parts, so you have to have the permission to modify it $this->denyAccessUnlessGranted('edit', $part); switch ($action) { case 'favorite': $part->setFavorite(true); break; case 'unfavorite': $part->setFavorite(false); break; case 'delete': $this->denyAccessUnlessGranted('delete', $part); $this->entityManager->remove($part); break; case 'change_category': $this->denyAccessUnlessGranted('category.edit', $part); $part->setCategory($this->entityManager->find(Category::class, $target_id)); break; case 'change_footprint': $this->denyAccessUnlessGranted('footprint.edit', $part); $part->setFootprint(null === $target_id ? null : $this->entityManager->find(Footprint::class, $target_id)); break; case 'change_manufacturer': $this->denyAccessUnlessGranted('manufacturer.edit', $part); $part->setManufacturer(null === $target_id ? null : $this->entityManager->find(Manufacturer::class, $target_id)); break; case 'change_unit': $this->denyAccessUnlessGranted('unit.edit', $part); $part->setPartUnit(null === $target_id ? null : $this->entityManager->find(MeasurementUnit::class, $target_id)); break; default: throw new InvalidArgumentException('The given action is unknown! ('.$action.')'); } } } /** * Throws an exception unless the attributes are granted against the current authentication token and optionally * supplied subject. * * @throws AccessDeniedException */ private function denyAccessUnlessGranted($attributes, $subject = null, string $message = 'Access Denied.'): void { if (!$this->security->isGranted($attributes, $subject)) { $exception = new AccessDeniedException($message); $exception->setAttributes($attributes); $exception->setSubject($subject); throw $exception; } } }