DummyGenerator::handleAwareness()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 2

Importance

Changes 0
Metric Value
eloc 3
dl 0
loc 7
ccs 4
cts 4
cp 1
rs 10
c 0
b 0
f 0
cc 2
nc 2
nop 1
crap 2
1
<?php
2
3
declare(strict_types = 1);
4
5
namespace DummyGenerator;
6
7
use DummyGenerator\Container\DefinitionContainerBuilder;
8
use DummyGenerator\Container\DefinitionContainerInterface;
9
use DummyGenerator\Container\ResolvedDefinition;
10
use DummyGenerator\Definitions\DefinitionInterface;
11
use DummyGenerator\Definitions\Exception\DefinitionNotFound;
12
use DummyGenerator\Definitions\Extension\Awareness\GeneratorAwareExtensionInterface;
13
use DummyGenerator\Strategy\SimpleStrategy;
14
use DummyGenerator\Strategy\StrategyInterface;
15
16
class DummyGenerator
17
{
18
    /** @var array<string, ResolvedDefinition> */
19
    protected array $extensions = [];
20
    private DefinitionContainerInterface $container;
21
    private StrategyInterface $strategy;
22
23 152
    public function __construct(?DefinitionContainerInterface $container = null, ?StrategyInterface $strategy = null)
24
    {
25 152
        $this->container = $container ?: DefinitionContainerBuilder::base();
26 152
        $this->strategy = $strategy ?: new SimpleStrategy();
27
    }
28
29
    /**
30
     * Returns new Generator with given strategy and same extensions
31
     */
32 1
    public function withStrategy(StrategyInterface $strategy): self
33
    {
34 1
        return new self($this->container, $strategy);
35
    }
36
37 1
    public function usedStrategy(string $strategy): bool
38
    {
39 1
        return $this->strategy instanceof $strategy;
40
    }
41
42
    /**
43
     * Return extension stored in container with given ID
44
     *
45
     * @throws DefinitionNotFound
46
     */
47 7
    public function ext(string $id): DefinitionInterface
48
    {
49 7
        if (!$this->container->has($id)) {
50 1
            throw new DefinitionNotFound(sprintf(
51 1
                'No DummyGenerator definition with id "%s" was loaded.',
52 1
                $id,
53 1
            ));
54
        }
55
56 6
        $extension = $this->container->get($id);
57
58 6
        return $this->handleAwareness($extension);
59
    }
60
61
    /**
62
     * Add new definition
63
     *
64
     * @param DefinitionInterface|class-string<DefinitionInterface>|callable():DefinitionInterface $value
0 ignored issues
show
Documentation Bug introduced by
The doc comment DefinitionInterface|clas...e():DefinitionInterface at position 2 could not be parsed: Unknown type name 'class-string' at position 2 in DefinitionInterface|class-string<DefinitionInterface>|callable():DefinitionInterface.
Loading history...
65
     */
66 5
    public function addDefinition(string $name, callable|DefinitionInterface|string $value): void
67
    {
68 5
        $this->container->add($name, $value);
69
70 5
        $this->extensions = array_filter(
71 5
            $this->extensions,
72 5
            static fn (ResolvedDefinition $definition) => $definition->definitionId !== $name,
73 5
        );
74
    }
75
76
    /**
77
     * Replaces tokens ('{{ tokenName }}') in given string with the result from the token method call
78
     */
79 19
    public function parse(string $string): string
80
    {
81 19
        $callback = fn ($matches) => $this->process($matches[1]);
82
83 19
        $replaced = preg_replace_callback('/{{\s?(\w+|[\w\\\]+->\w+?)\s?}}/u', $callback, $string);
84
85 19
        return !empty($replaced) ? $replaced : '';
86
    }
87
88
    /**
89
     * @param array<int, mixed> $arguments
90
     *
91
     * Magic method used to load proper extension for given function name (like firstName) and it's parameters
92
     */
93 147
    public function __call(string $name, array $arguments): mixed
94
    {
95 147
        return $this->strategy->generate($name, fn () => $this->process($name, $arguments));
96
    }
97
98
    /**
99
     * @param array<int, mixed> $arguments
100
     *
101
     * Get Extension for given method name
102
     */
103 148
    protected function process(string $method, array $arguments = []): mixed
104
    {
105 148
        return $this->findProcessor($method)->$method(...$arguments);
106
    }
107
108
    /**
109
     * Return callable for given method
110
     */
111 148
    protected function findProcessor(string $method): DefinitionInterface
112
    {
113 148
        if (isset($this->extensions[$method])) {
114 13
            return $this->extensions[$method]->service;
115
        }
116
117 148
        $resolvedDefinition = $this->container->findProcessor($method);
118
119 148
        if ($resolvedDefinition !== null) {
120 148
            $extension = $this->handleAwareness($resolvedDefinition->service);
121
122 148
            $this->extensions[$method] = $resolvedDefinition->withService($extension);
123
124 148
            return $extension;
125
        }
126
127 2
        throw new \InvalidArgumentException(sprintf('Unknown method "%s"', $method));
128
    }
129
130 149
    private function handleAwareness(DefinitionInterface $extension): DefinitionInterface
131
    {
132 149
        if ($extension instanceof GeneratorAwareExtensionInterface) {
133 53
            $extension = $extension->withGenerator($this);
134
        }
135
136 149
        return $extension;
137
    }
138
}
139