Completed
Push — master ( 9f33f4...b7f3a4 )
by Woody
23s
created

FactoryLocator::assertValidFactory()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 3

Importance

Changes 0
Metric Value
cc 3
eloc 4
nc 3
nop 2
dl 0
loc 8
ccs 5
cts 5
cp 1
crap 3
rs 10
c 0
b 0
f 0
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 13
    public static function locate(string $factoryInterface): string
61
    {
62 13
        foreach (self::$candidates[$factoryInterface] ?? [] as $candidate) {
63 12
            if (class_exists($candidate) && is_subclass_of($candidate, $factoryInterface, true)) {
64 12
                return $candidate;
65
            }
66
        }
67
68 1
        throw new RuntimeException("$factoryInterface has no available implementations");
69
    }
70
71 8
    public static function register(string $factoryInterface, string $factoryImplementation): void
72
    {
73 8
        self::assertValidFactory($factoryInterface, $factoryImplementation);
74
75 6
        array_unshift(self::$candidates[$factoryInterface], $factoryImplementation);
76 6
    }
77
78 8
    public static function unregister(string $factoryInterface, string $factoryImplementation): void
79
    {
80 8
        self::assertValidFactory($factoryInterface, $factoryImplementation);
81
82 6
        self::$candidates[$factoryInterface] = array_diff(
83 6
            self::$candidates[$factoryInterface],
84 6
            [$factoryImplementation]
85
        );
86 6
    }
87
88
    /**
89
     * @throws InvalidArgumentException If the factory is not supported or the implementation is invalid
90
     */
91 10
    private static function assertValidFactory(string $factoryInterface, string $factoryImplementation): void
92
    {
93 10
        if (! isset(self::$candidates[$factoryInterface])) {
94 2
            throw new InvalidArgumentException("$factoryInterface is not a supported factory");
95
        }
96
97 8
        if (! is_subclass_of($factoryImplementation, $factoryInterface, true)) {
98 2
            throw new InvalidArgumentException("$factoryImplementation does not implement $factoryInterface");
99
        }
100 6
    }
101
}
102