Add entity lifecycle listener for emoji sanitisation
[MAILPOET-3196]
This commit is contained in:
committed by
Veljko V
parent
7449d3df3e
commit
96f2bfaa20
@@ -124,6 +124,7 @@ class ContainerConfigurator implements IContainerConfigurator {
|
||||
$container->autowire(\MailPoetVendor\Doctrine\ORM\EntityManager::class)
|
||||
->setFactory([new Reference(\MailPoet\Doctrine\EntityManagerFactory::class), 'createEntityManager'])
|
||||
->setPublic(true);
|
||||
$container->autowire(\MailPoet\Doctrine\EventListeners\EmojiEncodingListener::class)->setPublic(true);
|
||||
$container->autowire(\MailPoet\Doctrine\EventListeners\TimestampListener::class);
|
||||
$container->autowire(\MailPoet\Doctrine\EventListeners\ValidationListener::class);
|
||||
$container->autowire(\MailPoet\Doctrine\Validator\ValidatorFactory::class);
|
||||
|
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace MailPoet\Doctrine;
|
||||
|
||||
use MailPoet\Doctrine\EventListeners\EmojiEncodingListener;
|
||||
use MailPoet\Doctrine\EventListeners\TimestampListener;
|
||||
use MailPoet\Doctrine\EventListeners\ValidationListener;
|
||||
use MailPoet\Tracy\DoctrinePanel\DoctrinePanel;
|
||||
@@ -25,16 +26,21 @@ class EntityManagerFactory {
|
||||
/** @var ValidationListener */
|
||||
private $validationListener;
|
||||
|
||||
/** @var EmojiEncodingListener */
|
||||
private $emojiEncodingListener;
|
||||
|
||||
public function __construct(
|
||||
Connection $connection,
|
||||
Configuration $configuration,
|
||||
TimestampListener $timestampListener,
|
||||
ValidationListener $validationListener
|
||||
ValidationListener $validationListener,
|
||||
EmojiEncodingListener $emojiEncodingListener
|
||||
) {
|
||||
$this->connection = $connection;
|
||||
$this->configuration = $configuration;
|
||||
$this->timestampListener = $timestampListener;
|
||||
$this->validationListener = $validationListener;
|
||||
$this->emojiEncodingListener = $emojiEncodingListener;
|
||||
}
|
||||
|
||||
public function createEntityManager() {
|
||||
@@ -56,5 +62,10 @@ class EntityManagerFactory {
|
||||
[Events::onFlush],
|
||||
$this->validationListener
|
||||
);
|
||||
|
||||
$entityManager->getEventManager()->addEventListener(
|
||||
[Events::prePersist, Events::preUpdate],
|
||||
$this->emojiEncodingListener
|
||||
);
|
||||
}
|
||||
}
|
||||
|
34
lib/Doctrine/EventListeners/EmojiEncodingListener.php
Normal file
34
lib/Doctrine/EventListeners/EmojiEncodingListener.php
Normal file
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
namespace MailPoet\Doctrine\EventListeners;
|
||||
|
||||
use MailPoet\Entities\FormEntity;
|
||||
use MailPoet\WP\Emoji;
|
||||
use MailPoetVendor\Doctrine\ORM\Event\LifecycleEventArgs;
|
||||
|
||||
class EmojiEncodingListener {
|
||||
/** @var Emoji */
|
||||
private $emoji;
|
||||
|
||||
public function __construct(Emoji $emoji) {
|
||||
$this->emoji = $emoji;
|
||||
}
|
||||
|
||||
public function prePersist(LifecycleEventArgs $eventArgs) {
|
||||
$this->sanitizeEmojiBeforeSaving($eventArgs);
|
||||
}
|
||||
|
||||
public function preUpdate(LifecycleEventArgs $eventArgs) {
|
||||
$this->sanitizeEmojiBeforeSaving($eventArgs);
|
||||
}
|
||||
|
||||
private function sanitizeEmojiBeforeSaving(LifecycleEventArgs $eventArgs) {
|
||||
$entity = $eventArgs->getEntity();
|
||||
if ($entity instanceof FormEntity) {
|
||||
$body = $entity->getBody();
|
||||
if ($body !== null) {
|
||||
$entity->setBody($this->emoji->sanitizeEmojisInFormBody($body));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -29,6 +29,12 @@ class Emoji {
|
||||
return $this->decodeEntities($newsletterRenderedBody);
|
||||
}
|
||||
|
||||
public function sanitizeEmojisInFormBody(array $body): array {
|
||||
$bodyJson = json_encode($body, JSON_UNESCAPED_UNICODE);
|
||||
$fixedJson = $this->encodeForUTF8Column(MP_FORMS_TABLE, 'body', $bodyJson);
|
||||
return json_decode($fixedJson, true);
|
||||
}
|
||||
|
||||
private function encodeRenderedBodyForUTF8Column($value) {
|
||||
return $this->encodeForUTF8Column(
|
||||
MP_SENDING_QUEUES_TABLE,
|
||||
|
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
namespace MailPoet\Test\Doctrine\EventListeners;
|
||||
|
||||
use MailPoet\Doctrine\EventListeners\EmojiEncodingListener;
|
||||
use MailPoet\Entities\FormEntity;
|
||||
use MailPoet\WP\Emoji;
|
||||
use MailPoetVendor\Doctrine\ORM\Events;
|
||||
|
||||
class EmojiEncodingListenerTest extends \MailPoetTest {
|
||||
public function testItSanitizeFormEntityOnPersistAndUpdate() {
|
||||
$form = new FormEntity('Form' );
|
||||
$form->setBody(['body']);
|
||||
$emojiMock = $this->createMock(Emoji::class);
|
||||
$emojiMock->expects($this->exactly(2))
|
||||
->method('sanitizeEmojisInFormBody')
|
||||
->willReturn(['sanitizedBody']);
|
||||
$emojiEncodingListenerWithMockedEmoji = new EmojiEncodingListener($emojiMock);
|
||||
$originalListener = $this->diContainer->get(EmojiEncodingListener::class);
|
||||
$this->replaceListeners($originalListener, $emojiEncodingListenerWithMockedEmoji);
|
||||
$this->entityManager->persist($form);
|
||||
$this->entityManager->flush($form);
|
||||
expect($form->getBody())->equals(['sanitizedBody']);
|
||||
$form->setBody(['updatedBody']);
|
||||
$this->entityManager->flush($form);
|
||||
expect($form->getBody())->equals(['sanitizedBody']);
|
||||
$this->replaceListeners($emojiEncodingListenerWithMockedEmoji, $originalListener);
|
||||
}
|
||||
|
||||
/**
|
||||
* We have to replace event listeners since EventManager
|
||||
* is shared for all entity managers using same DB connection
|
||||
*/
|
||||
private function replaceListeners($original, $replacement) {
|
||||
$this->entityManager->getEventManager()->removeEventListener(
|
||||
[Events::prePersist, Events::preUpdate],
|
||||
$original
|
||||
);
|
||||
|
||||
$this->entityManager->getEventManager()->addEventListener(
|
||||
[Events::prePersist, Events::preUpdate],
|
||||
$replacement
|
||||
);
|
||||
}
|
||||
|
||||
public function _after() {
|
||||
parent::_after();
|
||||
$this->truncateEntity(FormEntity::class);
|
||||
}
|
||||
}
|
@@ -5,9 +5,11 @@ namespace MailPoet\Test\Doctrine\EventListeners;
|
||||
use MailPoet\Doctrine\Annotations\AnnotationReaderProvider;
|
||||
use MailPoet\Doctrine\ConfigurationFactory;
|
||||
use MailPoet\Doctrine\EntityManagerFactory;
|
||||
use MailPoet\Doctrine\EventListeners\EmojiEncodingListener;
|
||||
use MailPoet\Doctrine\EventListeners\TimestampListener;
|
||||
use MailPoet\Doctrine\EventListeners\ValidationListener;
|
||||
use MailPoet\Doctrine\Validator\ValidatorFactory;
|
||||
use MailPoet\WP\Emoji;
|
||||
use MailPoet\WP\Functions as WPFunctions;
|
||||
use MailPoetVendor\Carbon\Carbon;
|
||||
use MailPoetVendor\Doctrine\Common\Cache\ArrayCache;
|
||||
@@ -91,7 +93,8 @@ class TimestampListenerTest extends \MailPoetTest {
|
||||
$validatorFactory = new ValidatorFactory($annotationReaderProvider);
|
||||
$timestampListener = new TimestampListener($this->wp);
|
||||
$validationListener = new ValidationListener($validatorFactory->createValidator());
|
||||
$entityManagerFactory = new EntityManagerFactory($this->connection, $configuration, $timestampListener, $validationListener);
|
||||
$emojiEncodingListener = new EmojiEncodingListener(new Emoji($this->wp));
|
||||
$entityManagerFactory = new EntityManagerFactory($this->connection, $configuration, $timestampListener, $validationListener, $emojiEncodingListener);
|
||||
return $entityManagerFactory->createEntityManager();
|
||||
}
|
||||
}
|
||||
|
@@ -5,10 +5,12 @@ namespace MailPoet\Test\Doctrine\EventListeners;
|
||||
use MailPoet\Doctrine\Annotations\AnnotationReaderProvider;
|
||||
use MailPoet\Doctrine\ConfigurationFactory;
|
||||
use MailPoet\Doctrine\EntityManagerFactory;
|
||||
use MailPoet\Doctrine\EventListeners\EmojiEncodingListener;
|
||||
use MailPoet\Doctrine\EventListeners\TimestampListener;
|
||||
use MailPoet\Doctrine\EventListeners\ValidationListener;
|
||||
use MailPoet\Doctrine\Validator\ValidationException;
|
||||
use MailPoet\Doctrine\Validator\ValidatorFactory;
|
||||
use MailPoet\WP\Emoji;
|
||||
use MailPoet\WP\Functions as WPFunctions;
|
||||
use MailPoetVendor\Doctrine\Common\Cache\ArrayCache;
|
||||
|
||||
@@ -75,7 +77,8 @@ class ValidationTest extends \MailPoetTest {
|
||||
$validatorFactory = new ValidatorFactory($annotationReaderProvider);
|
||||
$timestampListener = new TimestampListener($this->wp);
|
||||
$validationListener = new ValidationListener($validatorFactory->createValidator());
|
||||
$entityManagerFactory = new EntityManagerFactory($this->connection, $configuration, $timestampListener, $validationListener);
|
||||
$emojiEncodingListener = new EmojiEncodingListener(new Emoji($this->wp));
|
||||
$entityManagerFactory = new EntityManagerFactory($this->connection, $configuration, $timestampListener, $validationListener, $emojiEncodingListener);
|
||||
return $entityManagerFactory->createEntityManager();
|
||||
}
|
||||
}
|
||||
|
@@ -6,10 +6,12 @@ use Exception;
|
||||
use MailPoet\Doctrine\Annotations\AnnotationReaderProvider;
|
||||
use MailPoet\Doctrine\ConfigurationFactory;
|
||||
use MailPoet\Doctrine\EntityManagerFactory;
|
||||
use MailPoet\Doctrine\EventListeners\EmojiEncodingListener;
|
||||
use MailPoet\Doctrine\EventListeners\TimestampListener;
|
||||
use MailPoet\Doctrine\EventListeners\ValidationListener;
|
||||
use MailPoet\Doctrine\Validator\ValidatorFactory;
|
||||
use MailPoet\Test\Doctrine\Types\JsonEntity;
|
||||
use MailPoet\WP\Emoji;
|
||||
use MailPoet\WP\Functions as WPFunctions;
|
||||
use MailPoetVendor\Doctrine\Common\Cache\ArrayCache;
|
||||
use RuntimeException;
|
||||
@@ -183,7 +185,8 @@ class JsonTypesTest extends \MailPoetTest {
|
||||
$validatorFactory = new ValidatorFactory($annotationReaderProvider);
|
||||
$timestampListener = new TimestampListener($this->wp);
|
||||
$validationListener = new ValidationListener($validatorFactory->createValidator());
|
||||
$entityManagerFactory = new EntityManagerFactory($this->connection, $configuration, $timestampListener, $validationListener);
|
||||
$emojiEncodingListener = new EmojiEncodingListener(new Emoji($this->wp));
|
||||
$entityManagerFactory = new EntityManagerFactory($this->connection, $configuration, $timestampListener, $validationListener, $emojiEncodingListener);
|
||||
return $entityManagerFactory->createEntityManager();
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user