Make StopRepository more fluent
This commit is contained in:
parent
67f7ba2a88
commit
847e3a078f
@ -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,Entity,Model,Migrations,Tests,Functions,Kernel.php}'
|
||||
exclude: '../src/{DependencyInjection,Exception,Modifiers,Entity,Model,Migrations,Tests,Functions,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
|
||||
|
@ -80,7 +80,7 @@ export class FinderComponent extends Vue {
|
||||
|
||||
this.state = 'fetching';
|
||||
|
||||
const response = await fetch(urls.prepare(urls.stops.grouped, { name: this.filter }));
|
||||
const response = await fetch(urls.prepare(urls.stops.grouped, { name: this.filter, 'include-destinations': true }));
|
||||
|
||||
if (response.ok) {
|
||||
this.found = (await response.json()).reduce((accumulator, { name, stops }) => Object.assign(accumulator, { [name]: stops }), {});
|
||||
|
@ -8,7 +8,11 @@ export function query(params: UrlParams = { }) {
|
||||
function *simplify(name: string, param: any): IterableIterator<ParamValuePair> {
|
||||
if (typeof param === 'string') {
|
||||
yield [ name, param ];
|
||||
} else if (typeof param === 'number') {
|
||||
} else if (typeof param === 'boolean') {
|
||||
if (param) {
|
||||
yield [ name, '1' ];
|
||||
}
|
||||
} else if (typeof param === 'number') {
|
||||
yield [ name, param.toString() ];
|
||||
} else if (param instanceof Array) {
|
||||
for (let entry of param) {
|
||||
|
@ -5,6 +5,7 @@ namespace App\Controller\Api\v1;
|
||||
|
||||
use App\Controller\Controller;
|
||||
use App\Model\Departure;
|
||||
use App\Modifier\IdFilter;
|
||||
use App\Provider\DepartureRepository;
|
||||
use App\Provider\StopRepository;
|
||||
use App\Service\SerializerContextFactory;
|
||||
@ -34,7 +35,7 @@ class DeparturesController extends Controller
|
||||
*/
|
||||
public function stop(DepartureRepository $departures, StopRepository $stops, $stop)
|
||||
{
|
||||
$stop = $stops->getById($stop);
|
||||
$stop = $stops->first(new IdFilter($stop));
|
||||
|
||||
return $this->json($departures->getForStop($stop));
|
||||
}
|
||||
@ -65,7 +66,7 @@ class DeparturesController extends Controller
|
||||
public function stops(DepartureRepository $departures, StopRepository $stops, Request $request)
|
||||
{
|
||||
$stops = $stops
|
||||
->getManyById($request->query->get('stop'))
|
||||
->all(new IdFilter($request->query->get('stop')))
|
||||
->flatMap(ref([ $departures, 'getForStop' ]))
|
||||
->sortBy(property('departure'));
|
||||
|
||||
|
@ -7,6 +7,9 @@ use App\Controller\Controller;
|
||||
use App\Model\Stop;
|
||||
use App\Model\Track;
|
||||
use App\Model\StopGroup;
|
||||
use App\Modifier\IdFilter;
|
||||
use App\Modifier\FieldFilter;
|
||||
use App\Modifier\IncludeDestinations;
|
||||
use App\Provider\StopRepository;
|
||||
use App\Provider\TrackRepository;
|
||||
use App\Service\Proxy\ReferenceFactory;
|
||||
@ -46,16 +49,9 @@ class StopsController extends Controller
|
||||
*/
|
||||
public function index(Request $request, StopRepository $stops)
|
||||
{
|
||||
switch (true) {
|
||||
case $request->query->has('id'):
|
||||
$result = $stops->getManyById($request->query->get('id'));
|
||||
break;
|
||||
$modifiers = $this->getModifiersFromRequest($request);
|
||||
|
||||
default:
|
||||
$result = $stops->getAll();
|
||||
}
|
||||
|
||||
return $this->json($result->all());
|
||||
return $this->json($stops->all(...$modifiers)->toArray());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -76,16 +72,9 @@ class StopsController extends Controller
|
||||
*/
|
||||
public function groups(Request $request, StopRepository $stops)
|
||||
{
|
||||
switch (true) {
|
||||
case $request->query->has('name'):
|
||||
$result = $stops->findByName($request->query->get('name'));
|
||||
break;
|
||||
$modifiers = $this->getModifiersFromRequest($request);
|
||||
|
||||
default:
|
||||
$result = $stops->getAll();
|
||||
}
|
||||
|
||||
return $this->json(static::group($result)->all());
|
||||
return $this->json(static::group($stops->all(...$modifiers))->toArray());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -106,7 +95,7 @@ class StopsController extends Controller
|
||||
*/
|
||||
public function one(Request $request, StopRepository $stops, $id)
|
||||
{
|
||||
return $this->json($stops->getById($id));
|
||||
return $this->json($stops->first(new IdFilter($id), new IncludeDestinations()));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -145,4 +134,28 @@ class StopsController extends Controller
|
||||
return $group;
|
||||
})->values();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function getModifiersFromRequest(Request $request): array
|
||||
{
|
||||
$modifiers = [];
|
||||
|
||||
if ($request->query->has('name')) {
|
||||
$modifiers[] = FieldFilter::contains('name', $request->query->get('name'));
|
||||
}
|
||||
|
||||
if ($request->query->has('id')) {
|
||||
$modifiers[] = new IdFilter($request->query->get('id'));
|
||||
}
|
||||
|
||||
if ($request->query->has('include-destinations')) {
|
||||
$modifiers[] = new IncludeDestinations();
|
||||
}
|
||||
|
||||
return $modifiers;
|
||||
}
|
||||
}
|
||||
|
@ -3,7 +3,7 @@
|
||||
namespace App\Event;
|
||||
|
||||
use App\Event\HandleModifierEvent;
|
||||
use App\Modifiers\Modifier;
|
||||
use App\Modifier\Modifier;
|
||||
use App\Provider\Repository;
|
||||
use Doctrine\ORM\QueryBuilder;
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
namespace App\Event;
|
||||
|
||||
use App\Modifiers\Modifier;
|
||||
use App\Modifier\Modifier;
|
||||
use App\Provider\Repository;
|
||||
|
||||
class HandleModifierEvent
|
||||
|
27
src/Event/PostProcessEvent.php
Normal file
27
src/Event/PostProcessEvent.php
Normal file
@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
namespace App\Event;
|
||||
|
||||
use App\Modifier\Modifier;
|
||||
use App\Provider\Repository;
|
||||
|
||||
class PostProcessEvent extends HandleModifierEvent
|
||||
{
|
||||
private $data;
|
||||
|
||||
public function __construct($data, Modifier $modifier, Repository $repository, array $meta = [])
|
||||
{
|
||||
parent::__construct($modifier, $repository, $meta);
|
||||
$this->data = $data;
|
||||
}
|
||||
|
||||
public function getData()
|
||||
{
|
||||
return $this->data;
|
||||
}
|
||||
|
||||
public function setData($data): void
|
||||
{
|
||||
$this->data = $data;
|
||||
}
|
||||
}
|
@ -4,7 +4,6 @@
|
||||
namespace App\Exception;
|
||||
|
||||
|
||||
class NonExistentServiceException extends \Exception
|
||||
class NonExistentServiceException extends \LogicException
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,6 @@
|
||||
|
||||
namespace App\Exception;
|
||||
|
||||
class NotSupportedException extends \RuntimeException
|
||||
class NotSupportedException extends \LogicException
|
||||
{
|
||||
}
|
||||
}
|
||||
|
@ -2,10 +2,10 @@
|
||||
|
||||
namespace App\Exception;
|
||||
|
||||
use App\Modifiers\Modifier;
|
||||
use App\Modifier\Modifier;
|
||||
use App\Provider\Repository;
|
||||
|
||||
class UnsupportedModifierException extends \Exception
|
||||
class UnsupportedModifierException extends \LogicException
|
||||
{
|
||||
public static function createFromModifier(Modifier $modifier, Repository $repository)
|
||||
{
|
||||
|
52
src/Handler/Database/FieldFilterDatabaseHandler.php
Normal file
52
src/Handler/Database/FieldFilterDatabaseHandler.php
Normal file
@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
namespace App\Handler\Database;
|
||||
|
||||
use App\Event\HandleDatabaseModifierEvent;
|
||||
use App\Event\HandleModifierEvent;
|
||||
use App\Handler\ModifierHandler;
|
||||
use App\Model\Stop;
|
||||
use App\Modifier\FieldFilter;
|
||||
|
||||
class FieldFilterDatabaseHandler implements ModifierHandler
|
||||
{
|
||||
protected $mapping = [
|
||||
Stop::class => [
|
||||
'name' => 'name',
|
||||
],
|
||||
];
|
||||
|
||||
public function process(HandleModifierEvent $event)
|
||||
{
|
||||
if (!$event instanceof HandleDatabaseModifierEvent) {
|
||||
return;
|
||||
}
|
||||
|
||||
/** @var FieldFilter $modifier */
|
||||
$modifier = $event->getModifier();
|
||||
$builder = $event->getBuilder();
|
||||
$alias = $event->getMeta()['alias'];
|
||||
|
||||
$field = $this->mapFieldName($event->getMeta()['type'], $modifier->getField());
|
||||
$operator = $modifier->getOperator();
|
||||
$value = $modifier->getValue();
|
||||
|
||||
$parameter = sprintf(":%s_%s", $alias, $field);
|
||||
|
||||
$builder
|
||||
->where(sprintf("%s.%s %s %s", $alias, $field, $operator, $parameter))
|
||||
->setParameter($parameter, $value)
|
||||
;
|
||||
}
|
||||
|
||||
protected function mapFieldName(string $class, string $field)
|
||||
{
|
||||
if (!isset($this->mapping[$class][$field])) {
|
||||
throw new \InvalidArgumentException(
|
||||
sprintf("Unable to map field %s of %s into entity field.", $field, $class)
|
||||
);
|
||||
}
|
||||
|
||||
return $this->mapping[$class][$field];
|
||||
}
|
||||
}
|
@ -1,9 +1,9 @@
|
||||
<?php
|
||||
|
||||
namespace App\Handlers\Database;
|
||||
namespace App\Handler\Database;
|
||||
|
||||
use App\Handlers\ModifierHandler;
|
||||
use App\Modifiers\IdFilter;
|
||||
use App\Handler\ModifierHandler;
|
||||
use App\Modifier\IdFilter;
|
||||
use App\Event\HandleDatabaseModifierEvent;
|
||||
use App\Event\HandleModifierEvent;
|
||||
use App\Service\IdUtils;
|
76
src/Handler/Database/IncludeDestinationsDatabaseHandler.php
Normal file
76
src/Handler/Database/IncludeDestinationsDatabaseHandler.php
Normal file
@ -0,0 +1,76 @@
|
||||
<?php
|
||||
|
||||
namespace App\Handler\Database;
|
||||
|
||||
use App\Entity\TrackEntity;
|
||||
use App\Event\PostProcessEvent;
|
||||
use App\Handler\PostProcessingHandler;
|
||||
use App\Model\Destination;
|
||||
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;
|
||||
|
||||
class IncludeDestinationsDatabaseHandler implements PostProcessingHandler
|
||||
{
|
||||
private $em;
|
||||
private $converter;
|
||||
private $id;
|
||||
|
||||
public function __construct(EntityManagerInterface $entityManager, Converter $converter, IdUtils $id)
|
||||
{
|
||||
$this->em = $entityManager;
|
||||
$this->converter = $converter;
|
||||
$this->id = $id;
|
||||
}
|
||||
|
||||
public function process(PostProcessEvent $event)
|
||||
{
|
||||
$provider = $event->getMeta()['provider'];
|
||||
$stops = $event
|
||||
->getData()
|
||||
->map(t\property('id'))
|
||||
->map(f\apply([$this->id, 'generate'], $provider))
|
||||
->all();
|
||||
|
||||
$destinations = collect($this->em->createQueryBuilder()
|
||||
->select('t', 'tl', 'f', 'fs', 'ts')
|
||||
->from(TrackEntity::class, 't')
|
||||
->join('t.stopsInTrack', 'ts')
|
||||
->join('t.line', 'tl')
|
||||
->where('ts.stop IN (:stops)')
|
||||
->join('t.final', 'f')
|
||||
->join('f.stop', 'fs')
|
||||
->getQuery()
|
||||
->execute(['stops' => $stops]))
|
||||
->reduce(function ($grouped, TrackEntity $track) {
|
||||
foreach ($track->getStopsInTrack()->map(t\property('stop'))->map(t\property('id')) as $stop) {
|
||||
$grouped[$stop] = ($grouped[$stop] ?? collect())->add($track);
|
||||
}
|
||||
|
||||
return $grouped;
|
||||
}, collect())
|
||||
->map(function (Collection $tracks) {
|
||||
return $tracks
|
||||
->groupBy(function (TrackEntity $track) {
|
||||
return $track->getFinal()->getStop()->getId();
|
||||
})->map(function (Collection $tracks, $id) {
|
||||
return Destination::createFromArray([
|
||||
'stop' => $this->converter->convert($tracks->first()->getFinal()->getStop()),
|
||||
'lines' => $tracks
|
||||
->map(t\property('line'))
|
||||
->unique(t\property('id'))
|
||||
->map(f\ref([$this->converter, 'convert']))
|
||||
->values(),
|
||||
]);
|
||||
})->values();
|
||||
});
|
||||
|
||||
$event->getData()->each(function (Stop $stop) use ($provider, $destinations) {
|
||||
$stop->setDestinations($destinations[$this->id->generate($provider, $stop->getId())]);
|
||||
});
|
||||
}
|
||||
}
|
@ -1,11 +1,11 @@
|
||||
<?php
|
||||
|
||||
namespace App\Handlers\Database;
|
||||
namespace App\Handler\Database;
|
||||
|
||||
use App\Event\HandleDatabaseModifierEvent;
|
||||
use App\Event\HandleModifierEvent;
|
||||
use App\Handlers\ModifierHandler;
|
||||
use App\Modifiers\Limit;
|
||||
use App\Handler\ModifierHandler;
|
||||
use App\Modifier\Limit;
|
||||
|
||||
class LimitDatabaseHandler implements ModifierHandler
|
||||
{
|
@ -1,6 +1,6 @@
|
||||
<?php
|
||||
|
||||
namespace App\Handlers;
|
||||
namespace App\Handler;
|
||||
|
||||
use App\Event\HandleModifierEvent;
|
||||
|
11
src/Handler/PostProcessingHandler.php
Normal file
11
src/Handler/PostProcessingHandler.php
Normal file
@ -0,0 +1,11 @@
|
||||
<?php
|
||||
|
||||
namespace App\Handler;
|
||||
|
||||
use App\Event\HandleModifierEvent;
|
||||
use App\Event\PostProcessEvent;
|
||||
|
||||
interface PostProcessingHandler
|
||||
{
|
||||
public function process(PostProcessEvent $event);
|
||||
}
|
37
src/Modifier/FieldFilter.php
Normal file
37
src/Modifier/FieldFilter.php
Normal file
@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
namespace App\Modifier;
|
||||
|
||||
class FieldFilter implements Modifier
|
||||
{
|
||||
private $field;
|
||||
private $value;
|
||||
private $operator;
|
||||
|
||||
public function __construct(string $field, $value, string $operator = '=')
|
||||
{
|
||||
$this->field = $field;
|
||||
$this->value = $value;
|
||||
$this->operator = $operator;
|
||||
}
|
||||
|
||||
public static function contains(string $field, string $value)
|
||||
{
|
||||
return new static($field, "%$value%", 'LIKE');
|
||||
}
|
||||
|
||||
public function getField(): string
|
||||
{
|
||||
return $this->field;
|
||||
}
|
||||
|
||||
public function getValue()
|
||||
{
|
||||
return $this->value;
|
||||
}
|
||||
|
||||
public function getOperator(): string
|
||||
{
|
||||
return $this->operator;
|
||||
}
|
||||
}
|
@ -1,9 +1,9 @@
|
||||
<?php
|
||||
|
||||
namespace App\Modifiers;
|
||||
namespace App\Modifier;
|
||||
|
||||
use App\Exception\InvalidOptionException;
|
||||
use App\Modifiers\Modifier;
|
||||
use App\Modifier\Modifier;
|
||||
|
||||
class IdFilter implements Modifier
|
||||
{
|
7
src/Modifier/IncludeDestinations.php
Normal file
7
src/Modifier/IncludeDestinations.php
Normal file
@ -0,0 +1,7 @@
|
||||
<?php
|
||||
|
||||
namespace App\Modifier;
|
||||
|
||||
class IncludeDestinations implements Modifier
|
||||
{
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
<?php
|
||||
|
||||
namespace App\Modifiers;
|
||||
namespace App\Modifier;
|
||||
|
||||
class Limit implements Modifier
|
||||
{
|
@ -1,6 +1,6 @@
|
||||
<?php
|
||||
|
||||
namespace App\Modifiers;
|
||||
namespace App\Modifier;
|
||||
|
||||
interface Modifier
|
||||
{
|
@ -4,8 +4,17 @@ namespace App\Provider\Database;
|
||||
|
||||
use App\Entity\ProviderEntity;
|
||||
use App\Event\HandleDatabaseModifierEvent;
|
||||
use App\Event\PostProcessEvent;
|
||||
use App\Exception\UnsupportedModifierException;
|
||||
use App\Handler\Database\IdFilterDatabaseHandler;
|
||||
use App\Handler\Database\LimitDatabaseHandler;
|
||||
use App\Handler\Database\FieldFilterDatabaseHandler;
|
||||
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\Provider\Repository;
|
||||
use App\Service\Converter;
|
||||
use App\Service\IdUtils;
|
||||
@ -71,21 +80,60 @@ abstract class DatabaseRepository implements ServiceSubscriberInterface, Reposit
|
||||
|
||||
protected function processQueryBuilder(QueryBuilder $builder, iterable $modifiers, array $meta = [])
|
||||
{
|
||||
$reducers = [];
|
||||
|
||||
foreach ($modifiers as $modifier) {
|
||||
$event = new HandleDatabaseModifierEvent($modifier, $this, $builder, array_merge([
|
||||
'provider' => $this->provider,
|
||||
], $meta));
|
||||
$handler = $this->getHandler($modifier);
|
||||
|
||||
$class = get_class($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 (!$this->handlers->has($class)) {
|
||||
throw UnsupportedModifierException::createFromModifier($modifier, $this);
|
||||
$handler->process($event);
|
||||
|
||||
return $event->getData();
|
||||
};
|
||||
break;
|
||||
|
||||
default:
|
||||
$event = new HandleDatabaseModifierEvent($modifier, $this, $builder, array_merge([
|
||||
'provider' => $this->provider,
|
||||
], $meta));
|
||||
|
||||
$handler->process($event);
|
||||
break;
|
||||
}
|
||||
|
||||
$handler = $this->handlers->get($class);
|
||||
|
||||
$handler->process($event);
|
||||
}
|
||||
|
||||
return collect($reducers);
|
||||
}
|
||||
|
||||
protected function allFromQueryBuilder(QueryBuilder $builder, iterable $modifiers, array $meta = [])
|
||||
{
|
||||
$reducers = $this->processQueryBuilder($builder, $modifiers, $meta);
|
||||
|
||||
return $reducers->reduce(function ($result, $reducer) {
|
||||
return $reducer($result);
|
||||
}, collect($builder->getQuery()->execute())->map(\Closure::fromCallable([$this, 'convert'])));
|
||||
}
|
||||
|
||||
public function first(Modifier ...$modifiers)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -106,6 +154,10 @@ abstract class DatabaseRepository implements ServiceSubscriberInterface, Reposit
|
||||
*/
|
||||
public static function getSubscribedServices()
|
||||
{
|
||||
return static::getHandlers();
|
||||
return array_merge([
|
||||
IdFilter::class => IdFilterDatabaseHandler::class,
|
||||
Limit::class => LimitDatabaseHandler::class,
|
||||
FieldFilter::class => FieldFilterDatabaseHandler::class,
|
||||
], static::getHandlers());
|
||||
}
|
||||
}
|
||||
|
@ -4,24 +4,19 @@ namespace App\Provider\Database;
|
||||
|
||||
use App\Entity\LineEntity;
|
||||
use App\Event\HandleDatabaseModifierEvent;
|
||||
use App\Handlers\Database\LimitDatabaseHandler;
|
||||
use App\Handlers\Database\IdFilterDatabaseHandler;
|
||||
use App\Handlers\ModifierHandler;
|
||||
use App\Handler\Database\LimitDatabaseHandler;
|
||||
use App\Handler\Database\IdFilterDatabaseHandler;
|
||||
use App\Handler\ModifierHandler;
|
||||
use App\Model\Line;
|
||||
use App\Modifiers\Limit;
|
||||
use App\Modifiers\IdFilter;
|
||||
use App\Modifier\Limit;
|
||||
use App\Modifier\IdFilter;
|
||||
use App\Provider\LineRepository;
|
||||
use App\Modifiers\Modifier;
|
||||
use App\Modifier\Modifier;
|
||||
use Tightenco\Collect\Support\Collection;
|
||||
use Kadet\Functional as f;
|
||||
|
||||
class GenericLineRepository extends DatabaseRepository implements LineRepository
|
||||
{
|
||||
public function first(Modifier ...$modifiers)
|
||||
{
|
||||
return $this->all(Limit::count(1), ...$modifiers)->first();
|
||||
}
|
||||
|
||||
public function all(Modifier ...$modifiers): Collection
|
||||
{
|
||||
$builder = $this->em
|
||||
@ -30,21 +25,10 @@ class GenericLineRepository extends DatabaseRepository implements LineRepository
|
||||
->select('line')
|
||||
;
|
||||
|
||||
$this->processQueryBuilder($builder, $modifiers, [
|
||||
return $this->allFromQueryBuilder($builder, $modifiers, [
|
||||
'alias' => 'line',
|
||||
'entity' => LineEntity::class,
|
||||
'type' => Line::class,
|
||||
]);
|
||||
|
||||
return collect($builder->getQuery()->execute())->map(f\ref([$this, 'convert']));
|
||||
}
|
||||
|
||||
/** @return ModifierHandler[] */
|
||||
protected static function getHandlers()
|
||||
{
|
||||
return [
|
||||
IdFilter::class => IdFilterDatabaseHandler::class,
|
||||
Limit::class => LimitDatabaseHandler::class,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
@ -3,89 +3,34 @@
|
||||
namespace App\Provider\Database;
|
||||
|
||||
use App\Entity\StopEntity;
|
||||
use App\Entity\TrackEntity;
|
||||
use App\Model\Destination;
|
||||
use App\Handler\Database\IncludeDestinationsDatabaseHandler;
|
||||
use App\Model\Stop;
|
||||
use App\Modifier\Modifier;
|
||||
use App\Modifier\IncludeDestinations;
|
||||
use App\Provider\StopRepository;
|
||||
use Kadet\Functional as f;
|
||||
use Kadet\Functional\Transforms as t;
|
||||
use Tightenco\Collect\Support\Collection;
|
||||
|
||||
class GenericStopRepository extends DatabaseRepository implements StopRepository
|
||||
{
|
||||
public function getAll(): Collection
|
||||
public function all(Modifier ...$modifiers): Collection
|
||||
{
|
||||
$stops = $this->em->getRepository(StopEntity::class)->findAll();
|
||||
$builder = $this->em
|
||||
->createQueryBuilder()
|
||||
->from(StopEntity::class, 'stop')
|
||||
->select('stop')
|
||||
;
|
||||
|
||||
return collect($stops)->map(f\ref([$this, 'convert']));
|
||||
}
|
||||
|
||||
public function getById($id): ?Stop
|
||||
{
|
||||
$id = $this->id->generate($this->provider, $id);
|
||||
$stop = $this->em->getRepository(StopEntity::class)->find($id);
|
||||
|
||||
return $this->convert($stop);
|
||||
}
|
||||
|
||||
public function getManyById($ids): Collection
|
||||
{
|
||||
$ids = collect($ids)->map(f\apply(f\ref([$this->id, 'generate']), $this->provider));
|
||||
$stops = $this->em->getRepository(StopEntity::class)->findBy(['id' => $ids->all()]);
|
||||
|
||||
return collect($stops)->map(f\ref([$this, 'convert']));
|
||||
}
|
||||
|
||||
public function findByName(string $name): Collection
|
||||
{
|
||||
$query = $this->em->createQueryBuilder()
|
||||
->select('s')
|
||||
->from(StopEntity::class, 's')
|
||||
->where('s.name LIKE :name')
|
||||
->getQuery();
|
||||
|
||||
$stops = collect($query->execute([':name' => "%$name%"]));
|
||||
|
||||
$destinations = collect($this->em->createQueryBuilder()
|
||||
->select('t', 'tl', 'f', 'fs', 'ts')
|
||||
->from(TrackEntity::class, 't')
|
||||
->join('t.stopsInTrack', 'ts')
|
||||
->join('t.line', 'tl')
|
||||
->where('ts.stop IN (:stops)')
|
||||
->join('t.final', 'f')
|
||||
->join('f.stop', 'fs')
|
||||
->getQuery()
|
||||
->execute(['stops' => $stops->map(t\property('id'))->all()]))
|
||||
->reduce(function ($grouped, TrackEntity $track) {
|
||||
foreach ($track->getStopsInTrack()->map(t\property('stop'))->map(t\property('id')) as $stop) {
|
||||
$grouped[$stop] = ($grouped[$stop] ?? collect())->add($track);
|
||||
}
|
||||
|
||||
return $grouped;
|
||||
}, collect())
|
||||
->map(function (Collection $tracks) {
|
||||
return $tracks
|
||||
->groupBy(function (TrackEntity $track) {
|
||||
return $track->getFinal()->getStop()->getId();
|
||||
})->map(function (Collection $tracks, $id) {
|
||||
return Destination::createFromArray([
|
||||
'stop' => $this->convert($tracks->first()->getFinal()->getStop()),
|
||||
'lines' => $tracks
|
||||
->map(t\property('line'))
|
||||
->unique(t\property('id'))
|
||||
->map(f\ref([$this, 'convert']))
|
||||
->values(),
|
||||
]);
|
||||
})->values();
|
||||
});
|
||||
|
||||
return collect($stops)->map(f\ref([$this, 'convert']))->each(function (Stop $stop) use ($destinations) {
|
||||
$stop->setDestinations($destinations[$this->id->generate($this->provider, $stop->getId())]);
|
||||
});
|
||||
return $this->allFromQueryBuilder($builder, $modifiers, [
|
||||
'alias' => 'stop',
|
||||
'entity' => StopEntity::class,
|
||||
'type' => Stop::class,
|
||||
]);
|
||||
}
|
||||
|
||||
protected static function getHandlers()
|
||||
{
|
||||
return [];
|
||||
return array_merge(parent::getHandlers(), [
|
||||
IncludeDestinations::class => IncludeDestinationsDatabaseHandler::class,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
@ -3,6 +3,7 @@
|
||||
namespace App\Provider\Dummy;
|
||||
|
||||
use App\Model\Stop;
|
||||
use App\Modifier\Modifier;
|
||||
use App\Provider\StopRepository;
|
||||
use App\Service\Proxy\ReferenceFactory;
|
||||
use Tightenco\Collect\Support\Collection;
|
||||
@ -41,4 +42,14 @@ class DummyStopRepository implements StopRepository
|
||||
{
|
||||
return collect();
|
||||
}
|
||||
|
||||
public function first(Modifier ...$modifiers)
|
||||
{
|
||||
// TODO: Implement first() method.
|
||||
}
|
||||
|
||||
public function all(Modifier ...$modifiers): Collection
|
||||
{
|
||||
// TODO: Implement all() method.
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
namespace App\Provider;
|
||||
|
||||
use App\Modifiers\Modifier;
|
||||
use App\Modifier\Modifier;
|
||||
use Tightenco\Collect\Support\Collection;
|
||||
|
||||
interface FluentRepository extends Repository
|
||||
|
@ -7,10 +7,6 @@ namespace App\Provider;
|
||||
use App\Model\Stop;
|
||||
use Tightenco\Collect\Support\Collection;
|
||||
|
||||
interface StopRepository extends Repository
|
||||
interface StopRepository extends FluentRepository
|
||||
{
|
||||
public function getAll(): Collection;
|
||||
public function getById($id): ?Stop;
|
||||
public function getManyById($ids): Collection;
|
||||
public function findByName(string $name): Collection;
|
||||
}
|
||||
|
@ -6,7 +6,7 @@ use App\Model\Departure;
|
||||
use App\Model\Line;
|
||||
use App\Model\Stop;
|
||||
use App\Model\Vehicle;
|
||||
use App\Modifiers\IdFilter;
|
||||
use App\Modifier\IdFilter;
|
||||
use App\Provider\Database\GenericScheduleRepository;
|
||||
use App\Provider\DepartureRepository;
|
||||
use App\Provider\LineRepository;
|
||||
|
@ -11,6 +11,7 @@ class IdUtils
|
||||
|
||||
public function generate(ProviderEntity $provider, $id)
|
||||
{
|
||||
// todo: use array cache if not fast enough
|
||||
return sprintf('%s%s%s', $provider->getId(), self::DELIMITER, $id);
|
||||
}
|
||||
|
||||
@ -23,4 +24,4 @@ class IdUtils
|
||||
{
|
||||
return $this->strip($entity->getId());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user