Refactor ListPersonHelper and ListPerson to simplify process and allow to add customization of fields

This commit is contained in:
2024-03-15 15:02:12 +01:00
parent dfe780f0f5
commit ccf3324bc2
10 changed files with 134 additions and 251 deletions

View File

@@ -0,0 +1,36 @@
<?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\PersonBundle\Export\Helper;
use Doctrine\ORM\QueryBuilder;
/**
* This interface provides methods for customizing the list of person.
*/
interface CustomizeListPersonHelperInterface
{
/**
* Alter the keys possibles (column header) for the list.
*/
public function alterKeys(array $existing): array;
public function alterSelect(QueryBuilder $qb, \DateTimeImmutable $computedDate): void;
/**
* Return the callable which transform the doctrine result representation.
*
* If the key is not managed by the current implementation, this method must return null.
*
* @return callable|null return null if the key is not managed by the current implementation
*/
public function getLabels(string $key, array $values, array $data): ?callable;
}

View File

@@ -35,9 +35,9 @@ use Symfony\Contracts\Translation\TranslatorInterface;
*
* for some fields
*/
class ListPersonHelper
final readonly class ListPersonHelper
{
final public const FIELDS = [
private const FIELDS = [
'personId',
'civility',
'firstName',
@@ -60,17 +60,31 @@ class ListPersonHelper
'countryOfBirth',
'nationality',
// add full addresses
'address_fields',
// 'address_fields',
// add a list of spoken languages
'spokenLanguages',
// add household id
'household_id',
// add created at, created by, updated at, and updated by
'lifecycleUpdate',
// 'lifecycleUpdate',
'createdAt', 'createdBy', 'updatedAt', 'updatedBy',
];
public function __construct(private readonly ExportAddressHelper $addressHelper, private readonly CenterRepositoryInterface $centerRepository, private readonly CivilityRepositoryInterface $civilityRepository, private readonly CountryRepository $countryRepository, private readonly LanguageRepositoryInterface $languageRepository, private readonly MaritalStatusRepositoryInterface $maritalStatusRepository, private readonly TranslatableStringHelper $translatableStringHelper, private readonly TranslatorInterface $translator, private readonly UserRepositoryInterface $userRepository)
{
public function __construct(
private ExportAddressHelper $addressHelper,
private CenterRepositoryInterface $centerRepository,
private CivilityRepositoryInterface $civilityRepository,
private CountryRepository $countryRepository,
private LanguageRepositoryInterface $languageRepository,
private MaritalStatusRepositoryInterface $maritalStatusRepository,
private TranslatableStringHelper $translatableStringHelper,
private TranslatorInterface $translator,
private UserRepositoryInterface $userRepository,
/**
* @var iterable<CustomizeListPersonHelperInterface>
*/
private iterable $customPersonHelpers,
) {
}
/**
@@ -82,26 +96,34 @@ class ListPersonHelper
*/
public function getAllKeys(): array
{
return [
...array_filter(
ListPersonHelper::FIELDS,
fn (string $key) => !\in_array($key, ['address_fields', 'lifecycleUpdate'], true)
),
$keys = [
...ListPersonHelper::FIELDS,
...$this->addressHelper->getKeys(ExportAddressHelper::F_ALL, 'address_fields'),
...['createdAt', 'createdBy', 'updatedAt', 'updatedBy'],
];
foreach ($this->customPersonHelpers as $customize) {
$keys = $customize->alterKeys($keys);
}
return $keys;
}
/**
* @param array<value-of<self::FIELDS>> $fields
*/
public function addSelect(QueryBuilder $qb, array $fields, \DateTimeImmutable $computedDate): void
public function addSelect(QueryBuilder $qb, \DateTimeImmutable $computedDate): void
{
foreach (ListPersonHelper::FIELDS as $f) {
if (!\in_array($f, $fields, true)) {
continue;
}
// we first add all the fields which are handled by the
$focusedFieldKeys = [
'personId', 'countryOfBirth', 'nationality', // 'address_fields',
'spokenLanguages', 'household_id', 'center', // 'lifecycleUpdate',
'genderComment', 'maritalStatus', 'maritalStatusComment', 'civility',
'createdAt', 'createdBy', 'updatedAt', 'updatedBy',
];
$filteredFields = array_filter(
ListPersonHelper::FIELDS,
fn ($field) => !in_array($field, $focusedFieldKeys, true)
);
foreach ($this->getAllKeys() as $f) {
switch ($f) {
case 'personId':
$qb->addSelect('person.id AS personId');
@@ -114,13 +136,6 @@ class ListPersonHelper
break;
case 'address_fields':
$this->addCurrentAddressAt($qb, $computedDate);
$qb->leftJoin('personHouseholdAddress.address', 'personAddress');
$this->addressHelper->addSelectClauses(ExportAddressHelper::F_ALL, $qb, 'personAddress', 'address_fields');
break;
case 'spokenLanguages':
$qb->addSelect('(SELECT AGGREGATE(language.id) FROM '.Language::class.' language WHERE language MEMBER OF person.spokenLanguages) AS spokenLanguages');
@@ -154,15 +169,6 @@ class ListPersonHelper
break;
case 'lifecycleUpdate':
$qb
->addSelect('person.createdAt AS createdAt')
->addSelect('IDENTITY(person.createdBy) AS createdBy')
->addSelect('person.updatedAt AS updatedAt')
->addSelect('IDENTITY(person.updatedBy) AS updatedBy');
break;
case 'genderComment':
$qb->addSelect('person.genderComment.comment AS genderComment');
@@ -184,25 +190,47 @@ class ListPersonHelper
break;
default:
$qb->addSelect(sprintf('person.%s as %s', $f, $f));
if (in_array($f, $filteredFields, true)) {
$qb->addSelect(sprintf('person.%s as %s', $f, $f));
}
}
}
// address
$this->addCurrentAddressAt($qb, $computedDate);
$qb->leftJoin('personHouseholdAddress.address', 'personAddress');
$this->addressHelper->addSelectClauses(ExportAddressHelper::F_ALL, $qb, 'personAddress', 'address_fields');
// lifecycle update
$qb
->addSelect('person.createdAt AS createdAt')
->addSelect('IDENTITY(person.createdBy) AS createdBy')
->addSelect('person.updatedAt AS updatedAt')
->addSelect('IDENTITY(person.updatedBy) AS updatedBy');
foreach ($this->customPersonHelpers as $customPersonHelper) {
$customPersonHelper->alterSelect($qb, $computedDate);
}
}
/**
* @return array|string[]
*
* @deprecated
*/
public function getAllPossibleFields(): array
{
return array_merge(
self::FIELDS,
['createdAt', 'createdBy', 'updatedAt', 'updatedBy'],
$this->addressHelper->getKeys(ExportAddressHelper::F_ALL, 'address_fields')
);
return $this->getAllKeys();
}
public function getLabels($key, array $values, $data): callable
{
foreach ($this->customPersonHelpers as $customPersonHelper) {
if (null !== $callable = $customPersonHelper->getLabels($key, $values, $data)) {
return $callable;
}
}
if (str_starts_with((string) $key, 'address_fields')) {
return $this->addressHelper->getLabel($key, $values, $data, 'address_fields');
}
@@ -366,7 +394,7 @@ class ListPersonHelper
};
default:
if (!\in_array($key, self::getAllPossibleFields(), true)) {
if (!\in_array($key, self::getAllKeys(), true)) {
throw new \RuntimeException("this key is not supported by this helper: {$key}");
}