Repository: pheature-flags/pheature-flags (php)

Issue:
[toggle-core] ChainTogleStrategyFactory must implement ToggleStrategyFactory interface
**Epic:** https://github.com/pheature-flags/pheature-flags/issues/1 Toggle Core
**Package:** https://github.com/pheature-flags/toggle-core 

**Description:**

At the current time, the ChainTogleStrategyFactory class doesn't fit any contract, it must implement the ToggleStrategyFactory interface.

Pull request:
[#219] update chain toggle strategy factory to fit strategy factory contract
closes #219 

Patch:
diff --git a/packages/toggle-core/src/Read/ChainToggleStrategyFactory.php b/packages/toggle-core/src/Read/ChainToggleStrategyFactory.php
index e7c9aa7..3715276 100644
--- a/packages/toggle-core/src/Read/ChainToggleStrategyFactory.php
+++ b/packages/toggle-core/src/Read/ChainToggleStrategyFactory.php
@@ -6,7 +6,11 @@ namespace Pheature\Core\Toggle\Read;
 
 use Pheature\Core\Toggle\Exception\InvalidStrategyTypeGiven;
 
-final class ChainToggleStrategyFactory
+use function array_map;
+use function array_merge;
+use function in_array;
+
+final class ChainToggleStrategyFactory implements ToggleStrategyFactory
 {
     private SegmentFactory $segmentFactory;
     /** @var ToggleStrategyFactory[] */
@@ -31,32 +35,8 @@ final class ChainToggleStrategyFactory
         /** @var string $strategyType */
         $strategyType = $strategy['strategy_type'];
 
-        foreach ($this->toggleStrategyFactories as $toggleStrategyFactory) {
-            if (in_array($strategy['strategy_type'], $toggleStrategyFactory->types(), true)) {
-                return $this->makeStrategy($toggleStrategyFactory, $strategyId, $strategyType, $segments);
-            }
-        }
-
-        throw InvalidStrategyTypeGiven::withType($strategyType);
-    }
-
-    /**
-     * @param ToggleStrategyFactory $toggleStrategyFactory
-     * @param string $strategyId
-     * @param string $strategyType
-     * @param array<array<string, string|array<string, mixed>>> $segments
-     * @return ToggleStrategy
-     */
-    private function makeStrategy(
-        ToggleStrategyFactory $toggleStrategyFactory,
-        string $strategyId,
-        string $strategyType,
-        array $segments
-    ): ToggleStrategy {
-        return $toggleStrategyFactory->create(
-            $strategyId,
-            $strategyType,
-            new Segments(...array_map(function (array $segment) {
+        return $this->create($strategyId, $strategyType, new Segments(...array_map(
+            function (array $segment) {
                 /** @var string $segmentId */
                 $segmentId = $segment['segment_id'];
                 /** @var string $segmentType */
@@ -65,7 +45,29 @@ final class ChainToggleStrategyFactory
                 $criteria = $segment['criteria'];
 
                 return $this->segmentFactory->create($segmentId, $segmentType, $criteria);
-            }, $segments))
+            },
+            $segments
+        )));
+    }
+
+    public function create(string $strategyId, string $strategyType, ?Segments $segments = null): ToggleStrategy
+    {
+        foreach ($this->toggleStrategyFactories as $toggleStrategyFactory) {
+            if (in_array($strategyType, $toggleStrategyFactory->types(), true)) {
+                return $toggleStrategyFactory->create($strategyId, $strategyType, $segments);
+            }
+        }
+
+        throw InvalidStrategyTypeGiven::withType($strategyType);
+    }
+
+    public function types(): array
+    {
+        return array_merge(
+            ...array_map(
+                static fn(ToggleStrategyFactory $strategyFactory) => $strategyFactory->types(),
+                $this->toggleStrategyFactories
+            )
         );
     }
 }


Test patch:
diff --git a/packages/toggle-core/test/Read/ChainToggleStrategyFactoryTest.php b/packages/toggle-core/test/Read/ChainToggleStrategyFactoryTest.php
index b10ffa8..9b0be7d 100644
--- a/packages/toggle-core/test/Read/ChainToggleStrategyFactoryTest.php
+++ b/packages/toggle-core/test/Read/ChainToggleStrategyFactoryTest.php
@@ -47,7 +47,7 @@ final class ChainToggleStrategyFactoryTest extends TestCase
     {
         $segmentFactory = $this->createMock(SegmentFactory::class);
         $toggleStrategyFactory = $this->createMock(ToggleStrategyFactory::class);
-        $toggleStrategyFactory->expects(self::once())
+        $toggleStrategyFactory->expects(self::atLeastOnce())
             ->method('types')
             ->willReturn([self::STRATEGY_TYPE]);
         $expectedStrategy = $this->createMock(ToggleStrategy::class);
@@ -64,6 +64,7 @@ final class ChainToggleStrategyFactoryTest extends TestCase
         ]);
 
         self::assertSame($expectedStrategy, $current);
+        self::assertSame([self::STRATEGY_TYPE], $chainToggleStrategyFactory->types());
     }
 
     public function testItShouldBeCreatedWithAtLeastOneToggleStrategyFactoryInstanceAndSegments(): void
@@ -74,9 +75,9 @@ final class ChainToggleStrategyFactoryTest extends TestCase
             ->with(self::SEGMENTS[0]['segment_id'], self::SEGMENTS[0]['segment_type'],self::SEGMENTS[0]['criteria'])
             ->willReturn($this->createMock(Segment::class));
         $toggleStrategyFactory = $this->createMock(ToggleStrategyFactory::class);
-        $toggleStrategyFactory->expects(self::once())
+        $toggleStrategyFactory->expects(self::atLeastOnce())
             ->method('types')
-            ->willReturn([self::STRATEGY_TYPE]);
+            ->willReturn([self::STRATEGY_TYPE, 'other_type']);
         $expectedStrategy = $this->createMock(ToggleStrategy::class);
         $toggleStrategyFactory->expects(self::once())
             ->method('create')
@@ -91,6 +92,7 @@ final class ChainToggleStrategyFactoryTest extends TestCase
         ]);
 
         self::assertSame($expectedStrategy, $current);
+        self::assertSame([self::STRATEGY_TYPE, 'other_type'], $chainToggleStrategyFactory->types());
     }
 }
     
\ No newline at end of file