mirror of
https://gitlab.com/Chill-Projet/chill-bundles.git
synced 2025-08-25 00:53:48 +00:00
[generic doc] listing generic doc for person
This commit is contained in:
@@ -25,8 +25,6 @@ interface GenericDocForAccompanyingPeriodProviderInterface
|
||||
|
||||
/**
|
||||
* Return true if the user is allowed to see some documents for this provider.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isAllowedForAccompanyingPeriod(AccompanyingPeriod $accompanyingPeriod): bool;
|
||||
|
||||
|
@@ -0,0 +1,31 @@
|
||||
<?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\DocStoreBundle\GenericDoc;
|
||||
|
||||
use Chill\PersonBundle\Entity\Person;
|
||||
use DateTimeImmutable;
|
||||
|
||||
interface GenericDocForPersonProviderInterface
|
||||
{
|
||||
public function buildFetchQueryForPerson(
|
||||
Person $person,
|
||||
?DateTimeImmutable $startDate = null,
|
||||
?DateTimeImmutable $endDate = null,
|
||||
?string $content = null,
|
||||
?string $origin = null
|
||||
): FetchQueryInterface;
|
||||
|
||||
/**
|
||||
* Return true if the user is allowed to see some documents for this provider.
|
||||
*/
|
||||
public function isAllowedForPerson(Person $person): bool;
|
||||
}
|
@@ -17,16 +17,21 @@ use Doctrine\DBAL\Connection;
|
||||
use Doctrine\DBAL\Exception;
|
||||
use Doctrine\DBAL\Types\Types;
|
||||
|
||||
class Manager
|
||||
final readonly class Manager
|
||||
{
|
||||
private readonly FetchQueryToSqlBuilder $builder;
|
||||
private FetchQueryToSqlBuilder $builder;
|
||||
|
||||
public function __construct(
|
||||
/**
|
||||
* @var iterable<GenericDocForAccompanyingPeriodProviderInterface>
|
||||
*/
|
||||
private readonly iterable $providersForAccompanyingPeriod,
|
||||
private readonly Connection $connection,
|
||||
private iterable $providersForAccompanyingPeriod,
|
||||
|
||||
/**
|
||||
* @var iterable<GenericDocForPersonProviderInterface>
|
||||
*/
|
||||
private iterable $providersForPerson,
|
||||
private Connection $connection,
|
||||
) {
|
||||
$this->builder = new FetchQueryToSqlBuilder();
|
||||
}
|
||||
@@ -44,6 +49,11 @@ class Manager
|
||||
): int {
|
||||
['sql' => $sql, 'params' => $params, 'types' => $types] = $this->buildUnionQuery($accompanyingPeriod, $startDate, $endDate, $content, $places);
|
||||
|
||||
return $this->countDoc($sql, $params, $types);
|
||||
}
|
||||
|
||||
private function countDoc(string $sql, array $params, array $types): int
|
||||
{
|
||||
if ($sql === '') {
|
||||
return 0;
|
||||
}
|
||||
@@ -60,8 +70,21 @@ class Manager
|
||||
return $number;
|
||||
}
|
||||
|
||||
public function countDocForPerson(
|
||||
Person $person,
|
||||
?\DateTimeImmutable $startDate = null,
|
||||
?\DateTimeImmutable $endDate = null,
|
||||
?string $content = null,
|
||||
array $places = []
|
||||
): int {
|
||||
['sql' => $sql, 'params' => $params, 'types' => $types] = $this->buildUnionQuery($person, $startDate, $endDate, $content, $places);
|
||||
|
||||
return $this->countDoc($sql, $params, $types);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param list<string> $places places to search. When empty, search in all places
|
||||
* @return iterable<GenericDocDTO>
|
||||
* @throws Exception
|
||||
*/
|
||||
public function findDocForAccompanyingPeriod(
|
||||
@@ -75,6 +98,15 @@ class Manager
|
||||
): iterable {
|
||||
['sql' => $sql, 'params' => $params, 'types' => $types] = $this->buildUnionQuery($accompanyingPeriod, $startDate, $endDate, $content, $places);
|
||||
|
||||
return $this->findDocs($accompanyingPeriod, $sql, $params, $types, $offset, $limit);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws \JsonException
|
||||
* @throws Exception
|
||||
*/
|
||||
private function findDocs(AccompanyingPeriod|Person $linked, string $sql, array $params, array $types, int $offset, int $limit): iterable
|
||||
{
|
||||
if ($sql === '') {
|
||||
return [];
|
||||
}
|
||||
@@ -88,20 +120,50 @@ class Manager
|
||||
$row['key'],
|
||||
json_decode($row['identifiers'], true, 512, JSON_THROW_ON_ERROR),
|
||||
new \DateTimeImmutable($row['doc_date']),
|
||||
$accompanyingPeriod,
|
||||
$linked,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param list<string> $places places to search. When empty, search in all places
|
||||
* @return iterable<GenericDocDTO>
|
||||
*/
|
||||
public function findDocForPerson(
|
||||
Person $person,
|
||||
int $offset = 0,
|
||||
int $limit = 20,
|
||||
?\DateTimeImmutable $startDate = null,
|
||||
?\DateTimeImmutable $endDate = null,
|
||||
?string $content = null,
|
||||
array $places = []
|
||||
): iterable {
|
||||
['sql' => $sql, 'params' => $params, 'types' => $types] = $this->buildUnionQuery($person, $startDate, $endDate, $content, $places);
|
||||
|
||||
return $this->findDocs($person, $sql, $params, $types, $offset, $limit);
|
||||
}
|
||||
|
||||
public function placesForPerson(Person $person): array
|
||||
{
|
||||
['sql' => $sql, 'params' => $params, 'types' => $types] = $this->buildUnionQuery($person);
|
||||
|
||||
return $this->places($sql, $params, $types);
|
||||
}
|
||||
|
||||
public function placesForAccompanyingPeriod(AccompanyingPeriod $accompanyingPeriod): array
|
||||
{
|
||||
['sql' => $sql, 'params' => $params, 'types' => $types] = $this->buildUnionQuery($accompanyingPeriod);
|
||||
|
||||
return $this->places($sql, $params, $types);
|
||||
}
|
||||
|
||||
private function places(string $sql, array $params, array $types): array
|
||||
{
|
||||
if ($sql === '') {
|
||||
return [];
|
||||
}
|
||||
|
||||
$runSql = "SELECT DISTINCT key FROM ({$sql}) AS sq";
|
||||
$runSql = "SELECT DISTINCT key FROM ({$sql}) AS sq ORDER BY key";
|
||||
|
||||
$keys = [];
|
||||
|
||||
@@ -122,28 +184,38 @@ class Manager
|
||||
?string $content = null,
|
||||
array $places = [],
|
||||
): array {
|
||||
$sql = [];
|
||||
$params = [];
|
||||
$types = [];
|
||||
$queries = [];
|
||||
|
||||
if ($linked instanceof AccompanyingPeriod) {
|
||||
foreach ($this->providersForAccompanyingPeriod as $provider) {
|
||||
if (!$provider->isAllowedForAccompanyingPeriod($linked)) {
|
||||
continue;
|
||||
}
|
||||
$query = $provider->buildFetchQueryForAccompanyingPeriod($linked, $startDate, $endDate, $content);
|
||||
|
||||
if ([] !== $places and !in_array($query->getSelectKeyString(), $places, true)) {
|
||||
$queries[] = $provider->buildFetchQueryForAccompanyingPeriod($linked, $startDate, $endDate, $content);
|
||||
}
|
||||
} else {
|
||||
foreach ($this->providersForPerson as $provider) {
|
||||
if (!$provider->isAllowedForPerson($linked)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
['sql' => $q, 'params' => $p, 'types' => $t ] = $this->builder->toSql($query);
|
||||
|
||||
$sql[] = $q;
|
||||
$params = [...$params, ...$p];
|
||||
$types = [...$types, ...$t];
|
||||
$queries[] = $provider->buildFetchQueryForPerson($linked, $startDate, $endDate, $content);
|
||||
}
|
||||
}
|
||||
$sql = [];
|
||||
$params = [];
|
||||
$types = [];
|
||||
|
||||
foreach ($queries as $query) {
|
||||
if ([] !== $places and !in_array($query->getSelectKeyString(), $places, true)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
['sql' => $q, 'params' => $p, 'types' => $t ] = $this->builder->toSql($query);
|
||||
|
||||
$sql[] = $q;
|
||||
$params = [...$params, ...$p];
|
||||
$types = [...$types, ...$t];
|
||||
}
|
||||
|
||||
return ['sql' => implode(' UNION ', $sql), 'params' => $params, 'types' => $types];
|
||||
}
|
||||
|
@@ -0,0 +1,51 @@
|
||||
<?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\DocStoreBundle\GenericDoc\Providers;
|
||||
|
||||
use Chill\DocStoreBundle\GenericDoc\FetchQueryInterface;
|
||||
use Chill\DocStoreBundle\GenericDoc\GenericDocForPersonProviderInterface;
|
||||
use Chill\DocStoreBundle\Repository\PersonDocumentACLAwareRepositoryInterface;
|
||||
use Chill\DocStoreBundle\Security\Authorization\PersonDocumentVoter;
|
||||
use Chill\PersonBundle\Entity\Person;
|
||||
use DateTimeImmutable;
|
||||
use Symfony\Component\Security\Core\Security;
|
||||
|
||||
final readonly class PersonDocumentGenericDocProvider implements GenericDocForPersonProviderInterface
|
||||
{
|
||||
public const KEY = 'person_document';
|
||||
|
||||
public function __construct(
|
||||
private Security $security,
|
||||
private PersonDocumentACLAwareRepositoryInterface $personDocumentACLAwareRepository,
|
||||
) {
|
||||
}
|
||||
|
||||
public function buildFetchQueryForPerson(
|
||||
Person $person,
|
||||
?DateTimeImmutable $startDate = null,
|
||||
?DateTimeImmutable $endDate = null,
|
||||
?string $content = null,
|
||||
?string $origin = null
|
||||
): FetchQueryInterface {
|
||||
return $this->personDocumentACLAwareRepository->buildFetchQueryForPerson(
|
||||
$person,
|
||||
$startDate,
|
||||
$endDate,
|
||||
$content
|
||||
);
|
||||
}
|
||||
|
||||
public function isAllowedForPerson(Person $person): bool
|
||||
{
|
||||
return $this->security->isGranted(PersonDocumentVoter::SEE, $person);
|
||||
}
|
||||
}
|
@@ -12,20 +12,25 @@ declare(strict_types=1);
|
||||
namespace Chill\DocStoreBundle\GenericDoc\Renderer;
|
||||
|
||||
use Chill\DocStoreBundle\GenericDoc\GenericDocDTO;
|
||||
use Chill\DocStoreBundle\GenericDoc\Providers\PersonDocumentGenericDocProvider;
|
||||
use Chill\DocStoreBundle\GenericDoc\Twig\GenericDocRendererInterface;
|
||||
use Chill\DocStoreBundle\GenericDoc\Providers\AccompanyingProviderCourseDocumentGenericDoc;
|
||||
use Chill\DocStoreBundle\Repository\AccompanyingCourseDocumentRepository;
|
||||
use Chill\DocStoreBundle\Repository\PersonDocumentRepository;
|
||||
use Chill\PersonBundle\Entity\AccompanyingPeriod;
|
||||
|
||||
final readonly class AccompanyingCourseDocumentGenericDocRenderer implements GenericDocRendererInterface
|
||||
{
|
||||
public function __construct(
|
||||
private AccompanyingCourseDocumentRepository $accompanyingCourseDocumentRepository,
|
||||
private PersonDocumentRepository $personDocumentRepository,
|
||||
) {
|
||||
}
|
||||
|
||||
public function supports(GenericDocDTO $genericDocDTO, $options = []): bool
|
||||
{
|
||||
return $genericDocDTO->key === AccompanyingProviderCourseDocumentGenericDoc::KEY;
|
||||
return $genericDocDTO->key === AccompanyingProviderCourseDocumentGenericDoc::KEY
|
||||
|| $genericDocDTO->key === PersonDocumentGenericDocProvider::KEY;
|
||||
}
|
||||
|
||||
public function getTemplate(GenericDocDTO $genericDocDTO, $options = []): string
|
||||
@@ -35,9 +40,18 @@ final readonly class AccompanyingCourseDocumentGenericDocRenderer implements Gen
|
||||
|
||||
public function getTemplateData(GenericDocDTO $genericDocDTO, $options = []): array
|
||||
{
|
||||
if ($genericDocDTO->linked instanceof AccompanyingPeriod) {
|
||||
return [
|
||||
'document' => $this->accompanyingCourseDocumentRepository->find($genericDocDTO->identifiers['id']),
|
||||
'accompanyingCourse' => $genericDocDTO->linked,
|
||||
'options' => $options,
|
||||
];
|
||||
}
|
||||
|
||||
// this is a person
|
||||
return [
|
||||
'document' => $this->accompanyingCourseDocumentRepository->find($genericDocDTO->identifiers['id']),
|
||||
'accompanyingCourse' => $genericDocDTO->linked,
|
||||
'document' => $this->personDocumentRepository->find($genericDocDTO->identifiers['id']),
|
||||
'person' => $genericDocDTO->linked,
|
||||
'options' => $options,
|
||||
];
|
||||
}
|
||||
|
Reference in New Issue
Block a user