CallableFactory   A
last analyzed

Complexity

Total Complexity 17

Size/Duplication

Total Lines 69
Duplicated Lines 0 %

Test Coverage

Coverage 96.67%

Importance

Changes 0
Metric Value
eloc 26
dl 0
loc 69
ccs 29
cts 30
cp 0.9667
rs 10
c 0
b 0
f 0
wmc 17

3 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 2 1
B create() 0 27 9
B fromDefinition() 0 22 7
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Queue\Middleware;
6
7
use Psr\Container\ContainerExceptionInterface;
8
use Psr\Container\ContainerInterface;
9
use Psr\Container\NotFoundExceptionInterface;
10
use ReflectionException;
11
use ReflectionMethod;
12
13
use function is_array;
14
use function is_callable;
15
use function is_string;
16
17
/**
18
 * @internal Create real callable listener from configuration.
19
 */
20
final class CallableFactory
21
{
22 98
    public function __construct(private ContainerInterface $container)
23
    {
24 98
    }
25
26
    /**
27
     * Create real callable listener from definition.
28
     *
29
     * @param mixed $definition Definition to create listener from.
30
     *
31
     * @throws InvalidCallableConfigurationException Failed to create listener.
32
     * @throws ContainerExceptionInterface Error while retrieving the entry from container.
33
     */
34 24
    public function create(mixed $definition): callable
35
    {
36 24
        $callable = null;
37
38 24
        if (is_string($definition) && $this->container->has($definition)) {
39
            // Object with an __invoke() method
40
            $callable = $this->container->get($definition);
41
        }
42
43 24
        if (is_array($definition)
44 24
            && array_keys($definition) === [0, 1]
45 24
            && is_string($definition[0])
46 24
            && is_string($definition[1])
47
        ) {
48 20
            [$className, $methodName] = $definition;
49 20
            $callable = $this->fromDefinition($className, $methodName);
50
        }
51
52 24
        if ($callable === null) {
53 10
            $callable = $definition;
54
        }
55
56 24
        if (is_callable($callable)) {
57 15
            return $callable;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $callable could return the type null which is incompatible with the type-hinted return callable. Consider adding an additional type-check to rule them out.
Loading history...
58
        }
59
60 9
        throw new InvalidCallableConfigurationException();
61
    }
62
63
    /**
64
     * @throws ContainerExceptionInterface Error while retrieving the entry from container.
65
     * @throws NotFoundExceptionInterface
66
     */
67 20
    private function fromDefinition(string $className, string $methodName): ?callable
68
    {
69 20
        $result = null;
70
71 20
        if (class_exists($className)) {
72
            try {
73 17
                $reflection = new ReflectionMethod($className, $methodName);
74 14
                if ($reflection->isStatic()) {
75 14
                    $result = [$className, $methodName];
76
                }
77 3
            } catch (ReflectionException) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
78
            }
79
        }
80
81 20
        if ($result === null && $this->container->has($className)) {
82 14
            $result = [
83 14
                $this->container->get($className),
84 14
                $methodName,
85 14
            ];
86
        }
87
88 20
        return is_callable($result) ? $result : null;
89
    }
90
}
91