Application::getConfigPath()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
dl 0
loc 8
ccs 0
cts 6
cp 0
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 5
nc 2
nop 0
crap 6
1
<?php
2
3
/**
4
 * This file is part of slick/mvc package
5
 *
6
 * For the full copyright and license information, please view the LICENSE
7
 * file that was distributed with this source code.
8
 */
9
10
namespace Slick\Mvc;
11
12
use Interop\Container\ContainerInterface;
13
use Slick\Configuration\Configuration;
14
use Slick\Di\Container;
15
use Slick\Di\ContainerBuilder;
16
use Slick\Http\PhpEnvironment\MiddlewareRunnerInterface;
17
use Slick\Http\PhpEnvironment\Request;
18
use Slick\Http\PhpEnvironment\Response;
19
20
/**
21
 * Class Application
22
 * @package Slick\Mvc
23
 */
24
class Application
25
{
26
27
    /**
28
     * @var ContainerInterface
29
     */
30
    private static $container;
31
32
    /**
33
     * @var string
34
     */
35
    private $configPath;
36
37
    /**
38
     * @var Request
39
     */
40
    private $request;
41
42
    /**
43
     * @var MiddlewareRunnerInterface
44
     */
45
    private $runner;
46
47
    /**
48
     * @var Response
49
     */
50
    private $response;
51
52
    /**
53
     * @var ContainerInterface
54
     */
55
    private static $defaultContainer;
56
57
    /**
58
     * Creates an application with an HTTP request
59
     *
60
     * If no request is provided then a Slick\Http\PhpEnvironment\Request is
61
     * created with values form current php environment settings.
62
     *
63
     * @param Request $request
64
     */
65 8
    public function __construct(Request $request = null)
66
    {
67 8
        $this->request = $request;
68 8
        Configuration::addPath(__DIR__.'/Configuration');
69 8
        $definitions = include __DIR__.'/Configuration/services.php';
70 8
        self::$defaultContainer = (
71 8
            new ContainerBuilder($definitions)
72 1
        )
73 8
        ->getContainer();
74 8
    }
75
76
    /**
77
     * Sets a new request
78
     *
79
     * @param Request $request
80
     *
81
     * @return Application
82
     */
83 2
    public function setRequest(Request $request)
84
    {
85 2
        $this->request = $request;
86 2
        $this->getContainer()->register('request', $request);
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Interop\Container\ContainerInterface as the method register() does only exist in the following implementations of said interface: Slick\Di\Container.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
87 2
        return $this;
88
    }
89
90
    /**
91
     * Gets the application dependency injection container
92
     *
93
     * @return ContainerInterface|Container
94
     */
95 6
    public function getContainer()
96
    {
97 6
        if (is_null(self::$container)) {
98 2
            self::$container = $this->checkContainer();
99 1
        }
100 6
        return self::$container;
101
    }
102
103
    /**
104
     * Sets the dependency injection container
105
     *
106
     * @param ContainerInterface $container
107
     */
108 22
    public static function setContainer(ContainerInterface $container)
109
    {
110 22
        self::$container = $container;
111 22
    }
112
113
    /**
114
     * Returns the application dependency container
115
     *
116
     * @return ContainerInterface|Container
117
     */
118 20
    public static function container()
119
    {
120 20
        if (null == self::$container) {
121 2
            $app = new static;
122 2
            $app->getContainer();
123 1
        }
124 20
        return self::$container;
125
    }
126
127
    /**
128
     * Set middleware runner
129
     *
130
     * @param MiddlewareRunnerInterface $runner
131
     *
132
     * @return $this|self|Application
133
     */
134 2
    public function setRunner(MiddlewareRunnerInterface $runner)
135
    {
136 2
        $this->runner = $runner;
137 2
        return $this;
138
    }
139
140
    /**
141
     * Returns the processed response
142
     *
143
     * @return Response
144
     */
145 2
    public function getResponse()
146
    {
147 2
        if (is_null($this->response)) {
148 2
            $this->response = $this->getRunner()->run();
149 1
        }
150 2
        return $this->response;
151
    }
152
153
    /**
154
     * Gets the HTTP middleware runner for this application
155
     *
156
     * @return MiddlewareRunnerInterface
157
     */
158 2
    public function getRunner()
159
    {
160 2
        if (null === $this->runner) {
161 2
            $runner = $this->getContainer()
162 2
                ->get('middleware.runner')
163 2
                ->setRequest($this->getRequest())
164 1
            ;
165 2
            $this->setRunner($runner);
166 1
        }
167 2
        return $this->runner;
168
    }
169
170
    /**
171
     * Set configuration path
172
     * 
173
     * @param string $configPath
174
     * 
175
     * @return Application|self
176
     */
177
    public function setConfigPath($configPath)
178
    {
179
        $this->configPath = $configPath;
180
        Configuration::addPath($configPath);
181
        return $this;
182
    }
183
184
    /**
185
     * Gets configuration path
186
     * 
187
     * @return string
188
     */
189
    public function getConfigPath()
190
    {
191
        if (null == $this->configPath) {
192
            $this->configPath = getcwd().'/Configuration';
193
            Configuration::addPath($this->configPath);
194
        }
195
        return $this->configPath;
196
    }
197
198
    /**
199
     * Gets HTTP request object
200
     *
201
     * @return Request
202
     */
203 4
    public function getRequest()
204
    {
205 4
        if (null === $this->request) {
206 2
            $this->request = $this->getContainer()
207 2
                ->get('request');
208 1
        }
209 4
        return $this->request;
210
    }
211
212
    /**
213
     * Gets container with user overridden settings
214
     * 
215
     * @return ContainerInterface|\Slick\Di\Container
216
     */
217 2
    protected function checkContainer()
218
    {
219 2
        $container = self::$defaultContainer;
220
        if (
221 2
            null != $this->configPath &&
222 1
            file_exists($this->configPath.'/services.php')
223 1
        ) {
224
            $definitions = include $this->configPath.'/services.php';
225
            $container = (
226
                new ContainerBuilder(
227
                    $definitions,
228
                    true
229
                )
230
            )->getContainer();
231
        }
232 2
        return $container;
233
    }
234
235
}