From 895734d8e5903fd095ab61ed4a8a7c33ee2e8297 Mon Sep 17 00:00:00 2001 From: roxblnfk Date: Sat, 20 Jan 2024 23:43:43 +0400 Subject: [PATCH] Add AttributeReader helper and TaskQueue attribute --- src/Attribute/TaskQueue.php | 17 ++++ src/Internal/AttributeReader.php | 91 +++++++++++++++++++ src/Stub/ClientFactory.php | 2 +- src/Stub/WorkflowFactory.php | 2 +- tests/Stub/Attributed/AbstractAttributed.php | 12 +++ tests/Stub/Attributed/ExtendedAttributed.php | 12 +++ tests/Stub/Attributed/InterfaceAttributed.php | 12 +++ .../Attributed/ParentInterfaceAttributed.php | 12 +++ .../ParentParentInterfaceAttributed.php | 12 +++ tests/Stub/Attributed/SimpleClass.php | 12 +++ tests/Unit/Internal/AttributeReaderTest.php | 66 ++++++++++++++ 11 files changed, 248 insertions(+), 2 deletions(-) create mode 100644 src/Attribute/TaskQueue.php create mode 100644 src/Internal/AttributeReader.php create mode 100644 tests/Stub/Attributed/AbstractAttributed.php create mode 100644 tests/Stub/Attributed/ExtendedAttributed.php create mode 100644 tests/Stub/Attributed/InterfaceAttributed.php create mode 100644 tests/Stub/Attributed/ParentInterfaceAttributed.php create mode 100644 tests/Stub/Attributed/ParentParentInterfaceAttributed.php create mode 100644 tests/Stub/Attributed/SimpleClass.php create mode 100644 tests/Unit/Internal/AttributeReaderTest.php diff --git a/src/Attribute/TaskQueue.php b/src/Attribute/TaskQueue.php new file mode 100644 index 0000000..45df2e5 --- /dev/null +++ b/src/Attribute/TaskQueue.php @@ -0,0 +1,17 @@ + $attributes + * + * @return array> + */ + public static function fromClass( + string $class, + array $attributes, + bool $merge = true, + bool $inheritance = true, + bool $interfaces = true, + ): array { + $reflection = new \ReflectionClass($class); + if ($reflection->isInternal()) { + return []; + } + + /** @var array>> $cache */ + static $cache = []; + + $result = $cache[$class] ?? self::initAttributes($reflection, $attributes); + + if (!$inheritance) { + return $result; + } + + if ($parent = $reflection->getParentClass()) { + $attrs = self::fromClass($parent->getName(), $attributes, $merge, true, false); + $result = $merge + ? \array_merge_recursive($result, $attrs) + : $result + $attrs; + } + + if (!$interfaces) { + return $result; + } + + foreach (self::sortInterfaces($reflection) as $interface) { + $attrs = self::fromClass($interface, $attributes, $merge, false, false); + $result = $merge + ? \array_merge_recursive($result, $attrs) + : $result + $attrs; + } + + return $result; + } + + /** + * @param \ReflectionClass $reflection + * @param array $filter + * @return array> + */ + private static function initAttributes(\ReflectionClass $reflection, array $filter): array + { + $result = []; + foreach ($reflection->getAttributes() as $attribute) { + $instance = $attribute->newInstance(); + foreach ($filter as $attributeClass) { + if ($instance instanceof $attributeClass) { + $result[$attributeClass][] = $instance; + } + } + } + + return $result; + } + + private static function sortInterfaces(\ReflectionClass $class): array + { + $result = []; + foreach ($class->getInterfaces() as $reflection) { + $result[$reflection->getName()] = \count($reflection->getInterfaces()); + } + + \arsort($result); + + return \array_keys($result); + } +} diff --git a/src/Stub/ClientFactory.php b/src/Stub/ClientFactory.php index f5207ac..6c6c939 100644 --- a/src/Stub/ClientFactory.php +++ b/src/Stub/ClientFactory.php @@ -105,7 +105,7 @@ public static function workflow( // Timeouts $executionTimeout === 0 or $options = $options->withWorkflowExecutionTimeout($executionTimeout); $runTimeout === 0 or $options = $options->withWorkflowRunTimeout($executionTimeout); - $taskTimeout > 10 and $options = $options->withWorkflowTaskTimeout(\max(60, $taskTimeout)); + $taskTimeout !== 10 and $options = $options->withWorkflowTaskTimeout(\max(60, $taskTimeout)); // Workflow ID $workflowId === null or $options = $options->withWorkflowId((string)$workflowId); $workflowIdReusePolicy === IdReusePolicy::Unspecified or $options = $options diff --git a/src/Stub/WorkflowFactory.php b/src/Stub/WorkflowFactory.php index c91eb27..371aafe 100644 --- a/src/Stub/WorkflowFactory.php +++ b/src/Stub/WorkflowFactory.php @@ -109,7 +109,7 @@ public static function childWorkflow( // Timeouts $executionTimeout === 0 or $options = $options->withWorkflowExecutionTimeout($executionTimeout); $runTimeout === 0 or $options = $options->withWorkflowRunTimeout($executionTimeout); - $taskTimeout > 10 and $options = $options->withWorkflowTaskTimeout(\max(60, $taskTimeout)); + $taskTimeout !== 10 and $options = $options->withWorkflowTaskTimeout(\max(60, $taskTimeout)); // Workflow ID $workflowId === null or $options = $options->withWorkflowId((string)$workflowId); $workflowIdReusePolicy === IdReusePolicy::Unspecified or $options = $options diff --git a/tests/Stub/Attributed/AbstractAttributed.php b/tests/Stub/Attributed/AbstractAttributed.php new file mode 100644 index 0000000..9d1c220 --- /dev/null +++ b/tests/Stub/Attributed/AbstractAttributed.php @@ -0,0 +1,12 @@ +assertArrayHasKey(TaskQueue::class, $result); + $this->assertIsArray($result[TaskQueue::class]); + $this->assertCount(1, $result[TaskQueue::class]); + $this->assertInstanceOf(TaskQueue::class, $result[TaskQueue::class][0]); + $this->assertEquals('test-queue', $result[TaskQueue::class][0]->name); + } + + public function testFromExtendedClassWithInheritanceWithMerge(): void + { + $result = AttributeReader::fromClass( + \Temporal\Sugar\Tests\Stub\Attributed\ExtendedAttributed::class, + [TaskQueue::class], + merge: true, + ); + + $this->assertArrayHasKey(TaskQueue::class, $result); + $this->assertIsArray($result[TaskQueue::class]); + $this->assertCount(5, $result[TaskQueue::class]); + $this->assertInstanceOf(TaskQueue::class, $result[TaskQueue::class][0]); + $this->assertInstanceOf(TaskQueue::class, $result[TaskQueue::class][1]); + $this->assertInstanceOf(TaskQueue::class, $result[TaskQueue::class][3]); + $this->assertEquals('test-queue-extended', $result[TaskQueue::class][0]->name); + $this->assertEquals('test-queue-abstract', $result[TaskQueue::class][1]->name); + $this->assertEquals('test-queue-interface', $result[TaskQueue::class][2]->name); + $this->assertEquals('test-queue-parent-interface', $result[TaskQueue::class][3]->name); + $this->assertEquals('test-queue-parent-parent-interface', $result[TaskQueue::class][4]->name); + } + + public function testFromInterfaceWithInheritance(): void + { + $result = AttributeReader::fromClass( + \Temporal\Sugar\Tests\Stub\Attributed\InterfaceAttributed::class, + [TaskQueue::class], + merge: true, + ); + + $this->assertArrayHasKey(TaskQueue::class, $result); + $this->assertIsArray($result[TaskQueue::class]); + $this->assertCount(3, $result[TaskQueue::class]); + $this->assertInstanceOf(TaskQueue::class, $result[TaskQueue::class][0]); + $this->assertInstanceOf(TaskQueue::class, $result[TaskQueue::class][1]); + $this->assertInstanceOf(TaskQueue::class, $result[TaskQueue::class][2]); + $this->assertEquals('test-queue-interface', $result[TaskQueue::class][0]->name); + $this->assertEquals('test-queue-parent-interface', $result[TaskQueue::class][1]->name); + $this->assertEquals('test-queue-parent-parent-interface', $result[TaskQueue::class][2]->name); + } +}