-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathFeature.php
More file actions
111 lines (86 loc) · 2.58 KB
/
Copy pathFeature.php
File metadata and controls
111 lines (86 loc) · 2.58 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
<?php
namespace Vehikl\Flip;
/**
* @method boolean enabled(...$params)
*/
abstract class Feature
{
const ENABLED = 'enabled';
const DISABLED = 'disabled';
private static $resolver;
protected $caller;
protected static $forceState;
// Maybe it's worth requiring an interface be applied?
public function __construct($caller)
{
$this->caller = $caller;
}
public static function new($caller): Feature
{
return new static($caller);
}
abstract public function toggles(): array;
public static function registerResolver($resolver): void
{
self::$resolver = $resolver;
}
public function resolver(): Resolver
{
if (! self::$resolver) {
self::registerResolver(new DefaultResolver);
}
return self::$resolver;
}
public function hasToggle(string $method): bool
{
return array_key_exists($method, $this->toggles());
}
protected function caller()
{
return $this->caller;
}
private function methodToCall(string $toggle): string
{
$toggles = $this->toggles();
if (array_key_exists($toggle, $toggles)) {
// if $toggles was a class, it'd be a lot less error prone.
return $this->resolver()->resolve($this, 'enabled') ? $toggles[$toggle]['on'] : $toggles[$toggle]['off'];
}
return $toggle;
}
public function __call($name, $arguments)
{
$methodToCall = $this->methodToCall($name);
if (method_exists($this, $methodToCall)) {
return $this->{$methodToCall}(...$arguments);
}
// Probably easier to just expect a public method.
$name = (new \ReflectionClass($this->caller()))->getMethod($methodToCall);
$name->setAccessible(true);
return $name->invoke($this->caller(), $arguments);
}
public static function __callStatic($method, $arguments)
{
// Could be extracted, but I wonder how reliable this would be?
// Does it really improve the API that much?
$caller = Caller::guess();
$instance = new static($caller);
return $instance->{$method}($arguments);
}
public static function alwaysOn() : void
{
static::$forceState = self::ENABLED;
}
public static function alwaysOff() : void
{
static::$forceState = self::DISABLED;
}
public function hasForcedState() : bool
{
return static::$forceState !== null;
}
public function isAlwaysOn() : bool
{
return static::$forceState === self::ENABLED;
}
}