From 5a9096830f23f1caed211e20d2f4415de7993c8c Mon Sep 17 00:00:00 2001 From: Kacper Donat Date: Sat, 12 Jan 2019 23:10:13 +0100 Subject: [PATCH] add schedule updating --- config/packages/doctrine.yaml | 2 + src/Entity/TripEntity.php | 4 +- .../{TripStop.php => TripStopEntity.php} | 3 +- src/Migrations/Version20190111212909.php | 2 +- src/Model/ScheduleStop.php | 74 +++++++++++++++++ src/Model/Trip.php | 83 +++++++++++++++++++ .../ZtmGdanskDataUpdateSubscriber.php | 70 +++++++++++++++- src/Service/DataUpdater.php | 17 ++-- src/Service/EntityConverter.php | 37 ++++++--- 9 files changed, 262 insertions(+), 30 deletions(-) rename src/Entity/{TripStop.php => TripStopEntity.php} (96%) create mode 100644 src/Model/ScheduleStop.php create mode 100644 src/Model/Trip.php diff --git a/config/packages/doctrine.yaml b/config/packages/doctrine.yaml index dcc3040..8e6fdee 100644 --- a/config/packages/doctrine.yaml +++ b/config/packages/doctrine.yaml @@ -5,6 +5,8 @@ doctrine: dbal: driver: 'pdo_sqlite' url: '%env(resolve:DATABASE_URL)%' + logging: false + profiling: false orm: auto_generate_proxy_classes: '%kernel.debug%' diff --git a/src/Entity/TripEntity.php b/src/Entity/TripEntity.php index 2a8247c..f767cce 100644 --- a/src/Entity/TripEntity.php +++ b/src/Entity/TripEntity.php @@ -49,9 +49,9 @@ class TripEntity implements Entity, Fillable private $note; /** - * @var Collection + * @var Collection * - * @ORM\OneToMany(targetEntity=StopInTrack::class, fetch="EXTRA_LAZY", mappedBy="track", cascade={"persist"}) + * @ORM\OneToMany(targetEntity=TripStopEntity::class, fetch="EXTRA_LAZY", mappedBy="trip", cascade={"persist"}) * @ORM\OrderBy({"order": "ASC"}) */ private $stops; diff --git a/src/Entity/TripStop.php b/src/Entity/TripStopEntity.php similarity index 96% rename from src/Entity/TripStop.php rename to src/Entity/TripStopEntity.php index c2799d8..7c5eded 100644 --- a/src/Entity/TripStop.php +++ b/src/Entity/TripStopEntity.php @@ -11,7 +11,7 @@ use Doctrine\ORM\Mapping as ORM; * @ORM\Entity * @ORM\Table("trip_stop") */ -class TripStop implements Fillable +class TripStopEntity implements Fillable { use FillTrait; @@ -32,6 +32,7 @@ class TripStop implements Fillable * @var int * * @ORM\Column(name="sequence", type="integer") + * @ORM\Id */ private $order; diff --git a/src/Migrations/Version20190111212909.php b/src/Migrations/Version20190111212909.php index 03066a9..da2e8dc 100644 --- a/src/Migrations/Version20190111212909.php +++ b/src/Migrations/Version20190111212909.php @@ -15,7 +15,7 @@ final class Version20190111212909 extends AbstractMigration // this up() migration is auto-generated, please modify it to your needs $this->abortIf($this->connection->getDatabasePlatform()->getName() !== 'sqlite', 'Migration can only be executed safely on \'sqlite\'.'); - $this->addSql('CREATE TABLE trip_stop (stop_id VARCHAR(255) NOT NULL, trip_id VARCHAR(255) NOT NULL, sequence INTEGER NOT NULL, arrival DATETIME NOT NULL, departure DATETIME NOT NULL, PRIMARY KEY(stop_id, trip_id))'); + $this->addSql('CREATE TABLE trip_stop (stop_id VARCHAR(255) NOT NULL, trip_id VARCHAR(255) NOT NULL, sequence INTEGER NOT NULL, arrival DATETIME NOT NULL, departure DATETIME NOT NULL, PRIMARY KEY(stop_id, trip_id, sequence))'); $this->addSql('CREATE INDEX IDX_926E85DD3902063D ON trip_stop (stop_id)'); $this->addSql('CREATE INDEX IDX_926E85DDA5BC2E0E ON trip_stop (trip_id)'); $this->addSql('CREATE TABLE trip (id VARCHAR(255) NOT NULL, operator_id VARCHAR(255) DEFAULT NULL, track_id VARCHAR(255) DEFAULT NULL, provider_id VARCHAR(255) DEFAULT NULL, variant VARCHAR(255) DEFAULT NULL, note VARCHAR(255) DEFAULT NULL, PRIMARY KEY(id))'); diff --git a/src/Model/ScheduleStop.php b/src/Model/ScheduleStop.php new file mode 100644 index 0000000..067df7f --- /dev/null +++ b/src/Model/ScheduleStop.php @@ -0,0 +1,74 @@ +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; + } + + public function setArrival(Carbon $arrival): void + { + $this->arrival = $arrival; + } + + public function getDeparture(): Carbon + { + return $this->departure; + } + + public function setDeparture(Carbon $departure): void + { + $this->departure = $departure; + } +} \ No newline at end of file diff --git a/src/Model/Trip.php b/src/Model/Trip.php new file mode 100644 index 0000000..dafb13f --- /dev/null +++ b/src/Model/Trip.php @@ -0,0 +1,83 @@ + + */ + private $schedule; + + /** + * Track constructor. + */ + public function __construct() + { + $this->setSchedule([]); + } + + public function getVariant(): ?string + { + return $this->variant; + } + + public function setVariant(?string $variant): void + { + $this->variant = $variant; + } + + public function getDescription(): ?string + { + return $this->description; + } + + public function setDescription(?string $description): void + { + $this->description = $description; + } + + public function getTrack(): ?Track + { + return $this->track; + } + + public function setTrack(?Track $track): void + { + $this->track = $track; + } + + public function getSchedule(): Collection + { + return $this->schedule; + } + + public function setSchedule($schedule = []) + { + return $this->schedule = collect($schedule); + } +} \ No newline at end of file diff --git a/src/Provider/ZtmGdansk/ZtmGdanskDataUpdateSubscriber.php b/src/Provider/ZtmGdansk/ZtmGdanskDataUpdateSubscriber.php index 7eca18c..5074a05 100644 --- a/src/Provider/ZtmGdansk/ZtmGdanskDataUpdateSubscriber.php +++ b/src/Provider/ZtmGdansk/ZtmGdanskDataUpdateSubscriber.php @@ -8,13 +8,17 @@ use App\Entity\ProviderEntity; use App\Entity\StopEntity; use App\Entity\StopInTrack; use App\Entity\TrackEntity; +use App\Entity\TripEntity; +use App\Entity\TripStopEntity; use App\Model\Line as LineModel; -use App\Provider\ZtmGdansk\ZtmGdanskProvider; use App\Service\DataUpdater; use App\Service\IdUtils; +use Carbon\Carbon; use Doctrine\ORM\EntityManagerInterface; +use function Kadet\Functional\partial; use Psr\Log\LoggerInterface; use Symfony\Component\EventDispatcher\EventSubscriberInterface; +use Tightenco\Collect\Support\Collection; class ZtmGdanskDataUpdateSubscriber implements EventSubscriberInterface { @@ -62,11 +66,9 @@ class ZtmGdanskDataUpdateSubscriber implements EventSubscriberInterface $save = [$this->em, 'persist']; $this->getOperators($provider)->each($save); - $this->getLines($provider)->each($save); $this->getStops($provider)->each($save); $this->getTracks($provider)->each($save); - - $this->em->flush(); + $this->getLines($provider)->each($save)->each(partial([$this, 'getSchedule'], $provider, $save)); } private function getOperators(ProviderEntity $provider) @@ -190,6 +192,66 @@ class ZtmGdanskDataUpdateSubscriber implements EventSubscriberInterface }); } + public function getSchedule(ProviderEntity $provider, callable $save, LineEntity $line) + { + $this->logger->info(sprintf('Obtaining schedule for line %s from ZTM GdaƄsk', $line->getId())); + + $schedule = file_get_contents("http://87.98.237.99:88/stopTimes?date=".(date('Y-m-d'))."&routeId=".$this->ids->of($line)); + $schedule = json_decode($schedule, true)['stopTimes']; + $schedule = collect($schedule)->groupBy(function ($stop) { + return sprintf("%s-%d", $stop['busServiceName'], $stop['order']); + }); + + collect($schedule)->map(function (Collection $trips, $id) use ($provider) { + $entity = TripEntity::createFromArray([ + 'id' => $this->ids->generate($provider, $id), + 'operator' => $this->em->getReference( + OperatorEntity::class, + $this->ids->generate($provider, $trips->first()['agencyId']) + ), + 'track' => $this->em->getReference( + TrackEntity::class, + $this->ids->generate($provider, $trips->first()['tripId']) + ), + 'variant' => $trips->first(function ($trip) { + return !empty($trip['noteSymbol']); + }, ['noteSymbol' => null])['noteSymbol'], + 'note' => $trips->first(function ($trip) { + return !empty($trip['noteSymbol']); + }, ['noteDescription' => null])['noteDescription'], + ]); + + $stops = $trips->map(function ($stop) use ($entity, $provider) { + $base = Carbon::create(1899, 12, 30, 00, 00, 00); + $date = Carbon::createFromFormat('Y-m-d', $stop['date'])->setTime(00, 00, 00); + + $arrival = $base->diff(Carbon::createFromTimeString($stop['arrivalTime'])); + $departure = $base->diff(Carbon::createFromTimeString($stop['departureTime'])); + + $arrival = (clone $date)->add($arrival); + $departure = (clone $date)->add($departure); + + return TripStopEntity::createFromArray([ + 'trip' => $entity, + 'stop' => $this->em->getReference( + StopEntity::class, + $this->ids->generate($provider, $stop['stopId']) + ), + 'order' => $stop['stopSequence'], + 'arrival' => $arrival, + 'departure' => $departure, + ]); + }); + + $entity->setStops($stops); + + return $entity; + })->each($save); + + $this->em->flush(); + $this->em->clear(); + } + public static function getSubscribedEvents() { return [ diff --git a/src/Service/DataUpdater.php b/src/Service/DataUpdater.php index bf68deb..75616dd 100644 --- a/src/Service/DataUpdater.php +++ b/src/Service/DataUpdater.php @@ -31,20 +31,13 @@ class DataUpdater public function update() { $connection = $this->em->getConnection(); + $connection->getConfiguration()->setSQLLogger(null); $schema = $connection->getSchemaManager(); - try { - $connection->beginTransaction(); + collect($schema->listTables())->reject(function (Table $schema) { + return $schema->getName() === 'migration_versions'; + })->each([$schema, 'dropAndCreateTable']); - collect($schema->listTables())->reject(function (Table $schema) { - return $schema->getName() === 'migration_versions'; - })->each([$schema, 'dropAndCreateTable']); - - $this->dispatcher->dispatch(self::UPDATE_EVENT, new DataUpdateEvent()); - $connection->commit(); - } catch (\Throwable $exception) { - $connection->rollBack(); - throw $exception; - } + $this->dispatcher->dispatch(self::UPDATE_EVENT, new DataUpdateEvent()); } } \ No newline at end of file diff --git a/src/Service/EntityConverter.php b/src/Service/EntityConverter.php index c36aa39..84e2e97 100644 --- a/src/Service/EntityConverter.php +++ b/src/Service/EntityConverter.php @@ -2,15 +2,8 @@ namespace App\Service; -use App\Entity\Entity; -use App\Entity\LineEntity; -use App\Entity\OperatorEntity; -use App\Entity\StopEntity; -use App\Entity\TrackEntity; -use App\Model\Line; -use App\Model\Operator; -use App\Model\Stop; -use App\Model\Track; +use App\Entity\{Entity, LineEntity, OperatorEntity, StopEntity, TrackEntity, TripEntity, TripStopEntity}; +use App\Model\{Line, Operator, ScheduleStop, Stop, Track, Trip}; use App\Service\Proxy\ReferenceFactory; use Doctrine\ORM\PersistentCollection; use Doctrine\ORM\Proxy\Proxy; @@ -33,7 +26,7 @@ final class EntityConverter * @param Entity $entity * @param array $cache * - * @return Line|Track|Stop|Operator + * @return Line|Track|Stop|Operator|Trip|ScheduleStop */ public function convert(Entity $entity, array $cache = []) { @@ -93,6 +86,24 @@ final class EntityConverter ], ]); break; + + case $entity instanceof TripEntity: + $result->fill([ + 'variant' => $entity->getVariant(), + 'note' => $entity->getNote(), + 'schedule' => $this->collection($entity->getStops())->map($convert), + 'track' => $convert($entity->getTrack()), + ]); + break; + + case $entity instanceof TripStopEntity: + $result->fill([ + 'arrival' => $entity->getArrival(), + 'departure' => $entity->getDeparture(), + 'stop' => $convert($entity->getStop()), + 'order' => $convert($entity->getOrder()), + ]); + break; } return $result; @@ -134,6 +145,12 @@ final class EntityConverter case $entity instanceof StopEntity: return Stop::class; + case $entity instanceof TripEntity: + return Trip::class; + + case $entity instanceof TripStopEntity: + return ScheduleStop::class; + default: return false; }