From c2391f88e5616e0930411a792b94ce787b2888bc Mon Sep 17 00:00:00 2001 From: Kevin Bond Date: Wed, 12 Jun 2024 11:33:04 -0400 Subject: [PATCH 1/2] bug: attributes added in `beforeInstantiate` are not passed to `afterPersist` --- .../GenericProxyFactoryTestCase.php | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/tests/Integration/Persistence/GenericProxyFactoryTestCase.php b/tests/Integration/Persistence/GenericProxyFactoryTestCase.php index e9597638..fe1f5afe 100644 --- a/tests/Integration/Persistence/GenericProxyFactoryTestCase.php +++ b/tests/Integration/Persistence/GenericProxyFactoryTestCase.php @@ -280,6 +280,27 @@ public function can_use_after_persist_with_attributes(): void $this->assertSame($value, $object->getProp1()); } + /** + * @test + */ + public function can_use_after_persist_with_attributes_added_in_before_instantiate(): void + { + $value = 'value set with before instantiate'; + $object = $this->factory() + ->instantiateWith(Instantiator::withConstructor()->allowExtra('extra')) + ->beforeInstantiate(function (array $attributes) use ($value) { + $attributes['extra'] = $value; + + return $attributes; + }) + ->afterPersist(function (GenericModel $object, array $attributes) { + $object->setProp1($attributes['extra']); + }) + ->create(); + + $this->assertSame($value, $object->getProp1()); + } + /** * @return PersistentProxyObjectFactory */ From 5e44ec89678e9498e7731767882d250338e276fb Mon Sep 17 00:00:00 2001 From: Nicolas PHILIPPE Date: Wed, 19 Jun 2024 16:38:56 +0200 Subject: [PATCH 2/2] fix: attributes added in are not passed to --- src/Factory.php | 31 +++++++++++++-------- src/Persistence/PersistentObjectFactory.php | 2 +- tests/Integration/ObjectFactoryTest.php | 16 +++++++++++ 3 files changed, 36 insertions(+), 13 deletions(-) diff --git a/src/Factory.php b/src/Factory.php index a11f1d80..8ef0e5b8 100644 --- a/src/Factory.php +++ b/src/Factory.php @@ -28,12 +28,19 @@ abstract class Factory /** @var Attributes[] */ private array $attributes; + /** + * Memoization of normalized parameters + * + * @internal + * @var Parameters|null + */ + protected array|null $normalizedParameters = null; + // keep an empty constructor for BC public function __construct() { } - /** * @param Attributes $attributes */ @@ -144,6 +151,16 @@ final protected static function faker(): Faker\Generator return Configuration::instance()->faker; } + /** + * Override to adjust default attributes & config. + * + * @return static + */ + protected function initialize(): static + { + return $this; + } + /** * @internal * @@ -170,16 +187,6 @@ final protected function normalizeAttributes(array|callable $attributes = []): a ); } - /** - * Override to adjust default attributes & config. - * - * @return static - */ - protected function initialize(): static - { - return $this; - } - /** * @internal * @@ -189,7 +196,7 @@ protected function initialize(): static */ protected function normalizeParameters(array $parameters): array { - return array_combine( + return $this->normalizedParameters = array_combine( array_keys($parameters), \array_map($this->normalizeParameter(...), array_keys($parameters), $parameters) ); diff --git a/src/Persistence/PersistentObjectFactory.php b/src/Persistence/PersistentObjectFactory.php index 2bd83ffd..eb54b175 100644 --- a/src/Persistence/PersistentObjectFactory.php +++ b/src/Persistence/PersistentObjectFactory.php @@ -226,7 +226,7 @@ final public function create(callable|array $attributes = []): object $this->tempAfterPersist = []; if ($this->afterPersist) { - $attributes = $this->normalizeAttributes($attributes); + $attributes = $this->normalizedParameters ?? throw new \LogicException('Factory::$normalizedParameters has not been initialized.'); foreach ($this->afterPersist as $callback) { $callback($object, $attributes); diff --git a/tests/Integration/ObjectFactoryTest.php b/tests/Integration/ObjectFactoryTest.php index 4dbaf095..96f3ca87 100644 --- a/tests/Integration/ObjectFactoryTest.php +++ b/tests/Integration/ObjectFactoryTest.php @@ -44,4 +44,20 @@ public function can_create_non_service_factories(): void $this->assertSame('router-constructor', $object->object->getProp1()); } + + /** + * @test + */ + public function can_create_different_objects_based_on_same_factory(): void + { + $factory = Object1Factory::new(['prop1' => 'first object']); + $object1 = $factory->create(); + self::assertSame('first object-constructor', $object1->getProp1()); + + $object2 = $factory->create(['prop1' => 'second object']); + self::assertSame('second object-constructor', $object2->getProp1()); + + $object3 = $factory->with(['prop1' => 'third object'])->create(); + self::assertSame('third object-constructor', $object3->getProp1()); + } }