Passed
Push — master ( 1a5091...509fe7 )
by Woody
01:46
created

FactoryLocator   A

Complexity

Total Complexity 10

Size/Duplication

Total Lines 86
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 46
dl 0
loc 86
rs 10
c 0
b 0
f 0
wmc 10

3 Methods

Rating   Name   Duplication   Size   Complexity  
A register() 0 11 3
A locate() 0 9 4
A unregister() 0 11 3
1
<?php
2
declare(strict_types=1);
3
4
namespace Http\Factory\Discovery;
5
6
use InvalidArgumentException;
7
use Psr\Http\Message\RequestFactoryInterface;
8
use Psr\Http\Message\ResponseFactoryInterface;
9
use Psr\Http\Message\ServerRequestFactoryInterface;
10
use Psr\Http\Message\StreamFactoryInterface;
11
use Psr\Http\Message\UploadedFileFactoryInterface;
12
use Psr\Http\Message\UriFactoryInterface;
13
use RuntimeException;
14
15
final class FactoryLocator
16
{
17
    /** @var array */
18
    private static $candidates = [
19
        RequestFactoryInterface::class => [
20
            'Http\Factory\Diactoros\RequestFactory',
21
            'Http\Factory\Guzzle\RequestFactory',
22
            'Http\Factory\Slim\RequestFactory',
23
            'Nyholm\Psr7\Factory\Psr17Factory',
24
        ],
25
        ResponseFactoryInterface::class => [
26
            'Http\Factory\Diactoros\ResponseFactory',
27
            'Http\Factory\Guzzle\ResponseFactory',
28
            'Http\Factory\Slim\ResponseFactory',
29
            'Nyholm\Psr7\Factory\Psr17Factory',
30
        ],
31
        ServerRequestFactoryInterface::class => [
32
            'Http\Factory\Diactoros\ServerRequestFactory',
33
            'Http\Factory\Guzzle\ServerRequestFactory',
34
            'Http\Factory\Slim\ServerRequestFactory',
35
            'Nyholm\Psr7\Factory\Psr17Factory',
36
        ],
37
        StreamFactoryInterface::class => [
38
            'Http\Factory\Diactoros\StreamFactory',
39
            'Http\Factory\Guzzle\StreamFactory',
40
            'Http\Factory\Slim\StreamFactory',
41
            'Nyholm\Psr7\Factory\Psr17Factory',
42
        ],
43
        UploadedFileFactoryInterface::class => [
44
            'Http\Factory\Diactoros\UploadedFileFactory',
45
            'Http\Factory\Guzzle\UploadedFileFactory',
46
            'Http\Factory\Slim\UploadedFileFactory',
47
            'Nyholm\Psr7\Factory\Psr17Factory',
48
        ],
49
        UriFactoryInterface::class => [
50
            'Http\Factory\Diactoros\UriFactory',
51
            'Http\Factory\Guzzle\UriFactory',
52
            'Http\Factory\Slim\UriFactory',
53
            'Nyholm\Psr7\Factory\Psr17Factory',
54
        ],
55
    ];
56
57
    /**
58
     * @throws RuntimeException If no implementation is available
59
     */
60
    public static function locate(string $factoryInterface): string
61
    {
62
        foreach (self::$candidates[$factoryInterface] ?? [] as $candidate) {
63
            if (class_exists($candidate) && is_a($candidate, $factoryInterface, true)) {
64
                return $candidate;
65
            }
66
        }
67
68
        throw new RuntimeException("$factoryInterface has no available implementations");
69
    }
70
71
    /**
72
     * @throws InvalidArgumentException If the factory is not supported or the implementation is invalid
73
     */
74
    public static function register(string $factoryInterface, string $factoryImplementation): void
75
    {
76
        if (! isset(self::$candidates[$factoryInterface])) {
77
            throw new InvalidArgumentException("$factoryInterface is not a supported factory");
78
        }
79
80
        if (! is_a($factoryImplementation, $factoryInterface, true)) {
81
            throw new InvalidArgumentException("$factoryImplementation does not implement $factoryInterface");
82
        }
83
84
        array_unshift(self::$candidates[$factoryInterface], $factoryImplementation);
85
    }
86
87
    /**
88
     * @throws InvalidArgumentException If the factory is not supported or the implementation is invalid
89
     */
90
    public static function unregister(string $factoryInterface, string $factoryImplementation): void
91
    {
92
        if (! isset(self::$candidates[$factoryInterface])) {
93
            throw new InvalidArgumentException("$factoryInterface is not a supported factory");
94
        }
95
96
        if (! is_a($factoryImplementation, $factoryInterface, true)) {
97
            throw new InvalidArgumentException("$factoryImplementation does not implement $factoryInterface");
98
        }
99
100
        self::$candidates[$factoryInterface] = array_diff(self::$candidates[$factoryInterface], [$factoryImplementation]);
101
    }
102
}
103