Track stops fluent quering
This commit is contained in:
parent
9f3f6bf22b
commit
a9a0f2f413
@ -4,7 +4,7 @@ namespace App\Controller\Api\v1;
|
||||
|
||||
use App\Controller\Controller;
|
||||
use App\Model\Stop;
|
||||
use App\Model\Track;
|
||||
use App\Model\TrackStop;
|
||||
use App\Model\StopGroup;
|
||||
use App\Modifier\IdFilter;
|
||||
use App\Modifier\FieldFilter;
|
||||
@ -12,7 +12,6 @@ use App\Modifier\IncludeDestinations;
|
||||
use App\Modifier\RelatedFilter;
|
||||
use App\Provider\StopRepository;
|
||||
use App\Provider\TrackRepository;
|
||||
use App\Service\Proxy\ReferenceFactory;
|
||||
use Nelmio\ApiDocBundle\Annotation\Model;
|
||||
use Swagger\Annotations as SWG;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
@ -105,21 +104,12 @@ class StopsController extends Controller
|
||||
* @SWG\Response(
|
||||
* response=200,
|
||||
* description="Returns specific stop referenced via identificator.",
|
||||
* @SWG\Schema(type="object", properties={
|
||||
* @SWG\Property(property="track", type="object", ref=@Model(type=Track::class)),
|
||||
* @SWG\Property(property="order", type="integer", minimum="0")
|
||||
* })
|
||||
* @SWG\Schema(ref=@Model(type=TrackStop::class))
|
||||
* )
|
||||
*
|
||||
* @SWG\Tag(name="Tracks")
|
||||
*/
|
||||
public function tracks(ReferenceFactory $reference, TrackRepository $tracks, $id)
|
||||
public function tracks(TrackRepository $tracks, $id)
|
||||
{
|
||||
$stop = $reference->get(Stop::class, $id);
|
||||
|
||||
return $this->json($tracks->getByStop($stop)->map(function ($tuple) {
|
||||
return array_combine(['track', 'order'], $tuple);
|
||||
}));
|
||||
return $this->json($tracks->stops(new RelatedFilter(Stop::reference($id))));
|
||||
}
|
||||
|
||||
public static function group(Collection $stops)
|
||||
|
@ -19,6 +19,7 @@ use function App\Functions\encapsulate;
|
||||
|
||||
/**
|
||||
* @Route("/tracks")
|
||||
* @SWG\Tag(name="Tracks")
|
||||
*/
|
||||
class TracksController extends Controller
|
||||
{
|
||||
@ -27,7 +28,6 @@ class TracksController extends Controller
|
||||
* response=200,
|
||||
* description="Returns all tracks for specific provider, e.g. ZTM Gdańsk.",
|
||||
* )
|
||||
* @SWG\Tag(name="Tracks")
|
||||
* @Route("/", methods={"GET"})
|
||||
*/
|
||||
public function index(Request $request, TrackRepository $repository)
|
||||
@ -37,6 +37,17 @@ class TracksController extends Controller
|
||||
return $this->json($repository->all(...$modifiers));
|
||||
}
|
||||
|
||||
/**
|
||||
* @Route("/stops", methods={"GET"})
|
||||
* @Route("/{track}/stops", methods={"GET"})
|
||||
*/
|
||||
public function stops(Request $request, TrackRepository $repository)
|
||||
{
|
||||
$modifiers = $this->getStopsModifiersFromRequest($request);
|
||||
|
||||
return $this->json($repository->stops(...$modifiers));
|
||||
}
|
||||
|
||||
private function getModifiersFromRequest(Request $request)
|
||||
{
|
||||
if ($request->query->has('stop')) {
|
||||
@ -59,4 +70,27 @@ class TracksController extends Controller
|
||||
yield new IdFilter($id);
|
||||
}
|
||||
}
|
||||
|
||||
private function getStopsModifiersFromRequest(Request $request)
|
||||
{
|
||||
if ($request->query->has('stop')) {
|
||||
$stop = $request->query->get('stop');
|
||||
$stop = Stop::reference($stop);
|
||||
|
||||
yield new RelatedFilter($stop);
|
||||
}
|
||||
|
||||
if ($request->query->has('track') || $request->attributes->has('track')) {
|
||||
$track = $request->get('track');
|
||||
$track = Track::reference($track);
|
||||
|
||||
yield new RelatedFilter($track);
|
||||
}
|
||||
|
||||
if ($request->query->has('id')) {
|
||||
$id = encapsulate($request->query->get('id'));
|
||||
|
||||
yield new IdFilter($id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -45,16 +45,18 @@ class TrackEntity implements Entity, Fillable
|
||||
|
||||
/**
|
||||
* Stops in track
|
||||
* @var StopInTrack[]|Collection
|
||||
* @ORM\OneToMany(targetEntity=StopInTrack::class, fetch="LAZY", mappedBy="track", cascade={"persist"})
|
||||
*
|
||||
* @var TrackStopEntity[]|Collection
|
||||
* @ORM\OneToMany(targetEntity=TrackStopEntity::class, fetch="LAZY", mappedBy="track", cascade={"persist"})
|
||||
* @ORM\OrderBy({"order": "ASC"})
|
||||
*/
|
||||
private $stopsInTrack;
|
||||
|
||||
/**
|
||||
* Final stop in this track.
|
||||
* @var StopInTrack
|
||||
* @ORM\OneToOne(targetEntity=StopInTrack::class, fetch="LAZY")
|
||||
*
|
||||
* @var TrackStopEntity
|
||||
* @ORM\OneToOne(targetEntity=TrackStopEntity::class, fetch="LAZY")
|
||||
*/
|
||||
private $final;
|
||||
|
||||
@ -114,7 +116,7 @@ class TrackEntity implements Entity, Fillable
|
||||
$this->final = $this->stopsInTrack->last();
|
||||
}
|
||||
|
||||
public function getFinal(): StopInTrack
|
||||
public function getFinal(): TrackStopEntity
|
||||
{
|
||||
return $this->final;
|
||||
}
|
||||
|
@ -14,7 +14,7 @@ use Doctrine\ORM\Mapping as ORM;
|
||||
* @ORM\UniqueConstraint(name="stop_in_track_idx", columns={"stop_id", "track_id", "sequence"})
|
||||
* })
|
||||
*/
|
||||
class StopInTrack implements Fillable, Referable
|
||||
class TrackStopEntity implements Fillable, Referable
|
||||
{
|
||||
use FillTrait, ReferableEntityTrait;
|
||||
|
@ -8,9 +8,10 @@ use App\Handler\ModifierHandler;
|
||||
use App\Model\Line;
|
||||
use App\Model\Stop;
|
||||
use App\Model\Track;
|
||||
use App\Model\TrackStop;
|
||||
use App\Modifier\RelatedFilter;
|
||||
use App\Service\IdUtils;
|
||||
use App\Service\ReferenceFactory;
|
||||
use App\Service\EntityReferenceFactory;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Psr\Container\ContainerInterface;
|
||||
use Symfony\Contracts\Service\ServiceSubscriberInterface;
|
||||
@ -18,10 +19,14 @@ use Symfony\Contracts\Service\ServiceSubscriberInterface;
|
||||
class RelatedFilterDatabaseGenericHandler implements ModifierHandler, ServiceSubscriberInterface
|
||||
{
|
||||
protected $mapping = [
|
||||
Track::class => [
|
||||
Track::class => [
|
||||
Line::class => 'line',
|
||||
Stop::class => TrackByStopDatabaseHandler::class,
|
||||
],
|
||||
TrackStop::class => [
|
||||
Stop::class => 'stop',
|
||||
Track::class => 'track',
|
||||
],
|
||||
];
|
||||
|
||||
private $em;
|
||||
@ -33,11 +38,11 @@ class RelatedFilterDatabaseGenericHandler implements ModifierHandler, ServiceSub
|
||||
ContainerInterface $inner,
|
||||
EntityManagerInterface $em,
|
||||
IdUtils $idUtils,
|
||||
ReferenceFactory $references
|
||||
EntityReferenceFactory $references
|
||||
) {
|
||||
$this->inner = $inner;
|
||||
$this->em = $em;
|
||||
$this->id = $idUtils;
|
||||
$this->inner = $inner;
|
||||
$this->em = $em;
|
||||
$this->id = $idUtils;
|
||||
$this->references = $references;
|
||||
}
|
||||
|
||||
@ -71,6 +76,7 @@ class RelatedFilterDatabaseGenericHandler implements ModifierHandler, ServiceSub
|
||||
/** @var ModifierHandler $inner */
|
||||
$inner = $this->inner->get($relationship);
|
||||
$inner->process($event);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@ -80,8 +86,7 @@ class RelatedFilterDatabaseGenericHandler implements ModifierHandler, ServiceSub
|
||||
$builder
|
||||
->join(sprintf('%s.%s', $alias, $relationship), $relationship)
|
||||
->andWhere(sprintf("%s = %s", $relationship, $parameter))
|
||||
->setParameter($parameter, $reference)
|
||||
;
|
||||
->setParameter($parameter, $reference);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -2,18 +2,18 @@
|
||||
|
||||
namespace App\Handler\Database;
|
||||
|
||||
use App\Entity\StopInTrack;
|
||||
use App\Entity\TrackStopEntity;
|
||||
use App\Event\HandleDatabaseModifierEvent;
|
||||
use App\Event\HandleModifierEvent;
|
||||
use App\Handler\ModifierHandler;
|
||||
use App\Modifier\RelatedFilter;
|
||||
use App\Service\ReferenceFactory;
|
||||
use App\Service\EntityReferenceFactory;
|
||||
|
||||
class TrackByStopDatabaseHandler implements ModifierHandler
|
||||
{
|
||||
private $references;
|
||||
|
||||
public function __construct(ReferenceFactory $references)
|
||||
public function __construct(EntityReferenceFactory $references)
|
||||
{
|
||||
$this->references = $references;
|
||||
}
|
||||
|
@ -138,4 +138,4 @@ class Line implements Fillable, Referable
|
||||
{
|
||||
$this->operator = $operator;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4,22 +4,8 @@ namespace App\Model;
|
||||
|
||||
use Carbon\Carbon;
|
||||
|
||||
class ScheduledStop implements Fillable
|
||||
class ScheduledStop extends TrackStop
|
||||
{
|
||||
use FillTrait;
|
||||
|
||||
/**
|
||||
* Stop (as a place) related to that scheduled bus stop
|
||||
* @var Stop
|
||||
*/
|
||||
private $stop;
|
||||
|
||||
/**
|
||||
* Order in trip
|
||||
* @var int
|
||||
*/
|
||||
private $order;
|
||||
|
||||
/**
|
||||
* Arrival time
|
||||
* @var Carbon
|
||||
@ -32,26 +18,6 @@ class ScheduledStop implements Fillable
|
||||
*/
|
||||
private $departure;
|
||||
|
||||
public function getStop()
|
||||
{
|
||||
return $this->stop;
|
||||
}
|
||||
|
||||
public function setStop($stop): void
|
||||
{
|
||||
$this->stop = $stop;
|
||||
}
|
||||
|
||||
public function getOrder(): int
|
||||
{
|
||||
return $this->order;
|
||||
}
|
||||
|
||||
public function setOrder(int $order): void
|
||||
{
|
||||
$this->order = $order;
|
||||
}
|
||||
|
||||
public function getArrival(): Carbon
|
||||
{
|
||||
return $this->arrival;
|
||||
|
58
src/Model/TrackStop.php
Normal file
58
src/Model/TrackStop.php
Normal file
@ -0,0 +1,58 @@
|
||||
<?php
|
||||
|
||||
namespace App\Model;
|
||||
|
||||
use JMS\Serializer\Annotation as Serializer;
|
||||
|
||||
class TrackStop implements Fillable
|
||||
{
|
||||
use FillTrait;
|
||||
|
||||
/**
|
||||
* Order in trip
|
||||
* @var int
|
||||
*/
|
||||
private $order;
|
||||
|
||||
/**
|
||||
* Stop (as a place) related to that scheduled bus stop
|
||||
* @var Stop
|
||||
*/
|
||||
private $stop;
|
||||
|
||||
/**
|
||||
* Track that this stop is part of.
|
||||
* @var Track|null
|
||||
*/
|
||||
private $track;
|
||||
|
||||
public function getStop()
|
||||
{
|
||||
return $this->stop;
|
||||
}
|
||||
|
||||
public function setStop($stop): void
|
||||
{
|
||||
$this->stop = $stop;
|
||||
}
|
||||
|
||||
public function getOrder(): int
|
||||
{
|
||||
return $this->order;
|
||||
}
|
||||
|
||||
public function setOrder(int $order): void
|
||||
{
|
||||
$this->order = $order;
|
||||
}
|
||||
|
||||
public function getTrack(): ?Track
|
||||
{
|
||||
return $this->track;
|
||||
}
|
||||
|
||||
public function setTrack(?Track $track): void
|
||||
{
|
||||
$this->track = $track;
|
||||
}
|
||||
}
|
@ -28,6 +28,8 @@ use Symfony\Contracts\Service\ServiceSubscriberInterface;
|
||||
|
||||
abstract class DatabaseRepository implements ServiceSubscriberInterface, Repository
|
||||
{
|
||||
const DEFAULT_LIMIT = 100;
|
||||
|
||||
/** @var EntityManagerInterface */
|
||||
protected $em;
|
||||
|
||||
@ -115,6 +117,8 @@ abstract class DatabaseRepository implements ServiceSubscriberInterface, Reposit
|
||||
|
||||
protected function allFromQueryBuilder(QueryBuilder $builder, iterable $modifiers, array $meta = [])
|
||||
{
|
||||
$builder->setMaxResults(self::DEFAULT_LIMIT);
|
||||
|
||||
$reducers = $this->processQueryBuilder($builder, $modifiers, $meta);
|
||||
|
||||
return $reducers->reduce(function ($result, $reducer) {
|
||||
|
@ -3,7 +3,7 @@
|
||||
namespace App\Provider\Database;
|
||||
|
||||
use App\Entity\StopEntity;
|
||||
use App\Entity\StopInTrack;
|
||||
use App\Entity\TrackStopEntity;
|
||||
use App\Entity\TrackEntity;
|
||||
use App\Entity\TripEntity;
|
||||
use App\Entity\TripStopEntity;
|
||||
|
@ -2,33 +2,28 @@
|
||||
|
||||
namespace App\Provider\Database;
|
||||
|
||||
use App\Entity\StopEntity;
|
||||
use App\Entity\StopInTrack;
|
||||
use App\Entity\TrackStopEntity;
|
||||
use App\Entity\TrackEntity;
|
||||
use App\Model\TrackStop;
|
||||
use App\Modifier\Modifier;
|
||||
use App\Model\Track;
|
||||
use App\Provider\TrackRepository;
|
||||
use Tightenco\Collect\Support\Collection;
|
||||
use Kadet\Functional as f;
|
||||
use function App\Functions\encapsulate;
|
||||
|
||||
class GenericTrackRepository extends DatabaseRepository implements TrackRepository
|
||||
{
|
||||
public function getByStop($stop): Collection
|
||||
public function stops(Modifier ...$modifiers): Collection
|
||||
{
|
||||
$reference = f\apply(f\ref([$this, 'reference']), StopEntity::class);
|
||||
$builder = $this->em
|
||||
->createQueryBuilder()
|
||||
->from(TrackStopEntity::class, 'track_stop')
|
||||
->select(['track_stop']);
|
||||
|
||||
$tracks = $this->em->createQueryBuilder()
|
||||
->from(StopInTrack::class, 'st')
|
||||
->join('st.track', 't')
|
||||
->where('st.stop in (:stop)')
|
||||
->select(['st', 't'])
|
||||
->getQuery()
|
||||
->execute(['stop' => array_map($reference, encapsulate($stop))]);
|
||||
|
||||
return collect($tracks)->map(function (StopInTrack $entity) {
|
||||
return [ $this->convert($entity->getTrack()), $entity->getOrder() ];
|
||||
});
|
||||
return $this->allFromQueryBuilder($builder, $modifiers, [
|
||||
'alias' => 'track_stop',
|
||||
'entity' => TrackStopEntity::class,
|
||||
'type' => TrackStop::class,
|
||||
]);
|
||||
}
|
||||
|
||||
public function all(Modifier ...$modifiers): Collection
|
||||
|
@ -3,9 +3,10 @@
|
||||
namespace App\Provider;
|
||||
|
||||
use App\Model\Track;
|
||||
use App\Modifier\Modifier;
|
||||
use Tightenco\Collect\Support\Collection;
|
||||
|
||||
interface TrackRepository extends FluentRepository
|
||||
{
|
||||
public function getByStop($stop): Collection;
|
||||
public function stops(Modifier ...$modifiers): Collection;
|
||||
}
|
||||
|
@ -6,7 +6,7 @@ use App\Entity\LineEntity;
|
||||
use App\Entity\OperatorEntity;
|
||||
use App\Entity\ProviderEntity;
|
||||
use App\Entity\StopEntity;
|
||||
use App\Entity\StopInTrack;
|
||||
use App\Entity\TrackStopEntity;
|
||||
use App\Entity\TrackEntity;
|
||||
use App\Entity\TripEntity;
|
||||
use App\Entity\TripStopEntity;
|
||||
@ -216,7 +216,7 @@ class ZtmGdanskDataUpdateSubscriber implements EventSubscriberInterface
|
||||
return !in_array($stop['stopId'], $this->stopBlacklist);
|
||||
})
|
||||
->map(function ($stop) use ($entity, $provider) {
|
||||
return StopInTrack::createFromArray([
|
||||
return TrackStopEntity::createFromArray([
|
||||
'stop' => $this->em->getReference(
|
||||
StopEntity::class,
|
||||
$this->ids->generate($provider, $stop['stopId'])
|
||||
|
@ -5,16 +5,19 @@ namespace App\Service;
|
||||
use App\Entity\LineEntity;
|
||||
use App\Entity\ProviderEntity;
|
||||
use App\Entity\StopEntity;
|
||||
use App\Entity\TrackEntity;
|
||||
use App\Model\Line;
|
||||
use App\Model\Referable;
|
||||
use App\Model\Stop;
|
||||
use App\Model\Track;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
|
||||
final class ReferenceFactory
|
||||
final class EntityReferenceFactory
|
||||
{
|
||||
protected $mapping = [
|
||||
Line::class => LineEntity::class,
|
||||
Stop::class => StopEntity::class,
|
||||
Line::class => LineEntity::class,
|
||||
Stop::class => StopEntity::class,
|
||||
Track::class => TrackEntity::class,
|
||||
];
|
||||
|
||||
private $em;
|
@ -2,6 +2,7 @@
|
||||
|
||||
namespace App\Service;
|
||||
|
||||
use App\Entity\TrackStopEntity;
|
||||
use App\Entity\TripStopEntity;
|
||||
use App\Model\ScheduledStop;
|
||||
|
||||
@ -11,18 +12,28 @@ class ScheduledStopConverter implements Converter, RecursiveConverter
|
||||
|
||||
public function convert($entity)
|
||||
{
|
||||
/** @var ScheduledStop $entity */
|
||||
|
||||
return ScheduledStop::createFromArray([
|
||||
'arrival' => $entity->getArrival(),
|
||||
'departure' => $entity->getDeparture(),
|
||||
'stop' => $this->parent->convert($entity->getStop()),
|
||||
'order' => $entity->getOrder(),
|
||||
]);
|
||||
if ($entity instanceof TrackStopEntity) {
|
||||
return ScheduledStop::createFromArray([
|
||||
'stop' => $this->parent->convert($entity->getStop()),
|
||||
'track' => $this->parent->convert($entity->getTrack()),
|
||||
'order' => $entity->getOrder(),
|
||||
]);
|
||||
}
|
||||
|
||||
if ($entity instanceof TripStopEntity) {
|
||||
return ScheduledStop::createFromArray([
|
||||
'arrival' => $entity->getArrival(),
|
||||
'departure' => $entity->getDeparture(),
|
||||
'stop' => $this->parent->convert($entity->getStop()),
|
||||
'order' => $entity->getOrder(),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
public function supports($entity)
|
||||
{
|
||||
return $entity instanceof TripStopEntity;
|
||||
return $entity instanceof TripStopEntity
|
||||
|| $entity instanceof TrackStopEntity;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user