Completed
Pull Request — master (#81)
by Tom
03:18
created

Configurator::withContainerAdapter()   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 mixed[]
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 string[]
53
     */
54
    private $fileReaders = self::FILE_READERS;
55
56
    /**
57
     * @var string[]
58
     */
59
    private $containerAdapters = self::CONTAINER_ADAPTERS;
60
61
    /**
62
     * @var string
63
     */
64
    private static $containerIdentifier;
65
66
    /**
67
     * @api
68
     *
69
     * @return Configurator
70
     */
71
    public static function apply()
72
    {
73
        return new self();
74
    }
75
76
    private function __construct()
77
    {
78
        $this->config = new ApplicationConfig([]);
79
    }
80
81
    /**
82
     * @api
83
     *
84
     * @return string
85
     */
86
    public static function container()
87
    {
88
        if (!self::$containerIdentifier) {
89
            self::$containerIdentifier = uniqid(__CLASS__ . '::CONTAINER_ID::');
90
        }
91
92
        return self::$containerIdentifier;
93
    }
94
95
    /**
96
     * @api
97
     *
98
     * @param array $config
99
     *
100
     * @return $this
101
     */
102
    public function configFromArray(array $config)
103
    {
104
        $this->config->merge($config);
105
106
        return $this;
107
    }
108
109
    /**
110
     * @api
111
     *
112
     * @param string $filename
113
     *
114
     * @throws InvalidArgumentException
115
     *
116
     * @return $this
117
     */
118
    public function configFromFile($filename)
119
    {
120
        Assertion::file($filename);
121
122
        $this->readFileAndMergeConfig($filename);
123
124
        return $this;
125
    }
126
127
    /**
128
     * @api
129
     *
130
     * @param string $pattern
131
     *
132
     * @throws NoMatchingFilesException
133
     * @throws InvalidArgumentException
134
     *
135
     * @return $this
136
     */
137
    public function configFromFiles($pattern)
138
    {
139
        Assertion::string($pattern);
140
141
        $locator = new FileReader\FileLocator();
142
143
        $files = $locator->locate($pattern);
144
145
        if (count($files) === 0) {
146
            throw NoMatchingFilesException::fromPattern($pattern);
147
        }
148
149
        foreach ($files as $filename) {
150
            $this->readFileAndMergeConfig($filename);
151
        }
152
153
        return $this;
154
    }
155
156
    /**
157
     * @api
158
     *
159
     * @param string $name
160
     * @param mixed  $value
161
     *
162
     * @throws UnknownSettingException
163
     * @throws InvalidArgumentException
164
     *
165
     * @return $this
166
     */
167
    public function withSetting($name, $value)
168
    {
169
        Assertion::string($name);
170
        Assertion::scalar($value);
171
172
        if (!array_key_exists($name, $this->settings)) {
173
            throw UnknownSettingException::fromSetting($name, array_keys($this->settings));
174
        }
175
176
        $this->settings[$name] = $value;
177
178
        return $this;
179
    }
180
181
    /**
182
     * @param string $extension
183
     * @param string $className
184
     *
185
     * @return $this
186
     */
187
    public function withFileReader($extension, $className)
188
    {
189
        $this->fileReaders[$extension] = $className;
190
191
        return $this;
192
    }
193
194
    /**
195
     * @param string $containerName
196
     * @param string $adapterName
197
     *
198
     * @return $this
199
     */
200
    public function withContainerAdapter($containerName, $adapterName)
201
    {
202
        $this->containerAdapters[$containerName] = $adapterName;
203
204
        return $this;
205
    }
206
207
    /**
208
     * @api
209
     *
210
     * @param object $container
211
     *
212
     * @return void
213
     */
214
    public function to($container)
215
    {
216
        $this->config->setSeparator($this->settings[self::SETTING_SEPARATOR]);
217
218
        $factory = new ContainerAdapterFactory($this->containerAdapters);
219
220
        $configurator = $factory->create($container);
221
222
        $configurator->addApplicationConfig($this->config, $this->settings[self::SETTING_PREFIX]);
223
224 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...
225
            $configurator->addServiceConfig(new ServiceConfig(
226
                $this->config[$this->settings[self::SETTING_SERVICES_KEY]],
227
                $this->settings[self::SETTING_DEFAULT_SINGLETON_SERVICES]
228
            ));
229
        }
230
231 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...
232
            $configurator->addInflectorConfig(new InflectorConfig(
233
                $this->config[$this->settings[self::SETTING_INFLECTORS_KEY]]
234
            ));
235
        }
236
    }
237
238
    /**
239
     * @param string $filename
240
     *
241
     * @return void
242
     */
243
    private function readFileAndMergeConfig($filename)
244
    {
245
        $reader = $this->getReaderFor($filename);
246
247
        $this->config->merge($reader->read($filename));
248
    }
249
250
    /**
251
     * @param string $filename
252
     *
253
     * @return FileReader\FileReader
254
     */
255
    private function getReaderFor($filename)
256
    {
257
        if (!$this->readerFactory) {
258
            $this->readerFactory = new FileReader\ReaderFactory($this->fileReaders);
259
        }
260
261
        return $this->readerFactory->create($filename);
262
    }
263
}
264