Completed
Push — develop ( 172ce8...ea9a36 )
by Neomerx
04:47
created

Application::createFileSettingsProvider()   B

Complexity

Conditions 3
Paths 3

Size

Total Lines 24
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 12
CRAP Score 3

Importance

Changes 0
Metric Value
dl 0
loc 24
ccs 12
cts 12
cp 1
rs 8.9713
c 0
b 0
f 0
cc 3
eloc 12
nc 3
nop 0
crap 3
1
<?php namespace Limoncello\Application\Packages\Application;
2
3
/**
4
 * Copyright 2015-2017 [email protected]
5
 *
6
 * Licensed under the Apache License, Version 2.0 (the "License");
7
 * you may not use this file except in compliance with the License.
8
 * You may obtain a copy of the License at
9
 *
10
 * http://www.apache.org/licenses/LICENSE-2.0
11
 *
12
 * Unless required by applicable law or agreed to in writing, software
13
 * distributed under the License is distributed on an "AS IS" BASIS,
14
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
 * See the License for the specific language governing permissions and
16
 * limitations under the License.
17
 */
18
19
use Limoncello\Application\Contracts\Settings\CacheSettingsProviderInterface;
20
use Limoncello\Application\CoreSettings\CoreSettings;
21
use Limoncello\Application\Settings\CacheSettingsProvider;
22
use Limoncello\Application\Settings\FileSettingsProvider;
23
use Limoncello\Application\Settings\InstanceSettingsProvider;
24
use Limoncello\Container\Container;
25
use Limoncello\Contracts\Application\ApplicationSettingsInterface as A;
26
use Limoncello\Contracts\Container\ContainerInterface as LimoncelloContainerInterface;
27
use Limoncello\Contracts\Core\SapiInterface;
28
use Limoncello\Contracts\Provider\ProvidesSettingsInterface;
29
use Limoncello\Contracts\Settings\SettingsProviderInterface;
30
use Limoncello\Core\Application\Sapi;
31
use Limoncello\Core\Contracts\CoreSettingsInterface;
32
use Limoncello\Core\Reflection\ClassIsTrait;
33
use Zend\Diactoros\Response\SapiEmitter;
34
35
/**
36
 * @package Limoncello\Application
37
 *
38
 * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
39
 */
40
class Application extends \Limoncello\Core\Application\Application
41
{
42
    use ClassIsTrait;
43
44
    /**
45
     * @var string
46
     */
47
    private $settingsPath;
48
49
    /**
50
     * @var callable|string|null
51
     */
52
    private $settingCacheMethod;
53
54
    /**
55
     * @param string                     $settingsPath
56
     * @param string|array|callable|null $settingCacheMethod
57
     * @param SapiInterface|null         $sapi
58
     */
59 2
    public function __construct(string $settingsPath, $settingCacheMethod = null, SapiInterface $sapi = null)
60
    {
61
        // The reason we do not use `callable` for the input parameter is that at the moment
62
        // of calling the callable might not exist. Therefore when created it will pass
63
        // `is_callable` check and will be used for getting the cached data.
64 2
        assert(is_null($settingCacheMethod) || is_string($settingCacheMethod) || is_array($settingCacheMethod));
65
66 2
        $this->settingsPath       = $settingsPath;
67 2
        $this->settingCacheMethod = $settingCacheMethod;
68
69 2
        $this->setSapi($sapi ?? new Sapi(new SapiEmitter()));
70
    }
71
72
    /**
73
     * Get container from application. If `method` and `path` are specified the container will be configured
74
     * not only with global container configurators but with route's one as well.
75
     *
76
     * @param string|null $method
77
     * @param string|null $path
78
     *
79
     * @return LimoncelloContainerInterface
80
     *
81
     * @SuppressWarnings(PHPMD.StaticAccess)
82
     */
83 2
    public function createContainer(string $method = null, string $path = null): LimoncelloContainerInterface
84
    {
85 2
        $container = $this->createContainerInstance();
86
87 2
        $settingsProvider = $this->createSettingsProvider();
88 2
        $container->offsetSet(SettingsProviderInterface::class, $settingsProvider);
89 2
        $container->offsetSet(CacheSettingsProviderInterface::class, $settingsProvider);
90
91 2
        $coreSettings = $settingsProvider->get(CoreSettingsInterface::class);
92
93 2
        $routeConfigurators = [];
94 2
        if (empty($method) === false && empty($path) === false) {
95 2
            list(, , , , , $routeConfigurators) = $this->initRouter($coreSettings)->match($method, $path);
96
        }
97
98
        // configure container
99 2
        $globalConfigurators = CoreSettings::getGlobalConfiguratorsFromData($coreSettings);
100 2
        $this->configureContainer($container, $globalConfigurators, $routeConfigurators);
101
102 2
        return $container;
103
    }
104
105
    /**
106
     * @return SettingsProviderInterface
107
     *
108
     * @SuppressWarnings(PHPMD.ElseExpression)
109
     */
110 2
    protected function createSettingsProvider(): SettingsProviderInterface
111
    {
112 2
        $provider = new CacheSettingsProvider();
113 2
        if (is_callable($method = $this->getSettingCacheMethod()) === true) {
114 1
            $data = call_user_func($method);
115 1
            $provider->unserialize($data);
116
        } else {
117 1
            $provider->setInstanceSettings($this->createFileSettingsProvider());
118
        }
119
120 2
        return $provider;
121
    }
122
123
    /**
124
     * @return InstanceSettingsProvider
125
     */
126 1
    protected function createFileSettingsProvider(): InstanceSettingsProvider
127
    {
128
        // Load all settings from path specified
129 1
        $provider = (new FileSettingsProvider())->load($this->getSettingsPath());
130
131
        // Application settings have a list of providers which might have additional settings to load
132 1
        $appSettings     = $provider->get(A::class);
133 1
        $providerClasses = $appSettings[A::KEY_PROVIDER_CLASSES];
134 1
        foreach ($this->selectClassImplements($providerClasses, ProvidesSettingsInterface::class) as $providerClass) {
135
            /** @var ProvidesSettingsInterface $providerClass */
136 1
            foreach ($providerClass::getSettings() as $setting) {
137 1
                $provider->register($setting);
138
            }
139
        }
140
141
        // App settings (paths, lists) --> core settings (container configurators, routes, middleware and etc).
142 1
        $routesPath     = $appSettings[A::KEY_ROUTES_PATH];
143 1
        $containersPath = $appSettings[A::KEY_CONTAINER_CONFIGURATORS_PATH];
144 1
        $coreSettings   = new CoreSettings($routesPath, $containersPath, $providerClasses);
145
146 1
        $provider->register($coreSettings);
147
148 1
        return $provider;
149
    }
150
151
    /**
152
     * @return LimoncelloContainerInterface
153
     */
154 2
    protected function createContainerInstance(): LimoncelloContainerInterface
155
    {
156 2
        return new Container();
157
    }
158
159
    /**
160
     * @return string
161
     */
162 1
    protected function getSettingsPath(): string
163
    {
164 1
        return $this->settingsPath;
165
    }
166
167
    /**
168
     * @return callable|string|null
169
     */
170 2
    protected function getSettingCacheMethod()
171
    {
172 2
        return $this->settingCacheMethod;
173
    }
174
}
175