Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix onClear and skip encryption of non updated entities #13

Merged
merged 1 commit into from
Apr 7, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 33 additions & 2 deletions src/Subscribers/DoctrineCiphersweetSubscriber.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

namespace Odandb\DoctrineCiphersweetEncryptionBundle\Subscribers;

use Doctrine\ORM\UnitOfWork;
use Odandb\DoctrineCiphersweetEncryptionBundle\Configuration\EncryptedField;
use Odandb\DoctrineCiphersweetEncryptionBundle\Configuration\IndexableField;
use Odandb\DoctrineCiphersweetEncryptionBundle\Encryptors\EncryptorInterface;
Expand Down Expand Up @@ -77,6 +78,7 @@ public function onFlush(OnFlushEventArgs $args): void
$unitOfWork = $em->getUnitOfWork();

$this->postFlushDecryptQueue = [];
$this->entitiesToEncrypt = [];

foreach ($unitOfWork->getScheduledEntityInsertions() as $entity) {
$this->entityOnFlush($entity, $em);
Expand All @@ -93,16 +95,20 @@ public function onFlush(OnFlushEventArgs $args): void
$this->entityOnFlush($entity, $em);
$unitOfWork->recomputeSingleEntityChangeSet($em->getClassMetadata(\get_class($entity)), $entity);
}

// We flush the array of entities to encrypt after the loop to avoid memory leaks
$this->entitiesToEncrypt = [];
}

public function onClear(OnClearEventArgs $args): void
{
unset($this->_originalValues, $this->decodedRegistry, $this->encryptedFieldCache, $this->postFlushDecryptQueue);
unset($this->_originalValues, $this->decodedRegistry, $this->encryptedFieldCache, $this->postFlushDecryptQueue, $this->entitiesToEncrypt);

$this->_originalValues = [];
$this->decodedRegistry = [];
$this->encryptedFieldCache = [];
$this->postFlushDecryptQueue = [];
$this->entitiesToEncrypt = [];
}

/**
Expand All @@ -117,7 +123,14 @@ private function entityOnFlush(object $entity, EntityManagerInterface $em): void

$fields = [];

foreach ($this->getEncryptedFields($entity, $em) as $field) {
$ecnryptedFields = $this->getEncryptedFields($entity, $em);

// If no encryptedFields detected we early return as we don't need to process anything
if ($ecnryptedFields === []) {
return;
}

foreach ($ecnryptedFields as $field) {
$fields[$field->getName()] = [
'field' => $field,
'value' => $field->getValue($entity),
Expand Down Expand Up @@ -178,12 +191,30 @@ private function getEncryptedFields(object $entity, EntityManagerInterface $em):

/**
* Process (encrypt/decrypt) entities fields.
*
* Upon encryption operation, if the entity is not new, we check if there are changes in the entity.
* If no changes, we early return.
* Make sure you call first $unitOfWork->computeChangeSet or $unitOfWork->recomputeSingleEntityChangeSet
* if you think your entity should be updated and has not been handled by entity manager.
*/
public function processFields(object $entity, EntityManagerInterface $em, $isEncryptOperation = true, $force = null): bool
{
$properties = $this->getEncryptedFields($entity, $em);
$unitOfWork = $em->getUnitOfWork();

// If there is no encrypted fields nor changes in given entity upon encryption operation and the entity is not new, we early return
// In case of new entity, there is no need to check for changes as they may not have been persisted nor computed yet
if (
$properties === []
|| (
$isEncryptOperation
&& $unitOfWork->getEntityState($entity) !== UnitOfWork::STATE_NEW
&& $unitOfWork->getEntityChangeSet($entity) === []
)
) {
return false;
}

$oid = spl_object_id($entity);

$entityClassName = $em->getClassMetadata(get_class($entity))->getName();
Expand Down