Completed
Push — master ( b659c5...c65770 )
by Michael
10:22
created

ConfigWiring::wire()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 48
Code Lines 24

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 2
Bugs 0 Features 0
Metric Value
dl 0
loc 48
ccs 0
cts 30
cp 0
rs 9.125
c 2
b 0
f 0
cc 2
eloc 24
nc 2
nop 1
crap 6
1
<?php
2
declare(strict_types = 1);
3
/**
4
 * Contains class ConfigWiring.
5
 *
6
 * PHP version 7.0+
7
 *
8
 * LICENSE:
9
 * This file is part of Yet Another Php Eve Api Library also know as Yapeal
10
 * which can be used to access the Eve Online API data and place it into a
11
 * database.
12
 * Copyright (C) 2016-2017 Michael Cummings
13
 *
14
 * This program is free software: you can redistribute it and/or modify it
15
 * under the terms of the GNU Lesser General Public License as published by the
16
 * Free Software Foundation, either version 3 of the License, or (at your
17
 * option) any later version.
18
 *
19
 * This program is distributed in the hope that it will be useful, but WITHOUT
20
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21
 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
22
 * for more details.
23
 *
24
 * You should have received a copy of the GNU Lesser General Public License
25
 * along with this program. If not, see
26
 * <http://spdx.org/licenses/LGPL-3.0.html>.
27
 *
28
 * You should be able to find a copy of this license in the COPYING-LESSER.md
29
 * file. A copy of the GNU GPL should also be available in the COPYING.md file.
30
 *
31
 * @author    Michael Cummings <[email protected]>
32
 * @copyright 2016-2017 Michael Cummings
33
 * @license   LGPL-3.0+
34
 */
35
namespace Yapeal\Configuration;
36
37
use Yapeal\Container\ContainerInterface;
38
39
/**
40
 * Class ConfigWiring.
41
 */
42
class ConfigWiring implements WiringInterface
43
{
44
    /**
45
     * @param ContainerInterface $dic
46
     *
47
     * @throws \DomainException
48
     * @throws \InvalidArgumentException
49
     * @throws \LogicException
50
     */
51
    public function wire(ContainerInterface $dic)
52
    {
53
        $this->wireYaml($dic)
54
            ->wireManager($dic)
55
            ->wireExtractorCallable($dic);
56
        $path = dirname(str_replace('\\', '/', __DIR__), 2) . '/';
57
        // These two paths are critical to Yapeal-ng working and can't be overridden.
58
        $dic['Yapeal.baseDir'] = $path;
59
        $dic['Yapeal.libDir'] = $path . 'lib/';
60
        $settings = $this->gitVersionSetting($dic, []);
61
        $configFiles = [
62
            [
63
                'pathName' => str_replace('\\', '/', __DIR__) . '/yapealDefaults.yaml',
64
                PHP_INT_MAX,
65
                false
66
            ]
67
        ];
68
        /**
69
         * Do to the importance that the cache/ and log/ directories and the main configuration file _not_ point to
70
         * somewhere under Composer's vendor/ directory they are now forced to use either vendor parent directory or
71
         * Yapeal-ng's base directory depending on if Yapeal-ng finds itself under a vendor/ directory.
72
         *
73
         * If as an application developer you wish to use a different directory than cache/ or log/ in your
74
         * application's root directory you __MUST__ set the 'Yapeal.FileSystem.Cache.dir' and/or 'Yapeal.Log.dir'
75
         * setting(s) of the Container before you give it to the Wiring class to prevent them being changed here when
76
         * Wiring::wireAll() calls this class method during wireAll()'s normal processing. On the command line you have
77
         * the -c or --configFile option to override the settings as well.
78
         *
79
         * Read the existing [Configuration Files](../../docs/config/ConfigurationFiles.md) docs for more about how to
80
         * override the optional config/yapeal.yaml file as well.
81
         */
82
        if (false !== $vendorPos = strpos($path, 'vendor/')) {
83
            $dic['Yapeal.vendorParentDir'] = substr($path, 0, $vendorPos);
84
            $configFiles[] = $dic['Yapeal.vendorParentDir'] . 'config/yapeal.yaml';
85
            $settings['Yapeal.FileSystem.Cache.dir'] = '{Yapeal.vendorParentDir}cache/';
86
            $settings['Yapeal.Log.dir'] = '{Yapeal.vendorParentDir}log/';
87
        } else {
88
            $configFiles[] = $path . 'config/yapeal.yaml';
89
            $settings['Yapeal.FileSystem.Cache.dir'] = '{Yapeal.baseDir}cache/';
90
            $settings['Yapeal.Log.dir'] = '{Yapeal.baseDir}log/';
91
        }
92
        /**
93
         * @var ConfigManagementInterface $manager
94
         */
95
        $manager = $dic['Yapeal.Configuration.Callable.Manager'];
96
        $manager->setSettings($settings)
97
            ->create($configFiles);
98
    }
99
    /**
100
     * Writes git version to Container if found else default setting that can be overridden latter in config file.
101
     *
102
     * @param ContainerInterface $dic
103
     * @param array              $settings
104
     *
105
     * @return array
106
     */
107
    private function gitVersionSetting(ContainerInterface $dic, array $settings): array
108
    {
109
        $gitVersion = trim(exec('git describe --always --long 2>&1', $junk, $status));
110
        if (0 === $status && '' !== $gitVersion) {
111
            $dic['Yapeal.version'] = $gitVersion . '-dev';
112
        } else {
113
            $settings['Yapeal.version'] = '0.0.0-0-noGit-unknown';
114
        }
115
        return $settings;
116
    }
117
    /**
118
     * Adds a protected function that will extract all scalar settings that share a common prefix.
119
     *
120
     * The prefix should end with a '.' if not the function will end one before starting search.
121
     *
122
     * @param ContainerInterface $dic
123
     *
124
     * @return ConfigWiring Fluent interface.
125
     * @throws \InvalidArgumentException Could only be thrown if Container or PHP were broken.
126
     */
127
    private function wireExtractorCallable(ContainerInterface $dic): self
128
    {
129
        if (empty($dic['Yapeal.Config.Callable.ExtractScalarsByKeyPrefix'])) {
130
            $dic['Yapeal.Config.Callable.ExtractScalarsByKeyPrefix'] = $dic->protect(
131
            /**
132
             * @param ContainerInterface $dic
133
             * @param string             $prefix
134
             *
135
             * @return \Generator
136
             */
137
            function (ContainerInterface $dic, string $prefix): \Generator {
138
                $preLen = strlen($prefix);
139
                if ($preLen !== strrpos($prefix, '.') + 1) {
140
                    $prefix .= '.';
141
                    ++$preLen;
142
                }
143
                try {
144
                    foreach ($dic->keys() as $key) {
145
                        $lastDotPlusOne = strrpos($key, '.') + 1;
146
                        if (0 === strpos($key, $prefix) && $preLen === $lastDotPlusOne && is_scalar($dic[$key])) {
147
                            $name = substr($key, $lastDotPlusOne);
148
                            yield $name => $dic[$key];
149
                        }
150
                    }
151
                } catch (\InvalidArgumentException $exc) {
152
                    // Only way this can happen is if the Container or PHP are broken.
153
                    $mess = 'Container or PHP are fatally broken;'
154
                        . ' Received InvalidArgumentException when accessing setting in Container with known good key';
155
                    trigger_error($mess, E_USER_ERROR);
156
                    exit(254);
157
                }
158
            });
159
        }
160
        return $this;
161
    }
162
    /**
163
     * @param ContainerInterface $dic
164
     *
165
     * @return self Fluent interface.
166
     */
167
    private function wireManager(ContainerInterface $dic): self
168
    {
169
        if (empty($dic['Yapeal.Configuration.Callable.Manager'])) {
170
            /**
171
             * @param ContainerInterface $dic
172
             *
173
             * @return ConfigManagementInterface
174
             */
175
            $dic['Yapeal.Configuration.Callable.Manager'] = function (ContainerInterface $dic): ConfigManagementInterface {
0 ignored issues
show
Coding Style introduced by
This line exceeds maximum limit of 120 characters; contains 123 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
176
                $manager = $dic['Yapeal.Configuration.Classes.manager'] ?? '\Yapeal\Configuration\ConfigManager';
177
                /**
178
                 * @var ConfigManager $manager
179
                 */
180
                $manager = new $manager($dic);
181
                $match = $dic['Yapeal.Configuration.Parameters.manager.matchYapealOnly'] ?? false;
182
                return $manager->setMatchYapealOnly($match);
183
            };
184
        }
185
        return $this;
186
    }
187
    /**
188
     * @param ContainerInterface $dic
189
     *
190
     * @return self Fluent interface.
191
     */
192
    private function wireYaml(ContainerInterface $dic): self
193
    {
194
        if (empty($dic['Yapeal.Config.Callable.Yaml'])) {
195
            $dic['Yapeal.Config.Callable.Yaml'] = $dic->factory(
196
            /**
197
             * @param ContainerInterface $dic
198
             *
199
             * @return mixed
200
             */
201
            function (ContainerInterface $dic) {
202
            $yaml = $dic['Yapeal.Configuration.Classes.yaml'] ?? '\Yapeal\Configuration\YamlConfigFile';
203
            return new $yaml();
204
            });
205
        }
206
        return $this;
207
    }
208
}
209