Passed
Pull Request — master (#1)
by Harry
02:06
created

Config   A

Complexity

Total Complexity 16

Size/Duplication

Total Lines 149
Duplicated Lines 0 %

Test Coverage

Coverage 0%

Importance

Changes 0
Metric Value
eloc 63
dl 0
loc 149
ccs 0
cts 79
cp 0
rs 10
c 0
b 0
f 0
wmc 16

6 Methods

Rating   Name   Duplication   Size   Complexity  
A getSchemaConfiguration() 0 7 2
A parse() 0 30 5
A getGroupPath() 0 7 2
A __construct() 0 19 1
A getSchemaPath() 0 4 2
A get() 0 13 4
1
<?php
2
/**
3
 * This file is part of graze/sprout.
4
 *
5
 * Copyright (c) 2017 Nature Delivered Ltd. <https://www.graze.com>
6
 *
7
 * For the full copyright and license information, please view the LICENSE
8
 * file that was distributed with this source code.
9
 *
10
 * @license https://github.com/graze/sprout/blob/master/LICENSE.md
11
 * @link    https://github.com/graze/sprout
12
 */
13
14
namespace Graze\Sprout;
15
16
use Graze\ConfigValidation\ConfigValidatorInterface;
17
use Graze\ConfigValidation\Validate;
18
use Graze\Sprout\Config\ConnectionConfig;
19
use Graze\Sprout\Config\GroupConfig;
20
use Graze\Sprout\Config\SchemaConfig;
21
use Graze\Sprout\Config\SchemaConfigInterface;
22
use InvalidArgumentException;
23
use Respect\Validation\Validator as v;
24
use Symfony\Component\Yaml\Parser;
25
26
/**
27
 * Config contains all the configuration required for this application
28
 */
29
class Config
30
{
31
    const DEFAULT_GROUP       = 'core';
32
    const DEFAULT_PATH        = '/seed';
33
    const DEFAULT_CONFIG_PATH = 'config/sprout.yml';
34
    const DEFAULT_PROCESSES   = 10;
35
36
    const CONFIG_DEFAULT_GROUP                  = 'defaults.group';
37
    const CONFIG_DEFAULT_PATH                   = 'defaults.path';
38
    const CONFIG_DEFAULT_SIMULTANEOUS_PROCESSES = 'defaults.simultaneousProcesses';
39
40
    const CONFIG_SCHEMAS = 'schemas';
41
42
    const CONFIG_GROUPS = 'groups';
43
44
    /** @var array */
45
    private $config;
46
47
    /** @var ConfigValidatorInterface */
48
    private $validator;
49
50
    public function __construct()
51
    {
52
        $this->validator =
53
            Validate::arr(false)
54
                    ->optional(static::CONFIG_DEFAULT_GROUP, v::stringType()->alnum('_'), static::DEFAULT_GROUP)
55
                    ->optional(static::CONFIG_DEFAULT_PATH, v::stringType()->directory(), static::DEFAULT_PATH)
56
                    ->optional(static::CONFIG_DEFAULT_SIMULTANEOUS_PROCESSES, v::intVal(), static::DEFAULT_PROCESSES)
57
                    ->optional(
58
                        static::CONFIG_GROUPS,
59
                        v::arrayVal()->each(
60
                            GroupConfig::getValidator()
61
                                       ->getValidator()
62
                        )
63
                    )
64
                    ->required(
65
                        static::CONFIG_SCHEMAS,
66
                        v::arrayVal()->length(1, null)->each(
67
                            SchemaConfig::getValidator()
68
                                        ->getValidator()
69
                        )
70
                    );
71
    }
72
73
    /**
74
     * Parse the config file provided in the constructor.
75
     *
76
     * @param string $path
77
     *
78
     * @return $this
79
     * @throws \Graze\ConfigValidation\Exceptions\ConfigValidationFailedException
80
     */
81
    public function parse(string $path): Config
0 ignored issues
show
Coding Style introduced by
Unknown type hint "string" found for $path
Loading history...
82
    {
83
        if (!file_exists($path)) {
84
            throw new \RuntimeException(sprintf('The supplied path %s does not exist', $path));
85
        }
86
87
        $parser = new Parser();
88
        $fileConfig = $parser->parse(file_get_contents($path));
89
90
        $config = $this->validator->validate($fileConfig);
91
92
        // populates the schema / connection.dbname properties for each defined schema if not set
93
        $schemas = $config['schemas'];
94
        foreach ($schemas as $schema => $value) {
95
            // TODO: remove these when config-validator is updated to handle child builders
0 ignored issues
show
Coding Style Best Practice introduced by
Comments for TODO tasks are often forgotten in the code; it might be better to use a dedicated issue tracker.
Loading history...
96
            $value = SchemaConfig::getValidator()->validate($value);
97
            $value['connection'] = ConnectionConfig::getValidator()->validate($value['connection']);
98
99
            if (is_null($value['schema'])) {
100
                $config['schemas'][$schema]['schema'] = $schema;
101
            }
102
            if (is_null($value['connection']['dbName'])) {
103
                $config['schemas'][$schema]['connection']['dbName'] = $schema;
104
            }
105
            $config['schemas'][$schema] = new SchemaConfig($config['schemas'][$schema]);
106
        }
107
108
        $this->config = $config;
109
110
        return $this;
111
    }
112
113
    /**
114
     * Get an element from the configuration
115
     *
116
     * @param string     $keyPath A dot separated identifier describing the name of the key to retrieve.
117
     *                            `get('defaults.path', '/some/path')` will return `$config['defaults']['path']` or
118
     *                            `'/some/path'` if it doesn't exist
119
     * @param mixed|null $default The default value to use if the field does not exist or is null. Note
120
     *
121
     * @return mixed the value of an item
122
     */
123
    public function get(string $keyPath, $default = null)
0 ignored issues
show
Coding Style introduced by
Unknown type hint "string" found for $keyPath
Loading history...
124
    {
125
        $paths = explode('.', $keyPath);
126
        $cur = $this->config;
127
        $trail = '';
128
        foreach ($paths as $path) {
129
            $trail .= '.' . $path;
130
            if (!isset($cur[$path]) || is_null($cur[$path])) {
131
                return $default;
132
            }
133
            $cur = $cur[$path];
134
        }
135
        return $cur;
136
    }
137
138
    /**
139
     * @param string $schema
140
     *
141
     * @return SchemaConfigInterface
142
     */
143
    public function getSchemaConfiguration(string $schema): SchemaConfigInterface
0 ignored issues
show
Coding Style introduced by
Unknown type hint "string" found for $schema
Loading history...
144
    {
145
        $value = $this->get("schemas.{$schema}");
146
        if (is_null($value)) {
147
            throw new InvalidArgumentException("no schema: {$schema} found in configuration");
148
        }
149
        return $value;
150
    }
151
152
    /**
153
     * Get the path for a specific schema
154
     *
155
     * @param SchemaConfigInterface $schema The schema configuration
156
     * @param string|null           $group  The group. If none supplied, uses the default
157
     *
158
     * @return string
159
     */
160
    public function getSchemaPath(SchemaConfigInterface $schema, string $group = null): string
161
    {
162
        $group = $group ?: $this->get("defaults.group");
163
        return sprintf('%s/%s/', $this->getGroupPath($group), $schema->getDirName());
0 ignored issues
show
Bug introduced by
It seems like $group can also be of type null; however, parameter $group of Graze\Sprout\Config::getGroupPath() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

163
        return sprintf('%s/%s/', $this->getGroupPath(/** @scrutinizer ignore-type */ $group), $schema->getDirName());
Loading history...
164
    }
165
166
    /**
167
     * @param string $group
168
     *
169
     * @return string
170
     */
171
    public function getGroupPath(string $group): string
0 ignored issues
show
Coding Style introduced by
Unknown type hint "string" found for $group
Loading history...
172
    {
173
        $configGroup = $this->get("groups.{$group}");
174
        if (!is_null($configGroup)) {
175
            return $configGroup['path'];
176
        } else {
177
            return sprintf('%s/%s/', $this->get(static::CONFIG_DEFAULT_PATH), $group);
178
        }
179
    }
180
}
181