Completed
Push — master ( a00622...08b3e1 )
by Martin
14:53
created

Core   A

Complexity

Total Complexity 33

Size/Duplication

Total Lines 307
Duplicated Lines 0 %

Coupling/Cohesion

Components 2
Dependencies 3

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 307
rs 9.3999
wmc 33
lcom 2
cbo 3

19 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 10 2
A version() 0 4 1
A basePath() 0 4 1
B register() 0 30 5
A getLoadedProviders() 0 4 1
A getPlugins() 0 4 1
A boot() 0 12 2
A isBooted() 0 4 1
A registerBaseBindings() 0 7 1
A registerBaseServiceProviders() 0 5 1
A setBasePath() 0 8 1
A bindPathsInContainer() 0 4 1
A getProvider() 0 12 4
A resolveProviderClass() 0 4 1
A markAsRegistered() 0 5 1
A addPlugins() 0 6 2
A registerConfig() 0 14 3
A registerProvider() 0 6 2
A bootProvider() 0 6 2
1
<?php
2
declare(strict_types=1);
3
4
namespace Spires\Core;
5
6
use Spires\Container\Container;
7
use Spires\Contracts\Core\Core as CoreContract;
8
use Spires\Contracts\Core\UndefinedConfigKeyException;
9
10
class Core extends Container implements CoreContract
11
{
12
    /**
13
     * @var string
14
     */
15
    const VERSION = '0.1.0';
16
17
    /**
18
     * @var string
19
     */
20
    protected $basePath;
21
22
    /**
23
     * @var bool
24
     */
25
    protected $hasBeenBootstrapped = false;
26
27
    /**
28
     * @var bool
29
     */
30
    protected $booted = false;
31
32
    /**
33
     * @var array
34
     */
35
    protected $serviceProviders = [];
36
37
    /**
38
     * @var array
39
     */
40
    protected $loadedProviders = [];
41
42
    /**
43
     * @var array
44
     */
45
    protected $plugins = [];
46
47
    /**
48
     * @param  string|null $basePath
49
     * @return void
0 ignored issues
show
Comprehensibility Best Practice introduced by
Adding a @return annotation to constructors is generally not recommended as a constructor does not have a meaningful return value.

Adding a @return annotation to a constructor is not recommended, since a constructor does not have a meaningful return value.

Please refer to the PHP core documentation on constructors.

Loading history...
50
     */
51
    public function __construct($basePath = null)
52
    {
53
        $this->registerBaseBindings();
54
        $this->registerBaseServiceProviders();
55
//        $this->registerCoreContainerAliases();
0 ignored issues
show
Unused Code Comprehensibility introduced by
72% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
56
57
        if ($basePath) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $basePath of type string|null is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
58
            $this->setBasePath($basePath);
59
        }
60
    }
61
62
    /**
63
     * @return string
64
     */
65
    public function version()
66
    {
67
        return static::VERSION;
68
    }
69
70
    /**
71
     * @return string
72
     */
73
    public function basePath()
74
    {
75
        return $this->basePath;
76
    }
77
78
    /**
79
     * @param  \Spires\Core\ServiceProvider|string $provider
80
     * @param  array $config
81
     * @param  bool $force
82
     * @return ServiceProvider
83
     */
84
    public function register($provider, array $config = [], $force = false)
85
    {
86
        if (($registered = $this->getProvider($provider)) && !$force) {
87
            return $registered;
88
        }
89
90
        // If the given "provider" is a string, we will resolve it, passing in the
91
        // application instance automatically for the developer. This is simply
92
        // a more convenient way of specifying your service provider classes.
93
        if (is_string($provider)) {
94
            $provider = $this->resolveProviderClass($provider);
95
        }
96
97
        $this->registerConfig($provider, $config);
98
99
        $this->registerProvider($provider);
100
101
        $this->markAsRegistered($provider);
102
103
        $this->addPlugins($provider);
104
105
        // If the application has already booted, we will call this boot method on
106
        // the provider class so it has an opportunity to do its boot logic and
107
        // will be ready for any usage by the developer's application logics.
108
        if ($this->booted) {
109
            $this->bootProvider($provider);
110
        }
111
112
        return $provider;
113
    }
114
115
    /**
116
     * Get the service providers that have been loaded.
117
     *
118
     * @return array
119
     */
120
    public function getLoadedProviders()
121
    {
122
        return $this->loadedProviders;
123
    }
124
125
    /**
126
     * Get all plugins.
127
     *
128
     * @return array
129
     */
130
    public function getPlugins()
131
    {
132
        return $this->plugins;
133
    }
134
135
    /**
136
     * Boot the application's service providers.
137
     *
138
     * @return void
139
     */
140
    public function boot()
141
    {
142
        if ($this->booted) {
143
            return;
144
        }
145
146
        array_walk($this->serviceProviders, function ($provider) {
147
            $this->bootProvider($provider);
148
        });
149
150
        $this->booted = true;
151
    }
152
153
    /**
154
     * Determine if the application has booted.
155
     *
156
     * @return bool
157
     */
158
    public function isBooted()
159
    {
160
        return $this->booted;
161
    }
162
163
    /**
164
     * Register the basic bindings into the container.
165
     *
166
     * @return void
167
     */
168
    protected function registerBaseBindings()
169
    {
170
        static::setInstance($this);
171
        $this->instance(\Spires\Contracts\Core\Core::class, $this);
172
        $this->instance('core', $this);
173
        $this->instance(Container::class, $this);
174
    }
175
176
    /**
177
     * Register all of the base service providers.
178
     *
179
     * @return void
180
     */
181
    protected function registerBaseServiceProviders()
182
    {
183
//        $this->register(new LogServiceProvider($this));
0 ignored issues
show
Unused Code Comprehensibility introduced by
67% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
184
//        $this->register(new RoutingServiceProvider($this));
185
    }
186
187
    /**
188
     * Set the base path for the application.
189
     *
190
     * @param  string $basePath
191
     * @return $this
192
     */
193
    protected function setBasePath($basePath)
194
    {
195
        $this->basePath = rtrim($basePath, '\/');
196
197
        $this->bindPathsInContainer();
198
199
        return $this;
200
    }
201
202
    /**
203
     * Bind all of the application paths in the container.
204
     *
205
     * @return void
206
     */
207
    protected function bindPathsInContainer()
208
    {
209
        $this->instance('path.base', $this->basePath());
210
    }
211
212
    /**
213
     * Get the registered service provider instance if it exists.
214
     *
215
     * @param  \Spires\Core\ServiceProvider|string $provider
216
     * @return \Spires\Core\ServiceProvider|null
217
     */
218
    protected function getProvider($provider)
219
    {
220
        $name = is_string($provider) ? $provider : get_class($provider);
221
222
        foreach ($this->serviceProviders as $key => $value) {
223
            if ($value instanceof $name) {
224
                return $value;
225
            }
226
        }
227
228
        return null;
229
    }
230
231
    /**
232
     * Resolve a service provider instance from the class name.
233
     *
234
     * @param  string $provider
235
     * @return \Spires\Core\ServiceProvider
236
     */
237
    protected function resolveProviderClass($provider)
238
    {
239
        return new $provider($this);
240
    }
241
242
    /**
243
     * Mark the given provider as registered.
244
     *
245
     * @param  \Spires\Core\ServiceProvider $provider
246
     * @return void
247
     */
248
    protected function markAsRegistered($provider)
249
    {
250
        $this->serviceProviders[] = $provider;
251
        $this->loadedProviders[get_class($provider)] = true;
252
    }
253
254
    /**
255
     * Add plugins from the service provider.
256
     *
257
     * @param  \Spires\Core\ServiceProvider $provider
258
     * @return void
259
     */
260
    protected function addPlugins($provider)
261
    {
262
        foreach ($provider->plugins() as $plugin) {
263
            $this->plugins[$plugin] = $this->make($plugin);
264
        }
265
    }
266
267
    /**
268
     * Register the given service provider.
269
     *
270
     * @param  \Spires\Core\ServiceProvider $provider
271
     * @param  array $config
272
     * @return mixed
273
     *
274
     * @throws \Spires\Contracts\Core\UndefinedConfigKeyException
275
     */
276
    protected function registerConfig(ServiceProvider $provider, array $config)
277
    {
278
        $default = $provider->config();
279
280
        if ($undefined = array_keys(array_diff_key($config, $default))) {
281
            throw new UndefinedConfigKeyException('Undefined config keys passed to provider: [' . implode(', ', $undefined) . ']');
282
        }
283
284
        foreach (array_merge($default, $config) as $key => $value) {
285
            $this->bind($key, function () use ($value) {
286
                return $value;
287
            });
288
        }
289
    }
290
291
    /**
292
     * Register the given service provider.
293
     *
294
     * @param  \Spires\Core\ServiceProvider $provider
295
     * @return mixed
296
     */
297
    protected function registerProvider(ServiceProvider $provider)
298
    {
299
        if (method_exists($provider, 'register')) {
300
            return $provider->register();
0 ignored issues
show
Documentation Bug introduced by
The method register does not exist on object<Spires\Core\ServiceProvider>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
301
        }
302
    }
303
304
    /**
305
     * Boot the given service provider.
306
     *
307
     * @param  \Spires\Core\ServiceProvider $provider
308
     * @return mixed
309
     */
310
    protected function bootProvider(ServiceProvider $provider)
311
    {
312
        if (method_exists($provider, 'boot')) {
313
            return $this->call([$provider, 'boot']);
314
        }
315
    }
316
}
317