Add service subscriber to database repository

This commit is contained in:
Kacper Donat 2020-02-12 20:08:56 +01:00
parent c1a58f4bd6
commit 6bd71f0ec5
10 changed files with 112 additions and 30 deletions

View File

@ -0,0 +1,14 @@
<?php
namespace App\Exception;
use App\Modifiers\Modifier;
use App\Provider\Repository;
class UnsupportedModifierException extends \Exception
{
public static function createFromModifier(Modifier $modifier, Repository $repository)
{
return new static(sprintf("Modifier %s is not supported by %s.", get_class($modifier), get_class($repository)));
}
}

View File

@ -3,14 +3,13 @@
namespace App\Handlers\Database;
use App\Handlers\ModifierHandler;
use App\Modifiers\WithId;
use App\Modifiers\IdFilter;
use App\Event\HandleDatabaseModifierEvent;
use App\Event\HandleModifierEvent;
use App\Service\IdUtils;
use function Kadet\Functional\apply;
use function Kadet\Functional\ref;
class WithIdDatabaseHandler implements ModifierHandler
class IdFilterDatabaseHandler implements ModifierHandler
{
/**
* @var IdUtils
@ -28,7 +27,7 @@ class WithIdDatabaseHandler implements ModifierHandler
return;
}
/** @var WithId $modifier */
/** @var IdFilter $modifier */
$modifier = $event->getModifier();
$builder = $event->getBuilder();
$alias = $event->getMeta()['alias'];

View File

@ -5,7 +5,7 @@ namespace App\Modifiers;
use App\Exception\InvalidOptionException;
use App\Modifiers\Modifier;
class WithId implements Modifier
class IdFilter implements Modifier
{
/** @var string|array */
private $id;

View File

@ -2,15 +2,19 @@
namespace App\Provider\Database;
use App\Entity\Entity;
use App\Entity\ProviderEntity;
use App\Event\HandleDatabaseModifierEvent;
use App\Exception\UnsupportedModifierException;
use App\Model\Referable;
use App\Provider\Repository;
use App\Service\Converter;
use App\Service\IdUtils;
use Doctrine\ORM\EntityManagerInterface;
use Kadet\Functional as f;
use Doctrine\ORM\QueryBuilder;
use Psr\Container\ContainerInterface;
use Symfony\Contracts\Service\ServiceSubscriberInterface;
class DatabaseRepository
abstract class DatabaseRepository implements ServiceSubscriberInterface, Repository
{
/** @var EntityManagerInterface */
protected $em;
@ -24,22 +28,30 @@ class DatabaseRepository
/** @var Converter */
protected $converter;
/** @var ContainerInterface */
protected $handlers;
/**
* DatabaseRepository constructor.
*
* @param EntityManagerInterface $em
*/
public function __construct(EntityManagerInterface $em, IdUtils $id, Converter $converter)
{
public function __construct(
EntityManagerInterface $em,
IdUtils $id,
Converter $converter,
ContainerInterface $handlers
) {
$this->em = $em;
$this->id = $id;
$this->converter = $converter;
$this->handlers = $handlers;
}
/** @return static */
public function withProvider(ProviderEntity $provider)
{
$result = clone $this;
$result = clone $this;
$result->provider = $provider;
return $result;
@ -56,4 +68,41 @@ class DatabaseRepository
return $this->em->getReference($class, $id);
}
protected function processQueryBuilder(QueryBuilder $builder, iterable $modifiers, array $meta = [])
{
foreach ($modifiers as $modifier) {
$event = new HandleDatabaseModifierEvent($modifier, $this, $builder, array_merge([
'provider' => $this->provider,
], $meta));
$class = get_class($modifier);
if (!$this->handlers->has($class)) {
throw UnsupportedModifierException::createFromModifier($modifier, $this);
}
$handler = $this->handlers->get($class);
$handler->process($event);
}
}
/**
* Returns array describing handlers for each modifier type. Syntax is as follows:
* [ IdFilter::class => IdFilterDatabaseHandler::class ]
*
* It is internally used as part of service subscriber.
*
* @return array
*/
protected abstract static function getHandlers();
/**
* @inheritDoc
*/
public static function getSubscribedServices()
{
return static::getHandlers();
}
}

View File

@ -5,11 +5,11 @@ namespace App\Provider\Database;
use App\Entity\LineEntity;
use App\Event\HandleDatabaseModifierEvent;
use App\Handlers\Database\LimitDatabaseHandler;
use App\Handlers\Database\WithIdDatabaseHandler;
use App\Handlers\Database\IdFilterDatabaseHandler;
use App\Handlers\ModifierHandler;
use App\Model\Line;
use App\Modifiers\Limit;
use App\Modifiers\WithId;
use App\Modifiers\IdFilter;
use App\Provider\LineRepository;
use App\Modifiers\Modifier;
use Tightenco\Collect\Support\Collection;
@ -24,12 +24,12 @@ class GenericLineRepository extends DatabaseRepository implements LineRepository
public function getById($id): ?Line
{
return $this->first(new WithId($id));
return $this->first(new IdFilter($id));
}
public function getManyById($ids): Collection
{
return $this->all(new WithId($ids));
return $this->all(new IdFilter($ids));
}
public function first(Modifier ...$modifiers)
@ -45,26 +45,21 @@ class GenericLineRepository extends DatabaseRepository implements LineRepository
->select('line')
;
foreach ($modifiers as $modifier) {
$event = new HandleDatabaseModifierEvent($modifier, $this, $builder, [
'alias' => 'line',
'provider' => $this->provider,
]);
$handler = $this->getHandlers()[get_class($modifier)];
$handler->process($event);
}
$this->processQueryBuilder($builder, $modifiers, [
'alias' => 'line',
'entity' => LineEntity::class,
'type' => Line::class,
]);
return collect($builder->getQuery()->execute())->map(f\ref([$this, 'convert']));
}
/** @return ModifierHandler[] */
private function getHandlers()
protected static function getHandlers()
{
return [
WithId::class => new WithIdDatabaseHandler($this->id),
Limit::class => new LimitDatabaseHandler(),
IdFilter::class => IdFilterDatabaseHandler::class,
Limit::class => LimitDatabaseHandler::class,
];
}
}

View File

@ -30,4 +30,9 @@ class GenericOperatorRepository extends DatabaseRepository implements OperatorRe
return collect($operators);
}
}
protected static function getHandlers()
{
return [];
}
}

View File

@ -70,4 +70,9 @@ class GenericScheduleRepository extends DatabaseRepository implements ScheduleRe
]);
});
}
protected static function getHandlers()
{
return [];
}
}

View File

@ -83,4 +83,9 @@ class GenericStopRepository extends DatabaseRepository implements StopRepository
$stop->setDestinations($destinations[$this->id->generate($this->provider, $stop->getId())]);
});
}
protected static function getHandlers()
{
return [];
}
}

View File

@ -64,4 +64,9 @@ class GenericTrackRepository extends DatabaseRepository implements TrackReposito
return collect($tracks)->map(f\ref([$this, 'convert']));
}
}
protected static function getHandlers()
{
return [];
}
}

View File

@ -25,4 +25,9 @@ class GenericTripRepository extends DatabaseRepository implements TripRepository
return $this->convert($trip);
}
protected static function getHandlers()
{
return [];
}
}