EnvironmentCheckSuite   A
last analyzed

Complexity

Total Complexity 23

Size/Duplication

Total Lines 181
Duplicated Lines 0 %

Importance

Changes 3
Bugs 0 Features 1
Metric Value
eloc 55
c 3
b 0
f 1
dl 0
loc 181
rs 10
wmc 23

7 Methods

Rating   Name   Duplication   Size   Complexity  
A inst() 0 6 2
A run() 0 17 3
A push() 0 6 3
A __construct() 0 24 6
A reset() 0 3 1
A register() 0 8 3
A checkInstances() 0 21 5
1
<?php
2
3
namespace SilverStripe\EnvironmentCheck;
4
5
use Exception;
6
use InvalidArgumentException;
7
use SilverStripe\Core\Config\Configurable;
8
use SilverStripe\Core\Extensible;
9
use SilverStripe\Core\Injector\Injectable;
10
use SilverStripe\Core\Injector\Injector;
11
12
/**
13
 * Represents a suite of environment checks.
14
 * Specific checks can be registered against a named instance of EnvironmentCheckSuite.
15
 *
16
 * Usage #1 - _config.php
17
 * EnvironmentCheckSuite::register('health', 'MyHealthCheck("my param")', 'Title of my health check');
18
 *
19
 * Usage #2 - config.yml
20
 * EnvironmentCheckSuite:
21
 *   registered_checks:
22
 *     mycheck:
23
 *       definition: 'MyHealthCheck("my param")'
24
 *       title: 'Title of my health check'
25
 *   registered_suites:
26
 *     health:
27
 *       - mycheck
28
 *
29
 * $result = EnvironmentCheckSuite::inst('health')->run();
30
 *
31
 * @package environmentcheck
32
 */
33
class EnvironmentCheckSuite
34
{
35
    use Configurable;
36
    use Injectable;
37
    use Extensible;
38
    /**
39
     * Name of this suite.
40
     *
41
     * @var string
42
     */
43
    protected $name;
44
45
    /**
46
     * @var array
47
     */
48
    protected $checks = [];
49
50
    /**
51
     * Associative array of named checks registered via the config system. Each check should specify:
52
     * - definition (e.g. 'MyHealthCheck("my param")')
53
     * - title (e.g. 'Is my feature working?')
54
     * - state (setting this to 'disabled' will cause suites to skip this check entirely.
55
     *
56
     * @var array
57
     */
58
    private static $registered_checks = [];
59
60
    /**
61
     * Associative array of named suites registered via the config system. Each suite should enumerate
62
     * named checks that have been configured in 'registered_checks'.
63
     *
64
     * @var array
65
     */
66
    private static $registered_suites = [];
67
68
    /**
69
     * Load checks for this suite from the configuration system. This is an alternative to the
70
     * EnvironmentCheckSuite::register - both can be used, checks will be appended to the suite.
71
     *
72
     * @param string $suiteName The name of this suite.
73
     */
74
    public function __construct($suiteName)
75
    {
76
        if (empty($this->config()->registered_suites[$suiteName])) {
77
            // Not registered via config system, but it still may be configured later via self::register.
78
            return;
79
        }
80
81
        foreach ($this->config()->registered_suites[$suiteName] as $checkName) {
82
            if (empty($this->config()->registered_checks[$checkName])) {
83
                throw new InvalidArgumentException(
84
                    "Bad EnvironmentCheck: '$checkName' - the named check has not been registered."
85
                );
86
            }
87
88
            $check = $this->config()->registered_checks[$checkName];
89
90
            // Existing named checks can be disabled by setting their 'state' to 'disabled'.
91
            // This is handy for disabling checks mandated by modules.
92
            if (!empty($check['state']) && $check['state'] === 'disabled') {
93
                continue;
94
            }
95
96
            // Add the check to this suite.
97
            $this->push($check['definition'], $check['title']);
98
        }
99
    }
100
101
    /**
102
     * Run this test suite and return the result code of the worst result.
103
     *
104
     * @return EnvironmentCheckSuiteResult
105
     */
106
    public function run()
107
    {
108
        $result = new EnvironmentCheckSuiteResult();
109
110
        foreach ($this->checkInstances() as $check) {
111
            list($checkClass, $checkTitle) = $check;
112
            try {
113
                list($status, $message) = $checkClass->check();
114
            // If the check fails, register that as an error
115
            } catch (Exception $e) {
116
                $status = EnvironmentCheck::ERROR;
117
                $message = $e->getMessage();
118
            }
119
            $result->addResult($status, $message, $checkTitle);
120
        }
121
122
        return $result;
123
    }
124
125
    /**
126
     * Get instances of all the environment checks.
127
     *
128
     * @return EnvironmentChecker[]
129
     * @throws InvalidArgumentException
130
     */
131
    protected function checkInstances()
132
    {
133
        $output = [];
134
        foreach ($this->checks as $check) {
135
            list($checkClass, $checkTitle) = $check;
136
            if (is_string($checkClass)) {
137
                $checkInst = Injector::inst()->create($checkClass);
138
                if ($checkInst instanceof EnvironmentCheck) {
139
                    $output[] = [$checkInst, $checkTitle];
140
                } else {
141
                    throw new InvalidArgumentException(
142
                        "Bad EnvironmentCheck: '$checkClass' - the named class doesn't implement EnvironmentCheck"
143
                    );
144
                }
145
            } elseif ($checkClass instanceof EnvironmentCheck) {
146
                $output[] = [$checkClass, $checkTitle];
147
            } else {
148
                throw new InvalidArgumentException("Bad EnvironmentCheck: " . var_export($check, true));
149
            }
150
        }
151
        return $output;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $output returns an array which contains values of type array<integer,SilverStri...EnvironmentCheck|mixed> which are incompatible with the documented value type SilverStripe\EnvironmentCheck\EnvironmentChecker.
Loading history...
152
    }
153
154
    /**
155
     * Add a check to this suite.
156
     *
157
     * @param mixed $check
158
     * @param string $title
159
     */
160
    public function push($check, $title = null)
161
    {
162
        if (!$title) {
163
            $title = is_string($check) ? $check : get_class($check);
164
        }
165
        $this->checks[] = [$check, $title];
166
    }
167
168
    /////////////////////////////////////////////////////////////////////////////////////////////
169
170
    /**
171
     * @var array
172
     */
173
    protected static $instances = [];
174
175
    /**
176
     * Return a named instance of EnvironmentCheckSuite.
177
     *
178
     * @param string $name
179
     *
180
     * @return EnvironmentCheckSuite
181
     */
182
    public static function inst($name)
183
    {
184
        if (!isset(self::$instances[$name])) {
185
            self::$instances[$name] = new EnvironmentCheckSuite($name);
186
        }
187
        return self::$instances[$name];
188
    }
189
190
    /**
191
     * Register a check against the named check suite.
192
     *
193
     * @param string|array $names
194
     * @param EnvironmentCheck $check
195
     * @param string|array
196
     */
197
    public static function register($names, $check, $title = null)
198
    {
199
        if (!is_array($names)) {
200
            $names = [$names];
201
        }
202
203
        foreach ($names as $name) {
204
            self::inst($name)->push($check, $title);
205
        }
206
    }
207
208
    /**
209
     * Unregisters all checks.
210
     */
211
    public static function reset()
212
    {
213
        self::$instances = [];
214
    }
215
}
216