Merge remote-tracking branch 'origin/master' into upgrade-sf5

This commit is contained in:
2024-04-04 18:45:01 +02:00
162 changed files with 3849 additions and 713 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

@@ -16,10 +16,12 @@ use Chill\MainBundle\Entity\Scope;
use Chill\MainBundle\Export\Helper\DateTimeHelper;
use Chill\MainBundle\Export\Helper\ExportAddressHelper;
use Chill\MainBundle\Export\Helper\UserHelper;
use Chill\MainBundle\Repository\CenterRepository;
use Chill\MainBundle\Templating\TranslatableStringHelperInterface;
use Chill\PersonBundle\Entity\AccompanyingPeriod;
use Chill\PersonBundle\Entity\AccompanyingPeriodParticipation;
use Chill\PersonBundle\Entity\Household\PersonHouseholdAddress;
use Chill\PersonBundle\Entity\Person\PersonCenterHistory;
use Chill\PersonBundle\Entity\SocialWork\SocialIssue;
use Chill\PersonBundle\Repository\PersonRepository;
use Chill\PersonBundle\Repository\SocialWork\SocialIssueRepository;
@@ -39,6 +41,8 @@ final readonly class ListAccompanyingPeriodHelper
'stepSince',
'openingDate',
'closingDate',
'duration',
'centers',
'referrer',
'referrerSince',
'acpParticipantPersons',
@@ -83,7 +87,9 @@ final readonly class ListAccompanyingPeriodHelper
private TranslatorInterface $translator,
private UserHelper $userHelper,
private LabelPersonHelper $labelPersonHelper,
) {}
private CenterRepository $centerRepository
) {
}
public function getQueryKeys($data)
{
@@ -201,6 +207,25 @@ final readonly class ListAccompanyingPeriodHelper
AccompanyingPeriod::INTENSITY_REGULAR => $this->translator->trans('regular'),
default => $value,
},
'centers' => function ($value) use ($key) {
if ('_header' === $value) {
return 'export.list.acp.'.$key;
}
if (null === $value || '' === $value || !json_validate((string) $value)) {
return '';
}
return implode(
'|',
array_map(
fn ($cid) => $this->centerRepository->find($cid)->getName(),
array_unique(
json_decode((string) $value, true, 512, JSON_THROW_ON_ERROR)
)
)
);
},
default => static function ($value) use ($key) {
if ('_header' === $value) {
return 'export.list.acp.'.$key;
@@ -314,6 +339,19 @@ final readonly class ListAccompanyingPeriodHelper
// social issues
->addSelect('(SELECT AGGREGATE(socialIssue.id) FROM '.SocialIssue::class.' socialIssue WHERE socialIssue MEMBER OF acp.socialIssues) AS socialIssues');
// duration
$qb->addSelect('DATE_DIFF(COALESCE(acp.closingDate, :calcDate), acp.openingDate) AS duration');
// centers
$qb->addSelect(
'(SELECT AGGREGATE(IDENTITY(cppch.center))
FROM '.AccompanyingPeriodParticipation::class.' part
JOIN '.PersonCenterHistory::class." cppch
WITH IDENTITY(cppch.person) = IDENTITY(part.person)
AND OVERLAPSI (cppch.startDate, cppch.endDate), (part.startDate, part.endDate) = 'TRUE'
WHERE part.accompanyingPeriod = acp
) AS centers"
);
// add parameter
$qb->setParameter('calcDate', $calcDate);
}

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,16 +60,32 @@ 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,
) {
}
/**
* Those keys are the "direct" keys, which are created when we decide to use to list all the keys.
@@ -80,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');
@@ -112,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');
@@ -152,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');
@@ -182,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');
}
@@ -364,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}");
}