Add paginator to properly handle limits

This commit is contained in:
Kacper Donat 2020-03-16 20:32:15 +01:00
parent 3e695bfef7
commit ae05646888
8 changed files with 49 additions and 19 deletions

View File

@ -5,6 +5,7 @@ namespace App\Controller\Api\v1;
use App\Controller\Controller;
use App\Model\Trip;
use App\Modifier\IdFilter;
use App\Modifier\With;
use App\Provider\TripRepository;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
@ -19,7 +20,7 @@ class TripController extends Controller
*/
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));
}

View File

@ -8,6 +8,7 @@ use App\Handler\ModifierHandler;
use App\Model\ScheduledStop;
use App\Model\Track;
use App\Model\TrackStop;
use App\Model\Trip;
use App\Modifier\RelatedFilter;
use App\Service\EntityReferenceFactory;
use App\Service\IdUtils;
@ -21,6 +22,9 @@ class GenericWithDatabaseHandler implements ModifierHandler
'line' => 'line',
'stops' => 'stopsInTrack',
],
Trip::class => [
'schedule' => 'stops.stop',
],
TrackStop::class => [
'track' => 'track',
],

View File

@ -25,6 +25,7 @@ use App\Service\HandlerProvider;
use App\Service\IdUtils;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\QueryBuilder;
use Doctrine\ORM\Tools\Pagination\Paginator;
abstract class DatabaseRepository implements Repository
{
@ -128,7 +129,10 @@ abstract class DatabaseRepository implements Repository
$builder->setMaxResults(self::DEFAULT_LIMIT);
$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 $reducer($result);

View File

@ -15,9 +15,7 @@ class GenericTripRepository extends DatabaseRepository implements TripRepository
$builder = $this->em
->createQueryBuilder()
->from(TripEntity::class, 'trip')
->join('trip.stops', 'ts')
->join('ts.stop', 's')
->select('t', 'ts');
->select('trip');
return $this->allFromQueryBuilder($builder, $modifiers, [
'alias' => 'trip',

View File

@ -174,7 +174,7 @@ class ZtmGdanskDepartureRepository implements DepartureRepository
}
return setup(clone $real, function (Departure $departure) use ($scheduled, $real) {
$departure->setDisplay($real->getDisplay());
$departure->setDisplay($this->extractDisplayFromScheduledStop($scheduled));
$departure->setTrack($scheduled->getTrack());
$departure->setTrip($scheduled->getTrip());
});
@ -183,7 +183,7 @@ class ZtmGdanskDepartureRepository implements DepartureRepository
private function convertScheduledStopToDeparture(ScheduledStop $stop): Departure
{
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->setTrack($stop->getTrack());
$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)
{
$result = [];

View File

@ -2,10 +2,7 @@
namespace App\Service;
use Hoa\Iterator\Recursive\Recursive;
use Symfony\Component\DependencyInjection\ServiceLocator;
use function Kadet\Functional\Predicates\equals;
use function Kadet\Functional\Predicates\method;
use Tightenco\Collect\Support\Collection;
class AggregateConverter implements Converter
{
@ -40,4 +37,9 @@ class AggregateConverter implements Converter
return $converter->supports($entity);
});
}
public function getConverters(): Collection
{
return clone $this->converters;
}
}

View File

@ -0,0 +1,8 @@
<?php
namespace App\Service;
interface CacheableConverter extends Converter
{
public function flushCache();
}

View File

@ -11,17 +11,19 @@ use Kadet\Functional as f;
use Kadet\Functional\Transforms as t;
use const Kadet\Functional\_;
final class EntityConverter implements Converter, RecursiveConverter
final class EntityConverter implements Converter, RecursiveConverter, CacheableConverter
{
use RecursiveConverterTrait;
private $id;
private $reference;
private $cache;
public function __construct(IdUtils $id, ReferenceFactory $reference)
{
$this->id = $id;
$this->reference = $reference;
$this->cache = [];
}
/**
@ -30,21 +32,22 @@ final class EntityConverter implements Converter, RecursiveConverter
*
* @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)) {
return $cache[$key];
if (array_key_exists($key = get_class($entity) . ':' . $this->getId($entity), $this->cache)) {
return $this->cache[$key];
}
if ($entity instanceof Proxy && !$entity->__isInitialized()) {
return $this->reference($entity);
}
$result = $this->create($entity);
$cache = $cache + [$key => $result];
$convert = function ($entity) use ($cache) {
$result = $this->create($entity);
$this->cache[$key] = $result;
$convert = function ($entity) {
return $this->supports($entity)
? $this->convert($entity, $cache)
? $this->convert($entity)
: $this->parent->convert($entity);
};
@ -173,4 +176,9 @@ final class EntityConverter implements Converter, RecursiveConverter
{
return $entity instanceof Entity;
}
public function flushCache()
{
$this->cache = [];
}
}