diff --git a/src/Tags.php b/src/Tags.php index 99a5d366..6684ec05 100644 --- a/src/Tags.php +++ b/src/Tags.php @@ -9,6 +9,7 @@ use Illuminate\Mail\SendQueuedMailable; use Illuminate\Notifications\SendQueuedNotifications; use ReflectionClass; +use ReflectionProperty; use stdClass; class Tags @@ -107,7 +108,7 @@ public static function modelsFor(array $targets) $models[] = collect((new ReflectionClass($target))->getProperties())->map(function ($property) use ($target) { $property->setAccessible(true); - $value = $property->getValue($target); + $value = static::getValue($property, $target); if ($value instanceof Model) { return [$value]; @@ -120,6 +121,17 @@ public static function modelsFor(array $targets) return collect($models)->collapse()->unique(); } + protected static function getValue(ReflectionProperty $property, $target) + { + if (method_exists($property, 'isInitialized')) { + if (! $property->isInitialized($target)) { + return; + } + } + + return $property->getValue($target); + } + /** * Extract the listener from a queued job. * diff --git a/tests/Unit/Fixtures/FakeListenerWithProperties.php b/tests/Unit/Fixtures/FakeListenerWithProperties.php new file mode 100644 index 00000000..b8e54238 --- /dev/null +++ b/tests/Unit/Fixtures/FakeListenerWithProperties.php @@ -0,0 +1,28 @@ +dispatcher = $dispatcher; + } + + public function handle(FakeEventWithModel $fakeEventWithModel): void + { + $this->fakeModel = $fakeEventWithModel->model; + } +} diff --git a/tests/Unit/Fixtures/FakeListenerWithTypedProperties.php b/tests/Unit/Fixtures/FakeListenerWithTypedProperties.php new file mode 100644 index 00000000..5062dddc --- /dev/null +++ b/tests/Unit/Fixtures/FakeListenerWithTypedProperties.php @@ -0,0 +1,22 @@ +dispatcher = $dispatcher; + } + + public function handle(FakeEventWithModel $fakeEventWithModel): void + { + $this->fakeModel = $fakeEventWithModel->model; + } +} diff --git a/tests/Unit/RedisPayloadTest.php b/tests/Unit/RedisPayloadTest.php index b6b04dfc..57095578 100644 --- a/tests/Unit/RedisPayloadTest.php +++ b/tests/Unit/RedisPayloadTest.php @@ -15,6 +15,8 @@ use Laravel\Horizon\Tests\Unit\Fixtures\FakeJobWithEloquentModel; use Laravel\Horizon\Tests\Unit\Fixtures\FakeJobWithTagsMethod; use Laravel\Horizon\Tests\Unit\Fixtures\FakeListener; +use Laravel\Horizon\Tests\Unit\Fixtures\FakeListenerWithProperties; +use Laravel\Horizon\Tests\Unit\Fixtures\FakeListenerWithTypedProperties; use Laravel\Horizon\Tests\Unit\Fixtures\FakeModel; use Laravel\Horizon\Tests\UnitTest; use Mockery; @@ -94,6 +96,31 @@ public function test_tags_are_correctly_extracted_for_listeners() ], $JobPayload->decoded['tags']); } + public function test_tags_are_correctly_determined_for_listeners() + { + $JobPayload = new JobPayload(json_encode(['id' => 1])); + + $job = new CallQueuedListener(FakeListenerWithProperties::class, 'handle', [new FakeEventWithModel(42)]); + + $JobPayload->prepare($job); + + $this->assertEquals([FakeModel::class.':42'], $JobPayload->decoded['tags']); + } + + /** + * @requires PHP 7.4 + */ + public function test_tags_are_correctly_determined_for_listeners_with_property_types() + { + $JobPayload = new JobPayload(json_encode(['id' => 1])); + + $job = new CallQueuedListener(FakeListenerWithTypedProperties::class, 'handle', [new FakeEventWithModel(21)]); + + $JobPayload->prepare($job); + + $this->assertEquals([FakeModel::class.':21'], $JobPayload->decoded['tags']); + } + public function test_listener_and_event_tags_can_merge_auto_tag_events() { $JobPayload = new JobPayload(json_encode(['id' => 1]));