Completed
Pull Request — master (#76)
by
unknown
03:28
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 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 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 $this
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 $this
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 $this
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 $this
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 string $extension
178
     * @param string $className
179
     *
180
     * @return $this
181
     */
182
    public function withFileReader($extension, $className)
183
    {
184
        $this->fileReaders[$extension] = $className;
185
186
        return $this;
187
    }
188
189
    /**
190
     * @api
191
     *
192
     * @param object $container
193
     *
194
     * @return void
195
     */
196
    public function to($container)
197
    {
198
        $this->config->setSeparator($this->settings[self::SETTING_SEPARATOR]);
199
200
        $factory = new ContainerAdapterFactory(self::CONTAINER_ADAPTERS);
201
202
        $configurator = $factory->create($container);
203
204
        $configurator->addApplicationConfig($this->config, $this->settings[self::SETTING_PREFIX]);
205
206 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...
207
            $configurator->addServiceConfig(new ServiceConfig(
208
                $this->config[$this->settings[self::SETTING_SERVICES_KEY]],
209
                $this->settings[self::SETTING_DEFAULT_SINGLETON_SERVICES]
210
            ));
211
        }
212
213 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...
214
            $configurator->addInflectorConfig(new InflectorConfig(
215
                $this->config[$this->settings[self::SETTING_INFLECTORS_KEY]]
216
            ));
217
        }
218
    }
219
220
    /**
221
     * @param string $filename
222
     *
223
     * @return void
224
     */
225
    private function readFileAndMergeConfig($filename)
226
    {
227
        $reader = $this->getReaderFor($filename);
228
229
        $this->config->merge($reader->read($filename));
230
    }
231
232
    /**
233
     * @param string $filename
234
     *
235
     * @return FileReader\FileReader
236
     */
237
    private function getReaderFor($filename)
238
    {
239
        if (!$this->readerFactory) {
240
            $this->readerFactory = new FileReader\ReaderFactory($this->fileReaders);
241
        }
242
243
        return $this->readerFactory->create($filename);
244
    }
245
}
246