Rewrite Track Repository into fluent pattern
This commit is contained in:
parent
950e310096
commit
a3de2b244f
@ -10,6 +10,7 @@ use App\Model\StopGroup;
|
||||
use App\Modifier\IdFilter;
|
||||
use App\Modifier\FieldFilter;
|
||||
use App\Modifier\IncludeDestinations;
|
||||
use App\Modifier\RelatedFilter;
|
||||
use App\Provider\StopRepository;
|
||||
use App\Provider\TrackRepository;
|
||||
use App\Service\Proxy\ReferenceFactory;
|
||||
|
@ -3,8 +3,11 @@
|
||||
namespace App\Controller\Api\v1;
|
||||
|
||||
use App\Controller\Controller;
|
||||
use App\Model\Line;
|
||||
use App\Model\Stop;
|
||||
use App\Model\Track;
|
||||
use App\Modifier\IdFilter;
|
||||
use App\Modifier\RelatedFilter;
|
||||
use App\Provider\TrackRepository;
|
||||
use Nelmio\ApiDocBundle\Annotation\Model;
|
||||
use Swagger\Annotations as SWG;
|
||||
@ -49,7 +52,7 @@ class TracksController extends Controller
|
||||
{
|
||||
$id = encapsulate($request->query->get('id'));
|
||||
|
||||
return $this->json($repository->getManyById($id));
|
||||
return $this->json($repository->all(new IdFilter($id)));
|
||||
}
|
||||
|
||||
private function byStop(Request $request, TrackRepository $repository)
|
||||
@ -63,8 +66,8 @@ class TracksController extends Controller
|
||||
private function byLine(Request $request, TrackRepository $repository)
|
||||
{
|
||||
$line = $request->query->get('line');
|
||||
$line = array_map([Stop::class, 'reference'], encapsulate($line));
|
||||
$line = Line::reference($line);
|
||||
|
||||
return $this->json($repository->getByLine($line));
|
||||
return $this->json($repository->all(new RelatedFilter($line)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -7,6 +7,7 @@ use App\Event\HandleModifierEvent;
|
||||
use App\Handler\ModifierHandler;
|
||||
use App\Model\Stop;
|
||||
use App\Modifier\FieldFilter;
|
||||
use function App\Functions\encapsulate;
|
||||
|
||||
class FieldFilterDatabaseHandler implements ModifierHandler
|
||||
{
|
||||
@ -33,8 +34,13 @@ class FieldFilterDatabaseHandler implements ModifierHandler
|
||||
|
||||
$parameter = sprintf(":%s_%s", $alias, $field);
|
||||
|
||||
if ($operator === 'in' || $operator === 'not in') {
|
||||
$parameter = "($parameter)";
|
||||
$value = encapsulate($value);
|
||||
}
|
||||
|
||||
$builder
|
||||
->where(sprintf("%s.%s %s %s", $alias, $field, $operator, $parameter))
|
||||
->andWhere(sprintf("%s.%s %s %s", $alias, $field, $operator, $parameter))
|
||||
->setParameter($parameter, $value)
|
||||
;
|
||||
}
|
||||
|
@ -37,7 +37,7 @@ class IdFilterDatabaseHandler implements ModifierHandler
|
||||
$mapper = apply([$this->id, 'generate'], $provider);
|
||||
|
||||
$builder
|
||||
->where($modifier->isMultiple() ? "{$alias} in (:id)" : "{$alias} = :id")
|
||||
->andWhere($modifier->isMultiple() ? "{$alias} in (:id)" : "{$alias} = :id")
|
||||
->setParameter(':id', $modifier->isMultiple() ? array_map($mapper, $id) : $mapper($id));
|
||||
;
|
||||
}
|
||||
|
@ -27,7 +27,7 @@ class IncludeDestinationsDatabaseHandler implements PostProcessingHandler
|
||||
$this->id = $id;
|
||||
}
|
||||
|
||||
public function process(PostProcessEvent $event)
|
||||
public function postProcess(PostProcessEvent $event)
|
||||
{
|
||||
$provider = $event->getMeta()['provider'];
|
||||
$stops = $event
|
||||
|
96
src/Handler/Database/RelatedFilterDatabaseGenericHandler.php
Normal file
96
src/Handler/Database/RelatedFilterDatabaseGenericHandler.php
Normal file
@ -0,0 +1,96 @@
|
||||
<?php
|
||||
|
||||
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\Track;
|
||||
use App\Modifier\RelatedFilter;
|
||||
use App\Service\IdUtils;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Psr\Container\ContainerInterface;
|
||||
use Symfony\Contracts\Service\ServiceSubscriberInterface;
|
||||
|
||||
class RelatedFilterDatabaseGenericHandler implements ModifierHandler, ServiceSubscriberInterface
|
||||
{
|
||||
protected $mapping = [
|
||||
Track::class => [
|
||||
Line::class => 'line',
|
||||
],
|
||||
];
|
||||
|
||||
protected $references = [
|
||||
Line::class => LineEntity::class,
|
||||
];
|
||||
|
||||
private $em;
|
||||
private $inner;
|
||||
private $id;
|
||||
|
||||
public function __construct(ContainerInterface $inner, EntityManagerInterface $em, IdUtils $idUtils)
|
||||
{
|
||||
$this->inner = $inner;
|
||||
$this->em = $em;
|
||||
$this->id = $idUtils;
|
||||
}
|
||||
|
||||
public function process(HandleModifierEvent $event)
|
||||
{
|
||||
if (!$event instanceof HandleDatabaseModifierEvent) {
|
||||
return;
|
||||
}
|
||||
|
||||
/** @var RelatedFilter $modifier */
|
||||
$modifier = $event->getModifier();
|
||||
$builder = $event->getBuilder();
|
||||
$alias = $event->getMeta()['alias'];
|
||||
$type = $event->getMeta()['type'];
|
||||
|
||||
if (!array_key_exists($type, $this->mapping)) {
|
||||
throw new \InvalidArgumentException(
|
||||
sprintf("Relationship filtering for %s is not supported.", $type)
|
||||
);
|
||||
}
|
||||
|
||||
if (!array_key_exists($modifier->getRelationship(), $this->mapping[$type])) {
|
||||
throw new \InvalidArgumentException(
|
||||
sprintf("Relationship %s is not supported for .", $type)
|
||||
);
|
||||
}
|
||||
|
||||
$relationship = $this->mapping[$type][$modifier->getRelationship()];
|
||||
|
||||
$parameter = sprintf(":%s_%s", $alias, $relationship);
|
||||
$reference = $this->getEntityReference($modifier->getRelated(), $event->getMeta()['provider']);
|
||||
|
||||
$builder
|
||||
->join(sprintf('%s.%s', $alias, $relationship), $relationship)
|
||||
->andWhere(sprintf("%s = %s", $relationship, $parameter))
|
||||
->setParameter($parameter, $reference)
|
||||
;
|
||||
}
|
||||
|
||||
// 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,
|
||||
];
|
||||
}
|
||||
}
|
@ -2,10 +2,9 @@
|
||||
|
||||
namespace App\Handler;
|
||||
|
||||
use App\Event\HandleModifierEvent;
|
||||
use App\Event\PostProcessEvent;
|
||||
|
||||
interface PostProcessingHandler
|
||||
{
|
||||
public function process(PostProcessEvent $event);
|
||||
public function postProcess(PostProcessEvent $event);
|
||||
}
|
||||
|
27
src/Modifier/RelatedFilter.php
Normal file
27
src/Modifier/RelatedFilter.php
Normal file
@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
namespace App\Modifier;
|
||||
|
||||
use App\Model\Referable;
|
||||
|
||||
class RelatedFilter implements Modifier
|
||||
{
|
||||
private $relationship;
|
||||
private $object;
|
||||
|
||||
public function __construct(Referable $object, ?string $relation = null)
|
||||
{
|
||||
$this->object = $object;
|
||||
$this->relationship = $relation ?: get_class($object);
|
||||
}
|
||||
|
||||
public function getRelationship(): string
|
||||
{
|
||||
return $this->relationship;
|
||||
}
|
||||
|
||||
public function getRelated(): Referable
|
||||
{
|
||||
return $this->object;
|
||||
}
|
||||
}
|
@ -9,12 +9,15 @@ use App\Exception\UnsupportedModifierException;
|
||||
use App\Handler\Database\IdFilterDatabaseHandler;
|
||||
use App\Handler\Database\LimitDatabaseHandler;
|
||||
use App\Handler\Database\FieldFilterDatabaseHandler;
|
||||
use App\Handler\Database\RelatedFilterDatabaseGenericHandler;
|
||||
use App\Handler\ModifierHandler;
|
||||
use App\Handler\PostProcessingHandler;
|
||||
use App\Model\Referable;
|
||||
use App\Modifier\IdFilter;
|
||||
use App\Modifier\Limit;
|
||||
use App\Modifier\Modifier;
|
||||
use App\Modifier\FieldFilter;
|
||||
use App\Modifier\RelatedFilter;
|
||||
use App\Provider\Repository;
|
||||
use App\Service\Converter;
|
||||
use App\Service\IdUtils;
|
||||
@ -85,27 +88,26 @@ abstract class DatabaseRepository implements ServiceSubscriberInterface, Reposit
|
||||
foreach ($modifiers as $modifier) {
|
||||
$handler = $this->getHandler($modifier);
|
||||
|
||||
switch (true) {
|
||||
case $handler instanceof PostProcessingHandler:
|
||||
$reducers[] = function ($result) use ($meta, $modifier, $handler) {
|
||||
$event = new PostProcessEvent($result, $modifier, $this, array_merge([
|
||||
'provider' => $this->provider,
|
||||
], $meta));
|
||||
if ($handler instanceof ModifierHandler) {
|
||||
$event = new HandleDatabaseModifierEvent($modifier, $this, $builder, array_merge([
|
||||
'provider' => $this->provider,
|
||||
], $meta));
|
||||
|
||||
$handler->process($event);
|
||||
$handler->process($event);
|
||||
}
|
||||
|
||||
return $event->getData();
|
||||
};
|
||||
break;
|
||||
|
||||
default:
|
||||
$event = new HandleDatabaseModifierEvent($modifier, $this, $builder, array_merge([
|
||||
if ($handler instanceof PostProcessingHandler) {
|
||||
$reducers[] = function ($result) use ($meta, $modifier, $handler) {
|
||||
$event = new PostProcessEvent($result, $modifier, $this, array_merge([
|
||||
'provider' => $this->provider,
|
||||
], $meta));
|
||||
|
||||
$handler->process($event);
|
||||
break;
|
||||
$handler->postProcess($event);
|
||||
|
||||
return $event->getData();
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return collect($reducers);
|
||||
@ -155,9 +157,10 @@ abstract class DatabaseRepository implements ServiceSubscriberInterface, Reposit
|
||||
public static function getSubscribedServices()
|
||||
{
|
||||
return array_merge([
|
||||
IdFilter::class => IdFilterDatabaseHandler::class,
|
||||
Limit::class => LimitDatabaseHandler::class,
|
||||
FieldFilter::class => FieldFilterDatabaseHandler::class,
|
||||
IdFilter::class => IdFilterDatabaseHandler::class,
|
||||
Limit::class => LimitDatabaseHandler::class,
|
||||
FieldFilter::class => FieldFilterDatabaseHandler::class,
|
||||
RelatedFilter::class => RelatedFilterDatabaseGenericHandler::class,
|
||||
], static::getHandlers());
|
||||
}
|
||||
}
|
||||
|
@ -2,36 +2,18 @@
|
||||
|
||||
namespace App\Provider\Database;
|
||||
|
||||
use App\Entity\LineEntity;
|
||||
use App\Entity\StopEntity;
|
||||
use App\Entity\StopInTrack;
|
||||
use App\Entity\TrackEntity;
|
||||
use function App\Functions\encapsulate;
|
||||
use App\Model\Stop;
|
||||
use App\Modifier\Modifier;
|
||||
use App\Model\Track;
|
||||
use App\Provider\TrackRepository;
|
||||
use Tightenco\Collect\Support\Collection;
|
||||
use Kadet\Functional as f;
|
||||
use function App\Functions\encapsulate;
|
||||
|
||||
class GenericTrackRepository extends DatabaseRepository implements TrackRepository
|
||||
{
|
||||
public function getAll(): Collection
|
||||
{
|
||||
$tracks = $this->em->getRepository(TrackEntity::class)->findAll();
|
||||
|
||||
return collect($tracks)->map(f\ref([$this, 'convert']));
|
||||
}
|
||||
|
||||
public function getById($id): Track
|
||||
{
|
||||
// TODO: Implement getById() method.
|
||||
}
|
||||
|
||||
public function getManyById($ids): Collection
|
||||
{
|
||||
// TODO: Implement getManyById() method.
|
||||
}
|
||||
|
||||
public function getByStop($stop): Collection
|
||||
{
|
||||
$reference = f\apply(f\ref([$this, 'reference']), StopEntity::class);
|
||||
@ -49,24 +31,17 @@ class GenericTrackRepository extends DatabaseRepository implements TrackReposito
|
||||
});
|
||||
}
|
||||
|
||||
public function getByLine($line): Collection
|
||||
public function all(Modifier ...$modifiers): Collection
|
||||
{
|
||||
$reference = f\apply(f\ref([$this, 'reference']), LineEntity::class);
|
||||
$builder = $this->em
|
||||
->createQueryBuilder()
|
||||
->from(TrackEntity::class, 'track')
|
||||
->select('track');
|
||||
|
||||
$tracks = $this->em->createQueryBuilder()
|
||||
->from(StopInTrack::class, 'st')
|
||||
->join('st.track', 't')
|
||||
->join('t.stops', 's')
|
||||
->where('st.line in (:line)')
|
||||
->select(['st', 't', 's'])
|
||||
->getQuery()
|
||||
->execute(['stop' => array_map($reference, encapsulate($line))]);
|
||||
|
||||
return collect($tracks)->map(f\ref([$this, 'convert']));
|
||||
}
|
||||
|
||||
protected static function getHandlers()
|
||||
{
|
||||
return [];
|
||||
return $this->allFromQueryBuilder($builder, $modifiers, [
|
||||
'alias' => 'track',
|
||||
'entity' => TrackEntity::class,
|
||||
'type' => Track::class,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
@ -20,7 +20,7 @@ class GenericTripRepository extends DatabaseRepository implements TripRepository
|
||||
->select('t', 'ts');
|
||||
|
||||
return $this->allFromQueryBuilder($builder, $modifiers, [
|
||||
'alias' => 'operator',
|
||||
'alias' => 'trip',
|
||||
'entity' => TripEntity::class,
|
||||
'type' => Trip::class,
|
||||
]);
|
||||
|
@ -5,13 +5,7 @@ namespace App\Provider;
|
||||
use App\Model\Track;
|
||||
use Tightenco\Collect\Support\Collection;
|
||||
|
||||
interface TrackRepository
|
||||
interface TrackRepository extends FluentRepository
|
||||
{
|
||||
public function getAll(): Collection;
|
||||
|
||||
public function getById($id): Track;
|
||||
public function getManyById($ids): Collection;
|
||||
|
||||
public function getByStop($stop): Collection;
|
||||
public function getByLine($line): Collection;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user