mirror of
https://gitlab.com/Chill-Projet/chill-bundles.git
synced 2025-08-30 11:33:49 +00:00
Feature: load french postal code from laposte hexasmal open data
This commit is contained in:
@@ -0,0 +1,105 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Chill is a software for social workers
|
||||
*
|
||||
* For the full copyright and license information, please view
|
||||
* the LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Chill\MainBundle\Service\Import;
|
||||
|
||||
use League\Csv\Reader;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use RuntimeException;
|
||||
use Symfony\Contracts\HttpClient\HttpClientInterface;
|
||||
|
||||
/**
|
||||
* Load French's postal codes from opendata.
|
||||
*
|
||||
* Currently, the source is datanova / la poste:
|
||||
* https://datanova.legroupe.laposte.fr/explore/dataset/laposte_hexasmal/information/
|
||||
*/
|
||||
class PostalCodeFRFromOpenData
|
||||
{
|
||||
private const CSV = 'https://datanova.legroupe.laposte.fr/explore/dataset/laposte_hexasmal/download/?format=csv&timezone=Europe/Berlin&lang=fr&use_labels_for_header=true&csv_separator=%3B';
|
||||
|
||||
private PostalCodeBaseImporter $baseImporter;
|
||||
|
||||
private HttpClientInterface $client;
|
||||
|
||||
private LoggerInterface $logger;
|
||||
|
||||
public function __construct(
|
||||
PostalCodeBaseImporter $baseImporter,
|
||||
HttpClientInterface $client,
|
||||
LoggerInterface $logger
|
||||
) {
|
||||
$this->baseImporter = $baseImporter;
|
||||
$this->client = $client;
|
||||
$this->logger = $logger;
|
||||
}
|
||||
|
||||
public function import(): void
|
||||
{
|
||||
$response = $this->client->request('GET', self::CSV);
|
||||
|
||||
if (200 !== $response->getStatusCode()) {
|
||||
throw new RuntimeException('could not download CSV');
|
||||
}
|
||||
|
||||
$tmpfile = tmpfile();
|
||||
|
||||
if (false === $tmpfile) {
|
||||
throw new RuntimeException('could not create temporary file');
|
||||
}
|
||||
|
||||
foreach ($this->client->stream($response) as $chunk) {
|
||||
fwrite($tmpfile, $chunk->getContent());
|
||||
}
|
||||
|
||||
fseek($tmpfile, 0);
|
||||
|
||||
$csv = Reader::createFromStream($tmpfile);
|
||||
$csv->setDelimiter(';');
|
||||
$csv->setHeaderOffset(0);
|
||||
|
||||
foreach ($csv as $offset => $record) {
|
||||
$this->handleRecord($record);
|
||||
}
|
||||
|
||||
$this->baseImporter->finalize();
|
||||
fclose($tmpfile);
|
||||
|
||||
$this->logger->info(__CLASS__ . ' postal code fetched', ['offset' => $offset]);
|
||||
}
|
||||
|
||||
private function handleRecord(array $record): void
|
||||
{
|
||||
if ('' !== trim($record['coordonnees_gps'])) {
|
||||
[$lat, $lon] = array_map(static fn ($el) => (float) trim($el), explode(',', $record['coordonnees_gps']));
|
||||
} else {
|
||||
$lat = $lon = 0.0;
|
||||
}
|
||||
|
||||
$ref = trim($record['Code_commune_INSEE']);
|
||||
|
||||
if ('987' === substr($ref, 0, 3)) {
|
||||
// some differences in French Polynesia
|
||||
$ref .= '.' . trim($record['Libellé_d_acheminement']);
|
||||
}
|
||||
|
||||
$this->baseImporter->importCode(
|
||||
'FR',
|
||||
trim($record['Libellé_d_acheminement']),
|
||||
trim($record['Code_postal']),
|
||||
$ref,
|
||||
'INSEE',
|
||||
$lat,
|
||||
$lon,
|
||||
4326
|
||||
);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user