185 lines
5.6 KiB
PHP
185 lines
5.6 KiB
PHP
<?php
|
|
|
|
namespace App\Service;
|
|
|
|
use App\Entity\{Entity, LineEntity, OperatorEntity, StopEntity, TrackEntity, TripEntity, TripStopEntity};
|
|
use App\Model\{Line, Location, Operator, ScheduledStop, Stop, Track, Trip};
|
|
use App\Service\Proxy\ReferenceFactory;
|
|
use Doctrine\ORM\PersistentCollection;
|
|
use Doctrine\ORM\Proxy\Proxy;
|
|
use Kadet\Functional as f;
|
|
use Kadet\Functional\Transforms as t;
|
|
use const Kadet\Functional\_;
|
|
|
|
final class EntityConverter implements Converter, RecursiveConverter, CacheableConverter
|
|
{
|
|
use RecursiveConverterTrait;
|
|
|
|
private $id;
|
|
private $reference;
|
|
private $cache;
|
|
|
|
public function __construct(IdUtils $id, ReferenceFactory $reference)
|
|
{
|
|
$this->id = $id;
|
|
$this->reference = $reference;
|
|
$this->cache = [];
|
|
}
|
|
|
|
/**
|
|
* @param Entity $entity
|
|
* @param array $cache
|
|
*
|
|
* @return Line|Track|Stop|Operator|Trip|ScheduledStop
|
|
*/
|
|
public function convert($entity)
|
|
{
|
|
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);
|
|
$this->cache[$key] = $result;
|
|
|
|
$convert = function ($entity) {
|
|
return $this->supports($entity)
|
|
? $this->convert($entity)
|
|
: $this->parent->convert($entity);
|
|
};
|
|
|
|
switch (true) {
|
|
case $entity instanceof OperatorEntity:
|
|
$result->fill([
|
|
'name' => $entity->getName(),
|
|
'phone' => $entity->getPhone(),
|
|
'email' => $entity->getEmail(),
|
|
'url' => $entity->getEmail(),
|
|
]);
|
|
break;
|
|
|
|
case $entity instanceof LineEntity:
|
|
$result->fill([
|
|
'id' => $this->id->of($entity),
|
|
'symbol' => $entity->getSymbol(),
|
|
'type' => $entity->getType(),
|
|
'operator' => $convert($entity->getOperator()),
|
|
'night' => $entity->isNight(),
|
|
'fast' => $entity->isFast(),
|
|
'tracks' => $this->collection($entity->getTracks())->map($convert),
|
|
]);
|
|
break;
|
|
|
|
case $entity instanceof TrackEntity:
|
|
$result->fill([
|
|
'variant' => $entity->getVariant(),
|
|
'description' => $entity->getDescription(),
|
|
'stops' => $this->collection($entity->getStopsInTrack())
|
|
->map(t\property('stop'))
|
|
->map($convert),
|
|
'line' => $convert($entity->getLine()),
|
|
'destination' => $convert($entity->getFinal()->getStop()),
|
|
]);
|
|
break;
|
|
|
|
case $entity instanceof StopEntity:
|
|
$result->fill([
|
|
'name' => $entity->getName(),
|
|
'variant' => $entity->getVariant(),
|
|
'description' => $entity->getDescription(),
|
|
'group' => $entity->getGroup(),
|
|
'location' => new Location(
|
|
$entity->getLongitude(),
|
|
$entity->getLatitude()
|
|
),
|
|
]);
|
|
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;
|
|
}
|
|
|
|
return $result;
|
|
}
|
|
|
|
// HACK to not trigger doctrine stupid lazy loading.
|
|
private function getId(Entity $entity)
|
|
{
|
|
if ($entity instanceof Proxy) {
|
|
$id = (new \ReflectionClass(get_parent_class($entity)))->getProperty('id');
|
|
$id->setAccessible(true);
|
|
|
|
return $id->getValue($entity);
|
|
}
|
|
|
|
return $entity->getId();
|
|
}
|
|
|
|
private function collection($collection)
|
|
{
|
|
if (!$collection instanceof PersistentCollection || $collection->isInitialized()) {
|
|
return collect($collection);
|
|
}
|
|
|
|
return collect();
|
|
}
|
|
|
|
private function getModelClassForEntity(Entity $entity)
|
|
{
|
|
switch (true) {
|
|
case $entity instanceof OperatorEntity:
|
|
return Operator::class;
|
|
|
|
case $entity instanceof LineEntity:
|
|
return Line::class;
|
|
|
|
case $entity instanceof TrackEntity:
|
|
return Track::class;
|
|
|
|
case $entity instanceof StopEntity:
|
|
return Stop::class;
|
|
|
|
case $entity instanceof TripEntity:
|
|
return Trip::class;
|
|
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
|
|
private function create(Entity $entity)
|
|
{
|
|
$id = $this->id->of($entity);
|
|
$class = $this->getModelClassForEntity($entity);
|
|
|
|
return $class::createFromArray(['id' => $id]);
|
|
}
|
|
|
|
private function reference(Entity $entity)
|
|
{
|
|
$id = $this->id->strip($this->getId($entity));
|
|
$class = $this->getModelClassForEntity($entity);
|
|
|
|
return $this->reference->get($class, ['id' => $id]);
|
|
}
|
|
|
|
public function supports($entity)
|
|
{
|
|
return $entity instanceof Entity;
|
|
}
|
|
|
|
public function flushCache()
|
|
{
|
|
$this->cache = [];
|
|
}
|
|
}
|