Passed
Push — master ( a063d5...82ab58 )
by Mikael
04:28
created

Configuration::loadFromDir()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 12

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
dl 0
loc 12
ccs 0
cts 7
cp 0
rs 9.8666
c 0
b 0
f 0
cc 2
nc 2
nop 1
crap 6
1
<?php
2
3
namespace Anax\Configure;
4
5
/**
6
 * Load configuration for a specified item, look in several places for the
7
 * configuration files or directories. Return the configuration as the value
8
 * received from the configuration file.
9
 */
10
class Configuration
11
{
12
    /**
13
     * @var array $dirs where to look for configuration items.
14
     */
15
    protected $dirs = [];
16
17
18
19
    /**
20
     * @var array $mapping mapping items to specific configuration file, mainly
21
     *                     useful for testing various configuration files.
22
     */
23
    protected $mapping = [];
24
25
26
27
    /**
28
     * Set a specific configuration file to load for a particluar item.
29
     *
30
     * @param string $item the item to map.
31
     * @param string $file file to load configuration from.
32
     *
33
     * @return self to allow chaining.
34
     */
35
    public function setMapping(string $item, string $file) : object
36
    {
37
        $this->mapping[$item] = $file;
38
        return $this;
39
    }
40
41
42
43
    /**
44
     * Set the directories where to look for configuration
45
     * items (files, directories) to load.
46
     *
47
     * @throws Exception when the path to any of the directories are incorrect.
48
     *
49
     * @param array $dirs with the path to the config directories to search in.
50
     *
51
     * @return self to allow chaining.
52
     */
53
    public function setBaseDirectories(array $dirs): object
54
    {
55
        if (empty($dirs)) {
56
            throw new Exception("The array for configuration directories can not be empty.");
57
        }
58
59
        foreach ($dirs as $dir) {
60
            if (!(is_readable($dir) && is_dir($dir))) {
61
                throw new Exception("The configuration dir '$dir' is not a valid path.");
62
            }
63
        }
64
65
        $this->dirs = $dirs;
66
        return $this;
67
    }
68
69
70
71
    /**
72
     * Read configuration from file or directory, if a file, look though all
73
     * base dirs and use the first configuration that is found. A configuration
74
     * item can be combined from a file and a directory, when available in the
75
     * same base directory.
76
     *
77
     * The resulting configuration is always an array, its structure contains
78
     * values from each individual configuration file, like this.
79
     *
80
     * $config = [
81
     *      "file" => filename for file.php,
82
     *      "config" => result returned from file.php,
83
     *      "items" => [
84
     *          [
85
     *              "file" => filename for dir/file1.php,
86
     *              "config" => result returned from dir/file1.php,
87
     *          ],
88
     *          [
89
     *              "file" => filename for dir/file2.php,
90
     *              "config" => result returned from dir/file2.php,
91
     *          ],
92
     *      ].
93
     * ]
94
     *
95
     * The configuration files in the directory are loaded per alphabetical
96
     * order.
97
     *
98
     * @param string $item is a name representing the module and is used to
99
     *                     combine the path to search for.
100
     *
101
     * @throws Exception when configuration item can not be found.
102
     * @throws Exception when $dirs are empty.
103
     *
104
     * @return array with returned value from the loaded configuration.
105
     */
106
    public function load(string $item) : array
107
    {
108
        if (empty($this->dirs)) {
109
            throw new Exception("The array for configuration directories can not be empty.");
110
        }
111
112
        $found = false;
113
        $config = [];
114
        $mapping = $this->mapping[$item] ?? null;
115
        if ($mapping) {
116
            $config["file"] = $mapping;
117
            $config["config"] = require $mapping;
118
            return $config;
119
        }
120
121
        foreach ($this->dirs as $dir) {
122
            $path = "$dir/$item";
123
            $file = "$path.php";
124
125
            // The configuration is found in ONLY a file
126 View Code Duplication
            if (is_readable($path) && is_file($path)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
127
                $found = true;
128
                $config["file"] = $path;
129
                $config["config"] = require $path;
130
                break;
131
            }
132
133
            // The configuration is found in a file
134 View Code Duplication
            if (is_readable($file) && is_file($file)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
135
                $found = true;
136
                $config["file"] = $file;
137
                $config["config"] = require $file;
138
            }
139
140
            // The configuration is found in a directory
141
            if (is_readable($path) && is_dir($path)) {
142
                $found = true;
143
                $config["items"] = $this->loadFromDir($path);
144
            }
145
146
            if ($found) {
147
                break;
148
            }
149
        }
150
151
        if (!$found) {
152
            throw new Exception("Configure item '$item' can not be found.");
153
        }
154
155
        return $config;
156
    }
157
158
159
160
    /**
161
     * Read configuration a directory, loop through all files and add
162
     * them into the $config array as:
163
     * [
164
     *      [
165
     *          "file" => filename for dir/file1.php,
166
     *          "config" => result returned from dir/file1.php,
167
     *      ],
168
     *      [
169
     *          "file" => filename for dir/file2.php,
170
     *          "config" => result returned from dir/file2.php,
171
     *      ],
172
     * ].
173
     *
174
     * @param string $path is the path to the directory containing config files.
175
     *
176
     * @return array with configuration for each file.
177
     */
178
    public function loadFromDir(string $path): array
179
    {
180
        $config = [];
181
        foreach (glob("$path/*.php") as $file) {
182
            $config[] = [
183
                "file" => $file,
184
                "config" => require $file,
185
            ];
186
        }
187
188
        return $config;
189
    }
190
}
191