Skip to content

Commit

Permalink
Ajoute le type Route nationale
Browse files Browse the repository at this point in the history
  • Loading branch information
florimondmanca committed Nov 27, 2024
1 parent 3eb3382 commit 410f2ae
Show file tree
Hide file tree
Showing 31 changed files with 1,032 additions and 330 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,15 @@
<property name="namedStreet">
<constraint name="Valid" />
</property>
<property name="numberedRoad">
<property name="departmentalRoad">
<constraint name="Valid" />
</property>
<property name="nationalRoad">
<constraint name="Valid" />
</property>
<property name="rawGeoJSON">
<constraint name="Valid" />
</property>
<constraint name="App\Infrastructure\Validator\SaveLocationCommandConstraint" />
</class>
</constraint-mapping>
Original file line number Diff line number Diff line change
Expand Up @@ -7,57 +7,25 @@
<constraint name="Length">
<option name="max">255</option>
</constraint>
<constraint name="When">
<option name="expression"> this.roadType === 'departmentalRoad' </option>
<option name="constraints">
<constraint name="NotBlank" />
</option>
</constraint>
</property>
<property name="roadNumber">
<constraint name="When">
<option name="expression"> this.roadType === 'departmentalRoad' </option>
<option name="constraints">
<constraint name="NotBlank" />
<constraint name="Length">
<option name="max">50</option>
</constraint>
</option>
</constraint>
</property>
<property name="fromPointNumber">
<constraint name="When">
<option name="expression"> this.roadType === 'departmentalRoad' </option>
<option name="constraints">
<constraint name="NotBlank"/>
</option>
</constraint>
</property>
<property name="toPointNumber">
<constraint name="When">
<option name="expression"> this.roadType === 'departmentalRoad' </option>
<option name="constraints">
<constraint name="NotBlank"/>
</option>
<constraint name="Length">
<option name="max">50</option>
</constraint>
</property>
<property name="fromAbscissa">
<constraint name="When">
<option name="expression"> this.roadType === 'departmentalRoad' </option>
<option name="constraints">
<constraint name="Type">
<option name="type">integer</option>
</constraint>
<constraint name="Type">
<option name="type">
<value>null</value>
<value>integer</value>
</option>
</constraint>
</property>
<property name="toAbscissa">
<constraint name="When">
<option name="expression"> this.roadType === 'departmentalRoad' </option>
<option name="constraints">
<constraint name="Type">
<option name="type">integer</option>
</constraint>
<constraint name="Type">
<option name="type">
<value>null</value>
<value>integer</value>
</option>
</constraint>
</property>
Expand Down
428 changes: 415 additions & 13 deletions data/gestionnaires.txt

Large diffs are not rendered by default.

8 changes: 8 additions & 0 deletions src/Application/Exception/AbscissaOutOfRangeException.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,12 @@

class AbscissaOutOfRangeException extends GeocodingFailureException
{
public function __construct(
public readonly string $roadType,
string $message = '',
?int $locationIndex = null,
?\Exception $previous = null,
) {
parent::__construct($message, $locationIndex, $previous);
}
}
8 changes: 8 additions & 0 deletions src/Application/Exception/RoadGeocodingFailureException.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,12 @@

final class RoadGeocodingFailureException extends GeocodingFailureException
{
public function __construct(
public readonly string $roadType,
string $message = '',
?int $locationIndex = null,
?\Exception $previous = null,
) {
parent::__construct($message, $locationIndex, $previous);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -62,17 +62,18 @@ public function __invoke(DuplicateMeasureCommand $command): Measure
$cmd->roadType = $location->getRoadType();

if ($numberedRoad = $location->getNumberedRoad()) {
$cmd->numberedRoad = new SaveNumberedRoadCommand();
$cmd->numberedRoad->geometry = $location->getGeometry();
$cmd->numberedRoad->roadType = $location->getRoadType();
$cmd->numberedRoad->administrator = $numberedRoad->getAdministrator();
$cmd->numberedRoad->roadNumber = $numberedRoad->getRoadNumber();
$cmd->numberedRoad->fromPointNumber = $numberedRoad->getFromPointNumber();
$cmd->numberedRoad->fromSide = $numberedRoad->getFromSide();
$cmd->numberedRoad->fromAbscissa = $numberedRoad->getFromAbscissa();
$cmd->numberedRoad->toPointNumber = $numberedRoad->getToPointNumber();
$cmd->numberedRoad->toAbscissa = $numberedRoad->getToAbscissa();
$cmd->numberedRoad->toSide = $numberedRoad->getToSide();
$numberedRoadCmd = new SaveNumberedRoadCommand();
$numberedRoadCmd->geometry = $location->getGeometry();
$numberedRoadCmd->roadType = $location->getRoadType();
$numberedRoadCmd->administrator = $numberedRoad->getAdministrator();
$numberedRoadCmd->roadNumber = $numberedRoad->getRoadNumber();
$numberedRoadCmd->fromPointNumber = $numberedRoad->getFromPointNumber();
$numberedRoadCmd->fromSide = $numberedRoad->getFromSide();
$numberedRoadCmd->fromAbscissa = $numberedRoad->getFromAbscissa();
$numberedRoadCmd->toPointNumber = $numberedRoad->getToPointNumber();
$numberedRoadCmd->toAbscissa = $numberedRoad->getToAbscissa();
$numberedRoadCmd->toSide = $numberedRoad->getToSide();
$cmd->assignNumberedRoad($numberedRoadCmd);
} elseif ($namedStreet = $location->getNamedStreet()) {
$cmd->namedStreet = new SaveNamedStreetCommand();
$cmd->namedStreet->geometry = $location->getGeometry();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ final class SaveLocationCommand implements CommandInterface
{
public ?string $roadType = null;
public ?Measure $measure = null;
public ?SaveNumberedRoadCommand $numberedRoad = null;
public ?SaveNumberedRoadCommand $departmentalRoad = null;
public ?SaveNumberedRoadCommand $nationalRoad = null;
public ?SaveNamedStreetCommand $namedStreet = null;
public ?SaveRawGeoJSONCommand $rawGeoJSON = null;
public array $permissions = []; // For validation
Expand All @@ -28,35 +29,57 @@ public function __construct(
}

if ($location?->getNumberedRoad()) {
$this->numberedRoad = new SaveNumberedRoadCommand($location->getNumberedRoad());
$this->assignNumberedRoad(new SaveNumberedRoadCommand($location->getNumberedRoad()));
}

if ($location?->getRawGeoJSON()) {
$this->rawGeoJSON = new SaveRawGeoJSONCommand($location->getRawGeoJSON());
}
}

public function assignNumberedRoad(SaveNumberedRoadCommand $numberedRoad): void
{
if ($this->roadType === RoadTypeEnum::DEPARTMENTAL_ROAD->value) {
$this->departmentalRoad = $numberedRoad;
} else {
$this->nationalRoad = $numberedRoad;
}
}

public function clean(): void
{
if ($this->roadType === RoadTypeEnum::DEPARTMENTAL_ROAD->value) {
$this->namedStreet = null;
$this->nationalRoad = null;
$this->rawGeoJSON = null;
}

if ($this->roadType === RoadTypeEnum::NATIONAL_ROAD->value) {
$this->namedStreet = null;
$this->departmentalRoad = null;
$this->rawGeoJSON = null;
}

if ($this->roadType === RoadTypeEnum::LANE->value) {
$this->numberedRoad = null;
$this->departmentalRoad = null;
$this->nationalRoad = null;
$this->rawGeoJSON = null;
}

if ($this->roadType == RoadTypeEnum::RAW_GEOJSON->value) {
$this->namedStreet = null;
$this->numberedRoad = null;
$this->departmentalRoad = null;
$this->nationalRoad = null;
}
}

public function getRoadCommand(): RoadCommandInterface
{
return $this->namedStreet ?? $this->numberedRoad ?? $this->rawGeoJSON ?? throw new \LogicException('No road command');
return $this->namedStreet
?? $this->departmentalRoad
?? $this->nationalRoad
?? $this->rawGeoJSON
?? throw new \LogicException('No road command');
}

public function getRoadDeleteCommand(): ?CommandInterface
Expand All @@ -65,7 +88,7 @@ public function getRoadDeleteCommand(): ?CommandInterface
return new DeleteNamedStreetCommand($namedStreet);
}

if (!$this->numberedRoad && $numberedRoad = $this->location->getNumberedRoad()) {
if (!$this->departmentalRoad && !$this->nationalRoad && $numberedRoad = $this->location->getNumberedRoad()) {
return new DeleteNumberedRoadCommand($numberedRoad);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,11 @@ private function computeGeometry(GetNumberedRoadGeometryQuery $query): string
{
$command = $query->command;

$fullDepartmentalRoadGeometry = $this->roadGeocoder->computeRoad($command->roadNumber, $command->administrator);
$fullRoadGeometry = $this->roadGeocoder->computeRoad($command->roadNumber, $command->administrator, $command->roadType);

return $this->roadSectionMaker->computeSection(
$fullDepartmentalRoadGeometry,
$command->roadType,
$fullRoadGeometry,
$command->administrator,
$command->roadNumber,
$command->fromPointNumber,
Expand Down
5 changes: 3 additions & 2 deletions src/Application/RoadGeocoderInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,12 @@ interface RoadGeocoderInterface

public function computeRoadLine(string $roadName, string $inseeCode): string;

public function findRoads(string $search, string $administrator): array;
public function findRoads(string $search, string $administrator, string $roadType): array;

public function computeRoad(string $roadNumber, string $administrator): string;
public function computeRoad(string $roadNumber, string $administrator, string $roadType): string;

public function computeReferencePoint(
string $roadType,
string $administrator,
string $roadNumber,
string $pointNumber,
Expand Down
3 changes: 2 additions & 1 deletion src/Application/RoadSectionMakerInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@
interface RoadSectionMakerInterface
{
public function computeSection(
string $fullDepartmentalRoadGeometry,
string $roadType,
string $fullRoadGeometry,
string $administrator,
string $roadNumber,
string $fromPointNumber,
Expand Down
1 change: 1 addition & 0 deletions src/Domain/Regulation/Enum/RoadTypeEnum.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,6 @@ enum RoadTypeEnum: string
{
case LANE = 'lane';
case DEPARTMENTAL_ROAD = 'departmentalRoad';
case NATIONAL_ROAD = 'nationalRoad';
case RAW_GEOJSON = 'rawGeoJSON';
}
41 changes: 28 additions & 13 deletions src/Infrastructure/Adapter/BdTopoRoadGeocoder.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
use App\Application\IntersectionGeocoderInterface;
use App\Application\RoadGeocoderInterface;
use App\Domain\Geography\Coordinates;
use App\Domain\Regulation\Enum\RoadTypeEnum;
use Doctrine\DBAL\ArrayParameterType;
use Doctrine\DBAL\Connection;

Expand Down Expand Up @@ -54,13 +55,18 @@ public function computeRoadLine(string $roadName, string $inseeCode): string
throw new GeocodingFailureException($message);
}

public function findRoads(string $search, string $administrator): array
public function findRoads(string $search, string $administrator, string $roadType): array
{
// Can search for a departmental road with the prefix "RD"
if (str_starts_with(strtoupper($search), 'RD')) {
$search = substr($search, 1);
}

// Can search for a national road with the prefix "RN"
if (str_starts_with(strtoupper($search), 'RN')) {
$search = substr($search, 1);
}

try {
$rows = $this->bdtopoConnection->fetchAllAssociative(
'
Expand All @@ -75,26 +81,29 @@ public function findRoads(string $search, string $administrator): array
[
'numero_pattern' => \sprintf('%s%%', strtoupper($search)),
'gestionnaire' => $administrator,
'type_de_route' => 'Départementale',
'type_de_route' => $roadType === RoadTypeEnum::DEPARTMENTAL_ROAD->value ? 'Départementale' : 'Nationale',
],
);
} catch (\Exception $exc) {
throw new GeocodingFailureException(\sprintf('Departmental roads query has failed: %s', $exc->getMessage()), previous: $exc);
throw new GeocodingFailureException(\sprintf('Numbered road query has failed: %s', $exc->getMessage()), previous: $exc);
}

$departmentalRoads = [];
$results = [];

foreach ($rows as $row) {
$departmentalRoads[] = [
$results[] = [
'roadNumber' => $row['numero'],
];
}

return $departmentalRoads;
return $results;
}

public function computeRoad(string $roadNumber, string $administrator): string
public function computeRoad(string $roadNumber, string $administrator, string $roadType): string
{
$numero = strtoupper($roadNumber);
$typeDeRoute = $roadType === RoadTypeEnum::DEPARTMENTAL_ROAD->value ? 'Départementale' : 'Nationale';

try {
$rows = $this->bdtopoConnection->fetchAllAssociative(
'
Expand All @@ -106,24 +115,30 @@ public function computeRoad(string $roadNumber, string $administrator): string
LIMIT 1
',
[
'numero' => strtoupper($roadNumber),
'numero' => $numero,
'gestionnaire' => $administrator,
'type_de_route' => 'Départementale',
'type_de_route' => $typeDeRoute,
],
);
} catch (\Exception $exc) {
throw new RoadGeocodingFailureException(\sprintf('Departmental roads query has failed: %s', $exc->getMessage()), previous: $exc);
throw new RoadGeocodingFailureException($roadType, \sprintf('Numbered road query has failed: %s', $exc->getMessage()), previous: $exc);
}

if ($rows) {
return $rows[0]['geometry'];
}

$message = \sprintf('no result found in route_numerotee_ou_nommee for roadNumber="%s", administrator="%s"', $roadNumber, $administrator);
throw new RoadGeocodingFailureException($message);
$message = \sprintf(
'no result found in route_numerotee_ou_nommee for numero="%s", gestionnaire="%s", type_de_route="%s"',
$numero,
$administrator,
$typeDeRoute,
);
throw new RoadGeocodingFailureException($roadType, $message);
}

public function computeReferencePoint(
string $roadType,
string $administrator,
string $roadNumber,
string $pointNumber,
Expand Down Expand Up @@ -190,7 +205,7 @@ public function computeReferencePoint(
}

if (empty($row['geom'])) {
throw new AbscissaOutOfRangeException();
throw new AbscissaOutOfRangeException($roadType);
}

$lonLat = json_decode($row['geom'], associative: true);
Expand Down
Loading

0 comments on commit 410f2ae

Please sign in to comment.