Refactor stop grouping

This commit is contained in:
Kacper Donat 2020-02-04 18:59:37 +01:00
parent 9b13612c43
commit cb6c3a3950
9 changed files with 121 additions and 48 deletions

View File

@ -14,6 +14,7 @@ use Nelmio\ApiDocBundle\Annotation\Model;
use Swagger\Annotations as SWG; use Swagger\Annotations as SWG;
use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Annotation\Route; use Symfony\Component\Routing\Annotation\Route;
use Tightenco\Collect\Support\Collection;
/** /**
* Class StopsController * Class StopsController
@ -51,7 +52,7 @@ class StopsController extends Controller
break; break;
default: default:
$result = $stops->getAllGroups(); $result = $stops->getAll();
} }
return $this->json($result->all()); return $this->json($result->all());
@ -77,14 +78,14 @@ class StopsController extends Controller
{ {
switch (true) { switch (true) {
case $request->query->has('name'): case $request->query->has('name'):
$result = $stops->findGroupsByName($request->query->get('name')); $result = $stops->findByName($request->query->get('name'));
break; break;
default: default:
$result = $stops->getAllGroups(); $result = $stops->getAll();
} }
return $this->json($result->all()); return $this->json(static::group($result)->all());
} }
/** /**
@ -130,4 +131,18 @@ class StopsController extends Controller
return array_combine(['track', 'order'], $tuple); return array_combine(['track', 'order'], $tuple);
})); }));
} }
public static function group(Collection $stops)
{
return $stops->groupBy(function (Stop $stop) {
return $stop->getGroup();
})->map(function ($stops, $key) {
$group = new StopGroup();
$group->setName($key);
$group->setStops($stops);
return $group;
})->values();
}
} }

View File

@ -9,7 +9,9 @@ use Doctrine\ORM\Mapping as ORM;
/** /**
* @ORM\Entity(readOnly=true) * @ORM\Entity(readOnly=true)
* @ORM\Table("stop") * @ORM\Table("stop", indexes={
* @ORM\Index(name="group_idx", columns={"group_name"})
* })
*/ */
class StopEntity implements Entity, Fillable class StopEntity implements Entity, Fillable
{ {
@ -27,10 +29,18 @@ class StopEntity implements Entity, Fillable
* Stop name * Stop name
* @var string * @var string
* *
* @ORM\Column(type="string") * @ORM\Column(type="string", length=255)
*/ */
private $name; private $name;
/**
* Stop group name
* @var string|null
*
* @ORM\Column(type="string", length=255, nullable=true, name="group_name")
*/
private $group;
/** /**
* Optional stop description, should not be longer than 255 chars * Optional stop description, should not be longer than 255 chars
* @var string|null * @var string|null
@ -43,7 +53,7 @@ class StopEntity implements Entity, Fillable
* Optional stop variant - for example number of shed * Optional stop variant - for example number of shed
* @var string|null * @var string|null
* *
* @ORM\Column(type="string", nullable=true) * @ORM\Column(type="string", length=255, nullable=true)
*/ */
private $variant; private $variant;
@ -81,6 +91,16 @@ class StopEntity implements Entity, Fillable
$this->name = $name; $this->name = $name;
} }
public function getGroup(): ?string
{
return $this->group;
}
public function setGroup(?string $group): void
{
$this->group = $group;
}
public function getDescription(): ?string public function getDescription(): ?string
{ {
return $this->description; return $this->description;

View File

@ -0,0 +1,45 @@
<?php
declare(strict_types=1);
namespace DoctrineMigrations;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;
/**
* Auto-generated Migration: Please modify to your needs!
*/
final class Version20200131151757 extends AbstractMigration
{
public function getDescription() : string
{
return '';
}
public function up(Schema $schema) : void
{
// 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 TEMPORARY TABLE __temp__stop AS SELECT id, provider_id, name, description, variant, latitude, longitude, on_demand FROM stop');
$this->addSql('DROP TABLE stop');
$this->addSql('CREATE TABLE stop (id VARCHAR(255) NOT NULL COLLATE BINARY, provider_id VARCHAR(255) DEFAULT NULL COLLATE BINARY, name VARCHAR(255) NOT NULL COLLATE BINARY, description VARCHAR(255) DEFAULT NULL COLLATE BINARY, variant VARCHAR(255) DEFAULT NULL COLLATE BINARY, latitude DOUBLE PRECISION DEFAULT NULL, longitude DOUBLE PRECISION DEFAULT NULL, on_demand BOOLEAN NOT NULL, group_name VARCHAR(255) DEFAULT NULL, PRIMARY KEY(id))');
$this->addSql('INSERT INTO stop (id, provider_id, name, description, variant, latitude, longitude, on_demand) SELECT id, provider_id, name, description, variant, latitude, longitude, on_demand FROM __temp__stop');
$this->addSql('DROP TABLE __temp__stop');
$this->addSql('CREATE INDEX group_idx ON stop (group_name)');
}
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 group_idx');
$this->addSql('CREATE TEMPORARY TABLE __temp__stop AS SELECT id, name, description, variant, latitude, longitude, on_demand, provider_id FROM stop');
$this->addSql('DROP TABLE stop');
$this->addSql('CREATE TABLE stop (id VARCHAR(255) NOT NULL, name VARCHAR(255) NOT NULL, description VARCHAR(255) DEFAULT NULL, variant VARCHAR(255) DEFAULT NULL, latitude DOUBLE PRECISION DEFAULT NULL, longitude DOUBLE PRECISION DEFAULT NULL, on_demand BOOLEAN NOT NULL, provider_id VARCHAR(255) DEFAULT NULL, PRIMARY KEY(id))');
$this->addSql('INSERT INTO stop (id, name, description, variant, latitude, longitude, on_demand, provider_id) SELECT id, name, description, variant, latitude, longitude, on_demand, provider_id FROM __temp__stop');
$this->addSql('DROP TABLE __temp__stop');
}
}

View File

@ -57,6 +57,15 @@ class Stop implements Referable, Fillable
*/ */
private $onDemand = false; private $onDemand = false;
/**
* Name of group that this stop is part of.
*
* @Serializer\Type("string")
* @SWG\Property(example="Jasień PKM")
* @var string|null
*/
private $group;
public function getName(): string public function getName(): string
{ {
return $this->name; return $this->name;
@ -106,4 +115,14 @@ class Stop implements Referable, Fillable
{ {
$this->location = $location; $this->location = $location;
} }
public function getGroup(): ?string
{
return $this->group;
}
public function setGroup(?string $group): void
{
$this->group = $group;
}
} }

View File

@ -4,7 +4,6 @@ namespace App\Provider\Database;
use App\Entity\StopEntity; use App\Entity\StopEntity;
use App\Model\Stop; use App\Model\Stop;
use App\Model\StopGroup;
use App\Provider\StopRepository; use App\Provider\StopRepository;
use Tightenco\Collect\Support\Collection; use Tightenco\Collect\Support\Collection;
use Kadet\Functional as f; use Kadet\Functional as f;
@ -18,11 +17,6 @@ class GenericStopRepository extends DatabaseRepository implements StopRepository
return collect($stops)->map(f\ref([$this, 'convert'])); return collect($stops)->map(f\ref([$this, 'convert']));
} }
public function getAllGroups(): Collection
{
return $this->group($this->getAll());
}
public function getById($id): ?Stop public function getById($id): ?Stop
{ {
$id = $this->id->generate($this->provider, $id); $id = $this->id->generate($this->provider, $id);
@ -34,12 +28,12 @@ class GenericStopRepository extends DatabaseRepository implements StopRepository
public function getManyById($ids): Collection 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()]); $stops = $this->em->getRepository(StopEntity::class)->findBy(['id' => $ids->all()]);
return collect($stops)->map(f\ref([$this, 'convert'])); return collect($stops)->map(f\ref([$this, 'convert']));
} }
public function findGroupsByName(string $name): Collection public function findByName(string $name): Collection
{ {
$query = $this->em->createQueryBuilder() $query = $this->em->createQueryBuilder()
->select('s') ->select('s')
@ -47,22 +41,6 @@ class GenericStopRepository extends DatabaseRepository implements StopRepository
->where('s.name LIKE :name') ->where('s.name LIKE :name')
->getQuery(); ->getQuery();
$stops = collect($query->execute([':name' => "%$name%"]))->map(f\ref([$this, 'convert'])); return collect($query->execute([':name' => "%$name%"]))->map(f\ref([$this, 'convert']));
return $this->group($stops);
}
private function group(Collection $stops)
{
return $stops->groupBy(function (Stop $stop) {
return $stop->getName();
})->map(function ($stops, $key) {
$group = new StopGroup();
$group->setName($key);
$group->setStops($stops);
return $group;
})->values();
} }
} }

View File

@ -27,11 +27,6 @@ class DummyStopRepository implements StopRepository
return collect(); return collect();
} }
public function getAllGroups(): Collection
{
return collect();
}
public function getById($id): ?Stop public function getById($id): ?Stop
{ {
return Stop::createFromArray(['id' => $id, 'name' => 'lorem']); return Stop::createFromArray(['id' => $id, 'name' => 'lorem']);
@ -42,7 +37,7 @@ class DummyStopRepository implements StopRepository
return collect($ids)->map(f\ref([ $this, 'getById' ])); return collect($ids)->map(f\ref([ $this, 'getById' ]));
} }
public function findGroupsByName(string $name): Collection public function findByName(string $name): Collection
{ {
return collect(); return collect();
} }

View File

@ -10,10 +10,7 @@ use Tightenco\Collect\Support\Collection;
interface StopRepository extends Repository interface StopRepository extends Repository
{ {
public function getAll(): Collection; public function getAll(): Collection;
public function getAllGroups(): Collection;
public function getById($id): ?Stop; public function getById($id): ?Stop;
public function getManyById($ids): Collection; public function getManyById($ids): Collection;
public function findByName(string $name): Collection;
public function findGroupsByName(string $name): Collection;
} }

View File

@ -162,14 +162,17 @@ class ZtmGdanskDataUpdateSubscriber implements EventSubscriberInterface
&& $stop['depot'] !== 1; && $stop['depot'] !== 1;
}) })
->map(function ($stop) use ($provider) { ->map(function ($stop) use ($provider) {
$name = trim($stop['stopName'] ?? $stop['stopDesc']);
return StopEntity::createFromArray([ return StopEntity::createFromArray([
'id' => $this->ids->generate($provider, $stop['stopId']), 'id' => $this->ids->generate($provider, $stop['stopId']),
'name' => trim($stop['stopName'] ?? $stop['stopDesc']), 'name' => $name,
'variant' => trim($stop['zoneName'] == 'Gdańsk' ? $stop['stopCode'] : null), 'variant' => trim($stop['zoneName'] == 'Gdańsk' ? $stop['stopCode'] ?? $stop['subName'] : null),
'latitude' => $stop['stopLat'], 'latitude' => $stop['stopLat'],
'longitude' => $stop['stopLon'], 'longitude' => $stop['stopLon'],
'onDemand' => (bool)$stop['onDemand'], 'onDemand' => (bool)$stop['onDemand'],
'provider' => $provider, 'provider' => $provider,
'group' => $name,
]); ]);
}) })
; ;

View File

@ -86,6 +86,7 @@ final class EntityConverter implements Converter, RecursiveConverter
'name' => $entity->getName(), 'name' => $entity->getName(),
'variant' => $entity->getVariant(), 'variant' => $entity->getVariant(),
'description' => $entity->getDescription(), 'description' => $entity->getDescription(),
'group' => $entity->getGroup(),
'location' => new Location( 'location' => new Location(
$entity->getLongitude(), $entity->getLongitude(),
$entity->getLatitude() $entity->getLatitude()