Passed
Push — main ( c19e8c...628b24 )
by Sebastian
03:36
created

Util::extractListFromJson()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 3

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 3
eloc 1
c 1
b 0
f 0
nc 4
nop 2
dl 0
loc 3
ccs 2
cts 2
cp 1
crap 3
rs 10
1
<?php
2
3
/**
4
 * This file is part of CaptainHook
5
 *
6
 * (c) Sebastian Feldmann <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace CaptainHook\App\Config;
13
14
use CaptainHook\App\Hook\Util as HookUtil;
15
use CaptainHook\App\Config;
16
use CaptainHook\App\Storage\File\Json;
17
use RuntimeException;
18
19
/**
20
 * Class Util
21
 *
22
 * @package CaptainHook
23
 * @author  Sebastian Feldmann <[email protected]>
24
 * @link    https://github.com/captainhookphp/captainhook
25
 * @since   Class available since Release 1.0.3
26
 * @internal
27
 */
28
abstract class Util
29
{
30
    /**
31
     * Validate a configuration
32
     *
33
     * @param  array<string, mixed> $json
34
     * @return void
35
     * @throws \RuntimeException
36
     */
37 68
    public static function validateJsonConfiguration(array $json): void
38
    {
39 68
        self::validatePluginConfig($json);
40
41 65
        foreach (HookUtil::getValidHooks() as $hook => $class) {
42 65
            if (isset($json[$hook])) {
43 65
                self::validateHookConfig($json[$hook]);
44
            }
45
        }
46
    }
47
48
    /**
49
     * Validate a hook configuration
50
     *
51
     * @param  array<string, mixed> $json
52
     * @return void
53
     * @throws \RuntimeException
54
     */
55 65
    public static function validateHookConfig(array $json): void
56
    {
57 65
        if (!self::keysExist(['enabled', 'actions'], $json)) {
58 2
            throw new RuntimeException('Config error: invalid hook configuration');
59
        }
60 63
        if (!is_array($json['actions'])) {
61 1
            throw new RuntimeException('Config error: \'actions\' must be an array');
62
        }
63 62
        self::validateActionsConfig($json['actions']);
64
    }
65
66
    /**
67
     * Validate a plugin configuration
68
     *
69
     * @param  array<string, mixed> $json
70
     * @return void
71
     * @throws \RuntimeException
72
     */
73 68
    public static function validatePluginConfig(array $json): void
74
    {
75 68
        if (!isset($json['config']['plugins'])) {
76 64
            return;
77
        }
78 4
        if (!is_array($json['config']['plugins'])) {
79 1
            throw new RuntimeException('Config error: \'plugins\' must be an array');
80
        }
81 3
        foreach ($json['config']['plugins'] as $plugin) {
82 3
            if (!self::keysExist(['plugin'], $plugin)) {
83 1
                throw new RuntimeException('Config error: \'plugin\' missing');
84
            }
85 2
            if (empty($plugin['plugin'])) {
86 1
                throw new RuntimeException('Config error: \'plugin\' can\'t be empty');
87
            }
88
        }
89
    }
90
91
    /**
92
     * Validate a list of action configurations
93
     *
94
     * @param  array<string, mixed> $json
95
     * @return void
96
     * @throws \RuntimeException
97
     */
98 62
    public static function validateActionsConfig(array $json): void
99
    {
100 62
        foreach ($json as $action) {
101 54
            if (!self::keysExist(['action'], $action)) {
102 1
                throw new RuntimeException('Config error: \'action\' missing');
103
            }
104 53
            if (empty($action['action'])) {
105 1
                throw new RuntimeException('Config error: \'action\' can\'t be empty');
106
            }
107 52
            if (!empty($action['conditions'])) {
108 9
                self::validateConditionsConfig($action['conditions']);
109
            }
110
        }
111
    }
112
113
    /**
114
     * Validate a list of condition configurations
115
     *
116
     * @param  array<int, array<string, mixed>> $json
117
     * @throws \RuntimeException
118
     */
119 9
    public static function validateConditionsConfig(array $json): void
120
    {
121 9
        foreach ($json as $condition) {
122 9
            if (!self::keysExist(['exec'], $condition) || empty($condition['exec'])) {
123 1
                throw new RuntimeException('Config error: \'exec\' is required for conditions');
124
            }
125 8
            if (!empty($condition['args']) && !is_array($condition['args'])) {
126 1
                throw new RuntimeException('Config error: invalid \'args\' configuration');
127
            }
128
        }
129
    }
130
131
    /**
132
     * Extracts a list from a json data struct with the necessary safeguards
133
     *
134
     * @param  array<string, mixed>  $json
135
     * @param  string                $value
136
     * @return array<string, mixed>
137
     */
138 56
    public static function extractListFromJson(array $json, string $value): array
139
    {
140 56
        return isset($json[$value]) && is_array($json[$value]) ? $json[$value] : [];
141
    }
142
143
    /**
144
     * Write the config to disk
145
     *
146
     * @param  \CaptainHook\App\Config $config
147
     * @return void
148
     */
149 6
    public static function writeToDisk(Config $config): void
150
    {
151 6
        $filePath = $config->getPath();
152 6
        $file     = new Json($filePath);
153 6
        $file->write($config->getJsonData());
154
    }
155
156
    /**
157
     * Merges a various list of settings arrays
158
     *
159
     * @param  array<string, mixed> $settings
160
     * @return array<string, mixed>
161
     */
162 57
    public static function mergeSettings(array ...$settings): array
163
    {
164 57
        $includes       = array_column($settings, Config::SETTING_INCLUDES);
165 57
        $custom         = array_column($settings, Config::SETTING_CUSTOM);
166 57
        $mergedSettings = array_merge(...$settings);
167 57
        if (!empty($includes)) {
168 8
            $mergedSettings[Config::SETTING_INCLUDES] = array_merge(...$includes);
169
        }
170 57
        if (!empty($custom)) {
171 1
            $mergedSettings[Config::SETTING_CUSTOM] = array_merge(...$custom);
172
        }
173
174 57
        return $mergedSettings;
175
    }
176
177
    /**
178
     * Does an array have the expected keys
179
     *
180
     * @param  array<string>        $keys
181
     * @param  array<string, mixed> $subject
182
     * @return bool
183
     */
184 67
    private static function keysExist(array $keys, array $subject): bool
185
    {
186 67
        foreach ($keys as $key) {
187 67
            if (!isset($subject[$key])) {
188 5
                return false;
189
            }
190
        }
191 64
        return true;
192
    }
193
}
194