Passed
Push — master ( 9dcc41...e347b7 )
by Woody
02:12
created

DiscoveryLocator::locate()   A

Complexity

Conditions 4
Paths 3

Size

Total Lines 9
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 4

Importance

Changes 0
Metric Value
cc 4
eloc 4
nc 3
nop 1
dl 0
loc 9
ccs 5
cts 5
cp 1
crap 4
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 RuntimeException;
8
9
abstract class DiscoveryLocator
10
{
11
    /** @var array  */
12
    protected static $candidates = [];
13
14
    /**
15
     * @throws RuntimeException If no implementation is available
16
     */
17 13
    public static function locate(string $interface): string
18
    {
19 13
        foreach (static::$candidates[$interface] ?? [] as $candidate) {
20 12
            if (class_exists($candidate) && is_subclass_of($candidate, $interface, true)) {
21 12
                return $candidate;
22
            }
23
        }
24
25 1
        throw new RuntimeException("$interface has no available implementations");
26
    }
27
28 8
    public static function register(string $interface, string $implementation): void
29
    {
30 8
        self::assertValidImplementation($interface, $implementation);
31
32 6
        array_unshift(static::$candidates[$interface], $implementation);
33 6
    }
34
35 8
    public static function unregister(string $interface, string $implementation): void
36
    {
37 8
        self::assertValidImplementation($interface, $implementation);
38
39 6
        static::$candidates[$interface] = array_diff(
40 6
            static::$candidates[$interface],
41 6
            [$implementation]
42
        );
43
44 6
        static::clearCache($interface);
45 6
    }
46
47
    /**
48
     * @throws InvalidArgumentException If the factory is not supported or the implementation is invalid
49
     */
50 10
    private static function assertValidImplementation(string $interface, string $implementation): void
51
    {
52 10
        if (! isset(static::$candidates[$interface])) {
53 2
            throw new InvalidArgumentException("$interface is not a supported factory");
54
        }
55
56 8
        if (! is_subclass_of($implementation, $interface, true)) {
57 2
            throw new InvalidArgumentException("$implementation does not implement $interface");
58
        }
59 6
    }
60
61
    abstract protected static function clearCache(?string $interface = null): void;
62
}
63