diff --git a/config/services.yaml b/config/services.yaml index 96c1b52..63cf264 100755 --- a/config/services.yaml +++ b/config/services.yaml @@ -39,7 +39,6 @@ services: resource: '../src/Controller/' tags: ['controller.service_arguments'] - App\Service\FileProcessor: arguments: $projectDir: '%kernel.project_dir%' diff --git a/migrations/Version20250507004714.php b/migrations/Version20250507004714.php new file mode 100644 index 0000000..3d00f7d --- /dev/null +++ b/migrations/Version20250507004714.php @@ -0,0 +1,29 @@ +addSql('ALTER TABLE rpps ADD original_address LONGTEXT DEFAULT NULL'); + } + + public function down(Schema $schema): void + { + $this->addSql('ALTER TABLE rpps DROP original_address'); + } +} diff --git a/src/Doctrine/PointWrapper.php b/src/Doctrine/PointWrapper.php index 04ef54c..8e5620e 100644 --- a/src/Doctrine/PointWrapper.php +++ b/src/Doctrine/PointWrapper.php @@ -2,12 +2,24 @@ namespace App\Doctrine; +use Doctrine\Common\EventManager; +use Doctrine\DBAL\Configuration; use Doctrine\DBAL\Connection; +use Doctrine\DBAL\Driver; +use Doctrine\DBAL\Exception; +use Doctrine\DBAL\ParameterType; use Doctrine\DBAL\Platforms\MySqlPlatform; +use Doctrine\DBAL\SQLParserUtils; +use Doctrine\DBAL\Types\Type; use Throwable; class PointWrapper extends Connection { + public function __construct(array $params, Driver $driver, Configuration $config, EventManager $eventManager) + { + parent::__construct($params, $driver, $config, $eventManager); + } + public function prepare($sql) { try { @@ -23,4 +35,136 @@ public function prepare($sql) return $stmt; } + + /** + * Executes an SQL statement with the given parameters and returns the number of affected rows. + * + * Could be used for: + * - DML statements: INSERT, UPDATE, DELETE, etc. + * - DDL statements: CREATE, DROP, ALTER, etc. + * - DCL statements: GRANT, REVOKE, etc. + * - Session control statements: ALTER SESSION, SET, DECLARE, etc. + * - Other statements that don't yield a row set. + * + * This method supports PDO binding types as well as DBAL mapping types. + * + * @param string $sql SQL statement + * @param array|array $params Statement parameters + * @param array|array $types Parameter types + * + * @return int|string the number of affected rows + * + * @throws Exception + */ + public function executeStatement($sql, array $params = [], array $types = []) + { + $logger = $this->_config->getSQLLogger(); + if ($logger) { + $logger->startQuery($sql, $params, $types); + } + + try { + if ($params) { + [$sql, $params, $types] = SQLParserUtils::expandListParameters($sql, $params, $types); + + $stmt = $this->prepare($sql); + + if ($types) { + $this->bindTypedValues($stmt, $params, $types); + $stmt->execute(); + } else { + $stmt->execute($params); + } + + $result = $stmt->rowCount(); + } else { + $result = $this->exec($sql); + } + } catch (Throwable $e) { + $this->handleExceptionDuringQuery( + $e, + $sql, + $params, + $types + ); + } + + if ($logger) { + $logger->stopQuery(); + } + + return $result; + } + + /** + * Binds a set of parameters, some or all of which are typed with a PDO binding type + * or DBAL mapping type, to a given statement. + * + * @internal duck-typing used on the $stmt parameter to support driver statements as well as + * raw PDOStatement instances + * + * @param Driver\Statement $stmt Prepared statement + * @param array|array $params Statement parameters + * @param array|array $types Parameter types + * + * @return void + * + * This is based on bindTypedValues + */ + private function bindTypedValues($stmt, array $params, array $types) + { + // Check whether parameters are positional or named. Mixing is not allowed, just like in PDO. + if (is_int(key($params))) { + // Positional parameters + $typeOffset = array_key_exists(0, $types) ? -1 : 0; + $bindIndex = 1; + foreach ($params as $value) { + $typeIndex = $bindIndex + $typeOffset; + if (isset($types[$typeIndex])) { + $type = $types[$typeIndex]; + [$value, $bindingType] = $this->getBindingInfo($value, $type); + $stmt->bindValue($bindIndex, $value, $bindingType); + } else { + $stmt->bindValue($bindIndex, $value); + } + + ++$bindIndex; + } + } else { + // Named parameters + foreach ($params as $name => $value) { + if (isset($types[$name])) { + $type = $types[$name]; + [$value, $bindingType] = $this->getBindingInfo($value, $type); + $stmt->bindValue($name, $value, $bindingType); + } else { + $stmt->bindValue($name, $value); + } + } + } + } + + /** + * Gets the binding type of a given type. The given type can be a PDO or DBAL mapping type. + * + * @param mixed $value the value to bind + * @param int|string|Type|null $type the type to bind (PDO or DBAL) + * + * @return array{mixed, int} [0] => the (escaped) value, [1] => the binding type + */ + private function getBindingInfo($value, $type): array + { + if (is_string($type)) { + $type = Type::getType($type); + } + + if ($type instanceof Type) { + $value = $type->convertToDatabaseValue($value, $this->getDatabasePlatform()); + $bindingType = $type->getBindingType(); + } else { + $bindingType = $type ?? ParameterType::STRING; + } + + return [$value, $bindingType]; + } } diff --git a/src/Doctrine/Statement.php b/src/Doctrine/Statement.php index 201977f..cb2e741 100644 --- a/src/Doctrine/Statement.php +++ b/src/Doctrine/Statement.php @@ -13,6 +13,10 @@ class Statement extends BaseStatement public function bindValue($param, $value, $type = ParameterType::STRING) { + if (is_string($value) && str_starts_with($value, 'ST_GeomFromText')) { + $value = $this->connexion->fetchOne("SELECT $value;"); + } + if ($this->connexion && PointType::POINT === $type) { $lat = $value['latitude'] ?? 0; $lng = $value['longitude'] ?? 0; diff --git a/src/Entity/RPPS.php b/src/Entity/RPPS.php index 0069b5a..1c74cac 100755 --- a/src/Entity/RPPS.php +++ b/src/Entity/RPPS.php @@ -197,6 +197,9 @@ class RPPS extends BaseEntity implements ImportableEntityInterface #[ORM\Column(type: 'float', nullable: true)] protected ?float $latitude = null; + #[ORM\Column(type: 'text', nullable: true)] + protected ?string $originalAddress = null; + #[ORM\Column(type: PointType::POINT, nullable: false)] private array $coordinates = []; @@ -638,4 +641,14 @@ public function setCoordinates(array $coordinates): void { $this->coordinates = $coordinates; } + + public function getOriginalAddress(): ?string + { + return $this->originalAddress; + } + + public function setOriginalAddress(?string $originalAddress): void + { + $this->originalAddress = $originalAddress; + } } diff --git a/src/Service/RPPSService.php b/src/Service/RPPSService.php index ad666cc..6f3762c 100755 --- a/src/Service/RPPSService.php +++ b/src/Service/RPPSService.php @@ -211,6 +211,14 @@ protected function processRPPS(array $data): ?RPPS $rpps->setZipcode($data[35]); $rpps->setCity($data[37]); + $originalAddress = $data[28] . ' ' . $data[31] . ' ' . $data[32] . ' ' . $data[33] . ' ' . $data[35] . ' ' . $data[37]; + + if ($originalAddress !== $rpps->getOriginalAddress()) { + $rpps->setLatitude(null); + $rpps->setLongitude(null); + } + $rpps->setOriginalAddress($originalAddress); + $cityEntity = $this->findCityEntity($data[35], $data[37]); if ($cityEntity) { $rpps->setCityEntity($cityEntity); @@ -232,6 +240,9 @@ protected function processRPPS(array $data): ?RPPS $this->entities[$rpps->getIdRpps()] = $rpps; + $this->em->persist($rpps); + $this->em->flush(); + return $rpps; }