Fixed: [export] improve memory footprint for filter by Geographical Unit

This commit is contained in:
Julien Fastré 2022-11-03 13:59:16 +01:00
parent 03e765f811
commit 6fd75a175f
5 changed files with 84 additions and 19 deletions

View File

@ -0,0 +1,52 @@
<?php
declare(strict_types=1);
/*
* 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.
*/
namespace Chill\MainBundle\Entity\GeographicalUnit;
/**
* Simple GeographialUnit Data Transfer Object.
*
* This allow to get access to id, unitName, unitRefId, and layer's id
*/
class SimpleGeographicalUnitDTO
{
/**
* @readonly
* @psalm-readonly
*/
public int $id;
/**
* @readonly
* @psalm-readonly
*/
public int $layerId;
/**
* @readonly
* @psalm-readonly
*/
public string $unitName;
/**
* @readonly
* @psalm-readonly
*/
public string $unitRefId;
public function __construct(int $id, string $unitName, string $unitRefId, int $layerId)
{
$this->id = $id;
$this->unitName = $unitName;
$this->unitRefId = $unitRefId;
$this->layerId = $layerId;
}
}

View File

@ -205,6 +205,7 @@ class ExportAddressHelper
case 'floor': case 'floor':
case '_lat': case '_lat':
case '_lon': case '_lon':
case 'steps':
case 'postcode_code': case 'postcode_code':
case 'postcode_name': case 'postcode_name':
return static function ($value) use ($sanitizedKey, $translationPrefix) { return static function ($value) use ($sanitizedKey, $translationPrefix) {

View File

@ -41,7 +41,7 @@ class GeographicalUnitRepository implements GeographicalUnitRepositoryInterface
{ {
return $this->repository return $this->repository
->createQueryBuilder('gu') ->createQueryBuilder('gu')
->select('PARTIAL gu.{id,unitName,unitRefId,layer}') ->select(sprintf('NEW %s(gu.id, gu.unitName, gu.unitRefId, IDENTITY(gu.layer))', GeographicalUnit\SimpleGeographicalUnitDTO::class))
->addOrderBy('IDENTITY(gu.layer)') ->addOrderBy('IDENTITY(gu.layer)')
->addOrderBy(('gu.unitName')) ->addOrderBy(('gu.unitName'))
->getQuery() ->getQuery()

View File

@ -13,8 +13,10 @@ namespace Chill\PersonBundle\Export\Filter\AccompanyingCourseFilters;
use Chill\MainBundle\Entity\Address; use Chill\MainBundle\Entity\Address;
use Chill\MainBundle\Entity\GeographicalUnit; use Chill\MainBundle\Entity\GeographicalUnit;
use Chill\MainBundle\Entity\GeographicalUnit\SimpleGeographicalUnitDTO;
use Chill\MainBundle\Export\FilterInterface; use Chill\MainBundle\Export\FilterInterface;
use Chill\MainBundle\Form\Type\ChillDateType; use Chill\MainBundle\Form\Type\ChillDateType;
use Chill\MainBundle\Repository\GeographicalUnitLayerRepositoryInterface;
use Chill\MainBundle\Repository\GeographicalUnitRepositoryInterface; use Chill\MainBundle\Repository\GeographicalUnitRepositoryInterface;
use Chill\MainBundle\Templating\TranslatableStringHelperInterface; use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
use Chill\PersonBundle\Entity\AccompanyingPeriod; use Chill\PersonBundle\Entity\AccompanyingPeriod;
@ -23,7 +25,7 @@ use Chill\PersonBundle\Export\Declarations;
use DateTimeImmutable; use DateTimeImmutable;
use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\QueryBuilder; use Doctrine\ORM\QueryBuilder;
use Symfony\Bridge\Doctrine\Form\Type\EntityType; use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\FormBuilderInterface;
/** /**
@ -33,6 +35,8 @@ class GeographicalUnitStatFilter implements FilterInterface
{ {
private EntityManagerInterface $em; private EntityManagerInterface $em;
private GeographicalUnitLayerRepositoryInterface $geographicalUnitLayerRepository;
private GeographicalUnitRepositoryInterface $geographicalUnitRepository; private GeographicalUnitRepositoryInterface $geographicalUnitRepository;
private TranslatableStringHelperInterface $translatableStringHelper; private TranslatableStringHelperInterface $translatableStringHelper;
@ -40,10 +44,12 @@ class GeographicalUnitStatFilter implements FilterInterface
public function __construct( public function __construct(
EntityManagerInterface $em, EntityManagerInterface $em,
GeographicalUnitRepositoryInterface $geographicalUnitRepository, GeographicalUnitRepositoryInterface $geographicalUnitRepository,
GeographicalUnitLayerRepositoryInterface $geographicalUnitLayerRepository,
TranslatableStringHelperInterface $translatableStringHelper TranslatableStringHelperInterface $translatableStringHelper
) { ) {
$this->em = $em; $this->em = $em;
$this->geographicalUnitRepository = $geographicalUnitRepository; $this->geographicalUnitRepository = $geographicalUnitRepository;
$this->geographicalUnitLayerRepository = $geographicalUnitLayerRepository;
$this->translatableStringHelper = $translatableStringHelper; $this->translatableStringHelper = $translatableStringHelper;
} }
@ -62,7 +68,7 @@ class GeographicalUnitStatFilter implements FilterInterface
WITH IDENTITY(acp_geog_filter_location_history.personLocation) = IDENTITY(acp_geog_filter_address_person_location.person) WITH IDENTITY(acp_geog_filter_location_history.personLocation) = IDENTITY(acp_geog_filter_address_person_location.person)
LEFT JOIN ' . Address::class . ' acp_geog_filter_address LEFT JOIN ' . Address::class . ' acp_geog_filter_address
WITH COALESCE(IDENTITY(acp_geog_filter_address_person_location.address), IDENTITY(acp_geog_filter_location_history.addressLocation)) = acp_geog_filter_address.id WITH COALESCE(IDENTITY(acp_geog_filter_address_person_location.address), IDENTITY(acp_geog_filter_location_history.addressLocation)) = acp_geog_filter_address.id
LEFT JOIN ' . GeographicalUnit::class . ' acp_geog_filter_units WITH ST_CONTAINS(acp_geog_units.geom, acp_geog_filter_address.point) = TRUE LEFT JOIN ' . GeographicalUnit::class . ' acp_geog_filter_units WITH ST_CONTAINS(acp_geog_filter_units.geom, acp_geog_filter_address.point) = TRUE
WHERE WHERE
(acp_geog_filter_location_history.startDate <= :acp_geog_filter_date AND ( (acp_geog_filter_location_history.startDate <= :acp_geog_filter_date AND (
acp_geog_filter_location_history.endDate IS NULL OR acp_geog_filter_location_history.endDate < :acp_geog_filter_date acp_geog_filter_location_history.endDate IS NULL OR acp_geog_filter_location_history.endDate < :acp_geog_filter_date
@ -78,7 +84,7 @@ class GeographicalUnitStatFilter implements FilterInterface
$qb $qb
->andWhere($qb->expr()->exists($subQueryDql)) ->andWhere($qb->expr()->exists($subQueryDql))
->setParameter('acp_geog_filter_date', $data['date_calc']) ->setParameter('acp_geog_filter_date', $data['date_calc'])
->setParameter('acp_geog_filter_units', $data['units']); ->setParameter('acp_geog_filter_units', array_map(static fn (SimpleGeographicalUnitDTO $unitDTO) => $unitDTO->id, $data['units']));
} }
public function applyOn(): string public function applyOn(): string
@ -95,13 +101,13 @@ class GeographicalUnitStatFilter implements FilterInterface
'data' => new DateTimeImmutable('today'), 'data' => new DateTimeImmutable('today'),
'input' => 'datetime_immutable', 'input' => 'datetime_immutable',
]) ])
->add('units', EntityType::class, [ ->add('units', ChoiceType::class, [
'label' => 'Geographical unit', 'label' => 'Geographical unit',
'placeholder' => 'Select a geographical unit', 'placeholder' => 'Select a geographical unit',
'class' => GeographicalUnit::class,
'choices' => $this->geographicalUnitRepository->findAll(), 'choices' => $this->geographicalUnitRepository->findAll(),
'choice_label' => function (GeographicalUnit $item) { 'choice_value' => static fn (SimpleGeographicalUnitDTO $item) => $item->id,
return $this->translatableStringHelper->localize($item->getLayer()->getName()) . ' > ' . $item->getUnitName(); 'choice_label' => function (SimpleGeographicalUnitDTO $item) {
return $this->translatableStringHelper->localize($this->geographicalUnitLayerRepository->find($item->layerId)->getName()) . ' > ' . $item->unitName;
}, },
'attr' => [ 'attr' => [
'class' => 'select2', 'class' => 'select2',
@ -117,8 +123,8 @@ class GeographicalUnitStatFilter implements FilterInterface
'%units' => implode( '%units' => implode(
', ', ', ',
array_map( array_map(
function (GeographicalUnit $item) { function (SimpleGeographicalUnitDTO $item) {
return $this->translatableStringHelper->localize($item->getLayer()->getName()) . ' > ' . $item->getUnitName(); return $this->translatableStringHelper->localize($this->geographicalUnitLayerRepository->find($item->layerId)->getName()) . ' > ' . $item->unitName;
}, },
$data['units'] $data['units']
) )

View File

@ -12,27 +12,33 @@ declare(strict_types=1);
namespace Chill\PersonBundle\Export\Filter\PersonFilters; namespace Chill\PersonBundle\Export\Filter\PersonFilters;
use Chill\MainBundle\Entity\GeographicalUnit; use Chill\MainBundle\Entity\GeographicalUnit;
use Chill\MainBundle\Entity\GeographicalUnit\SimpleGeographicalUnitDTO;
use Chill\MainBundle\Form\Type\ChillDateType; use Chill\MainBundle\Form\Type\ChillDateType;
use Chill\MainBundle\Repository\GeographicalUnitLayerRepositoryInterface;
use Chill\MainBundle\Repository\GeographicalUnitRepositoryInterface; use Chill\MainBundle\Repository\GeographicalUnitRepositoryInterface;
use Chill\MainBundle\Templating\TranslatableStringHelperInterface; use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
use Chill\PersonBundle\Entity\Household\PersonHouseholdAddress; use Chill\PersonBundle\Entity\Household\PersonHouseholdAddress;
use Chill\PersonBundle\Export\Declarations; use Chill\PersonBundle\Export\Declarations;
use DateTimeImmutable; use DateTimeImmutable;
use Doctrine\ORM\QueryBuilder; use Doctrine\ORM\QueryBuilder;
use Symfony\Bridge\Doctrine\Form\Type\EntityType; use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\Form\FormBuilderInterface;
class GeographicalUnitFilter implements \Chill\MainBundle\Export\FilterInterface class GeographicalUnitFilter implements \Chill\MainBundle\Export\FilterInterface
{ {
private GeographicalUnitLayerRepositoryInterface $geographicalUnitLayerRepository;
private GeographicalUnitRepositoryInterface $geographicalUnitRepository; private GeographicalUnitRepositoryInterface $geographicalUnitRepository;
private TranslatableStringHelperInterface $translatableStringHelper; private TranslatableStringHelperInterface $translatableStringHelper;
public function __construct( public function __construct(
GeographicalUnitRepositoryInterface $geographicalUnitRepository, GeographicalUnitRepositoryInterface $geographicalUnitRepository,
GeographicalUnitLayerRepositoryInterface $geographicalUnitLayerRepository,
TranslatableStringHelperInterface $translatableStringHelper TranslatableStringHelperInterface $translatableStringHelper
) { ) {
$this->geographicalUnitRepository = $geographicalUnitRepository; $this->geographicalUnitRepository = $geographicalUnitRepository;
$this->geographicalUnitLayerRepository = $geographicalUnitLayerRepository;
$this->translatableStringHelper = $translatableStringHelper; $this->translatableStringHelper = $translatableStringHelper;
} }
@ -65,7 +71,7 @@ class GeographicalUnitFilter implements \Chill\MainBundle\Export\FilterInterface
$qb->expr()->exists($subQuery) $qb->expr()->exists($subQuery)
) )
->setParameter('person_filter_geog_date', $data['date_calc']) ->setParameter('person_filter_geog_date', $data['date_calc'])
->setParameter('person_filter_geog_units', $data['units']); ->setParameter('person_filter_geog_units', array_map(static fn (SimpleGeographicalUnitDTO $unitDTO) => $unitDTO->id, $data['units']));
} }
public function applyOn() public function applyOn()
@ -82,13 +88,13 @@ class GeographicalUnitFilter implements \Chill\MainBundle\Export\FilterInterface
'data' => new DateTimeImmutable('today'), 'data' => new DateTimeImmutable('today'),
'input' => 'datetime_immutable', 'input' => 'datetime_immutable',
]) ])
->add('units', EntityType::class, [ ->add('units', ChoiceType::class, [
'label' => 'Geographical unit', 'label' => 'Geographical unit',
'placeholder' => 'Select a geographical unit', 'placeholder' => 'Select a geographical unit',
'class' => GeographicalUnit::class,
'choices' => $this->geographicalUnitRepository->findAll(), 'choices' => $this->geographicalUnitRepository->findAll(),
'choice_label' => function (GeographicalUnit $item) { 'choice_value' => static fn (SimpleGeographicalUnitDTO $item) => $item->id,
return $this->translatableStringHelper->localize($item->getLayer()->getName()) . ' > ' . $item->getUnitName(); 'choice_label' => function (SimpleGeographicalUnitDTO $item) {
return $this->translatableStringHelper->localize($this->geographicalUnitLayerRepository->find($item->layerId)->getName()) . ' > ' . $item->unitName;
}, },
'attr' => [ 'attr' => [
'class' => 'select2', 'class' => 'select2',
@ -106,10 +112,10 @@ class GeographicalUnitFilter implements \Chill\MainBundle\Export\FilterInterface
'units' => implode( 'units' => implode(
', ', ', ',
array_map( array_map(
function (GeographicalUnit $item) { function (SimpleGeographicalUnitDTO $item) {
return $this->translatableStringHelper->localize($item->getLayer()->getName()) . ' > ' . $item->getUnitName(); return $this->translatableStringHelper->localize($this->geographicalUnitLayerRepository->find($item->layerId)->getName()) . ' > ' . $item->unitName;
}, },
$data['units']->toArray() $data['units']
) )
), ),
], ],