diff --git a/src/Application/Cifs/PolylineMakerInterface.php b/src/Application/Cifs/PolylineMakerInterface.php index f95a29c69..71efb8367 100644 --- a/src/Application/Cifs/PolylineMakerInterface.php +++ b/src/Application/Cifs/PolylineMakerInterface.php @@ -6,5 +6,7 @@ interface PolylineMakerInterface { + public function attemptMergeLines(string $geometry): ?string; + public function getPolylines(string $geometry): array; } diff --git a/src/Application/Regulation/Query/GetCifsIncidentsQueryHandler.php b/src/Application/Regulation/Query/GetCifsIncidentsQueryHandler.php index 02de242fd..96c17b7d6 100644 --- a/src/Application/Regulation/Query/GetCifsIncidentsQueryHandler.php +++ b/src/Application/Regulation/Query/GetCifsIncidentsQueryHandler.php @@ -116,8 +116,16 @@ public function __invoke(GetCifsIncidentsQuery $query): array /** @var Location $location */ foreach ($measure->getLocations() as $location) { $locationId = $location->getUuid(); - $street = $location->getNamedStreet() ? $location->getNamedStreet()->getRoadName() : $location->getNumberedRoad()->getRoadNumber(); - $polylines = $this->polylineMaker->getPolylines($location->getGeometry()); + $street = $location->getCifsStreetLabel(); + + $geometry = $location->getGeometry(); + + if ($location->getRawGeoJSON()) { + // Simplify the geometry to a (MULTI)LINESTRING with deduplicated segments. + $geometry = $this->polylineMaker->attemptMergeLines($geometry); + } + + $polylines = $this->polylineMaker->getPolylines($geometry); foreach ($incidentPeriods as $incidentPeriod) { foreach ($polylines as $polyline) { diff --git a/src/Domain/Regulation/Location/Location.php b/src/Domain/Regulation/Location/Location.php index 8f4a31418..d98ef410b 100644 --- a/src/Domain/Regulation/Location/Location.php +++ b/src/Domain/Regulation/Location/Location.php @@ -54,6 +54,19 @@ public function getRawGeoJSON(): ?RawGeoJSON return $this->rawGeoJSON; } + public function getCifsStreetLabel(): string + { + if ($this->namedStreet) { + return $this->namedStreet->getRoadName(); + } + + if ($this->numberedRoad) { + return $this->numberedRoad->getRoadNumber(); + } + + return $this->rawGeoJSON->getLabel(); + } + public function update(string $roadType, ?string $geometry): void { $this->roadType = $roadType; diff --git a/src/Infrastructure/Cifs/PolylineMaker.php b/src/Infrastructure/Cifs/PolylineMaker.php index 14cd00aaf..b38a24062 100644 --- a/src/Infrastructure/Cifs/PolylineMaker.php +++ b/src/Infrastructure/Cifs/PolylineMaker.php @@ -14,6 +14,18 @@ public function __construct( ) { } + public function attemptMergeLines(string $geometry): ?string + { + $row = $this->em + ->getConnection() + ->fetchAssociative( + 'SELECT ST_AsGeoJSON(ST_LineMerge(:geom)) AS geom', + ['geom' => $geometry], + ); + + return $row['geom'] ?? $geometry; + } + public function getPolylines(string $geometry): array { $rows = $this->em diff --git a/src/Infrastructure/Persistence/Doctrine/Fixtures/LocationFixture.php b/src/Infrastructure/Persistence/Doctrine/Fixtures/LocationFixture.php index c1c50a060..76f16dfdf 100644 --- a/src/Infrastructure/Persistence/Doctrine/Fixtures/LocationFixture.php +++ b/src/Infrastructure/Persistence/Doctrine/Fixtures/LocationFixture.php @@ -261,6 +261,19 @@ public function load(ObjectManager $manager): void label: 'Zone Olympique', ); + $litteralisLocation1 = new Location( + '066e984f-4746-78f8-8000-dce555b28604', + $this->getReference('litteralisMeasure'), + roadType: RoadTypeEnum::RAW_GEOJSON->value, + geometry: '{"type":"MultiLineString","coordinates":[[[3.023890325,50.570177599],[3.023850386,50.570151247]],[[3.023890325,50.570177599],[3.024458944,50.570503315]],[[3.024458944,50.570503315],[3.024500711,50.570527945]],[[3.024500711,50.570527945],[3.024501619,50.570528488]],[[3.024501619,50.570528488],[3.025116052,50.570901355]],[[3.025116052,50.570901355],[3.02515503,50.570929555]],[[3.023850386,50.570151247],[3.02384667,50.570148629]],[[3.023475742,50.569868822],[3.023440948,50.569835923]],[[3.023475742,50.569868822],[3.02384667,50.570148629]],[[3.02515503,50.570929555],[3.025159053,50.570932711]],[[3.025159053,50.570932711],[3.025653937,50.571355649]],[[3.025653937,50.571355649],[3.02569009,50.57138952]],[[3.02569009,50.57138952],[3.025691455,50.571390856]],[[3.025691455,50.571390856],[3.026131049,50.571842058]],[[3.026131049,50.571842058],[3.026159516,50.571877523]],[[3.023440948,50.569835923],[3.02343789,50.569832708]],[[3.023149663,50.569492048],[3.023119275,50.569455721]],[[3.023149663,50.569492048],[3.02343789,50.569832708]],[[3.022717354,50.568969715],[3.023119183,50.56945561]],[[3.023119275,50.569455721],[3.023119183,50.56945561]],[[3.026159516,50.571877523],[3.02616073,50.571879188]],[[3.02616073,50.571879188],[3.027150974,50.57338937]]]}', + ); + + $litteralisLocation1RawGeoJSON = new RawGeoJSON( + uuid: '066e9850-3f1e-7735-8000-dacea1fe4ff1', + location: $litteralisLocation1, + label: 'ROUTE 147 (NOYELLES-LÈS-SECLIN) DU PR7 +779 AU PR8 +413', + ); + $manager->persist($namedStreetTypicalMeasureLocation1); $manager->persist($namedStreetTypicalMeasureLocation2); $manager->persist($namedStreetTypicalMeasureLocation3); @@ -289,6 +302,8 @@ public function load(ObjectManager $manager): void $manager->persist($cifsLocationDepartmentalRoad); $manager->persist($rawGeoJSONLocation); $manager->persist($rawGeoJSON); + $manager->persist($litteralisLocation1); + $manager->persist($litteralisLocation1RawGeoJSON); $manager->flush(); $this->addReference('typicalMeasureLocation1', $typicalMeasureLocation1); diff --git a/src/Infrastructure/Persistence/Doctrine/Fixtures/MeasureFixture.php b/src/Infrastructure/Persistence/Doctrine/Fixtures/MeasureFixture.php index 3d8d616fe..f49968dde 100644 --- a/src/Infrastructure/Persistence/Doctrine/Fixtures/MeasureFixture.php +++ b/src/Infrastructure/Persistence/Doctrine/Fixtures/MeasureFixture.php @@ -80,6 +80,13 @@ public function load(ObjectManager $manager): void new \DateTime('2023-01-06'), ); + $litteralisMeasure = new Measure( + '066e984c-9939-76ed-8000-d070d574f378', + $this->getReference('litteralisRegulationOrder'), + MeasureTypeEnum::NO_ENTRY->value, + new \DateTime('2023-06-01'), + ); + $manager->persist($typicalMeasure); $manager->persist($typicalMeasureToRemove); $manager->persist($publishedMeasure); @@ -88,6 +95,7 @@ public function load(ObjectManager $manager): void $manager->persist($cifsMeasure); $manager->persist($outDatedCifsMeasure); $manager->persist($rawGeoJSONMeasure); + $manager->persist($litteralisMeasure); $this->addReference('typicalMeasure', $typicalMeasure); $this->addReference('typicalMeasureToRemove', $typicalMeasureToRemove); @@ -97,6 +105,7 @@ public function load(ObjectManager $manager): void $this->addReference('cifsMeasure', $cifsMeasure); $this->addReference('outDatedCifsMeasure', $outDatedCifsMeasure); $this->addReference('rawGeoJSONMeasure', $rawGeoJSONMeasure); + $this->addReference('litteralisMeasure', $litteralisMeasure); $manager->flush(); } diff --git a/src/Infrastructure/Persistence/Doctrine/Fixtures/RegulationOrderFixture.php b/src/Infrastructure/Persistence/Doctrine/Fixtures/RegulationOrderFixture.php index 10b148329..dfebfc08e 100644 --- a/src/Infrastructure/Persistence/Doctrine/Fixtures/RegulationOrderFixture.php +++ b/src/Infrastructure/Persistence/Doctrine/Fixtures/RegulationOrderFixture.php @@ -116,6 +116,15 @@ public function load(ObjectManager $manager): void endDate: new \DateTimeImmutable('2020-06-10'), ); + $litteralisRegulationOrder = new RegulationOrder( + uuid: '066e9849-f802-7a4c-8000-845f47c4b0de', + identifier: '117374#24-A-0473', + category: RegulationOrderCategoryEnum::ROAD_MAINTENANCE->value, + description: 'Arrêté de voirie (URL : https://dl.sogelink.fr/?iX5UN3GL)', + startDate: new \DateTimeImmutable('2023-06-03'), + endDate: new \DateTimeImmutable('2023-11-10'), + ); + $manager->persist($typicalRegulationOrder); $manager->persist($publishedRegulationOrder); $manager->persist($regulationOrderDuplicate); @@ -127,6 +136,7 @@ public function load(ObjectManager $manager): void $manager->persist($regulationOrderCifs); $manager->persist($outDatedRegulationOrderCifs); $manager->persist($rawGeoJSONRegulationOrder); + $manager->persist($litteralisRegulationOrder); $manager->flush(); $this->addReference('typicalRegulationOrder', $typicalRegulationOrder); @@ -140,5 +150,6 @@ public function load(ObjectManager $manager): void $this->addReference('regulationOrderCifs', $regulationOrderCifs); $this->addReference('outDatedRegulationOrderCifs', $outDatedRegulationOrderCifs); $this->addReference('rawGeoJSONRegulationOrder', $rawGeoJSONRegulationOrder); + $this->addReference('litteralisRegulationOrder', $litteralisRegulationOrder); } } diff --git a/src/Infrastructure/Persistence/Doctrine/Fixtures/RegulationOrderRecordFixture.php b/src/Infrastructure/Persistence/Doctrine/Fixtures/RegulationOrderRecordFixture.php index ae4071460..045e6343e 100644 --- a/src/Infrastructure/Persistence/Doctrine/Fixtures/RegulationOrderRecordFixture.php +++ b/src/Infrastructure/Persistence/Doctrine/Fixtures/RegulationOrderRecordFixture.php @@ -36,6 +36,7 @@ final class RegulationOrderRecordFixture extends Fixture implements DependentFix public const UUID_NO_MEASURES = '0650037d-3e90-7a99-8000-a2099e71ae4a'; public const UUID_CIFS = '0654905d-6771-75d8-8000-d523184d0b55'; public const UUID_RAWGEOJSON = '06672e5e-8322-739f-8000-9ebfcd86e29a'; + public const UUID_LITTERALIS = '066e9849-1457-7a1e-8000-3142ece4a7de'; public function load(ObjectManager $manager): void { @@ -138,6 +139,15 @@ public function load(ObjectManager $manager): void $this->getReference('mainOrg'), ); + $litteralisRegulationOrderRecord = new RegulationOrderRecord( + self::UUID_LITTERALIS, + RegulationOrderRecordSourceEnum::LITTERALIS->value, + RegulationOrderRecordStatusEnum::PUBLISHED->value, + $this->getReference('litteralisRegulationOrder'), + new \DateTime('2024-09-05'), + $this->getReference('mainOrg'), + ); + $manager->persist($typicalRegulationOrderRecord); $manager->persist($publishedRegulationOrderRecord); $manager->persist($regulationOrderRecordDuplicate); @@ -149,6 +159,7 @@ public function load(ObjectManager $manager): void $manager->persist($regulationOrderRecordCifs); $manager->persist($outDatedRegulationOrderRecordCifs); $manager->persist($rawGeoJSONRegulationOrderRecord); + $manager->persist($litteralisRegulationOrderRecord); $manager->flush(); } diff --git a/src/Infrastructure/Persistence/Doctrine/Repository/Regulation/RegulationOrderRecordRepository.php b/src/Infrastructure/Persistence/Doctrine/Repository/Regulation/RegulationOrderRecordRepository.php index 5439f8c08..035043ade 100644 --- a/src/Infrastructure/Persistence/Doctrine/Repository/Regulation/RegulationOrderRecordRepository.php +++ b/src/Infrastructure/Persistence/Doctrine/Repository/Regulation/RegulationOrderRecordRepository.php @@ -251,7 +251,7 @@ public function findRegulationOrdersForCifsIncidentFormat( 'roc.status = :status', 'ro.endDate >= :today', 'loc.geometry IS NOT NULL', - 'loc.roadType NOT IN (:excludedRoadTypes)', + 'loc.roadType NOT IN (:excludedRoadTypes) OR (loc.roadType = :rawGeoJSONRoadType AND roc.source = :litteralisSource)', $allowedSources ? 'roc.source in (:allowedSources)' : null, $excludedIdentifiers ? 'ro.identifier NOT IN (:excludedIdentifiers)' : null, $allowedLocationIds ? 'loc.uuid IN (:allowedLocationIds)' : null, @@ -266,6 +266,9 @@ public function findRegulationOrdersForCifsIncidentFormat( 'measureType' => MeasureTypeEnum::NO_ENTRY->value, 'today' => $this->dateUtils->getNow(), 'excludedRoadTypes' => [RoadTypeEnum::RAW_GEOJSON->value], + // Allow RawGeoJSON locations only for Litteralis source + 'rawGeoJSONRoadType' => RoadTypeEnum::RAW_GEOJSON->value, + 'litteralisSource' => RegulationOrderRecordSourceEnum::LITTERALIS->value, ]) ->orderBy('loc.uuid') // Predictable order ->getQuery() diff --git a/tests/Integration/Infrastructure/Controller/Api/cifs-incidents-expected-result.xml b/tests/Integration/Infrastructure/Controller/Api/cifs-incidents-expected-result.xml index 2abd9968a..8f86d3d72 100644 --- a/tests/Integration/Infrastructure/Controller/Api/cifs-incidents-expected-result.xml +++ b/tests/Integration/Infrastructure/Controller/Api/cifs-incidents-expected-result.xml @@ -110,4 +110,20 @@ 08:00-10:00 + + + 2024-09-05T00:00:00+00:00 + ROAD_CLOSED + ROUTE 147 (NOYELLES-LÈS-SECLIN) DU PR7 +779 AU PR8 +413 : circulation interdite tous les jours pour tous les véhicles + ROUTE 147 (NOYELLES-LÈS-SECLIN) DU PR7 +779 AU PR8 +413 + BOTH_DIRECTIONS + 50.568969715 3.022717354 50.56945561 3.023119183 50.569455721 3.023119275 50.569492048 3.023149663 50.569832708 3.02343789 50.569835923 3.023440948 50.569868822 3.023475742 50.570148629 3.02384667 50.570151247 3.023850386 50.570177599 3.023890325 50.570503315 3.024458944 50.570527945 3.024500711 50.570528488 3.024501619 50.570901355 3.025116052 50.570929555 3.02515503 50.570932711 3.025159053 50.571355649 3.025653937 50.57138952 3.02569009 50.571390856 3.025691455 50.571842058 3.026131049 50.571877523 3.026159516 50.571879188 3.02616073 50.57338937 3.027150974 + 2023-06-03T00:00:00+00:00 + 2023-11-10T00:00:00+00:00 + + dialog.beta.gouv.fr + DiaLog + http://localhost/api/regulations/cifs.xml + + diff --git a/tests/Integration/Infrastructure/Controller/Api/get-regulations-expected-result.xml b/tests/Integration/Infrastructure/Controller/Api/get-regulations-expected-result.xml index 4f515475b..bd5d105e7 100644 --- a/tests/Integration/Infrastructure/Controller/Api/get-regulations-expected-result.xml +++ b/tests/Integration/Infrastructure/Controller/Api/get-regulations-expected-result.xml @@ -453,21 +453,17 @@ definedByValidityTimeSpec - 2023-09-03T00:00:00+00:00 - - 2023-09-06T00:00:00+00:00 + 2023-09-03T08:00:00+00:00 + 2023-09-05T10:00:00+00:00 - 12:00:00+00:00 - 14:00:00+00:00 - - - 19:00:00+00:00 - 21:00:00+00:00 + 08:00:00+00:00 + 10:00:00+00:00 tuesday + thursday @@ -502,17 +498,21 @@ definedByValidityTimeSpec - 2023-09-03T08:00:00+00:00 - 2023-09-05T10:00:00+00:00 + 2023-09-03T00:00:00+00:00 + + 2023-09-06T00:00:00+00:00 - 08:00:00+00:00 - 10:00:00+00:00 + 12:00:00+00:00 + 14:00:00+00:00 + + + 19:00:00+00:00 + 21:00:00+00:00 tuesday - thursday @@ -563,6 +563,61 @@ + + + + Arrêté de voirie (URL : https://dl.sogelink.fr/?iX5UN3GL) + + + + + Main Org + + + 117374#24-A-0473#e0d93630-acf7-4722-81e8-ff7d5fa64b66 + madeAndImplemented + + definedByValidityTimeSpec + + 2023-06-03T00:00:00.000Z + 2023-11-10T23:59:59.000Z + + + + active + + noEntry + + + and + + or + + + + + + ROUTE 147 (NOYELLES-LÈS-SECLIN) DU PR7 +779 AU PR8 +413 + + + + + + {"type":"MultiLineString","coordinates":[[[3.023890325,50.570177599],[3.023850386,50.570151247]],[[3.023890325,50.570177599],[3.024458944,50.570503315]],[[3.024458944,50.570503315],[3.024500711,50.570527945]],[[3.024500711,50.570527945],[3.024501619,50.570528488]],[[3.024501619,50.570528488],[3.025116052,50.570901355]],[[3.025116052,50.570901355],[3.02515503,50.570929555]],[[3.023850386,50.570151247],[3.02384667,50.570148629]],[[3.023475742,50.569868822],[3.023440948,50.569835923]],[[3.023475742,50.569868822],[3.02384667,50.570148629]],[[3.02515503,50.570929555],[3.025159053,50.570932711]],[[3.025159053,50.570932711],[3.025653937,50.571355649]],[[3.025653937,50.571355649],[3.02569009,50.57138952]],[[3.02569009,50.57138952],[3.025691455,50.571390856]],[[3.025691455,50.571390856],[3.026131049,50.571842058]],[[3.026131049,50.571842058],[3.026159516,50.571877523]],[[3.023440948,50.569835923],[3.02343789,50.569832708]],[[3.023149663,50.569492048],[3.023119275,50.569455721]],[[3.023149663,50.569492048],[3.02343789,50.569832708]],[[3.022717354,50.568969715],[3.023119183,50.56945561]],[[3.023119275,50.569455721],[3.023119183,50.56945561]],[[3.026159516,50.571877523],[3.02616073,50.571879188]],[[3.02616073,50.571879188],[3.027150974,50.57338937]]]} + + + + + + + + <_trafficRegulationOrderExtension> + + litteralis + http://localhost/regulations/066e9849-1457-7a1e-8000-3142ece4a7de + + + diff --git a/tests/Integration/Infrastructure/Controller/Map/Fragment/MapDataControllerTest.php b/tests/Integration/Infrastructure/Controller/Map/Fragment/MapDataControllerTest.php index cf62a091e..b6ed5f685 100644 --- a/tests/Integration/Infrastructure/Controller/Map/Fragment/MapDataControllerTest.php +++ b/tests/Integration/Infrastructure/Controller/Map/Fragment/MapDataControllerTest.php @@ -19,7 +19,7 @@ public function testGet(): void $data = $client->getResponse()->getContent(); - $this->assertSame('{"type":"FeatureCollection","features":[{"type":"Feature","geometry":{"type":"LineString","coordinates":[[1.35643852,44.01573612],[1.354256366,44.016628823]]},"properties":{"location_uuid":"06548f85-d545-7b45-8000-8a23c45850b3","measure_type":"noEntry"}},{"type":"Feature","geometry":{"type":"LineString","coordinates":[[4.813813598,49.591846975],[4.814740991,49.591873571],[4.816667381,49.592113537],[4.818187712,49.592210337],[4.819289813,49.592484173],[4.819889992,49.59252462],[4.829814141,49.591086495],[4.830170433,49.590879775],[4.830722512,49.590075935],[4.831041199,49.589784384],[4.831403969,49.589565876],[4.833546609,49.588543864],[4.834215703,49.588230832],[4.836971699,49.587235446],[4.837376079,49.587137641],[4.838472209,49.587013183],[4.839237347,49.586796648],[4.840037366,49.586396205],[4.841639596,49.585426275],[4.842908002,49.584902749],[4.843561098,49.584686088],[4.849655173,49.582987972],[4.850304524,49.582898976],[4.851311595,49.583030147],[4.851880087,49.582922598],[4.852786076,49.582589666],[4.854663703,49.581751986],[4.855401273,49.581503406],[4.857518763,49.580916405],[4.858136813,49.580613005],[4.859253989,49.579700589],[4.861152737,49.578726744],[4.863674717,49.577253393],[4.865404244,49.576040265],[4.867717907,49.574889139],[4.869863647,49.574064163],[4.870349249,49.57373397],[4.870681327,49.572870386],[4.87101305,49.572490424],[4.872740733,49.57150104],[4.873072333,49.571118377],[4.873345767,49.570543342],[4.87385572,49.570200173],[4.874742902,49.569740608],[4.875011836,49.569535096],[4.875258088,49.569162733],[4.875670018,49.567763933],[4.875814693,49.567411116],[4.876148691,49.566830641],[4.876363964,49.566594491],[4.87652815,49.566511049],[4.876749592,49.566481557],[4.878555698,49.5668887],[4.879036074,49.56691003],[4.879470406,49.566843976],[4.880579284,49.566553527],[4.880974307,49.566395488],[4.881244711,49.566193533],[4.882047478,49.565282158],[4.882265058,49.565147541],[4.882514114,49.565079854],[4.8850042,49.56495581],[4.886017708,49.564742301],[4.887448256,49.564331725],[4.887803303,49.564929388],[4.887977011,49.565105573],[4.888214995,49.565150414],[4.888984026,49.565053948],[4.88940902,49.565148014],[4.889549246,49.565277974],[4.889719641,49.565626804],[4.8900792,49.566083257],[4.890408287,49.566425119],[4.890621101,49.566536868],[4.895232631,49.566333708],[4.895596514,49.566344207],[4.895749664,49.566411932],[4.895795549,49.566531672],[4.895722966,49.566961597],[4.895411684,49.568076638],[4.894544659,49.569376543],[4.894218132,49.570229329],[4.893982229,49.571028561],[4.893942947,49.571350091],[4.894030516,49.571625595],[4.894256421,49.571866578],[4.895365423,49.572439863],[4.895801181,49.572748582],[4.89649466,49.573560268],[4.896618374,49.573765987],[4.896628389,49.574111917],[4.89612879,49.575930155],[4.896095023,49.576288454],[4.896138655,49.576945784]]},"properties":{"location_uuid":"065f94ef-ea0a-7ab5-8000-bd5686102151","measure_type":"noEntry"}}]}', $data); + $this->assertSame('{"type":"FeatureCollection","features":[{"type":"Feature","geometry":{"type":"LineString","coordinates":[[1.35643852,44.01573612],[1.354256366,44.016628823]]},"properties":{"location_uuid":"06548f85-d545-7b45-8000-8a23c45850b3","measure_type":"noEntry"}},{"type":"Feature","geometry":{"type":"LineString","coordinates":[[4.813813598,49.591846975],[4.814740991,49.591873571],[4.816667381,49.592113537],[4.818187712,49.592210337],[4.819289813,49.592484173],[4.819889992,49.59252462],[4.829814141,49.591086495],[4.830170433,49.590879775],[4.830722512,49.590075935],[4.831041199,49.589784384],[4.831403969,49.589565876],[4.833546609,49.588543864],[4.834215703,49.588230832],[4.836971699,49.587235446],[4.837376079,49.587137641],[4.838472209,49.587013183],[4.839237347,49.586796648],[4.840037366,49.586396205],[4.841639596,49.585426275],[4.842908002,49.584902749],[4.843561098,49.584686088],[4.849655173,49.582987972],[4.850304524,49.582898976],[4.851311595,49.583030147],[4.851880087,49.582922598],[4.852786076,49.582589666],[4.854663703,49.581751986],[4.855401273,49.581503406],[4.857518763,49.580916405],[4.858136813,49.580613005],[4.859253989,49.579700589],[4.861152737,49.578726744],[4.863674717,49.577253393],[4.865404244,49.576040265],[4.867717907,49.574889139],[4.869863647,49.574064163],[4.870349249,49.57373397],[4.870681327,49.572870386],[4.87101305,49.572490424],[4.872740733,49.57150104],[4.873072333,49.571118377],[4.873345767,49.570543342],[4.87385572,49.570200173],[4.874742902,49.569740608],[4.875011836,49.569535096],[4.875258088,49.569162733],[4.875670018,49.567763933],[4.875814693,49.567411116],[4.876148691,49.566830641],[4.876363964,49.566594491],[4.87652815,49.566511049],[4.876749592,49.566481557],[4.878555698,49.5668887],[4.879036074,49.56691003],[4.879470406,49.566843976],[4.880579284,49.566553527],[4.880974307,49.566395488],[4.881244711,49.566193533],[4.882047478,49.565282158],[4.882265058,49.565147541],[4.882514114,49.565079854],[4.8850042,49.56495581],[4.886017708,49.564742301],[4.887448256,49.564331725],[4.887803303,49.564929388],[4.887977011,49.565105573],[4.888214995,49.565150414],[4.888984026,49.565053948],[4.88940902,49.565148014],[4.889549246,49.565277974],[4.889719641,49.565626804],[4.8900792,49.566083257],[4.890408287,49.566425119],[4.890621101,49.566536868],[4.895232631,49.566333708],[4.895596514,49.566344207],[4.895749664,49.566411932],[4.895795549,49.566531672],[4.895722966,49.566961597],[4.895411684,49.568076638],[4.894544659,49.569376543],[4.894218132,49.570229329],[4.893982229,49.571028561],[4.893942947,49.571350091],[4.894030516,49.571625595],[4.894256421,49.571866578],[4.895365423,49.572439863],[4.895801181,49.572748582],[4.89649466,49.573560268],[4.896618374,49.573765987],[4.896628389,49.574111917],[4.89612879,49.575930155],[4.896095023,49.576288454],[4.896138655,49.576945784]]},"properties":{"location_uuid":"065f94ef-ea0a-7ab5-8000-bd5686102151","measure_type":"noEntry"}},{"type":"Feature","geometry":{"type":"MultiLineString","coordinates":[[[3.023890325,50.570177599],[3.023850386,50.570151247]],[[3.023890325,50.570177599],[3.024458944,50.570503315]],[[3.024458944,50.570503315],[3.024500711,50.570527945]],[[3.024500711,50.570527945],[3.024501619,50.570528488]],[[3.024501619,50.570528488],[3.025116052,50.570901355]],[[3.025116052,50.570901355],[3.02515503,50.570929555]],[[3.023850386,50.570151247],[3.02384667,50.570148629]],[[3.023475742,50.569868822],[3.023440948,50.569835923]],[[3.023475742,50.569868822],[3.02384667,50.570148629]],[[3.02515503,50.570929555],[3.025159053,50.570932711]],[[3.025159053,50.570932711],[3.025653937,50.571355649]],[[3.025653937,50.571355649],[3.02569009,50.57138952]],[[3.02569009,50.57138952],[3.025691455,50.571390856]],[[3.025691455,50.571390856],[3.026131049,50.571842058]],[[3.026131049,50.571842058],[3.026159516,50.571877523]],[[3.023440948,50.569835923],[3.02343789,50.569832708]],[[3.023149663,50.569492048],[3.023119275,50.569455721]],[[3.023149663,50.569492048],[3.02343789,50.569832708]],[[3.022717354,50.568969715],[3.023119183,50.56945561]],[[3.023119275,50.569455721],[3.023119183,50.56945561]],[[3.026159516,50.571877523],[3.02616073,50.571879188]],[[3.02616073,50.571879188],[3.027150974,50.57338937]]]},"properties":{"location_uuid":"066e984f-4746-78f8-8000-dce555b28604","measure_type":"noEntry"}}]}', $data); } public function testGetFilters(): void diff --git a/tests/Integration/Infrastructure/Controller/Regulation/ListRegulationsControllerTest.php b/tests/Integration/Infrastructure/Controller/Regulation/ListRegulationsControllerTest.php index 796d4da74..e07977a2b 100644 --- a/tests/Integration/Infrastructure/Controller/Regulation/ListRegulationsControllerTest.php +++ b/tests/Integration/Infrastructure/Controller/Regulation/ListRegulationsControllerTest.php @@ -36,7 +36,7 @@ public function testNavAndPagination(): void $this->assertSame('2', $navLi->eq(3)->filter('a')->text()); $this->assertSame('3', $navLi->eq(4)->filter('a')->text()); $this->assertSame('...', $navLi->eq(5)->text()); - $this->assertSame('11', $navLi->eq(6)->filter('a')->text()); + $this->assertSame('12', $navLi->eq(6)->filter('a')->text()); $this->assertSame('Page suivante', $navLi->eq(7)->filter('a')->text()); $this->assertSame('Dernière page', $navLi->eq(8)->filter('a')->text()); @@ -69,11 +69,11 @@ public function testRegulationRendering(): void $this->assertSame('http://localhost/regulations/' . RegulationOrderRecordFixture::UUID_NO_LOCATIONS, $links->eq(0)->link()->getUri()); // Second item - $pageTwo = $client->request('GET', '/regulations?pageSize=1&page=3'); + $otherPage = $client->request('GET', '/regulations?pageSize=1&page=4'); $this->assertResponseStatusCodeSame(200); $this->assertSecurityHeaders(); - $pageTwoRows = $pageTwo->filter('[data-testid="app-regulation-table"] tbody > tr'); + $pageTwoRows = $otherPage->filter('[data-testid="app-regulation-table"] tbody > tr'); $this->assertSame(1, $pageTwoRows->count()); // One item per page $pageTwoRow0 = $pageTwoRows->eq(0)->filter('td'); @@ -87,7 +87,7 @@ public function testRegulationRendering(): void public function testPublishedRegulationRendering(): void { $client = $this->login(); - $crawler = $client->request('GET', '/regulations?pageSize=1&page=7'); + $crawler = $client->request('GET', '/regulations?pageSize=1&page=8'); $this->assertResponseStatusCodeSame(200); $this->assertSecurityHeaders(); @@ -220,7 +220,7 @@ public function testRegulationOrderTypeFilterTemporary(): void $crawler = $client->submit($form); $rows = $crawler->filter('[data-testid="app-regulation-table"] tbody > tr'); - $this->assertSame(9, $rows->count()); + $this->assertSame(10, $rows->count()); } public function testStatusFilterPublished(): void @@ -248,10 +248,10 @@ public function testStatusFilterPublished(): void $crawler = $client->submit($form); $rows = $crawler->filter('[data-testid="app-regulation-table"] tbody > tr'); - $this->assertSame(4, $rows->count()); + $this->assertSame(5, $rows->count()); $statuses = $rows->filter('td:nth-child(5)')->each(fn ($node) => $node->text()); - $this->assertSame('Publié, Publié, Publié, Publié', implode(', ', $statuses)); + $this->assertSame('Publié, Publié, Publié, Publié, Publié', implode(', ', $statuses)); } public function testStatusFilterDraft(): void @@ -291,10 +291,10 @@ public function testStatusFilterAsAnonymousUser(): void $this->assertNotNull($node->closest('[class*="fr-hidden"]')); $rows = $crawler->filter('[data-testid="app-regulation-table"] tbody > tr'); - $this->assertSame(4, $rows->count()); + $this->assertSame(5, $rows->count()); $statuses = $rows->filter('td:nth-child(5)')->each(fn ($node) => $node->text()); - $this->assertSame('Publié, Publié, Publié, Publié', implode(', ', $statuses)); + $this->assertSame('Publié, Publié, Publié, Publié, Publié', implode(', ', $statuses)); } public function testStatusFilterAsAnonymousUserForceDraft(): void @@ -310,10 +310,10 @@ public function testStatusFilterAsAnonymousUserForceDraft(): void $this->assertSame('published', $form->get('status')->getValue()); $rows = $crawler->filter('[data-testid="app-regulation-table"] tbody > tr'); - $this->assertSame(4, $rows->count()); + $this->assertSame(5, $rows->count()); $statuses = $rows->filter('td:nth-child(5)')->each(fn ($node) => $node->text()); - $this->assertSame('Publié, Publié, Publié, Publié', implode(', ', $statuses)); + $this->assertSame('Publié, Publié, Publié, Publié, Publié', implode(', ', $statuses)); } public function testFilterCombinationViaUrl(): void diff --git a/tests/Integration/Infrastructure/Repository/RegulationOrderRecordRepositoryTest.php b/tests/Integration/Infrastructure/Repository/RegulationOrderRecordRepositoryTest.php index 45f218b6d..13125aee6 100644 --- a/tests/Integration/Infrastructure/Repository/RegulationOrderRecordRepositoryTest.php +++ b/tests/Integration/Infrastructure/Repository/RegulationOrderRecordRepositoryTest.php @@ -26,7 +26,10 @@ protected function setUp(): void public function testCifsFiltersEmpty(): void { $regulationOrderRecords = $this->repository->findRegulationOrdersForCifsIncidentFormat(); - $this->assertEquals([RegulationOrderRecordFixture::UUID_CIFS], array_map(fn ($roc) => $roc->getUuid(), $regulationOrderRecords)); + $this->assertEquals([ + RegulationOrderRecordFixture::UUID_CIFS, + RegulationOrderRecordFixture::UUID_LITTERALIS, + ], array_map(fn ($roc) => $roc->getUuid(), $regulationOrderRecords)); $this->assertEquals( [LocationFixture::UUID_CIFS_NAMED_STREET, LocationFixture::UUID_CIFS_DEPARTMENTAL_ROAD], array_map(fn ($loc) => $loc->getUuid(), $regulationOrderRecords[0]->getRegulationOrder()->getMeasures()[0]->getLocations()->toArray()), @@ -48,7 +51,7 @@ public function testCifsFiltersExcludedIdentifiers(): void excludedIdentifiers: [RegulationOrderFixture::IDENTIFIER_CIFS], ); - $this->assertEquals([], $regulationOrderRecords); + $this->assertEquals([RegulationOrderRecordFixture::UUID_LITTERALIS], array_map(fn ($roc) => $roc->getUuid(), $regulationOrderRecords)); } public function testCifsFiltersAllowedLocationIds(): void diff --git a/tests/Unit/Application/Regulation/Query/GetCifsIncidentsQueryHandlerTest.php b/tests/Unit/Application/Regulation/Query/GetCifsIncidentsQueryHandlerTest.php index 03334205c..11ae08953 100644 --- a/tests/Unit/Application/Regulation/Query/GetCifsIncidentsQueryHandlerTest.php +++ b/tests/Unit/Application/Regulation/Query/GetCifsIncidentsQueryHandlerTest.php @@ -15,7 +15,7 @@ use App\Domain\Condition\Period\TimeSlot; use App\Domain\Regulation\Enum\RegulationOrderCategoryEnum; use App\Domain\Regulation\Location\Location; -use App\Domain\Regulation\Location\NamedStreet; +use App\Domain\Regulation\Location\RawGeoJSON; use App\Domain\Regulation\Measure; use App\Domain\Regulation\RegulationOrder; use App\Domain\Regulation\RegulationOrderRecord; @@ -50,6 +50,8 @@ public function testGetAll(): void { $polyline1 = '44.0289961 1.362275 44.0256652 1.359310'; $polyline1Hash = md5($polyline1); + $polyline1bis = '44.028906 1.3621753 44.045665 1.3533105'; + $polyline1bisHash = md5($polyline1bis); $polyline2 = '44.0256652 1.359310 44.1545432 1.34541242'; $polyline2Hash = md5($polyline2); $polyline3 = '44.028996 1.3622753 44.025665 1.3593105'; @@ -69,6 +71,8 @@ public function testGetAll(): void ], ]); + $geometry1bis = '...geometry1bis...'; + $geometry2 = json_encode([ 'type' => 'LineString', 'coordinates' => [ @@ -111,6 +115,19 @@ public function testGetAll(): void schedule: $incident1->schedule, ); + $incident1bis = new CifsIncidentView( + id: \sprintf('2024T1:066e98a9-0ce0-7e4b-8000-677c1eafc53d:%s:0', $polyline1bisHash), + creationTime: $incident1->creationTime, + type: $incident1->type, + subType: $incident1->subType, + street: 'Zone Olympique', + direction: $incident1->direction, + polyline: $polyline1bis, + startTime: $incident1->startTime, + endTime: $incident1->endTime, + schedule: $incident1->schedule, + ); + $incident3 = new CifsIncidentView( id: \sprintf('2024T2:9698b212-705c-4c46-8968-63b5a55a4d66:%s:%s', $polyline3Hash, $period1Id), creationTime: new \DateTimeImmutable('2023-11-01T00:00:00+00:00'), @@ -263,28 +280,48 @@ public function testGetAll(): void ->willReturn([]); $location1 = $this->createMock(Location::class); - $namedStreet1 = $this->createMock(NamedStreet::class); $location1 ->expects(self::once()) ->method('getUuid') ->willReturn('02d5eb61-9ca3-4e67-aacd-726f124382d0'); $location1 - ->expects(self::exactly(2)) - ->method('getNamedStreet') - ->willReturn($namedStreet1); - $namedStreet1 ->expects(self::once()) - ->method('getRoadName') + ->method('getCifsStreetLabel') ->willReturn('Rue des Arts'); $location1 ->expects(self::once()) ->method('getGeometry') ->willReturn($geometry1); + $location1bis = $this->createMock(Location::class); + $rawGeoJSON = $this->createMock(RawGeoJSON::class); + $location1bis + ->expects(self::once()) + ->method('getUuid') + ->willReturn('066e98a9-0ce0-7e4b-8000-677c1eafc53d'); + $location1bis + ->expects(self::once()) + ->method('getRawGeoJSON') + ->willReturn($rawGeoJSON); + $location1bis + ->expects(self::once()) + ->method('getCifsStreetLabel') + ->willReturn('Zone Olympique'); + $location1bis + ->expects(self::once()) + ->method('getGeometry') + ->willReturn($geometry1bis); + + $this->polylineMaker + ->expects(self::once()) + ->method('attemptMergeLines') + ->with($geometry1bis) + ->willReturn('mergedGeometry1bis'); + $measure1 ->expects(self::once()) ->method('getLocations') - ->willReturn([$location1]); + ->willReturn([$location1, $location1bis]); $regulationOrder1 ->expects(self::once()) @@ -524,18 +561,13 @@ public function testGetAll(): void ->willReturn([$period1, $period2, $period3, $period4, $period5]); $location2 = $this->createMock(Location::class); - $namedStreet2 = $this->createMock(NamedStreet::class); $location2 ->expects(self::once()) ->method('getUuid') ->willReturn('9698b212-705c-4c46-8968-63b5a55a4d66'); $location2 - ->expects(self::exactly(2)) - ->method('getNamedStreet') - ->willReturn($namedStreet2); - $namedStreet2 ->expects(self::once()) - ->method('getRoadName') + ->method('getCifsStreetLabel') ->willReturn('Avenue de Fonneuve'); $location2 ->expects(self::once()) @@ -558,10 +590,10 @@ public function testGetAll(): void ->willReturn($regulationOrder2); $this->polylineMaker - ->expects(self::exactly(2)) + ->expects(self::exactly(3)) ->method('getPolylines') - ->withConsecutive([$geometry1], [$geometry2]) - ->willReturnOnConsecutiveCalls([$polyline1, $polyline2], [$polyline3]); + ->withConsecutive([$geometry1], ['mergedGeometry1bis'], [$geometry2]) + ->willReturnOnConsecutiveCalls([$polyline1, $polyline2], [$polyline1bis], [$polyline3]); $this->regulationOrderRecordRepository ->expects(self::once()) @@ -572,7 +604,7 @@ public function testGetAll(): void $incidents = $handler(new GetCifsIncidentsQuery()); $this->assertEquals( - [$incident1, $incident2, $incident3, $incident4, $incident5, $incident6, $incident7], + [$incident1, $incident2, $incident1bis, $incident3, $incident4, $incident5, $incident6, $incident7], $incidents, ); } diff --git a/tests/Unit/Domain/Regulation/Location/LocationTest.php b/tests/Unit/Domain/Regulation/Location/LocationTest.php index 9ab371e96..9498a0d50 100644 --- a/tests/Unit/Domain/Regulation/Location/LocationTest.php +++ b/tests/Unit/Domain/Regulation/Location/LocationTest.php @@ -71,6 +71,24 @@ public function testGetters(): void $this->assertSame($numberedRoad, $numberedRoadLocation->getNumberedRoad()); $this->assertSame($namedStreet, $namedStreetLocation->getNamedStreet()); + $namedStreet + ->expects(self::once()) + ->method('getRoadName') + ->willReturn('road name'); + $this->assertSame('road name', $namedStreetLocation->getCifsStreetLabel()); + + $numberedRoad + ->expects(self::once()) + ->method('getRoadNumber') + ->willReturn('road number'); + $this->assertSame('road number', $numberedRoadLocation->getCifsStreetLabel()); + + $rawGeoJSON + ->expects(self::once()) + ->method('getLabel') + ->willReturn('label'); + $this->assertSame('label', $rawGeoJSONLocation->getCifsStreetLabel()); + $numberedRoadLocation->setNumberedRoad($numberedRoad2); $namedStreetLocation->setNamedStreet($namedStreet2); $rawGeoJSONLocation->setRawGeoJSON($rawGeoJSON2);