Passed
Push — master ( a9aa6d...516004 )
by Robbie
01:39
created

CheckSuite::getCheckDetail()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 4
nc 2
nop 1
dl 0
loc 9
rs 9.6666
c 0
b 0
f 0
1
<?php
2
3
namespace SilverStripe\ModuleRatings;
4
5
use Exception;
6
use InvalidArgumentException;
7
use Symfony\Component\Yaml\Yaml;
8
9
class CheckSuite
10
{
11
    /**
12
     * @var Check[]|null
13
     */
14
    protected $checks = null;
15
16
    /**
17
     * @var array
18
     */
19
    protected $checkDetails = [];
20
21
    /**
22
     * @var int
23
     */
24
    protected $points = 0;
25
26
    /**
27
     * The physical filepath to the module's code
28
     *
29
     * @var string
30
     */
31
    protected $moduleRoot;
32
33
    /**
34
     * @var string
35
     */
36
    protected $repositorySlug = '';
37
38
    /**
39
     * Runs the check suite and processes the result of each
40
     *
41
     * @param callable $checkCallback If provided, will be called before each individual check is run, and will be
42
     *                                passed the Check instance as the first argument, and a delegatable callback
43
     *                                as the second argument for the consumer to control where the progressCheck()
44
     *                                method is called in their logic
45
     * @throws Exception              If no checks are defined
46
     */
47
    public function run(callable $checkCallback = null)
48
    {
49
        if (!$this->getChecks()) {
50
            throw new Exception('No checks have been defined! Please set some in config.yml.');
51
        }
52
        foreach ($this->getChecks() as $check) {
53
            /** @var Check $check */
54
            if (is_callable($checkCallback)) {
55
                $checkCallback($check, function () use ($check) {
56
                    $this->processCheck($check);
57
                });
58
            } else {
59
                $this->processCheck($check);
60
            }
61
        }
62
    }
63
64
    /**
65
     * Run the check and handle its results
66
     *
67
     * @param Check $check
68
     */
69
    protected function processCheck(Check $check)
70
    {
71
        $check->run();
72
73
        $this->addPoints($check->getResult());
74
        $this->addCheckDetail(
75
            $check->getKey(),
76
            [
77
                'description' => $check->getDescription(),
78
                'points' => $check->getResult(),
79
                'maximum' => $check->getPoints(),
80
            ]
81
        );
82
    }
83
84
    /**
85
     * Use the calculator class to get a relative score for the total number of points possible out of 100
86
     *
87
     * @return int
88
     */
89
    public function getScore()
90
    {
91
        return Calculator::getInstance()->calculate($this->getPoints());
92
    }
93
94
    /**
95
     * Get the number of points for this module's rating
96
     *
97
     * @return int
98
     */
99
    public function getPoints()
100
    {
101
        return (int) $this->points;
102
    }
103
104
    /**
105
     * Set the number of points for this module's rating
106
     *
107
     * @param int $points
108
     * @return $this
109
     */
110
    public function setPoints($points)
111
    {
112
        $this->points = (int) $points;
113
        return $this;
114
    }
115
116
    /**
117
     * Add the number of points to this module's rating
118
     *
119
     * @param int $points
120
     * @return $this
121
     */
122
    public function addPoints($points)
123
    {
124
        $this->setPoints($this->getPoints() + (int) $points);
125
        return $this;
126
    }
127
128
    /**
129
     * Set the detailed result for the checks in this suite
130
     *
131
     * @param array $checkResults
132
     * @return $this
133
     */
134
    public function setCheckDetails(array $checkDetails)
135
    {
136
        $this->checkDetails = $checkDetails;
137
        return $this;
138
    }
139
140
    /**
141
     * Add some metrics (description, points, etc) result for a check in this suite
142
     *
143
     * @param string $key
144
     * @param array $metrics
145
     * @return $this
146
     */
147
    public function addCheckDetail($key, array $metrics)
148
    {
149
        $this->checkDetails[$key] = $metrics;
150
        return $this;
151
    }
152
153
    /**
154
     * Get the detailed results for the checks in this suite
155
     * @return array
156
     */
157
    public function getCheckDetails()
158
    {
159
        return $this->checkDetails;
160
    }
161
162
    /**
163
     * Get the detailed result for one of the checks in this suite
164
     *
165
     * @param string $key
166
     * @return array
167
     * @throws Exception If the check was not in the details
168
     */
169
    public function getCheckDetail($key)
170
    {
171
        $checks = $this->getCheckDetails();
172
173
        if (isset($checks[$key])) {
174
            return $checks[$key];
175
        }
176
177
        throw new Exception('Check with code ' . $key. ' was not found');
178
    }
179
180
    /**
181
     * Get the registered check class instances
182
     *
183
     * @return Check[]
184
     */
185
    public function getChecks()
186
    {
187
        if ($this->checks === null) {
188
            $this->buildChecks();
189
        }
190
        return $this->checks;
191
    }
192
193
    /**
194
     * Set the registered check class instances
195
     *
196
     * @param Check[] $checks
197
     * @return $this
198
     */
199
    public function setChecks(array $checks = [])
200
    {
201
        $this->checks = $checks;
202
        return $this;
203
    }
204
205
    /**
206
     * Get the registered check class names and try to instantiate and add them
207
     *
208
     * @throws InvalidArgumentException If a registered check class does not exist
209
     */
210
    protected function buildChecks()
211
    {
212
        $checkClasses = $this->getCheckClasses();
213
        foreach ($checkClasses as $checkClass) {
214
            if (!class_exists($checkClass)) {
215
                throw new InvalidArgumentException('Registered check class ' . $checkClass . ' not found!');
216
            }
217
218
            /** @var Check $check */
219
            $check = new $checkClass;
220
            $check->setSuite($this);
221
222
            $this->addCheck($check);
223
        }
224
    }
225
226
    /**
227
     * Load the config.yml file and get the check class names from it
228
     *
229
     * @return string[]
230
     */
231
    protected function getCheckClasses()
232
    {
233
        $config = Yaml::parse(file_get_contents(dirname(__FILE__) . '/../config.yml'));
234
        if (empty($config[self::class]['checks'])) {
235
            return [];
236
        }
237
        return (array) $config[self::class]['checks'];
238
    }
239
240
    /**
241
     * Add a new check to the stack
242
     *
243
     * @param Check $check
244
     * @return $this
245
     */
246
    public function addCheck(Check $check)
247
    {
248
        $this->checks[] = $check;
249
        return $this;
250
    }
251
252
    /**
253
     * Set the path to the module's root folder that we're going to examine
254
     *
255
     * @param string $moduleRoot
256
     * @return $this
257
     */
258
    public function setModuleRoot($moduleRoot)
259
    {
260
        $this->moduleRoot = (string) rtrim($moduleRoot, '/');
261
        return $this;
262
    }
263
264
    /**
265
     * Get the path to the module's root folder
266
     *
267
     * @return string
268
     */
269
    public function getModuleRoot()
270
    {
271
        return $this->moduleRoot;
272
    }
273
274
    /**
275
     * Set the repository slug from/for the URL
276
     *
277
     * @param string $repositorySlug
278
     * @return $this
279
     */
280
    public function setRepositorySlug($repositorySlug)
281
    {
282
        $this->repositorySlug = (string) $repositorySlug;
283
        return $this;
284
    }
285
286
    /**
287
     * Get the repository slug for the URL
288
     *
289
     * @return string
290
     */
291
    public function getRepositorySlug()
292
    {
293
        return $this->repositorySlug;
294
    }
295
}
296