Feature: Add geographical unit name and ref ids in list, associated to address

This commit is contained in:
Julien Fastré 2022-11-14 17:06:26 +01:00
parent 2db778c4a4
commit 434ef075da
Signed by: julienfastre
GPG Key ID: BDE2190974723FCB

View File

@ -11,13 +11,16 @@ declare(strict_types=1);
namespace Chill\MainBundle\Export\Helper;
use Chill\MainBundle\Entity\GeographicalUnit;
use Chill\MainBundle\Entity\GeographicalUnitLayer;
use Chill\MainBundle\Repository\AddressRepository;
use Chill\MainBundle\Repository\GeographicalUnitLayerRepositoryInterface;
use Chill\MainBundle\Templating\Entity\AddressRender;
use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
use Doctrine\ORM\QueryBuilder;
use LogicException;
use Symfony\Component\PropertyAccess\PropertyAccess;
use Symfony\Component\PropertyAccess\PropertyAccessor;
use function array_key_exists;
use function count;
use function in_array;
use function strlen;
@ -26,9 +29,12 @@ use function strlen;
*/
class ExportAddressHelper
{
/**
* Compute all the F_* constants.
*/
public const F_ALL =
self::F_ATTRIBUTES | self::F_BUILDING | self::F_COUNTRY |
self::F_GEOM | self::F_POSTAL_CODE | self::F_STREET;
self::F_GEOM | self::F_POSTAL_CODE | self::F_STREET | self::F_GEOGRAPHICAL_UNITS;
public const F_AS_STRING = 0b00010000;
@ -38,6 +44,8 @@ class ExportAddressHelper
public const F_COUNTRY = 0b00000001;
public const F_GEOGRAPHICAL_UNITS = 0b1000000000;
public const F_GEOM = 0b00100000;
public const F_POSTAL_CODE = 0b00000010;
@ -52,6 +60,7 @@ class ExportAddressHelper
'string' => self::F_AS_STRING,
'geom' => self::F_GEOM,
'attributes' => self::F_ATTRIBUTES,
'geographical_units' => self::F_GEOGRAPHICAL_UNITS,
];
private const COLUMN_MAPPING = [
@ -62,23 +71,35 @@ class ExportAddressHelper
'string' => ['_as_string'],
'attributes' => ['isNoAddress', 'confidential', 'id'],
'geom' => ['_lat', '_lon'],
'geographical_units' => ['_unit_names', '_unit_refs'],
];
private AddressRender $addressRender;
private AddressRepository $addressRepository;
private PropertyAccessor $propertyAccess;
private GeographicalUnitLayerRepositoryInterface $geographicalUnitLayerRepository;
private TranslatableStringHelperInterface $translatableStringHelper;
/**
* @var array<string, string, GeographicalUnitLayer>>|null
*/
private ?array $unitNamesKeysCache = [];
/**
* @var array<string, array<string, GeographicalUnitLayer>>|null
*/
private ?array $unitRefsKeysCache = [];
public function __construct(
AddressRender $addressRender,
AddressRepository $addressRepository,
TranslatableStringHelperInterface $translatableStringHelper,
AddressRender $addressRender
GeographicalUnitLayerRepositoryInterface $geographicalUnitLayerRepository,
TranslatableStringHelperInterface $translatableStringHelper
) {
$this->addressRepository = $addressRepository;
$this->propertyAccess = PropertyAccess::createPropertyAccessor();
$this->geographicalUnitLayerRepository = $geographicalUnitLayerRepository;
$this->translatableStringHelper = $translatableStringHelper;
$this->addressRender = $addressRender;
}
@ -155,8 +176,60 @@ class ExportAddressHelper
break;
case '_unit_names':
foreach ($this->generateKeysForUnitsNames($prefix) as $alias => $layer) {
$queryBuilder
->addSelect(
sprintf(
'(SELECT AGGREGATE(u_n_%s_%s.unitName) FROM %s u_n_%s_%s WHERE u_n_%s_%s MEMBER OF %s.geographicalUnits AND u_n_%s_%s.layer = :layer_%s_%s) AS %s',
$prefix,
$layer->getId(),
GeographicalUnit::class,
$prefix,
$layer->getId(),
$prefix,
$layer->getId(),
$entityName,
$prefix,
$layer->getId(),
$prefix,
$layer->getId(),
$alias
)
)
->setParameter(sprintf('layer_%s_%s', $prefix, $layer->getId()), $layer);
}
break;
case '_unit_refs':
foreach ($this->generateKeysForUnitsRefs($prefix) as $alias => $layer) {
$queryBuilder
->addSelect(
sprintf(
'(SELECT AGGREGATE(u_r_%s_%s.unitRefId) FROM %s u_r_%s_%s WHERE u_r_%s_%s MEMBER OF %s.geographicalUnits AND u_r_%s_%s.layer = :layer_%s_%s) AS %s',
$prefix,
$layer->getId(),
GeographicalUnit::class,
$prefix,
$layer->getId(),
$prefix,
$layer->getId(),
$entityName,
$prefix,
$layer->getId(),
$prefix,
$layer->getId(),
$alias
)
)
->setParameter(sprintf('layer_%s_%s', $prefix, $layer->getId()), $layer);
}
break;
default:
throw new LogicException('This key is not supported: ' . $key);
throw new LogicException(sprintf('This key is not supported: %s, field %s', $key, $field));
}
}
}
@ -174,6 +247,13 @@ class ExportAddressHelper
foreach (self::ALL as $key => $bitmask) {
if (($params & $bitmask) === $bitmask) {
if ('geographical_units' === $key) {
// geographical unit generate keys dynamically, depending on layers
$prefixes = array_merge($prefixes, array_keys($this->generateKeysForUnitsNames($prefix)), array_keys($this->generateKeysForUnitsRefs($prefix)));
continue;
}
$prefixes = array_merge(
$prefixes,
array_map(
@ -271,7 +351,76 @@ class ExportAddressHelper
};
default:
$layerNamesKeys = array_merge($this->generateKeysForUnitsNames($prefix), $this->generateKeysForUnitsRefs($prefix));
if (array_key_exists($key, $layerNamesKeys)) {
return function ($value) use ($key, $layerNamesKeys) {
if ('_header' === $value) {
$header = $this->translatableStringHelper->localize($layerNamesKeys[$key]->getName());
if (str_contains($key, 'unit_ref')) {
$header .= ' (id)';
}
return $header;
}
if (null === $value) {
return '';
}
$decodedValues = json_decode($value, true);
switch (count($decodedValues)) {
case 0:
return '';
case 1:
return $decodedValues[0];
default:
return implode('|', $decodedValues);
}
};
}
throw new LogicException('this key is not supported: ' . $sanitizedKey);
}
}
/**
* @return array<string, GeographicalUnitLayer>
*/
private function generateKeysForUnitsNames(string $prefix): array
{
if (array_key_exists($prefix, $this->unitNamesKeysCache)) {
return $this->unitNamesKeysCache[$prefix];
}
$keys = [];
foreach ($this->geographicalUnitLayerRepository->findAllHavingUnits() as $layer) {
$keys[$prefix . 'unit_names_' . $layer->getId()] = $layer;
}
return $this->unitNamesKeysCache[$prefix] = $keys;
}
/**
* @return array<string, GeographicalUnitLayer>
*/
private function generateKeysForUnitsRefs(string $prefix): array
{
if (array_key_exists($prefix, $this->unitRefsKeysCache)) {
return $this->unitRefsKeysCache[$prefix];
}
$keys = [];
foreach ($this->geographicalUnitLayerRepository->findAllHavingUnits() as $layer) {
$keys[$prefix . 'unit_refs_' . $layer->getId()] = $layer;
}
return $this->unitRefsKeysCache[$prefix] = $keys;
}
}