Skip to content

Commit

Permalink
add doctrine event listeners - wip
Browse files Browse the repository at this point in the history
  • Loading branch information
bailletced committed Dec 12, 2024
1 parent f0defe8 commit 90f88b1
Show file tree
Hide file tree
Showing 24 changed files with 702 additions and 114 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
1. Attention à la création des communautés / places !
Les fields et leurs entités doivent être persistés ensemble avant de flush
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ interface CommunityRepositoryInterface extends RepositoryInterface
public function ofId(Uuid $communityid): ?Community;

/**
* @param array<string> $ids
* @param array<Uuid> $ids
*/
public function ofIds(array $ids): static;

Expand All @@ -27,4 +27,6 @@ public function add(Community $community): void;
public function withType(string $type): static;

public function withWikidataId(int $wikidataId): static;

public function withParentCommunityId(Uuid $parentId): static;
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ public function process(mixed $data, Operation $operation, array $uriVariables =
$community = new Community();
$this->communityRepo->add($community);

$community->fields = $this->fieldService->upsertFields($community, $data->fields);
$this->fieldService->upsertFields($community, $data->fields);

return CommunityResource::fromModel(
$community,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ public function process(mixed $data, Operation $operation, array $uriVariables =
Assert::isInstanceOf($data, CommunityResource::class);

$community = $this->communityRepo->ofId($data->id); // community cannot be null because we passed through CommunityItemProvider
$community->fields = $this->fieldService->upsertFields($community, $data->fields);
$this->fieldService->upsertFields($community, $data->fields);

return CommunityResource::fromModel($community);
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
use App\Core\Domain\Search\Service\SearchServiceInterface;
use App\Field\Domain\Enum\FieldCommunity;
use App\Shared\Infrastructure\ApiPlatform\State\Paginator;
use Symfony\Component\Uid\Uuid;

/**
* @implements ProviderInterface<CommunityResource>
Expand Down Expand Up @@ -60,7 +61,7 @@ public function provide(Operation $operation, array $uriVariables = [], array $c
}

$models = $this->communityRepo
->ofIds($entityIds ?? [])
->ofIds(array_map(fn (string $entityId) => Uuid::fromString($entityId), $entityIds ?? []))
->withType($type)
->withWikidataId((int) $wikidataId)
->withPagination($page, $itemsPerPage);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
<?php

declare(strict_types=1);

namespace App\Community\Infrastructure\Doctrine;

use App\Community\Domain\Enum\CommunityType;
use App\Community\Domain\Model\Community;
use App\Core\Domain\Search\Helper\SearchHelperInterface;
use App\Field\Domain\Enum\FieldCommunity;
use App\Shared\Domain\Enum\SearchIndex;
use Doctrine\Bundle\DoctrineBundle\Attribute\AsEntityListener;
use Doctrine\ORM\Events;

#[AsEntityListener(event: Events::postPersist, method: 'postPersist', entity: Community::class)]
final class DoctrineCommunityListener
{
public function __construct(
private readonly SearchHelperInterface $searchHelper,
) {
}

public function postPersist(Community $community): void
{
$type = $community->getMostTrustableFieldByName(FieldCommunity::TYPE)?->getValue();
if ($type === CommunityType::PARISH->value) {
// A new parish has been inserted
$parishName = $community->getMostTrustableFieldByName(FieldCommunity::NAME)?->getValue();
$dioceseName = null;
/** @var Community|null $diocese */
$diocese = $community->getMostTrustableFieldByName(FieldCommunity::PARENT_COMMUNITY_ID)?->getValue();
if ($diocese) {
$dioceseName = $diocese->getMostTrustableFieldByName(FieldCommunity::NAME)?->getValue();
}
$this->searchHelper->upsertElement(
SearchIndex::PARISH,
$community->id->toString(),
[
'parishName' => $parishName,
'dioceseName' => $dioceseName,
]
);
}

if ($type === CommunityType::DIOCESE->value) {
// A new diocese has been inserted
$dioceseName = $community->getMostTrustableFieldByName(FieldCommunity::NAME)?->getValue();
$this->searchHelper->upsertElement(
SearchIndex::DIOCESE,
$community->id->toString(),
[
'dioceseName' => $dioceseName,
]
);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ public function addSelectField(): static
}

/**
* @param array<string> $ids
* @param array<Uuid> $ids
*/
public function ofIds(array $ids): static
{
Expand All @@ -52,7 +52,7 @@ public function ofIds(array $ids): static
return
$this->filter(static function (QueryBuilder $qb) use ($ids): void {
$qb->andWhere('community.id IN (:ids)')
->setParameter('ids', array_map(fn (string $id) => Uuid::fromString($id)->toBinary(), $ids));
->setParameter('ids', array_map(fn (Uuid $id) => $id->toBinary(), $ids));
});
}

Expand Down Expand Up @@ -89,4 +89,21 @@ public function withWikidataId(?int $value): static
->setParameter('valueWikidata', $value);
});
}

public function withParentCommunityId(?Uuid $parentId): static
{
if (!$parentId) {
return $this;
}

return
$this->filter(static function (QueryBuilder $qb) use ($parentId): void {
$qb->andWhere("
EXISTS (SELECT 1 FROM App\Field\Domain\Model\Field f_community_parent_id
WHERE f_community_parent_id.community = community
AND f_community_parent_id.name = 'parentCommunityId' AND IDENTITY(f_community_parent_id.communityVal) = :valueParentCommunity)
")
->setParameter('valueParentCommunity', $parentId->toBinary());
});
}
}
14 changes: 14 additions & 0 deletions src/Core/Domain/Search/Helper/SearchHelperInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,20 @@ public function bulkIndex(SearchIndex $index, array $ids, array $bodies): void;

public function createIndex(SearchIndex $index): mixed;

/**
* @param array<mixed> $body
*
* @return array<mixed>
*/
public function upsertElement(SearchIndex $index, string $id, array $body): mixed;

public function existDocument(SearchIndex $index, string $id): bool;

/**
* @return array<mixed>|null
*/
public function getDocument(SearchIndex $index, string $id): ?array;

/**
* @return array<mixed>
*/
Expand Down
6 changes: 6 additions & 0 deletions src/Core/Domain/Search/Service/SearchServiceInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,24 @@

namespace App\Core\Domain\Search\Service;

use App\Community\Domain\Model\Community;

interface SearchServiceInterface
{
/**
* @return string[]
*/
public function searchParishIds(string $text, int $limit, int $offset): array;

public function findParish(string $id): ?Community;

/**
* @return string[]
*/
public function searchDioceseIds(string $text, int $limit, int $offset): array;

public function findDiocese(string $text): ?Community;

/**
* @return string[]
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,4 +45,4 @@ public function postGenerateSchema(GenerateSchemaEventArgs $args): void

$table->setPrimaryKey([$this->configuration->getVersionColumnName()]);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,54 @@ public function createIndex(SearchIndex $index): Elasticsearch|Promise
return $this->elasticsearchClient->indices()->create($params);
}

public function existDocument(SearchIndex $index, string $id): bool
{
$params = [
'index' => $index->value,
'id' => $id,
];

return $this->elasticsearchClient->exists($params)->asBool();
}

public function getDocument(SearchIndex $index, string $id): ?array
{
$params = [
'index' => $index->value,
'id' => $id,
];

if (!$this->existDocument($index, $id)) {
return null;
}

return $this->elasticsearchClient->get($params)->asArray();
}

/**
* @param array<mixed> $body
*
* @return array<mixed>
*/
public function upsertElement(SearchIndex $index, string $id, array $body): array
{
$params = [
'index' => $index->value,
'id' => $id,
'body' => $body,
];

if ($this->existDocument($index, $id)) {
$params['body'] = [
'doc' => $body,
];

return $this->elasticsearchClient->update($params)->asArray();
}

return $this->elasticsearchClient->index($params)->asArray();
}

/**
* @param array<string, mixed> $body
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,18 @@

namespace App\Core\Infrastructure\ElasticSearch\Service;

use App\Community\Domain\Model\Community;
use App\Community\Domain\Repository\CommunityRepositoryInterface;
use App\Core\Domain\Search\Helper\SearchHelperInterface;
use App\Core\Domain\Search\Service\SearchServiceInterface;
use App\Shared\Domain\Enum\SearchIndex;
use Symfony\Component\Uid\Uuid;

class OfficialElasticSearchService implements SearchServiceInterface
{
public function __construct(
private SearchHelperInterface $elasticSearchHelper,
private CommunityRepositoryInterface $communityRepo,
) {
}

Expand Down Expand Up @@ -94,6 +98,26 @@ private function buildQueryForDioceses(string $text, int $limit, int $offset): a
];
}

public function findParish(string $id): ?Community
{
$document = $this->elasticSearchHelper->getDocument(SearchIndex::PARISH, $id);
if ($document) {
return $this->communityRepo->ofId(Uuid::fromString($document['id']));
}

return null;
}

public function findDiocese(string $id): ?Community
{
$document = $this->elasticSearchHelper->getDocument(SearchIndex::DIOCESE, $id);
if ($document) {
return $this->communityRepo->ofId(Uuid::fromString($document['id']));
}

return null;
}

/** @return string[] */
public function searchDioceseIds(string $text, int $limit, int $offset): array
{
Expand Down
14 changes: 2 additions & 12 deletions src/Field/Application/FieldService.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
use App\Field\Domain\Repository\FieldRepositoryInterface;
use App\Place\Domain\Model\Place;
use App\Place\Domain\Repository\PlaceRepositoryInterface;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Symfony\Bundle\SecurityBundle\Security;
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
Expand All @@ -37,14 +36,9 @@ public function __construct(

/**
* @param Field[] $fieldPayloads
*
* @return Collection<int, Field>
*/
public function upsertFields(Place|Community $entity, array $fieldPayloads): Collection
public function upsertFields(Place|Community $entity, array $fieldPayloads): void
{
/** @var Collection<int, Field> $insertedFields */
$insertedFields = new ArrayCollection();

/** @var Agent $agent */
$agent = $this->security->getUser();

Expand Down Expand Up @@ -93,12 +87,8 @@ public function upsertFields(Place|Community $entity, array $fieldPayloads): Col
}

$field->applyValue(); // Dynamycally set the value to the correct property (intVal, stringVal, ...)

$this->fieldRepo->add($field);
$insertedFields[] = $field;
$entity->addField($field);
}

return $insertedFields;
}

private function getOrCreate(Place|Community $entity, FieldPlace|FieldCommunity $nameEnum, Agent $agent): Field
Expand Down
Loading

0 comments on commit 90f88b1

Please sign in to comment.