1 | <?php |
||||
2 | declare(strict_types = 1); |
||||
3 | |||||
4 | namespace Innmind\Reflection\ExtractionStrategy; |
||||
5 | |||||
6 | use Innmind\Reflection\{ |
||||
7 | ExtractionStrategy, |
||||
8 | Exception\InvalidArgumentException, |
||||
9 | Exception\PropertyCannotBeExtracted, |
||||
10 | }; |
||||
11 | use Innmind\Immutable\{ |
||||
12 | Sequence, |
||||
13 | Map, |
||||
14 | }; |
||||
15 | |||||
16 | final class DelegationStrategy implements ExtractionStrategy |
||||
17 | { |
||||
18 | /** @var Sequence<ExtractionStrategy> */ |
||||
19 | private Sequence $strategies; |
||||
20 | /** @var Map<string, ExtractionStrategy> */ |
||||
21 | 7 | private Map $cache; |
|||
22 | |||||
23 | 7 | public function __construct(ExtractionStrategy ...$strategies) |
|||
24 | 7 | { |
|||
25 | 7 | /** @var Sequence<ExtractionStrategy> */ |
|||
26 | $this->strategies = Sequence::of(ExtractionStrategy::class, ...$strategies); |
||||
0 ignored issues
–
show
Bug
introduced
by
![]() |
|||||
27 | /** @var Map<string, ExtractionStrategy> */ |
||||
28 | $this->cache = Map::of('string', ExtractionStrategy::class); |
||||
0 ignored issues
–
show
|
|||||
29 | } |
||||
30 | 1 | ||||
31 | /** |
||||
32 | * {@inheritdoc} |
||||
33 | 1 | */ |
|||
34 | 1 | public function supports(object $object, string $property): bool |
|||
35 | 1 | { |
|||
36 | return $this |
||||
0 ignored issues
–
show
|
|||||
37 | 1 | ->strategies |
|||
38 | 1 | ->reduce( |
|||
39 | false, |
||||
0 ignored issues
–
show
false of type false is incompatible with the type Innmind\Immutable\R expected by parameter $carry of Innmind\Immutable\Sequence::reduce() .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
40 | static function(bool $supports, ExtractionStrategy $strategy) use ($object, $property): bool { |
||||
41 | return $supports || $strategy->supports($object, $property); |
||||
42 | }, |
||||
43 | ); |
||||
44 | } |
||||
45 | 6 | ||||
46 | /** |
||||
47 | 6 | * {@inheritdoc} |
|||
48 | */ |
||||
49 | 6 | public function extract(object $object, string $property) |
|||
50 | { |
||||
51 | 1 | $key = $this->generateKey($object, $property); |
|||
52 | 1 | ||||
53 | 1 | if ($this->cache->contains($key)) { |
|||
54 | return $this |
||||
55 | ->cache |
||||
56 | 6 | ->get($key) |
|||
57 | 6 | ->extract($object, $property); |
|||
58 | } |
||||
59 | 6 | ||||
60 | 6 | $strategy = $this->strategies->reduce( |
|||
61 | null, |
||||
62 | static function(?ExtractionStrategy $target, ExtractionStrategy $strategy) use ($object, $property): ?ExtractionStrategy { |
||||
63 | 6 | return $target ?? ($strategy->supports($object, $property) ? $strategy : null); |
|||
64 | 2 | }, |
|||
65 | ); |
||||
66 | |||||
67 | 4 | if (!$strategy instanceof ExtractionStrategy) { |
|||
68 | throw new PropertyCannotBeExtracted($property); |
||||
69 | 4 | } |
|||
70 | |||||
71 | $this->cache = ($this->cache)($key, $strategy); |
||||
72 | 6 | ||||
73 | return $strategy->extract($object, $property); |
||||
74 | 6 | } |
|||
75 | |||||
76 | private function generateKey(object $object, string $property): string |
||||
77 | { |
||||
78 | return \get_class($object).'::'.$property; |
||||
79 | } |
||||
80 | } |
||||
81 |