#35 - Add paginator to properly handle limits
This commit is contained in:
parent
db30d69cdb
commit
720327424a
@ -5,6 +5,7 @@ namespace App\Controller\Api\v1;
|
|||||||
use App\Controller\Controller;
|
use App\Controller\Controller;
|
||||||
use App\Model\Trip;
|
use App\Model\Trip;
|
||||||
use App\Modifier\IdFilter;
|
use App\Modifier\IdFilter;
|
||||||
|
use App\Modifier\With;
|
||||||
use App\Provider\TripRepository;
|
use App\Provider\TripRepository;
|
||||||
use Symfony\Component\HttpFoundation\Response;
|
use Symfony\Component\HttpFoundation\Response;
|
||||||
use Symfony\Component\Routing\Annotation\Route;
|
use Symfony\Component\Routing\Annotation\Route;
|
||||||
@ -19,7 +20,7 @@ class TripController extends Controller
|
|||||||
*/
|
*/
|
||||||
public function one($id, TripRepository $repository)
|
public function one($id, TripRepository $repository)
|
||||||
{
|
{
|
||||||
$trip = $repository->all(new IdFilter($id));
|
$trip = $repository->first(new IdFilter($id), new With('schedule'));
|
||||||
|
|
||||||
return $this->json($trip, Response::HTTP_OK, [], $this->serializerContextFactory->create(Trip::class));
|
return $this->json($trip, Response::HTTP_OK, [], $this->serializerContextFactory->create(Trip::class));
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@ use App\Handler\ModifierHandler;
|
|||||||
use App\Model\ScheduledStop;
|
use App\Model\ScheduledStop;
|
||||||
use App\Model\Track;
|
use App\Model\Track;
|
||||||
use App\Model\TrackStop;
|
use App\Model\TrackStop;
|
||||||
|
use App\Model\Trip;
|
||||||
use App\Modifier\RelatedFilter;
|
use App\Modifier\RelatedFilter;
|
||||||
use App\Service\EntityReferenceFactory;
|
use App\Service\EntityReferenceFactory;
|
||||||
use App\Service\IdUtils;
|
use App\Service\IdUtils;
|
||||||
@ -21,6 +22,9 @@ class GenericWithDatabaseHandler implements ModifierHandler
|
|||||||
'line' => 'line',
|
'line' => 'line',
|
||||||
'stops' => 'stopsInTrack',
|
'stops' => 'stopsInTrack',
|
||||||
],
|
],
|
||||||
|
Trip::class => [
|
||||||
|
'schedule' => 'stops.stop',
|
||||||
|
],
|
||||||
TrackStop::class => [
|
TrackStop::class => [
|
||||||
'track' => 'track',
|
'track' => 'track',
|
||||||
],
|
],
|
||||||
|
@ -25,6 +25,7 @@ use App\Service\HandlerProvider;
|
|||||||
use App\Service\IdUtils;
|
use App\Service\IdUtils;
|
||||||
use Doctrine\ORM\EntityManagerInterface;
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
use Doctrine\ORM\QueryBuilder;
|
use Doctrine\ORM\QueryBuilder;
|
||||||
|
use Doctrine\ORM\Tools\Pagination\Paginator;
|
||||||
|
|
||||||
abstract class DatabaseRepository implements Repository
|
abstract class DatabaseRepository implements Repository
|
||||||
{
|
{
|
||||||
@ -128,7 +129,10 @@ abstract class DatabaseRepository implements Repository
|
|||||||
$builder->setMaxResults(self::DEFAULT_LIMIT);
|
$builder->setMaxResults(self::DEFAULT_LIMIT);
|
||||||
|
|
||||||
$reducers = $this->processQueryBuilder($builder, $modifiers, $meta);
|
$reducers = $this->processQueryBuilder($builder, $modifiers, $meta);
|
||||||
$result = collect($builder->getQuery()->execute())->map(\Closure::fromCallable([$this, 'convert']));
|
$query = $builder->getQuery();
|
||||||
|
|
||||||
|
$paginator = new Paginator($query);
|
||||||
|
$result = collect($paginator)->map(\Closure::fromCallable([$this, 'convert']));
|
||||||
|
|
||||||
return $reducers->reduce(function ($result, $reducer) {
|
return $reducers->reduce(function ($result, $reducer) {
|
||||||
return $reducer($result);
|
return $reducer($result);
|
||||||
|
@ -15,9 +15,7 @@ class GenericTripRepository extends DatabaseRepository implements TripRepository
|
|||||||
$builder = $this->em
|
$builder = $this->em
|
||||||
->createQueryBuilder()
|
->createQueryBuilder()
|
||||||
->from(TripEntity::class, 'trip')
|
->from(TripEntity::class, 'trip')
|
||||||
->join('trip.stops', 'ts')
|
->select('trip');
|
||||||
->join('ts.stop', 's')
|
|
||||||
->select('t', 'ts');
|
|
||||||
|
|
||||||
return $this->allFromQueryBuilder($builder, $modifiers, [
|
return $this->allFromQueryBuilder($builder, $modifiers, [
|
||||||
'alias' => 'trip',
|
'alias' => 'trip',
|
||||||
|
@ -174,7 +174,7 @@ class ZtmGdanskDepartureRepository implements DepartureRepository
|
|||||||
}
|
}
|
||||||
|
|
||||||
return setup(clone $real, function (Departure $departure) use ($scheduled, $real) {
|
return setup(clone $real, function (Departure $departure) use ($scheduled, $real) {
|
||||||
$departure->setDisplay($real->getDisplay());
|
$departure->setDisplay($this->extractDisplayFromScheduledStop($scheduled));
|
||||||
$departure->setTrack($scheduled->getTrack());
|
$departure->setTrack($scheduled->getTrack());
|
||||||
$departure->setTrip($scheduled->getTrip());
|
$departure->setTrip($scheduled->getTrip());
|
||||||
});
|
});
|
||||||
@ -183,7 +183,7 @@ class ZtmGdanskDepartureRepository implements DepartureRepository
|
|||||||
private function convertScheduledStopToDeparture(ScheduledStop $stop): Departure
|
private function convertScheduledStopToDeparture(ScheduledStop $stop): Departure
|
||||||
{
|
{
|
||||||
return setup(new Departure(), function (Departure $converted) use ($stop) {
|
return setup(new Departure(), function (Departure $converted) use ($stop) {
|
||||||
$converted->setDisplay($stop->getTrack()->getDestination()->getName());
|
$converted->setDisplay($this->extractDisplayFromScheduledStop($stop));
|
||||||
$converted->setLine($stop->getTrack()->getLine());
|
$converted->setLine($stop->getTrack()->getLine());
|
||||||
$converted->setTrack($stop->getTrack());
|
$converted->setTrack($stop->getTrack());
|
||||||
$converted->setTrip($stop->getTrip());
|
$converted->setTrip($stop->getTrip());
|
||||||
@ -192,6 +192,11 @@ class ZtmGdanskDepartureRepository implements DepartureRepository
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function extractDisplayFromScheduledStop(ScheduledStop $stop)
|
||||||
|
{
|
||||||
|
return $stop->getTrack()->getDestination()->getName();
|
||||||
|
}
|
||||||
|
|
||||||
private function extractModifiers(iterable $modifiers)
|
private function extractModifiers(iterable $modifiers)
|
||||||
{
|
{
|
||||||
$result = [];
|
$result = [];
|
||||||
|
@ -2,10 +2,7 @@
|
|||||||
|
|
||||||
namespace App\Service;
|
namespace App\Service;
|
||||||
|
|
||||||
use Hoa\Iterator\Recursive\Recursive;
|
use Tightenco\Collect\Support\Collection;
|
||||||
use Symfony\Component\DependencyInjection\ServiceLocator;
|
|
||||||
use function Kadet\Functional\Predicates\equals;
|
|
||||||
use function Kadet\Functional\Predicates\method;
|
|
||||||
|
|
||||||
class AggregateConverter implements Converter
|
class AggregateConverter implements Converter
|
||||||
{
|
{
|
||||||
@ -40,4 +37,9 @@ class AggregateConverter implements Converter
|
|||||||
return $converter->supports($entity);
|
return $converter->supports($entity);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getConverters(): Collection
|
||||||
|
{
|
||||||
|
return clone $this->converters;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
8
src/Service/CacheableConverter.php
Normal file
8
src/Service/CacheableConverter.php
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Service;
|
||||||
|
|
||||||
|
interface CacheableConverter extends Converter
|
||||||
|
{
|
||||||
|
public function flushCache();
|
||||||
|
}
|
@ -11,17 +11,19 @@ use Kadet\Functional as f;
|
|||||||
use Kadet\Functional\Transforms as t;
|
use Kadet\Functional\Transforms as t;
|
||||||
use const Kadet\Functional\_;
|
use const Kadet\Functional\_;
|
||||||
|
|
||||||
final class EntityConverter implements Converter, RecursiveConverter
|
final class EntityConverter implements Converter, RecursiveConverter, CacheableConverter
|
||||||
{
|
{
|
||||||
use RecursiveConverterTrait;
|
use RecursiveConverterTrait;
|
||||||
|
|
||||||
private $id;
|
private $id;
|
||||||
private $reference;
|
private $reference;
|
||||||
|
private $cache;
|
||||||
|
|
||||||
public function __construct(IdUtils $id, ReferenceFactory $reference)
|
public function __construct(IdUtils $id, ReferenceFactory $reference)
|
||||||
{
|
{
|
||||||
$this->id = $id;
|
$this->id = $id;
|
||||||
$this->reference = $reference;
|
$this->reference = $reference;
|
||||||
|
$this->cache = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -30,21 +32,22 @@ final class EntityConverter implements Converter, RecursiveConverter
|
|||||||
*
|
*
|
||||||
* @return Line|Track|Stop|Operator|Trip|ScheduledStop
|
* @return Line|Track|Stop|Operator|Trip|ScheduledStop
|
||||||
*/
|
*/
|
||||||
public function convert($entity, array $cache = [])
|
public function convert($entity)
|
||||||
{
|
{
|
||||||
if (array_key_exists($key = get_class($entity) . ':' . $this->getId($entity), $cache)) {
|
if (array_key_exists($key = get_class($entity) . ':' . $this->getId($entity), $this->cache)) {
|
||||||
return $cache[$key];
|
return $this->cache[$key];
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($entity instanceof Proxy && !$entity->__isInitialized()) {
|
if ($entity instanceof Proxy && !$entity->__isInitialized()) {
|
||||||
return $this->reference($entity);
|
return $this->reference($entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
$result = $this->create($entity);
|
$result = $this->create($entity);
|
||||||
$cache = $cache + [$key => $result];
|
$this->cache[$key] = $result;
|
||||||
$convert = function ($entity) use ($cache) {
|
|
||||||
|
$convert = function ($entity) {
|
||||||
return $this->supports($entity)
|
return $this->supports($entity)
|
||||||
? $this->convert($entity, $cache)
|
? $this->convert($entity)
|
||||||
: $this->parent->convert($entity);
|
: $this->parent->convert($entity);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -173,4 +176,9 @@ final class EntityConverter implements Converter, RecursiveConverter
|
|||||||
{
|
{
|
||||||
return $entity instanceof Entity;
|
return $entity instanceof Entity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function flushCache()
|
||||||
|
{
|
||||||
|
$this->cache = [];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user