|
<?php |
|
|
|
namespace App\EventListener; |
|
|
|
use App\Doctrine\Encryption\EncryptingEntityInterface; |
|
use App\Doctrine\Encryption\EncryptorInterface; |
|
use Doctrine\Common\EventSubscriber; |
|
use Doctrine\ORM\Event\LifecycleEventArgs; |
|
use Doctrine\ORM\Event\PreFlushEventArgs; |
|
use Doctrine\ORM\Events; |
|
|
|
/** |
|
* Doctrine event subscriber to encrypt/decrypt entity properties. |
|
* |
|
* Inspired from https://github.com/michaeldegroot/DoctrineEncryptBundle |
|
* |
|
* Instead of using an annotation, we programmatically encrypted/decrypted field relations. |
|
*/ |
|
class DoctrineEncryptListener implements EventSubscriber |
|
{ |
|
/** |
|
* @var EncryptorInterface |
|
*/ |
|
private $encryptor; |
|
|
|
public function __construct(EncryptorInterface $encryptor) |
|
{ |
|
$this->encryptor = $encryptor; |
|
} |
|
|
|
public function getSubscribedEvents(): array |
|
{ |
|
return [ |
|
Events::postLoad, |
|
Events::preFlush, |
|
]; |
|
} |
|
|
|
/** |
|
* After loading an entity, populate the decrypted properties by decrypting the encrypted tracked property. |
|
* |
|
* Track the entity so that we also update fields in preFlush. |
|
*/ |
|
public function postLoad(LifecycleEventArgs $args): void |
|
{ |
|
$entity = $args->getEntity(); |
|
if (!$entity instanceof EncryptingEntityInterface) { |
|
return; |
|
} |
|
|
|
$entity->decrypt($this->encryptor); |
|
} |
|
|
|
/** |
|
* Encrypt properties of entities that are newly inserted into the database or that have previously been loaded from the database. |
|
*/ |
|
public function preFlush(PreFlushEventArgs $preFlushEventArgs): void |
|
{ |
|
// encrypt entities that we are about to insert |
|
$unitOfWork = $preFlushEventArgs->getEntityManager()->getUnitOfWork(); |
|
foreach ($unitOfWork->getScheduledEntityInsertions() as $entity) { |
|
if ($entity instanceof EncryptingEntityInterface) { |
|
$entity->encrypt($this->encryptor); |
|
} |
|
} |
|
} |
|
} |
looking at absolute-quantum/DoctrineEncryptBundle#35, we should also listen to onFlush, as preFlush is missing cascading inserts and would lead to not explicitly persisted but cascading inserts not be encrypted.