Completed
Pull Request — master (#76)
by
unknown
02:47
created

Configurator::withFileReader()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 6
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 3
nc 1
nop 2
1
<?php
2
3
namespace TomPHP\ContainerConfigurator;
4
5
use Assert\Assertion;
6
use InvalidArgumentException;
7
use TomPHP\ContainerConfigurator\Exception\NoMatchingFilesException;
8
use TomPHP\ContainerConfigurator\Exception\UnknownSettingException;
9
10
final class Configurator
11
{
12
    const SETTING_PREFIX                     = 'config_prefix';
13
    const SETTING_SEPARATOR                  = 'config_separator';
14
    const SETTING_SERVICES_KEY               = 'services_key';
15
    const SETTING_INFLECTORS_KEY             = 'inflectors_key';
16
    const SETTING_DEFAULT_SINGLETON_SERVICES = 'default_singleton_services';
17
18
    const FILE_READERS = [
19
        '.json' => FileReader\JSONFileReader::class,
20
        '.php'  => FileReader\PHPFileReader::class,
21
        '.yaml' => FileReader\YAMLFileReader::class,
22
        '.yml'  => FileReader\YAMLFileReader::class,
23
    ];
24
25
    const CONTAINER_ADAPTERS = [
26
        \League\Container\Container::class => League\LeagueContainerAdapter::class,
27
        \Pimple\Container::class           => Pimple\PimpleContainerAdapter::class,
28
    ];
29
30
    /**
31
     * @var ApplicationConfig
32
     */
33
    private $config;
34
35
    /**
36
     * @var FileReader\ReaderFactory
37
     */
38
    private $readerFactory;
39
40
    /**
41
     * @var array
42
     */
43
    private $settings = [
44
        self::SETTING_PREFIX                     => 'config',
45
        self::SETTING_SEPARATOR                  => '.',
46
        self::SETTING_SERVICES_KEY               => 'di.services',
47
        self::SETTING_INFLECTORS_KEY             => 'di.inflectors',
48
        self::SETTING_DEFAULT_SINGLETON_SERVICES => false,
49
    ];
50
51
    /**
52
     * @var array
53
     */
54
    private $fileReaders = self::FILE_READERS;
55
56
    /**
57
     * @var string
58
     */
59
    private static $containerIdentifier;
60
61
    /**
62
     * @api
63
     *
64
     * @return Configurator
65
     */
66
    public static function apply()
67
    {
68
        return new self();
69
    }
70
71
    private function __construct()
72
    {
73
        $this->config = new ApplicationConfig([]);
74
    }
75
76
    /**
77
     * @api
78
     *
79
     * @return string
80
     */
81
    public static function container()
82
    {
83
        if (!self::$containerIdentifier) {
84
            self::$containerIdentifier = uniqid(__CLASS__ . '::CONTAINER_ID::');
85
        }
86
87
        return self::$containerIdentifier;
88
    }
89
90
    /**
91
     * @api
92
     *
93
     * @param array $config
94
     *
95
     * @return Configurator
96
     */
97
    public function configFromArray(array $config)
98
    {
99
        $this->config->merge($config);
100
101
        return $this;
102
    }
103
104
    /**
105
     * @api
106
     *
107
     * @param string $filename
108
     *
109
     * @throws InvalidArgumentException
110
     *
111
     * @return Configurator
112
     */
113
    public function configFromFile($filename)
114
    {
115
        Assertion::file($filename);
116
117
        $this->readFileAndMergeConfig($filename);
118
119
        return $this;
120
    }
121
122
    /**
123
     * @api
124
     *
125
     * @param string $pattern
126
     *
127
     * @throws NoMatchingFilesException
128
     * @throws InvalidArgumentException
129
     *
130
     * @return Configurator
131
     */
132
    public function configFromFiles($pattern)
133
    {
134
        Assertion::string($pattern);
135
136
        $locator = new FileReader\FileLocator();
137
138
        $files = $locator->locate($pattern);
139
140
        if (count($files) === 0) {
141
            throw NoMatchingFilesException::fromPattern($pattern);
142
        }
143
144
        foreach ($files as $filename) {
145
            $this->readFileAndMergeConfig($filename);
146
        }
147
148
        return $this;
149
    }
150
151
    /**
152
     * @api
153
     *
154
     * @param string $name
155
     * @param mixed  $value
156
     *
157
     * @throws UnknownSettingException
158
     * @throws InvalidArgumentException
159
     *
160
     * @return Configurator
161
     */
162
    public function withSetting($name, $value)
163
    {
164
        Assertion::string($name);
165
        Assertion::scalar($value);
166
167
        if (!array_key_exists($name, $this->settings)) {
168
            throw UnknownSettingException::fromSetting($name, array_keys($this->settings));
169
        }
170
171
        $this->settings[$name] = $value;
172
173
        return $this;
174
    }
175
176
    /**
177
     * @param $extension string
178
     * @param $className string
179
     */
180
    public function withFileReader($extension, $className)
181
    {
182
        $this->fileReaders[$extension] = $className;
183
184
        return $this;
185
    }
186
187
    /**
188
     * @api
189
     *
190
     * @param object $container
191
     *
192
     * @return void
193
     */
194
    public function to($container)
195
    {
196
        $this->config->setSeparator($this->settings[self::SETTING_SEPARATOR]);
197
198
        $factory = new ContainerAdapterFactory(self::CONTAINER_ADAPTERS);
199
200
        $configurator = $factory->create($container);
201
202
        $configurator->addApplicationConfig($this->config, $this->settings[self::SETTING_PREFIX]);
203
204 View Code Duplication
        if (isset($this->config[$this->settings[self::SETTING_SERVICES_KEY]])) {
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...
205
            $configurator->addServiceConfig(new ServiceConfig(
206
                $this->config[$this->settings[self::SETTING_SERVICES_KEY]],
207
                $this->settings[self::SETTING_DEFAULT_SINGLETON_SERVICES]
208
            ));
209
        }
210
211 View Code Duplication
        if (isset($this->config[$this->settings[self::SETTING_INFLECTORS_KEY]])) {
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...
212
            $configurator->addInflectorConfig(new InflectorConfig(
213
                $this->config[$this->settings[self::SETTING_INFLECTORS_KEY]]
214
            ));
215
        }
216
    }
217
218
    /**
219
     * @param string $filename
220
     *
221
     * @return void
222
     */
223
    private function readFileAndMergeConfig($filename)
224
    {
225
        $reader = $this->getReaderFor($filename);
226
227
        $this->config->merge($reader->read($filename));
228
    }
229
230
    /**
231
     * @param string $filename
232
     *
233
     * @return FileReader\FileReader
234
     */
235
    private function getReaderFor($filename)
236
    {
237
        if (!$this->readerFactory) {
238
            $this->readerFactory = new FileReader\ReaderFactory($this->fileReaders);
239
        }
240
241
        return $this->readerFactory->create($filename);
242
    }
243
}
244