+
+
-
-
-
+
+
+
-
-
+
+
+
-
diff --git a/resources/styles/_favourites.scss b/resources/styles/_favourites.scss
index bbb50c9..27f3d79 100644
--- a/resources/styles/_favourites.scss
+++ b/resources/styles/_favourites.scss
@@ -11,6 +11,7 @@
font-size: $small-font-size;
overflow-x: hidden;
text-overflow: ellipsis;
+ max-width: 100%;
&:last-child {
margin-bottom: 0;
diff --git a/resources/styles/_stop.scss b/resources/styles/_stop.scss
index f8191cc..e0c48fe 100644
--- a/resources/styles/_stop.scss
+++ b/resources/styles/_stop.scss
@@ -5,7 +5,7 @@
}
.stop__name {
- flex: 1 0;
+ //flex: 1 0;
line-height: 1.1;
margin-right: .5em;
}
@@ -46,3 +46,15 @@
}
}
}
+
+.stop__destinations {
+ @extend .favourite__stops;
+}
+
+.stop__destination {
+ @extend .favourite__stop;
+}
+
+.finder__stop {
+ max-width: 100%;
+}
diff --git a/resources/ts/model/stop.ts b/resources/ts/model/stop.ts
index ebb3bfb..fa6bc33 100644
--- a/resources/ts/model/stop.ts
+++ b/resources/ts/model/stop.ts
@@ -8,6 +8,7 @@ export interface Stop {
};
onDemand?: boolean;
variant?: string;
+ destinations?: Stop[];
}
export type StopGroup = Stop[];
diff --git a/src/Entity/StopInTrack.php b/src/Entity/StopInTrack.php
index 608327b..26cbd55 100644
--- a/src/Entity/StopInTrack.php
+++ b/src/Entity/StopInTrack.php
@@ -4,32 +4,42 @@ namespace App\Entity;
use App\Model\Fillable;
use App\Model\FillTrait;
+use App\Model\Referable;
+use App\Model\ReferableTrait;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity
- * @ORM\Table("track_stop")
+ * @ORM\Table("track_stop", uniqueConstraints={
+ * @ORM\UniqueConstraint(name="stop_in_track_idx", columns={"stop_id", "track_id", "sequence"})
+ * })
*/
-class StopInTrack implements Fillable
+class StopInTrack implements Fillable, Referable
{
- use FillTrait;
+ use FillTrait, ReferableEntityTrait;
+
+ /**
+ * Identifier for stop coming from provider
+ *
+ * @ORM\Column(type="integer")
+ * @ORM\Id
+ * @ORM\GeneratedValue
+ */
+ private $id;
/**
* @ORM\ManyToOne(targetEntity=StopEntity::class, fetch="EAGER")
- * @ORM\Id
*/
private $stop;
/**
* @ORM\ManyToOne(targetEntity=TrackEntity::class, fetch="EAGER", inversedBy="stopsInTrack")
- * @ORM\Id
*/
private $track;
/**
* Order in track
* @var int
- * @ORM\Id
* @ORM\Column(name="sequence", type="integer")
*/
private $order;
diff --git a/src/Entity/TrackEntity.php b/src/Entity/TrackEntity.php
index a56fd2e..a0eaa1d 100644
--- a/src/Entity/TrackEntity.php
+++ b/src/Entity/TrackEntity.php
@@ -4,6 +4,7 @@ namespace App\Entity;
use App\Model\Fillable;
use App\Model\FillTrait;
+use App\Service\IterableUtils;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
@@ -50,6 +51,12 @@ class TrackEntity implements Entity, Fillable
*/
private $stopsInTrack;
+ /**
+ * Final stop in this track.
+ * @var StopInTrack
+ * @ORM\OneToOne(targetEntity=StopInTrack::class, fetch="LAZY")
+ */
+ private $final;
/**
* Track constructor.
@@ -98,15 +105,17 @@ class TrackEntity implements Entity, Fillable
}
/**
- * @param Collection $stopsInTrack
+ * @param iterable $stopsInTrack
*/
- public function setStopsInTrack(array $stopsInTrack): void
+ public function setStopsInTrack(iterable $stopsInTrack): void
{
- $this->stopsInTrack = new ArrayCollection($stopsInTrack);
+ $this->stopsInTrack = IterableUtils::toArrayCollection($stopsInTrack);
+
+ $this->final = $this->stopsInTrack->last();
}
public function getFinal(): StopInTrack
{
- return $this->getStopsInTrack()->last();
+ return $this->final;
}
}
diff --git a/src/Migrations/Version20200206183956.php b/src/Migrations/Version20200206183956.php
new file mode 100644
index 0000000..d7485ab
--- /dev/null
+++ b/src/Migrations/Version20200206183956.php
@@ -0,0 +1,57 @@
+abortIf($this->connection->getDatabasePlatform()->getName() !== 'sqlite', 'Migration can only be executed safely on \'sqlite\'.');
+
+ $this->addSql('CREATE TEMPORARY TABLE __temp__track AS SELECT id, line_id, provider_id, variant, description FROM track');
+ $this->addSql('DROP TABLE track');
+ $this->addSql('CREATE TABLE track (id VARCHAR(255) NOT NULL COLLATE BINARY, line_id VARCHAR(255) DEFAULT NULL COLLATE BINARY, provider_id VARCHAR(255) DEFAULT NULL COLLATE BINARY, variant VARCHAR(16) DEFAULT NULL COLLATE BINARY, description VARCHAR(256) DEFAULT NULL COLLATE BINARY, final_id INTEGER DEFAULT NULL, PRIMARY KEY(id))');
+ $this->addSql('INSERT INTO track (id, line_id, provider_id, variant, description) SELECT id, line_id, provider_id, variant, description FROM __temp__track');
+ $this->addSql('DROP TABLE __temp__track');
+ $this->addSql('CREATE UNIQUE INDEX UNIQ_D6E3F8A613D41B2D ON track (final_id)');
+ $this->addSql('CREATE TEMPORARY TABLE __temp__track_stop AS SELECT stop_id, track_id, sequence FROM track_stop');
+ $this->addSql('DROP TABLE track_stop');
+ $this->addSql('CREATE TABLE track_stop (id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, sequence INTEGER NOT NULL, stop_id VARCHAR(255) DEFAULT NULL, track_id VARCHAR(255) DEFAULT NULL)');
+ $this->addSql('INSERT INTO track_stop (stop_id, track_id, sequence) SELECT stop_id, track_id, sequence FROM __temp__track_stop');
+ $this->addSql('DROP TABLE __temp__track_stop');
+ $this->addSql('CREATE UNIQUE INDEX stop_in_track_idx ON track_stop (stop_id, track_id, sequence)');
+ }
+
+ public function down(Schema $schema) : void
+ {
+ // this down() 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('DROP INDEX UNIQ_D6E3F8A613D41B2D');
+ $this->addSql('CREATE TEMPORARY TABLE __temp__track AS SELECT id, variant, description, line_id, provider_id FROM track');
+ $this->addSql('DROP TABLE track');
+ $this->addSql('CREATE TABLE track (id VARCHAR(255) NOT NULL, variant VARCHAR(16) DEFAULT NULL, description VARCHAR(256) DEFAULT NULL, line_id VARCHAR(255) DEFAULT NULL, provider_id VARCHAR(255) DEFAULT NULL, PRIMARY KEY(id))');
+ $this->addSql('INSERT INTO track (id, variant, description, line_id, provider_id) SELECT id, variant, description, line_id, provider_id FROM __temp__track');
+ $this->addSql('DROP TABLE __temp__track');
+ $this->addSql('DROP INDEX stop_in_track_idx');
+ $this->addSql('CREATE TEMPORARY TABLE __temp__track_stop AS SELECT sequence, stop_id, track_id FROM track_stop');
+ $this->addSql('DROP TABLE track_stop');
+ $this->addSql('CREATE TABLE track_stop (sequence INTEGER NOT NULL, stop_id VARCHAR(255) NOT NULL COLLATE BINARY, track_id VARCHAR(255) NOT NULL COLLATE BINARY, PRIMARY KEY(stop_id, track_id, sequence))');
+ $this->addSql('INSERT INTO track_stop (sequence, stop_id, track_id) SELECT sequence, stop_id, track_id FROM __temp__track_stop');
+ $this->addSql('DROP TABLE __temp__track_stop');
+ }
+}
diff --git a/src/Model/ReferableTrait.php b/src/Model/ReferableTrait.php
index 70280dc..bb4397f 100644
--- a/src/Model/ReferableTrait.php
+++ b/src/Model/ReferableTrait.php
@@ -2,6 +2,7 @@
namespace App\Model;
+use Doctrine\ORM\Mapping as ORM;
use JMS\Serializer\Annotation as Serializer;
trait ReferableTrait
@@ -38,4 +39,4 @@ trait ReferableTrait
return $result;
}
-}
\ No newline at end of file
+}
diff --git a/src/Provider/Database/GenericStopRepository.php b/src/Provider/Database/GenericStopRepository.php
index 2d3aa9a..737b11f 100644
--- a/src/Provider/Database/GenericStopRepository.php
+++ b/src/Provider/Database/GenericStopRepository.php
@@ -3,10 +3,8 @@
namespace App\Provider\Database;
use App\Entity\StopEntity;
-use App\Entity\StopInTrack;
use App\Entity\TrackEntity;
use App\Model\Stop;
-use App\Model\Track;
use App\Provider\StopRepository;
use Tightenco\Collect\Support\Collection;
use Kadet\Functional as f;
@@ -23,7 +21,7 @@ class GenericStopRepository extends DatabaseRepository implements StopRepository
public function getById($id): ?Stop
{
- $id = $this->id->generate($this->provider, $id);
+ $id = $this->id->generate($this->provider, $id);
$stop = $this->em->getRepository(StopEntity::class)->find($id);
return $this->convert($stop);
@@ -31,7 +29,7 @@ class GenericStopRepository extends DatabaseRepository implements StopRepository
public function getManyById($ids): Collection
{
- $ids = collect($ids)->map(f\apply(f\ref([$this->id, 'generate']), $this->provider));
+ $ids = collect($ids)->map(f\apply(f\ref([$this->id, 'generate']), $this->provider));
$stops = $this->em->getRepository(StopEntity::class)->findBy(['id' => $ids->all()]);
return collect($stops)->map(f\ref([$this, 'convert']));
@@ -48,12 +46,12 @@ class GenericStopRepository extends DatabaseRepository implements StopRepository
$stops = collect($query->execute([':name' => "%$name%"]));
$destinations = collect($this->em->createQueryBuilder()
- ->select('t', 'ts', 'ts2', 's')
+ ->select('t', 'f', 'fs', 'ts')
->from(TrackEntity::class, 't')
->join('t.stopsInTrack', 'ts')
- ->join('t.stopsInTrack', 'ts2')
- ->join('ts2.stop', 's')
->where('ts.stop IN (:stops)')
+ ->join('t.final', 'f')
+ ->join('f.stop', 'fs')
->getQuery()
->execute(['stops' => $stops->map(t\property('id'))->all()]))
->reduce(function ($grouped, TrackEntity $track) {
@@ -67,8 +65,7 @@ class GenericStopRepository extends DatabaseRepository implements StopRepository
return $tracks->map(function (TrackEntity $track) {
return $this->convert($track->getFinal()->getStop());
})->unique()->values();
- })
- ;
+ });
return collect($stops)->map(f\ref([$this, 'convert']))->each(function (Stop $stop) use ($destinations) {
$stop->setDestinations($destinations[$this->id->generate($this->provider, $stop->getId())]);
diff --git a/src/Provider/ZtmGdansk/ZtmGdanskDataUpdateSubscriber.php b/src/Provider/ZtmGdansk/ZtmGdanskDataUpdateSubscriber.php
index abf6553..146ef55 100644
--- a/src/Provider/ZtmGdansk/ZtmGdanskDataUpdateSubscriber.php
+++ b/src/Provider/ZtmGdansk/ZtmGdanskDataUpdateSubscriber.php
@@ -12,7 +12,6 @@ use App\Entity\TripEntity;
use App\Entity\TripStopEntity;
use App\Event\DataUpdateEvent;
use App\Model\Line as LineModel;
-use App\Model\Location;
use App\Service\DataUpdater;
use App\Service\IdUtils;
use Carbon\Carbon;
@@ -20,13 +19,10 @@ use Cerbero\JsonObjects\JsonObjects;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\Console\Helper\ProgressBar;
use Psr\Log\LoggerInterface;
-use Symfony\Component\Console\Output\ConsoleOutputInterface;
-use Symfony\Component\Console\Output\ConsoleSectionOutput;
-use Symfony\Component\Console\Output\NullOutput;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Tightenco\Collect\Support\Collection;
-use function Cerbero\JsonObjects\JsonObjects;
use function Kadet\Functional\ref;
+use function Kadet\Functional\Transforms\property;
class ZtmGdanskDataUpdateSubscriber implements EventSubscriberInterface
{
@@ -45,6 +41,8 @@ class ZtmGdanskDataUpdateSubscriber implements EventSubscriberInterface
private $logger;
private $provider;
+ private $stopBlacklist = [];
+
/**
* ZtmGdanskDataUpdateSubscriber constructor.
*
@@ -147,6 +145,7 @@ class ZtmGdanskDataUpdateSubscriber implements EventSubscriberInterface
private function getStops(ProviderEntity $provider, DataUpdateEvent $event)
{
+ $this->stopBlacklist = [];
$output = $event->getOutput();
$output->write('Obtaining stops from ZTM Gdańsk... ');
@@ -157,9 +156,12 @@ class ZtmGdanskDataUpdateSubscriber implements EventSubscriberInterface
$this->logger->debug(sprintf("Saving %d stops tracks from ZTM Gdańsk.", count($stops)));
return collect($stops)
->filter(function ($stop) {
- return $stop['nonpassenger'] !== 1
- && $stop['virtual'] !== 1
- && $stop['depot'] !== 1;
+ if ($stop['nonpassenger'] === 1 || $stop['virtual'] === 1 || $stop['depot'] === 1) {
+ $this->stopBlacklist[] = $stop['stopId'];
+ return false;
+ }
+
+ return true;
})
->map(function ($stop) use ($provider) {
$name = trim($stop['stopName'] ?? $stop['stopDesc']);
@@ -178,7 +180,7 @@ class ZtmGdanskDataUpdateSubscriber implements EventSubscriberInterface
;
}
- public function getTracks(ProviderEntity $provider, DataUpdateEvent $event, $stops = [])
+ public function getTracks(ProviderEntity $provider, DataUpdateEvent $event, Collection $stops = null)
{
$output = $event->getOutput();
@@ -209,19 +211,24 @@ class ZtmGdanskDataUpdateSubscriber implements EventSubscriberInterface
'provider' => $provider,
]);
- $stops = $stops->get($track['id'])->map(function ($stop) use ($entity, $provider) {
- return StopInTrack::createFromArray([
- 'stop' => $this->em->getReference(
- StopEntity::class,
- $this->ids->generate($provider, $stop['stopId'])
- ),
- 'track' => $entity,
- // HACK! Gdynia has 0 based sequence
- 'order' => $stop['stopSequence'] + (int)($stop['stopId'] > 30000),
- ]);
- });
+ $stops = $stops->get($track['id'])
+ ->filter(function ($stop) {
+ return !in_array($stop['stopId'], $this->stopBlacklist);
+ })
+ ->map(function ($stop) use ($entity, $provider) {
+ return StopInTrack::createFromArray([
+ 'stop' => $this->em->getReference(
+ StopEntity::class,
+ $this->ids->generate($provider, $stop['stopId'])
+ ),
+ 'track' => $entity,
+ // HACK! Gdynia has 0 based sequence
+ 'order' => $stop['stopSequence'] + (int)($stop['stopId'] > 30000),
+ ]);
+ })
+ ->sortBy(property("order"));
- $entity->setStopsInTrack($stops->all());
+ $entity->setStopsInTrack($stops);
return $entity;
});
diff --git a/src/Service/IterableUtils.php b/src/Service/IterableUtils.php
new file mode 100644
index 0000000..5018060
--- /dev/null
+++ b/src/Service/IterableUtils.php
@@ -0,0 +1,28 @@
+
-
-
+
+
+
+
+
@@ -143,7 +146,7 @@
-