[generic doc] listing generic doc for person

This commit is contained in:
2023-05-30 20:48:35 +02:00
parent eb107f5a15
commit 40af1e64ac
15 changed files with 842 additions and 42 deletions

View File

@@ -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];
}