diff --git a/src/Controller/Api/v1/TripController.php b/src/Controller/Api/v1/TripController.php index 031f39a..b91c8cb 100644 --- a/src/Controller/Api/v1/TripController.php +++ b/src/Controller/Api/v1/TripController.php @@ -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)); } diff --git a/src/Handler/Database/GenericWithDatabaseHandler.php b/src/Handler/Database/GenericWithDatabaseHandler.php index 35dc3b9..26445c7 100644 --- a/src/Handler/Database/GenericWithDatabaseHandler.php +++ b/src/Handler/Database/GenericWithDatabaseHandler.php @@ -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', ], diff --git a/src/Provider/Database/DatabaseRepository.php b/src/Provider/Database/DatabaseRepository.php index 898a431..7e7f86b 100644 --- a/src/Provider/Database/DatabaseRepository.php +++ b/src/Provider/Database/DatabaseRepository.php @@ -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); diff --git a/src/Provider/Database/GenericTripRepository.php b/src/Provider/Database/GenericTripRepository.php index 6ffd652..2a10b33 100644 --- a/src/Provider/Database/GenericTripRepository.php +++ b/src/Provider/Database/GenericTripRepository.php @@ -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', diff --git a/src/Provider/ZtmGdansk/ZtmGdanskDepartureRepository.php b/src/Provider/ZtmGdansk/ZtmGdanskDepartureRepository.php index eb7f401..8e8dbc4 100644 --- a/src/Provider/ZtmGdansk/ZtmGdanskDepartureRepository.php +++ b/src/Provider/ZtmGdansk/ZtmGdanskDepartureRepository.php @@ -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 = []; diff --git a/src/Service/AggregateConverter.php b/src/Service/AggregateConverter.php index 45cc308..ef180c7 100644 --- a/src/Service/AggregateConverter.php +++ b/src/Service/AggregateConverter.php @@ -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; + } } diff --git a/src/Service/CacheableConverter.php b/src/Service/CacheableConverter.php new file mode 100644 index 0000000..cf590df --- /dev/null +++ b/src/Service/CacheableConverter.php @@ -0,0 +1,8 @@ +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 = []; + } }