Dispatcher::dispatchClass()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 8
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 3
dl 0
loc 8
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 2
1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * This file is part of the Valkyrja Framework package.
7
 *
8
 * (c) Melech Mizrachi <[email protected]>
9
 *
10
 * For the full copyright and license information, please view the LICENSE
11
 * file that was distributed with this source code.
12
 */
13
14
namespace Valkyrja\Dispatcher;
15
16
use Override;
0 ignored issues
show
Bug introduced by
The type Override was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
17
use Valkyrja\Container\Contract\Container;
18
use Valkyrja\Dispatcher\Contract\Dispatcher as Contract;
19
use Valkyrja\Dispatcher\Data\CallableDispatch;
20
use Valkyrja\Dispatcher\Data\ClassDispatch;
21
use Valkyrja\Dispatcher\Data\ConstantDispatch;
22
use Valkyrja\Dispatcher\Data\Contract\Dispatch;
23
use Valkyrja\Dispatcher\Data\GlobalVariableDispatch;
24
use Valkyrja\Dispatcher\Data\MethodDispatch;
25
use Valkyrja\Dispatcher\Data\PropertyDispatch;
26
use Valkyrja\Dispatcher\Exception\InvalidArgumentException;
27
28
use function array_map;
29
use function constant;
30
31
/**
32
 * Class Dispatcher.
33
 *
34
 * @author Melech Mizrachi
35
 */
36
class Dispatcher implements Contract
37
{
38
    /**
39
     * Dispatcher constructor.
40
     *
41
     * @param Container $container The container
42
     */
43
    public function __construct(
44
        protected Container $container = new \Valkyrja\Container\Container()
45
    ) {
46
    }
47
48
    /**
49
     * @inheritDoc
50
     */
51
    #[Override]
52
    public function dispatch(Dispatch $dispatch, array|null $arguments = null): mixed
53
    {
54
        return match (true) {
55
            $dispatch instanceof MethodDispatch         => $this->dispatchClassMethod($dispatch, $arguments),
56
            $dispatch instanceof PropertyDispatch       => $this->dispatchClassProperty($dispatch),
57
            $dispatch instanceof ConstantDispatch       => $this->dispatchConstant($dispatch),
58
            $dispatch instanceof ClassDispatch          => $this->dispatchClass($dispatch, $arguments),
59
            $dispatch instanceof CallableDispatch       => $this->dispatchCallable($dispatch, $arguments),
60
            $dispatch instanceof GlobalVariableDispatch => $this->dispatchVariable($dispatch),
61
            default                                     => throw new InvalidArgumentException('Invalid dispatch'),
62
        };
63
    }
64
65
    /**
66
     * Dispatch a class method.
67
     *
68
     * @param MethodDispatch               $dispatch  The dispatch
69
     * @param array<array-key, mixed>|null $arguments The arguments
0 ignored issues
show
Documentation Bug introduced by
The doc comment array<array-key, mixed>|null at position 2 could not be parsed: Unknown type name 'array-key' at position 2 in array<array-key, mixed>|null.
Loading history...
70
     *
71
     * @return mixed
72
     */
73
    protected function dispatchClassMethod(MethodDispatch $dispatch, array|null $arguments = null): mixed
74
    {
75
        $method = $dispatch->getMethod();
76
        // Get the arguments with dependencies
77
        $arguments = $this->getArguments($dispatch, $arguments) ?? [];
78
        // Get the class
79
        $class = $dispatch->getClass();
80
        /**
81
         * @psalm-suppress MixedMethodCall The developer should have passed the proper arguments
82
         *
83
         * @var mixed $response
84
         */
85
        $response = $dispatch->isStatic()
86
            ? $class::$method(...$arguments)
87
            : $this->container->get($class)->$method(...$arguments);
88
89
        return $response;
90
    }
91
92
    /**
93
     * Dispatch a class property.
94
     *
95
     * @param PropertyDispatch $dispatch The dispatch
96
     *
97
     * @return mixed
98
     */
99
    protected function dispatchClassProperty(PropertyDispatch $dispatch): mixed
100
    {
101
        $property = $dispatch->getProperty();
102
        // Get the class
103
        $class = $dispatch->getClass();
104
        /** @var mixed $response */
105
        $response = $dispatch->isStatic()
106
            ? $class::$$property
107
            : $this->container->get($class)->{$property};
108
109
        return $response;
110
    }
111
112
    /**
113
     * Dispatch a constant.
114
     *
115
     * @param ConstantDispatch $dispatch The dispatch
116
     *
117
     * @return mixed
118
     */
119
    protected function dispatchConstant(ConstantDispatch $dispatch): mixed
120
    {
121
        $constant = $dispatch->getConstant();
122
        $constant = ($class = $dispatch->getClass())
123
            ? $class . '::' . $constant
124
            : $constant;
125
126
        return constant($constant);
127
    }
128
129
    /**
130
     * Dispatch a class.
131
     *
132
     * @param ClassDispatch                $dispatch  The dispatch
133
     * @param array<array-key, mixed>|null $arguments The arguments
0 ignored issues
show
Documentation Bug introduced by
The doc comment array<array-key, mixed>|null at position 2 could not be parsed: Unknown type name 'array-key' at position 2 in array<array-key, mixed>|null.
Loading history...
134
     *
135
     * @return mixed
136
     */
137
    protected function dispatchClass(ClassDispatch $dispatch, array|null $arguments = null): mixed
138
    {
139
        $className = $dispatch->getClass();
140
        // Get the arguments with dependencies
141
        $arguments = $this->getArguments($dispatch, $arguments) ?? [];
142
143
        // Get the class through the container
144
        return $this->container->get($className, $arguments);
145
    }
146
147
    /**
148
     * Dispatch a function.
149
     *
150
     * @param CallableDispatch             $dispatch  The dispatch
151
     * @param array<array-key, mixed>|null $arguments The arguments
0 ignored issues
show
Documentation Bug introduced by
The doc comment array<array-key, mixed>|null at position 2 could not be parsed: Unknown type name 'array-key' at position 2 in array<array-key, mixed>|null.
Loading history...
152
     *
153
     * @return mixed
154
     */
155
    protected function dispatchCallable(CallableDispatch $dispatch, array|null $arguments = null): mixed
156
    {
157
        $callable = $dispatch->getCallable();
158
        // Get the arguments with dependencies
159
        $arguments = $this->getArguments($dispatch, $arguments) ?? [];
160
161
        return $callable(...$arguments);
162
    }
163
164
    /**
165
     * Dispatch a variable.
166
     *
167
     * @param GlobalVariableDispatch $dispatch The dispatch
168
     *
169
     * @return mixed
170
     */
171
    protected function dispatchVariable(GlobalVariableDispatch $dispatch): mixed
172
    {
173
        $variable = $dispatch->getVariable();
174
175
        global $$variable;
176
177
        return $$variable;
178
    }
179
180
    /**
181
     * Get a dispatch's arguments.
182
     *
183
     * @param CallableDispatch|ClassDispatch|MethodDispatch $dispatch  The dispatch
184
     * @param array<array-key, mixed>|null                  $arguments [optional] The arguments
0 ignored issues
show
Documentation Bug introduced by
The doc comment array<array-key, mixed>|null at position 2 could not be parsed: Unknown type name 'array-key' at position 2 in array<array-key, mixed>|null.
Loading history...
185
     *
186
     * @return array<array-key, mixed>|null
0 ignored issues
show
Documentation Bug introduced by
The doc comment array<array-key, mixed>|null at position 2 could not be parsed: Unknown type name 'array-key' at position 2 in array<array-key, mixed>|null.
Loading history...
187
     */
188
    protected function getArguments(CallableDispatch|ClassDispatch|MethodDispatch $dispatch, array|null $arguments = null): array|null
189
    {
190
        // Get either the arguments passed or from the dispatch model
191
        $arguments ??= $dispatch->getArguments();
192
193
        // Set the listener arguments to a new blank array
194
        $dependencies = $this->getDependencies($dispatch);
195
196
        // If there are no arguments
197
        if ($arguments === null) {
198
            // Return the dependencies only
199
            return $dependencies;
200
        }
201
202
        // Iterate through the arguments
203
        /** @var mixed $argument */
204
        foreach ($arguments as $argument) {
205
            // Append the argument to the arguments list
206
            /** @psalm-suppress MixedAssignment */
207
            $dependencies[] = $this->getArgumentValue($argument);
208
        }
209
210
        return $dependencies;
211
    }
212
213
    /**
214
     * Get a dispatch's dependencies.
215
     *
216
     * @param CallableDispatch|ClassDispatch|MethodDispatch $dispatch The dispatch
217
     *
218
     * @return array<array-key, mixed>
0 ignored issues
show
Documentation Bug introduced by
The doc comment array<array-key, mixed> at position 2 could not be parsed: Unknown type name 'array-key' at position 2 in array<array-key, mixed>.
Loading history...
219
     */
220
    protected function getDependencies(CallableDispatch|ClassDispatch|MethodDispatch $dispatch): array
221
    {
222
        // If there are dependencies
223
        if (($dependencies = $dispatch->getDependencies()) === null) {
224
            return [];
225
        }
226
227
        // $context = match (true) {
228
        //     $dispatch instanceof ClassDispatch    => $dispatch->getClass(),
229
        //     $dispatch instanceof CallableDispatch => is_array($callable = $dispatch->getCallable()) && is_string($callable[0])
230
        //         ? $callable[0]
231
        //         : null,
232
        // };
233
        // $member  = match (true) {
234
        //     $dispatch instanceof MethodDispatch   => $dispatch->getMethod(),
235
        //     $dispatch instanceof CallableDispatch => is_array($callable = $dispatch->getCallable()) && is_string($callable[1])
236
        //         ? $callable[1]
237
        //         : null,
238
        //     default                               => null
239
        // };
240
241
        // $containerContext = null;
242
243
        $container = $this->container;
244
        // $hasContext = $context !== null && $container instanceof ContextAwareContainer;
245
        //
246
        // if ($hasContext) {
247
        //     /** @var ContextAwareContainer $container */
248
        //     $containerContext = $container->withContext($context, $member);
249
        // }
250
251
        return array_map(
252
            /** @param class-string $dependency */
0 ignored issues
show
Documentation Bug introduced by
The doc comment class-string at position 0 could not be parsed: Unknown type name 'class-string' at position 0 in class-string.
Loading history...
253
            // static fn (string $dependency): mixed => $containerContext !== null && $containerContext->has($dependency)
254
            //     ? $containerContext->get($dependency)
255
            //     : $container->get($dependency),
256
            static fn (string $dependency): mixed => $container->get($dependency),
257
            $dependencies
258
        );
259
    }
260
261
    /**
262
     * Get argument value.
263
     *
264
     * @param mixed $argument The argument
265
     *
266
     * @return mixed
267
     */
268
    protected function getArgumentValue(mixed $argument): mixed
269
    {
270
        if ($argument instanceof Dispatch) {
271
            /** @var mixed $argument */
272
            // Dispatch the argument and set the results to the argument
273
            $argument = $this->dispatch($argument);
274
        }
275
276
        return $argument;
277
    }
278
}
279