diff --git a/src/Controller/Api/v1/StopsController.php b/src/Controller/Api/v1/StopsController.php index 64c4107..669e58f 100644 --- a/src/Controller/Api/v1/StopsController.php +++ b/src/Controller/Api/v1/StopsController.php @@ -1,6 +1,5 @@ values(); } - /** - * @param Request $request - * - * @return array - */ - private function getModifiersFromRequest(Request $request): array + private function getModifiersFromRequest(Request $request) { - $modifiers = []; - if ($request->query->has('name')) { - $modifiers[] = FieldFilter::contains('name', $request->query->get('name')); + yield FieldFilter::contains('name', $request->query->get('name')); } if ($request->query->has('id')) { - $modifiers[] = new IdFilter($request->query->get('id')); + yield new IdFilter($request->query->get('id')); } if ($request->query->has('include-destinations')) { - $modifiers[] = new IncludeDestinations(); + yield new IncludeDestinations(); } - - return $modifiers; } } diff --git a/src/Controller/Api/v1/TracksController.php b/src/Controller/Api/v1/TracksController.php index 6f9fbad..71b7ae8 100644 --- a/src/Controller/Api/v1/TracksController.php +++ b/src/Controller/Api/v1/TracksController.php @@ -9,6 +9,7 @@ use App\Model\Track; use App\Modifier\IdFilter; use App\Modifier\RelatedFilter; use App\Provider\TrackRepository; +use App\Service\IterableUtils; use Nelmio\ApiDocBundle\Annotation\Model; use Swagger\Annotations as SWG; use Symfony\Component\HttpFoundation\Request; @@ -31,43 +32,31 @@ class TracksController extends Controller */ public function index(Request $request, TrackRepository $repository) { - switch (true) { - case $request->query->has('stop'): - return $this->byStop($request, $repository); - case $request->query->has('line'): - return $this->byLine($request, $repository); - case $request->query->has('id'): - return $this->byId($request, $repository); - default: - throw new BadRequestHttpException( - sprintf( - 'At least one parameter of %s must be set.', - implode(', ', ['stop', 'line', 'id']) - ) - ); + $modifiers = $this->getModifiersFromRequest($request); + + return $this->json($repository->all(...$modifiers)); + } + + private function getModifiersFromRequest(Request $request) + { + if ($request->query->has('stop')) { + $stop = $request->query->get('stop'); + $stop = Stop::reference($stop); + + yield new RelatedFilter($stop); + } + + if ($request->query->has('line')) { + $line = $request->query->get('line'); + $line = Line::reference($line); + + yield new RelatedFilter($line); + } + + if ($request->query->has('id')) { + $id = encapsulate($request->query->get('id')); + + yield new IdFilter($id); } } - - private function byId(Request $request, TrackRepository $repository) - { - $id = encapsulate($request->query->get('id')); - - return $this->json($repository->all(new IdFilter($id))); - } - - private function byStop(Request $request, TrackRepository $repository) - { - $stop = $request->query->get('stop'); - $stop = array_map([Stop::class, 'reference'], encapsulate($stop)); - - return $this->json($repository->getByStop($stop)); - } - - private function byLine(Request $request, TrackRepository $repository) - { - $line = $request->query->get('line'); - $line = Line::reference($line); - - return $this->json($repository->all(new RelatedFilter($line))); - } } diff --git a/src/Handler/Database/RelatedFilterDatabaseGenericHandler.php b/src/Handler/Database/RelatedFilterDatabaseGenericHandler.php index cb4627e..6a2683d 100644 --- a/src/Handler/Database/RelatedFilterDatabaseGenericHandler.php +++ b/src/Handler/Database/RelatedFilterDatabaseGenericHandler.php @@ -2,16 +2,15 @@ namespace App\Handler\Database; -use App\Entity\LineEntity; -use App\Entity\ProviderEntity; use App\Event\HandleDatabaseModifierEvent; use App\Event\HandleModifierEvent; use App\Handler\ModifierHandler; use App\Model\Line; -use App\Model\Referable; +use App\Model\Stop; use App\Model\Track; use App\Modifier\RelatedFilter; use App\Service\IdUtils; +use App\Service\ReferenceFactory; use Doctrine\ORM\EntityManagerInterface; use Psr\Container\ContainerInterface; use Symfony\Contracts\Service\ServiceSubscriberInterface; @@ -21,22 +20,25 @@ class RelatedFilterDatabaseGenericHandler implements ModifierHandler, ServiceSub protected $mapping = [ Track::class => [ Line::class => 'line', + Stop::class => TrackByStopDatabaseHandler::class, ], ]; - protected $references = [ - Line::class => LineEntity::class, - ]; - private $em; private $inner; private $id; + private $references; - public function __construct(ContainerInterface $inner, EntityManagerInterface $em, IdUtils $idUtils) - { + public function __construct( + ContainerInterface $inner, + EntityManagerInterface $em, + IdUtils $idUtils, + ReferenceFactory $references + ) { $this->inner = $inner; $this->em = $em; $this->id = $idUtils; + $this->references = $references; } public function process(HandleModifierEvent $event) @@ -65,8 +67,15 @@ class RelatedFilterDatabaseGenericHandler implements ModifierHandler, ServiceSub $relationship = $this->mapping[$type][$modifier->getRelationship()]; + if ($this->inner->has($relationship)) { + /** @var ModifierHandler $inner */ + $inner = $this->inner->get($relationship); + $inner->process($event); + return; + } + $parameter = sprintf(":%s_%s", $alias, $relationship); - $reference = $this->getEntityReference($modifier->getRelated(), $event->getMeta()['provider']); + $reference = $this->references->create($modifier->getRelated(), $event->getMeta()['provider']); $builder ->join(sprintf('%s.%s', $alias, $relationship), $relationship) @@ -75,22 +84,13 @@ class RelatedFilterDatabaseGenericHandler implements ModifierHandler, ServiceSub ; } - // todo: extract that to separate service - private function getEntityReference(Referable $object, ProviderEntity $provider) - { - return $this->em->getReference( - $this->references[get_class($object)], - $this->id->generate($provider, $object->getId()) - ); - } - /** * @inheritDoc */ public static function getSubscribedServices() { return [ - TrackRelatedFilterDatabaseHandler::class, + TrackByStopDatabaseHandler::class, ]; } } diff --git a/src/Handler/Database/TrackByStopDatabaseHandler.php b/src/Handler/Database/TrackByStopDatabaseHandler.php new file mode 100644 index 0000000..12789e5 --- /dev/null +++ b/src/Handler/Database/TrackByStopDatabaseHandler.php @@ -0,0 +1,43 @@ +references = $references; + } + + public function process(HandleModifierEvent $event) + { + if (!$event instanceof HandleDatabaseModifierEvent) { + return; + } + + /** @var RelatedFilter $modifier */ + $modifier = $event->getModifier(); + $builder = $event->getBuilder(); + $alias = $event->getMeta()['alias']; + + $relationship = 'stopsInTrack'; + + $parameter = sprintf(":%s_%s", $alias, $relationship); + $reference = $this->references->create($modifier->getRelated(), $event->getMeta()['provider']); + + $builder + ->join(sprintf("%s.%s", $alias, $relationship), 'stop_in_track') + ->andWhere(sprintf("stop_in_track.stop = %s", $parameter)) + ->setParameter($parameter, $reference) + ; + } +} diff --git a/src/Service/ReferenceFactory.php b/src/Service/ReferenceFactory.php new file mode 100644 index 0000000..3d91cd9 --- /dev/null +++ b/src/Service/ReferenceFactory.php @@ -0,0 +1,42 @@ + LineEntity::class, + Stop::class => StopEntity::class, + ]; + + private $em; + private $id; + + public function __construct(EntityManagerInterface $em, IdUtils $id) + { + $this->em = $em; + $this->id = $id; + } + + public function create(Referable $object, ProviderEntity $provider) + { + $class = get_class($object); + + if (!array_key_exists($class, $this->mapping)) { + throw new \InvalidArgumentException(sprintf("Cannot make entity reference of %s.", $class)); + } + + return $this->em->getReference( + $this->mapping[$class], + $this->id->generate($provider, $object->getId()) + ); + } +}