Magister::configPath()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 0
dl 0
loc 4
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace Magister;
4
5
use Magister\Services\Config\FileLoader;
6
use Magister\Services\Container\Container;
7
use Magister\Services\Contracts\Foundation\Application as ApplicationContract;
8
use Magister\Services\Filesystem\Filesystem;
9
use Magister\Services\Foundation\Http\Kernel;
10
use Magister\Services\Foundation\ProviderRepository;
11
use Magister\Services\Support\ServiceProvider;
12
13
/**
14
 * Class Magister.
15
 */
16
class Magister extends Container implements ApplicationContract
17
{
18
    /**
19
     * The API version.
20
     *
21
     * @var string
22
     */
23
    const VERSION = '2.1.6';
24
25
    /**
26
     * Indicates if the application has been bootstrapped before.
27
     *
28
     * @var bool
29
     */
30
    protected $hasBeenBootstrapped = false;
31
32
    /**
33
     * Indicates if the application has "booted".
34
     *
35
     * @var bool
36
     */
37
    protected $booted = false;
38
39
    /**
40
     * All of the registered service providers.
41
     *
42
     * @var array
43
     */
44
    protected $serviceProviders = [];
45
46
    /**
47
     * Create a new Magister instance.
48
     *
49
     * @param string $school
50
     * @param string $username
51
     * @param string $password
52
     */
53
    public function __construct($school, $username = null, $password = null)
54
    {
55
        $kernel = new Kernel($this);
56
57
        $this->registerBaseBindings($school, $username, $password);
58
59
        $this->bindPathsInContainer();
60
61
        $kernel->bootstrap();
62
    }
63
64
    /**
65
     * Get the version number of the application.
66
     *
67
     * @return string
68
     */
69
    public function version()
70
    {
71
        return static::VERSION;
72
    }
73
74
    /**
75
     * Register the basic bindings into the container.
76
     *
77
     * @param string $school
78
     * @param string $username
79
     * @param string $password
80
     *
81
     * @return void
82
     */
83
    protected function registerBaseBindings($school, $username, $password)
84
    {
85
        $this->bind('app', $this);
86
87
        $this->setSchool($school);
88
89
        if ($username && $password) {
90
            $this->setCredentials($username, $password);
91
        }
92
    }
93
94
    /**
95
     * Run the given array of bootstrap classes.
96
     *
97
     * @param array $bootstrappers
98
     *
99
     * @return void
100
     */
101
    public function bootstrapWith(array $bootstrappers)
102
    {
103
        foreach ($bootstrappers as $bootstrapper) {
104
            (new $bootstrapper())->bootstrap($this);
105
        }
106
107
        $this->hasBeenBootstrapped = true;
108
    }
109
110
    /**
111
     * Determine if the application has been bootstrapped before.
112
     *
113
     * @return bool
114
     */
115
    public function hasBeenBootstrapped()
116
    {
117
        return $this->hasBeenBootstrapped;
118
    }
119
120
    /**
121
     * Bind all of the application paths in the container.
122
     *
123
     * @return void
124
     */
125
    protected function bindPathsInContainer()
126
    {
127
        foreach (['base', 'config'] as $path) {
128
            $this->bind('path.'.$path, $this->{$path.'Path'}());
129
        }
130
    }
131
132
    /**
133
     * Get the base path of the Magister installation.
134
     *
135
     * @return string
136
     */
137
    public function basePath()
138
    {
139
        return realpath(__DIR__);
140
    }
141
142
    /**
143
     * Get the path to the application configuration files.
144
     *
145
     * @return string
146
     */
147
    public function configPath()
148
    {
149
        return $this->basePath().DIRECTORY_SEPARATOR.'Config';
150
    }
151
152
    /**
153
     * Boot the application's service providers.
154
     *
155
     * @return void
156
     */
157
    public function boot()
158
    {
159
        if ($this->booted) {
160
            return;
161
        }
162
163
        array_walk($this->serviceProviders, function ($p) {
164
            $this->bootProvider($p);
165
        });
166
167
        $this->booted = true;
168
    }
169
170
    /**
171
     * Boot the given service provider.
172
     *
173
     * @param \Magister\Services\Support\ServiceProvider $provider
174
     *
175
     * @return void
176
     */
177
    protected function bootProvider(ServiceProvider $provider)
178
    {
179
        if (method_exists($provider, 'boot')) {
180
            $provider->boot();
0 ignored issues
show
Documentation Bug introduced by
The method boot does not exist on object<Magister\Services\Support\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...
181
        }
182
    }
183
184
    /**
185
     * Determine if the application has booted.
186
     *
187
     * @return bool
188
     */
189
    public function isBooted()
190
    {
191
        return $this->booted;
192
    }
193
194
    /**
195
     * Get the configuration loader instance.
196
     *
197
     * @return \Magister\Services\Config\LoaderInterface
198
     */
199
    public function getConfigLoader()
200
    {
201
        return new FileLoader(new Filesystem(), $this['path.config']);
202
    }
203
204
    /**
205
     * Register all of the configured providers.
206
     *
207
     * @return void
208
     */
209
    public function registerProviders()
210
    {
211
        (new ProviderRepository($this))->load($this->config['app.providers']);
0 ignored issues
show
Documentation introduced by
The property config does not exist on object<Magister\Magister>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
212
    }
213
214
    /**
215
     * Register a service provider with the application.
216
     *
217
     * @param \Magister\Services\Support\ServiceProvider $provider
218
     * @param array                                      $options
219
     *
220
     * @return \Magister\Services\Support\ServiceProvider
221
     */
222
    public function register(ServiceProvider $provider, $options = [])
223
    {
224
        if (is_string($provider)) {
225
            $provider = $this->resolveProviderClass($provider);
226
        }
227
228
        $provider->register();
229
230
        foreach ($options as $key => $value) {
231
            $this[$key] = $value;
232
        }
233
234
        $this->markAsRegistered($provider);
235
236
        return $provider;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $provider; (Magister\Services\Support\ServiceProvider) is incompatible with the return type declared by the interface Magister\Services\Contra...n\Application::register of type Magister\Services\Contracts\Foundation\Application.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
237
    }
238
239
    /**
240
     * Get the registered service provider instance if it exists.
241
     *
242
     * @param \Magister\Services\Support\ServiceProvider|string $provider
243
     *
244
     * @return \Magister\Services\Support\ServiceProvider|null
245
     */
246
    public function getProvider($provider)
247
    {
248
        $name = is_string($provider) ? $provider : get_class($provider);
249
250
        return array_first($this->serviceProviders, function ($key, $value) use ($name) {
251
            return $value instanceof $name;
252
        });
253
    }
254
255
    /**
256
     * Resolve a service provider instance from the class name.
257
     *
258
     * @param string $provider
259
     *
260
     * @return \Magister\Services\Support\ServiceProvider
261
     */
262
    public function resolveProviderClass($provider)
263
    {
264
        return new $provider($this);
265
    }
266
267
    /**
268
     * Set the school for every request.
269
     *
270
     * @param string $school
271
     *
272
     * @return void
273
     */
274
    protected function setSchool($school)
275
    {
276
        $this->bind('school', $school);
277
    }
278
279
    /**
280
     * Set the credentials used by the authentication service.
281
     *
282
     * @param string $username
283
     * @param string $password
284
     *
285
     * @return void
286
     */
287
    protected function setCredentials($username, $password)
288
    {
289
        $this->bind('credentials', ['Gebruikersnaam' => $username, 'Wachtwoord' => $password]);
290
    }
291
292
    /**
293
     * Mark the given provider as registered.
294
     *
295
     * @param \Magister\Services\Support\ServiceProvider $provider
296
     *
297
     * @return void
298
     */
299
    protected function markAsRegistered($provider)
300
    {
301
        $this->serviceProviders[] = $provider;
302
    }
303
}
304