diff --git a/config/services.php b/config/services.php index 6252a9b..874c3bd 100644 --- a/config/services.php +++ b/config/services.php @@ -85,7 +85,8 @@ ->args([ service('annotation_reader')->nullOnInvalid(), // @deprecated service(EntityManagerInterface::class), - service('encryption.indexes_generator') + service('encryption.indexes_generator'), + service('property_accessor') ]) ->alias(IndexableFieldsService::class, 'encryption.indexable_field') diff --git a/src/Services/IndexableFieldsService.php b/src/Services/IndexableFieldsService.php index 8efdce6..00a9133 100644 --- a/src/Services/IndexableFieldsService.php +++ b/src/Services/IndexableFieldsService.php @@ -10,6 +10,7 @@ use Doctrine\Common\Annotations\Reader; use Doctrine\ORM\EntityManagerInterface; use Odandb\DoctrineCiphersweetEncryptionBundle\Exception\UndefinedGeneratorException; +use Symfony\Component\PropertyAccess\PropertyAccessorInterface; class IndexableFieldsService { @@ -19,12 +20,14 @@ class IndexableFieldsService private ?Reader $annReader; private EntityManagerInterface $em; private IndexesGenerator $indexesGenerator; + private PropertyAccessorInterface $propertyAccessor; - public function __construct(?Reader $annReader, EntityManagerInterface $em, IndexesGenerator $generator) + public function __construct(?Reader $annReader, EntityManagerInterface $em, IndexesGenerator $generator, PropertyAccessorInterface $propertyAccessor) { $this->annReader = $annReader; $this->em = $em; $this->indexesGenerator = $generator; + $this->propertyAccessor = $propertyAccessor; } /** @@ -122,11 +125,11 @@ public function purgeFiltersForContextAndIds(array $fieldsContexts, ?array $ids) * @param null|array $ids * @param array $fieldsContexts */ - public function handleFilterableFieldsForChunck(string $className, ?array $ids, array $fieldsContexts, bool $needsToComputeChangeset = false): void + public function handleFilterableFieldsForChunck(string $className, ?array $ids, array $fieldsContexts, bool $runtimeMode = false): void { $chunck = $this->em->getRepository($className)->findBy(!empty($ids) ? ['id' => $ids] : []); foreach ($chunck as $entity) { - $this->handleIndexableFieldsForEntity($entity, $fieldsContexts, $needsToComputeChangeset); + $this->handleIndexableFieldsForEntity($entity, $fieldsContexts, $runtimeMode); $this->em->flush(); } } @@ -138,7 +141,7 @@ public function handleFilterableFieldsForChunck(string $className, ?array $ids, * * @throws UndefinedGeneratorException|\ReflectionException */ - public function handleIndexableFieldsForEntity(object $entity, array $fieldsContexts, bool $needsToComputeChangeset = false): void + public function handleIndexableFieldsForEntity(object $entity, array $fieldsContexts, bool $runtimeMode = false): void { $className = get_class($entity); $searchIndexes = $this->generateIndexableValuesForEntity($entity, $fieldsContexts); @@ -152,10 +155,14 @@ public function handleIndexableFieldsForEntity(object $entity, array $fieldsCont $indexes = $this->indexesGenerator->generateBlindIndexesFromPossibleValues($className, $refProperty->getName(), $indexesToEncrypt, $indexableAnnotationConfig->fastIndexing); - // We create the filter object instances and associate them to the parent entity + // We create the filter object instances and associate them to the parent entity if is needed $indexEntities = []; $indexEntityClass = $indexableAnnotationConfig->indexesEntityClass; + // If we are in runtime with autoRefresh indexes, we need to compute the change set and set the inverse property to overwrite the existing one. With the orphanRemoval option, the old collection will be deleted. + // In other cases, the old indexes remain and must be purged by you. + $needToCompute = $runtimeMode && $indexableAnnotationConfig->autoRefresh; + $refClass = new \ReflectionClass($indexEntityClass); $classMetadata = $this->em->getClassMetadata($refClass->getName()); foreach ($indexes as $index) { @@ -168,11 +175,17 @@ public function handleIndexableFieldsForEntity(object $entity, array $fieldsCont $this->em->persist($indexEntity); - if ($needsToComputeChangeset) { + if ($needToCompute) { $this->em->getUnitOfWork()->computeChangeSet($classMetadata, $indexEntity); } } } + + if ($needToCompute) { + if ($this->propertyAccessor->isWritable($entity, $refClass->getShortName())) { + $this->propertyAccessor->setValue($entity, $refClass->getShortName(), $indexEntities); + } + } } }