Completed
Pull Request — master (#2)
by Colin
02:41
created

Feature::container()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
dl 0
loc 8
ccs 0
cts 4
cp 0
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 4
nc 2
nop 0
crap 6
1
<?php
2
3
namespace Vehikl\Flip;
4
5
use Illuminate\Container\Container;
6
7
/**
8
 * @method boolean enabled(...$params)
9
 */
10
abstract class Feature
11
{
12
    private static $container;
13
    private static $resolver;
14
    protected $caller;
15
16
    // Maybe it's worth requiring an interface be applied?
17 34
    public function __construct($caller)
18
    {
19 34
        $this->caller = $caller;
20 34
    }
21
22 16
    public static function new($caller): Feature
23
    {
24 16
        return new static($caller);
25
    }
26
27
    abstract public function toggles(): array;
28
29
    public static function registerContainer(Container $container): void
30
    {
31
        self::$container = $container;
32
    }
33
34
    public function container(): Container
35
    {
36
        if (! self::$container) {
37
            self::registerContainer(new Container);
38
        }
39
40
        return self::$container;
41
    }
42
43 20
    public static function registerResolver($resolver)
44
    {
45 20
        self::$resolver = $resolver;
46 20
    }
47
48 24
    public function resolver()
49
    {
50 24
        if (! self::$resolver) {
51 18
            self::registerResolver(new DefaultResolver);
52
        }
53
54 24
        return self::$resolver;
55
    }
56
57 10
    public function hasToggle(string $method): bool
58
    {
59 10
        return array_key_exists($method, $this->toggles());
60
    }
61
62 8
    protected function caller()
63
    {
64 8
        return $this->caller;
65
    }
66
67 22
    private function methodToCall(string $toggle): string
68
    {
69 22
        $toggles = $this->toggles();
70
71 22
        if (array_key_exists($toggle, $toggles)) {
72
            // if $toggles was a class, it'd be a lot less error prone.
73 20
            return $this->resolver()->resolve($this, 'enabled') ? $toggles[$toggle]['on'] : $toggles[$toggle]['off'];
74
        }
75
76 8
        return $toggle;
77
    }
78
79 22
    public function __call($name, $arguments)
80
    {
81 22
        $methodToCall = $this->methodToCall($name);
82
83 22
        if (method_exists($this, $methodToCall)) {
84 20
            return $this->{$methodToCall}(...$arguments);
85
        }
86
87
        // Probably easier to just expect a public method.
88 8
        $name = (new \ReflectionClass($this->caller()))->getMethod($methodToCall);
89 4
        $name->setAccessible(true);
90
91 4
        return $name->invoke($this->caller(), $arguments);
92
    }
93
94 2
    public static function __callStatic($method, $arguments)
95
    {
96
        // Could be extracted, but I wonder how reliable this would be?
97
        // Does it really improve the API that much?
98 2
        $caller = Caller::guess();
99
100 2
        $instance = new static($caller);
101
102 2
        return $instance->{$method}($arguments);
103
    }
104
}
105