Extract HandlerProvider to own class
This commit is contained in:
parent
87255eaf13
commit
7ffd3c02cd
@ -23,7 +23,7 @@ services:
|
||||
# this creates a service per class whose id is the fully-qualified class name
|
||||
App\:
|
||||
resource: '../src/*'
|
||||
exclude: '../src/{DependencyInjection,Exception,Modifiers,Entity,Model,Migrations,Tests,Functions,Kernel.php}'
|
||||
exclude: '../src/{DependencyInjection,Exception,Modifie,Entity,Model,Migrations,Tests,Functions,Handler,Kernel.php}'
|
||||
|
||||
# controllers are imported separately to make sure services can be injected
|
||||
# as action arguments even if you don't extend any base controller class
|
||||
@ -35,6 +35,10 @@ services:
|
||||
resource: '../src/Provider'
|
||||
public: true
|
||||
|
||||
App\Handler\:
|
||||
resource: '../src/Handler'
|
||||
tags: [ app.handler ]
|
||||
|
||||
# add more service definitions when explicit configuration is needed
|
||||
# please note that last definitions always *replace* previous ones
|
||||
|
||||
@ -90,3 +94,7 @@ services:
|
||||
# other servces
|
||||
App\Service\ProviderResolver:
|
||||
arguments: [!tagged app.provider, '%kernel.debug%']
|
||||
|
||||
App\Service\HandlerProvider:
|
||||
arguments: [!tagged_locator app.handler]
|
||||
shared: false
|
||||
|
@ -4,12 +4,12 @@ namespace App\Controller\Api\v1;
|
||||
|
||||
use App\Controller\Controller;
|
||||
use App\Model\Stop;
|
||||
use App\Model\TrackStop;
|
||||
use App\Model\StopGroup;
|
||||
use App\Modifier\IdFilter;
|
||||
use App\Model\TrackStop;
|
||||
use App\Modifier\FieldFilter;
|
||||
use App\Modifier\IncludeDestinations;
|
||||
use App\Modifier\IdFilter;
|
||||
use App\Modifier\RelatedFilter;
|
||||
use App\Modifier\With;
|
||||
use App\Provider\StopRepository;
|
||||
use App\Provider\TrackRepository;
|
||||
use Nelmio\ApiDocBundle\Annotation\Model;
|
||||
@ -95,7 +95,7 @@ class StopsController extends Controller
|
||||
*/
|
||||
public function one(Request $request, StopRepository $stops, $id)
|
||||
{
|
||||
return $this->json($stops->first(new IdFilter($id), new IncludeDestinations()));
|
||||
return $this->json($stops->first(new IdFilter($id), new With("destinations")));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -137,7 +137,7 @@ class StopsController extends Controller
|
||||
}
|
||||
|
||||
if ($request->query->has('include-destinations')) {
|
||||
yield new IncludeDestinations();
|
||||
yield new With("destinations");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3,12 +3,11 @@
|
||||
namespace App\Exception;
|
||||
|
||||
use App\Modifier\Modifier;
|
||||
use App\Provider\Repository;
|
||||
|
||||
class UnsupportedModifierException extends \LogicException
|
||||
{
|
||||
public static function createFromModifier(Modifier $modifier, Repository $repository)
|
||||
public static function createFromModifier(Modifier $modifier)
|
||||
{
|
||||
return new static(sprintf("Modifier %s is not supported by %s.", get_class($modifier), get_class($repository)));
|
||||
return new static(sprintf("Modifier %s is not supported.", get_class($modifier)));
|
||||
}
|
||||
}
|
||||
|
@ -10,11 +10,11 @@ use App\Model\Stop;
|
||||
use App\Service\Converter;
|
||||
use App\Service\IdUtils;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Tightenco\Collect\Support\Collection;
|
||||
use Kadet\Functional as f;
|
||||
use Kadet\Functional\Transforms as t;
|
||||
use Tightenco\Collect\Support\Collection;
|
||||
|
||||
class IncludeDestinationsDatabaseHandler implements PostProcessingHandler
|
||||
class WithDestinationsDatabaseHandler implements PostProcessingHandler
|
||||
{
|
||||
private $em;
|
||||
private $converter;
|
@ -1,7 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Modifier;
|
||||
|
||||
class IncludeDestinations implements Modifier
|
||||
{
|
||||
}
|
18
src/Modifier/With.php
Normal file
18
src/Modifier/With.php
Normal file
@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
namespace App\Modifier;
|
||||
|
||||
class With implements Modifier
|
||||
{
|
||||
private $relationship;
|
||||
|
||||
public function __construct(string $relationship)
|
||||
{
|
||||
$this->relationship = $relationship;
|
||||
}
|
||||
|
||||
public function getRelationship(): string
|
||||
{
|
||||
return $this->relationship;
|
||||
}
|
||||
}
|
@ -5,28 +5,26 @@ namespace App\Provider\Database;
|
||||
use App\Entity\ProviderEntity;
|
||||
use App\Event\HandleDatabaseModifierEvent;
|
||||
use App\Event\PostProcessEvent;
|
||||
use App\Exception\UnsupportedModifierException;
|
||||
use App\Handler\Database\FieldFilterDatabaseHandler;
|
||||
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\FieldFilter;
|
||||
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\HandlerProvider;
|
||||
use App\Service\IdUtils;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
use Psr\Container\ContainerInterface;
|
||||
use Symfony\Contracts\Service\ServiceSubscriberInterface;
|
||||
|
||||
abstract class DatabaseRepository implements ServiceSubscriberInterface, Repository
|
||||
abstract class DatabaseRepository implements Repository
|
||||
{
|
||||
const DEFAULT_LIMIT = 100;
|
||||
|
||||
@ -42,7 +40,7 @@ abstract class DatabaseRepository implements ServiceSubscriberInterface, Reposit
|
||||
/** @var Converter */
|
||||
protected $converter;
|
||||
|
||||
/** @var ContainerInterface */
|
||||
/** @var HandlerProvider */
|
||||
protected $handlers;
|
||||
|
||||
/**
|
||||
@ -54,12 +52,19 @@ abstract class DatabaseRepository implements ServiceSubscriberInterface, Reposit
|
||||
EntityManagerInterface $em,
|
||||
IdUtils $id,
|
||||
Converter $converter,
|
||||
ContainerInterface $handlers
|
||||
HandlerProvider $handlers
|
||||
) {
|
||||
$this->em = $em;
|
||||
$this->id = $id;
|
||||
$this->converter = $converter;
|
||||
$this->handlers = $handlers;
|
||||
|
||||
$this->handlers->loadConfiguration(array_merge([
|
||||
IdFilter::class => IdFilterDatabaseHandler::class,
|
||||
Limit::class => LimitDatabaseHandler::class,
|
||||
FieldFilter::class => FieldFilterDatabaseHandler::class,
|
||||
RelatedFilter::class => RelatedFilterDatabaseGenericHandler::class,
|
||||
], static::getHandlers()));
|
||||
}
|
||||
|
||||
/** @return static */
|
||||
@ -88,7 +93,7 @@ abstract class DatabaseRepository implements ServiceSubscriberInterface, Reposit
|
||||
$reducers = [];
|
||||
|
||||
foreach ($modifiers as $modifier) {
|
||||
$handler = $this->getHandler($modifier);
|
||||
$handler = $this->handlers->get($modifier);
|
||||
|
||||
if ($handler instanceof ModifierHandler) {
|
||||
$event = new HandleDatabaseModifierEvent($modifier, $this, $builder, array_merge([
|
||||
@ -120,10 +125,11 @@ abstract class DatabaseRepository implements ServiceSubscriberInterface, Reposit
|
||||
$builder->setMaxResults(self::DEFAULT_LIMIT);
|
||||
|
||||
$reducers = $this->processQueryBuilder($builder, $modifiers, $meta);
|
||||
$result = collect($builder->getQuery()->execute())->map(\Closure::fromCallable([$this, 'convert']));
|
||||
|
||||
return $reducers->reduce(function ($result, $reducer) {
|
||||
return $reducer($result);
|
||||
}, collect($builder->getQuery()->execute())->map(\Closure::fromCallable([$this, 'convert'])));
|
||||
}, $result);
|
||||
}
|
||||
|
||||
public function first(Modifier ...$modifiers)
|
||||
@ -131,17 +137,6 @@ abstract class DatabaseRepository implements ServiceSubscriberInterface, Reposit
|
||||
return $this->all(Limit::count(1), ...$modifiers)->first();
|
||||
}
|
||||
|
||||
protected function getHandler(Modifier $modifier)
|
||||
{
|
||||
$class = get_class($modifier);
|
||||
|
||||
if (!$this->handlers->has($class)) {
|
||||
throw UnsupportedModifierException::createFromModifier($modifier, $this);
|
||||
}
|
||||
|
||||
return $this->handlers->get($class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns array describing handlers for each modifier type. Syntax is as follows:
|
||||
* [ IdFilter::class => IdFilterDatabaseHandler::class ]
|
||||
@ -154,17 +149,4 @@ abstract class DatabaseRepository implements ServiceSubscriberInterface, Reposit
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public static function getSubscribedServices()
|
||||
{
|
||||
return array_merge([
|
||||
IdFilter::class => IdFilterDatabaseHandler::class,
|
||||
Limit::class => LimitDatabaseHandler::class,
|
||||
FieldFilter::class => FieldFilterDatabaseHandler::class,
|
||||
RelatedFilter::class => RelatedFilterDatabaseGenericHandler::class,
|
||||
], static::getHandlers());
|
||||
}
|
||||
}
|
||||
|
@ -3,10 +3,10 @@
|
||||
namespace App\Provider\Database;
|
||||
|
||||
use App\Entity\StopEntity;
|
||||
use App\Handler\Database\IncludeDestinationsDatabaseHandler;
|
||||
use App\Handler\Database\WithDestinationsDatabaseHandler;
|
||||
use App\Model\Stop;
|
||||
use App\Modifier\Modifier;
|
||||
use App\Modifier\IncludeDestinations;
|
||||
use App\Modifier\With;
|
||||
use App\Provider\StopRepository;
|
||||
use Tightenco\Collect\Support\Collection;
|
||||
|
||||
@ -30,7 +30,11 @@ class GenericStopRepository extends DatabaseRepository implements StopRepository
|
||||
protected static function getHandlers()
|
||||
{
|
||||
return array_merge(parent::getHandlers(), [
|
||||
IncludeDestinations::class => IncludeDestinationsDatabaseHandler::class,
|
||||
With::class => function (With $modifier) {
|
||||
return $modifier->getRelationship() === 'destinations'
|
||||
? WithDestinationsDatabaseHandler::class
|
||||
: GenericWithHandler::class;
|
||||
},
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
44
src/Service/HandlerProvider.php
Normal file
44
src/Service/HandlerProvider.php
Normal file
@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
namespace App\Service;
|
||||
|
||||
use App\Exception\UnsupportedModifierException;
|
||||
use App\Modifier\Modifier;
|
||||
use Symfony\Component\DependencyInjection\ServiceLocator;
|
||||
|
||||
class HandlerProvider
|
||||
{
|
||||
private $configuration = [];
|
||||
private $handlerLocator;
|
||||
|
||||
public function __construct(ServiceLocator $handlerLocator)
|
||||
{
|
||||
$this->handlerLocator = $handlerLocator;
|
||||
}
|
||||
|
||||
public function loadConfiguration(array $providers)
|
||||
{
|
||||
$this->configuration = $providers;
|
||||
}
|
||||
|
||||
public function get(Modifier $modifier)
|
||||
{
|
||||
$class = get_class($modifier);
|
||||
|
||||
if (!array_key_exists($class, $this->configuration)) {
|
||||
throw UnsupportedModifierException::createFromModifier($modifier);
|
||||
}
|
||||
|
||||
$handler = $this->configuration[$class];
|
||||
|
||||
if (is_callable($handler)) {
|
||||
$handler = $handler($modifier);
|
||||
}
|
||||
|
||||
if (is_string($handler)) {
|
||||
return $this->handlerLocator->get($handler);
|
||||
}
|
||||
|
||||
return $handler;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user