diff --git a/src/Application/Regulation/View/Measure/LocationView.php b/src/Application/Regulation/View/Measure/LocationView.php index a7757af1b..3f87afe5e 100644 --- a/src/Application/Regulation/View/Measure/LocationView.php +++ b/src/Application/Regulation/View/Measure/LocationView.php @@ -9,6 +9,7 @@ public function __construct( public string $uuid, public string $roadType, + public string $geometry, public ?NamedStreetView $namedStreet = null, public ?NumberedRoadView $numberedRoad = null, public ?RawGeoJSONView $rawGeoJSON = null, diff --git a/src/Application/Regulation/View/Measure/MeasureView.php b/src/Application/Regulation/View/Measure/MeasureView.php index 631e69a86..6356edde7 100644 --- a/src/Application/Regulation/View/Measure/MeasureView.php +++ b/src/Application/Regulation/View/Measure/MeasureView.php @@ -53,6 +53,7 @@ public static function fromEntity(Measure $measure): self $locations[] = new LocationView( uuid: $location->getUuid(), roadType: $location->getRoadType(), + geometry: $location->getGeometry(), namedStreet: new NamedStreetView( cityLabel: $namedStreet->getCityLabel(), roadName: $namedStreet->getRoadName(), @@ -66,6 +67,7 @@ public static function fromEntity(Measure $measure): self $locations[] = new LocationView( uuid: $location->getUuid(), roadType: $location->getRoadType(), + geometry: $location->getGeometry(), numberedRoad: new NumberedRoadView( administrator: $numberedRoad->getAdministrator(), roadNumber: $numberedRoad->getRoadNumber(), @@ -81,6 +83,7 @@ public static function fromEntity(Measure $measure): self $locations[] = new LocationView( uuid: $location->getUuid(), roadType: $location->getRoadType(), + geometry: $location->getGeometry(), rawGeoJSON: new RawGeoJSONView( label: $rawGeoJSON->getLabel(), ), diff --git a/src/Infrastructure/Adapter/WazeUrlMaker.php b/src/Infrastructure/Adapter/WazeUrlMaker.php new file mode 100644 index 000000000..8db55df9d --- /dev/null +++ b/src/Infrastructure/Adapter/WazeUrlMaker.php @@ -0,0 +1,69 @@ +uuid] = []; + + foreach ($measure->locations as $location) { + $hashes[] = implode('#', [$measure->uuid, $location->uuid]); + $geometries[] = $location->geometry; + } + } + + // Use a single SQL query + $urls = $this->bulkBuildUrls($geometries); + + foreach ($urls as $index => $url) { + $hash = $hashes[$index]; + [$measureUuid, $locationUuid] = explode('#', $hash); + $urlsByMeasureAndLocation[$measureUuid][$locationUuid] = $url; + } + + return $urlsByMeasureAndLocation; + } + + private function bulkBuildUrls(array $geometries): array + { + $rows = $this->connection->fetchAllAssociative( + 'SELECT ST_AsGeoJSON(ST_Centroid(g)) AS geom + FROM unnest(ARRAY[:geometries]) AS g', + ['geometries' => $geometries], + ['geometries' => ArrayParameterType::STRING], + ); + + $urls = []; + + foreach ($rows as $row) { + $lonLat = json_decode($row['geom'], true)['coordinates']; + + $urls[] = 'https://www.waze.com/en/live-map/directions?' . http_build_query([ + 'latlng' => \sprintf('%.6f,%.6f', $lonLat[1], $lonLat[0]), + ]); + } + + return $urls; + } +} diff --git a/src/Infrastructure/Controller/Regulation/RegulationDetailController.php b/src/Infrastructure/Controller/Regulation/RegulationDetailController.php index a26afa6ee..b8ca4f7a4 100644 --- a/src/Infrastructure/Controller/Regulation/RegulationDetailController.php +++ b/src/Infrastructure/Controller/Regulation/RegulationDetailController.php @@ -13,6 +13,7 @@ use App\Domain\Regulation\Specification\CanOrganizationAccessToRegulation; use App\Domain\Regulation\Specification\CanRegulationOrderRecordBePublished; use App\Domain\Regulation\Specification\CanViewRegulationDetail; +use App\Infrastructure\Adapter\WazeUrlMaker; use App\Infrastructure\Security\SymfonyUser; use Symfony\Bundle\SecurityBundle\Security; use Symfony\Component\HttpFoundation\Response; @@ -28,6 +29,7 @@ public function __construct( private CanViewRegulationDetail $canViewRegulationDetail, private CanDeleteMeasures $canDeleteMeasures, private CanRegulationOrderRecordBePublished $canRegulationOrderRecordBePublished, + private WazeUrlMaker $wazeUrlMaker, CanOrganizationAccessToRegulation $canOrganizationAccessToRegulation, Security $security, ) { @@ -58,6 +60,7 @@ public function __invoke(string $uuid): Response $organizationUuid = $regulationOrderRecord->getOrganizationUuid(); $measures = $this->queryBus->handle(new GetMeasuresQuery($uuid)); $isReadOnly = !($currentUser && $this->canOrganizationAccessToRegulation->isSatisfiedBy($organizationUuid, $currentUser->getUserOrganizationUuids())); + $wazeUrls = $this->wazeUrlMaker->makeAll($measures); $context = [ 'uuid' => $uuid, @@ -69,6 +72,7 @@ public function __invoke(string $uuid): Response 'isPermanent' => $regulationOrderRecord->getRegulationOrder()->isPermanent(), 'measures' => $measures, 'regulationOrderRecord' => $regulationOrderRecord, + 'wazeUrls' => $wazeUrls, ]; return new Response( diff --git a/templates/regulation/detail.html.twig b/templates/regulation/detail.html.twig index 85f66c9fe..e85d2ca77 100644 --- a/templates/regulation/detail.html.twig +++ b/templates/regulation/detail.html.twig @@ -36,7 +36,7 @@ diff --git a/templates/regulation/fragments/_measure.html.twig b/templates/regulation/fragments/_measure.html.twig index 62d711ff5..a278a22af 100644 --- a/templates/regulation/fragments/_measure.html.twig +++ b/templates/regulation/fragments/_measure.html.twig @@ -33,9 +33,16 @@