Pass a copy of the Carbon object to avoid unexpected side effects
This commit changes TimestampListener to pass a copy of the Carbon object representing the current time to the entity properties updatedAt and createdAt. Passing a copy instead of the object itself is needed to avoid unexpected side effects. Before this change, modifying the time of the createdAt or updatedAt field of a given entity could affect the same field of another entity as it could be the same object used inside TimestampListener for all entities. [MAILPOET-3870]
This commit is contained in:
@@ -27,11 +27,11 @@ class TimestampListener {
|
||||
&& method_exists($entity, 'getCreatedAt')
|
||||
&& !$entity->getCreatedAt()
|
||||
) {
|
||||
$entity->setCreatedAt($this->now);
|
||||
$entity->setCreatedAt($this->now->copy());
|
||||
}
|
||||
|
||||
if (in_array(UpdatedAtTrait::class, $entityTraits, true) && method_exists($entity, 'setUpdatedAt')) {
|
||||
$entity->setUpdatedAt($this->now);
|
||||
$entity->setUpdatedAt($this->now->copy());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@ class TimestampListener {
|
||||
$entityTraits = $this->getEntityTraits($entity);
|
||||
|
||||
if (in_array(UpdatedAtTrait::class, $entityTraits, true) && method_exists($entity, 'setUpdatedAt')) {
|
||||
$entity->setUpdatedAt($this->now);
|
||||
$entity->setUpdatedAt($this->now->copy());
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -72,6 +72,26 @@ class TimestampListenerTest extends \MailPoetTest {
|
||||
expect($entity->getUpdatedAt())->equals($this->now);
|
||||
}
|
||||
|
||||
public function testItUsesDifferentTimesWhenCreatingDifferentEntities() {
|
||||
$entity1 = new TimestampEntity();
|
||||
$entity1->setName('Entity 1');
|
||||
|
||||
$this->entityManager->persist($entity1);
|
||||
$this->entityManager->flush();
|
||||
|
||||
$createdAt1 = $entity1->getCreatedAt();
|
||||
$this->assertInstanceOf(Carbon::class, $createdAt1);
|
||||
$createdAt1->subMonth();
|
||||
|
||||
$entity2 = new TimestampEntity();
|
||||
$entity2->setName('Entity 2');
|
||||
|
||||
$this->entityManager->persist($entity2);
|
||||
$this->entityManager->flush();
|
||||
|
||||
$this->assertEquals($this->now, $entity2->getCreatedAt());
|
||||
}
|
||||
|
||||
public function _after() {
|
||||
parent::_after();
|
||||
$this->connection->executeStatement("DROP TABLE IF EXISTS $this->tableName");
|
||||
|
Reference in New Issue
Block a user