Issues (104)

Security Analysis    not enabled

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  Cross-Site Scripting
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Header Injection
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

Application.php (4 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
namespace Fwk\Core;
3
4
use Fwk\Events\Dispatcher;
5
use Symfony\Component\HttpFoundation\Request;
6
use Fwk\Di\Container;
7
use Fwk\Core\Events\RequestEvent;
8
use Fwk\Core\Events\DispatchEvent;
9
use Fwk\Core\Events\BeforeActionEvent;
10
use Fwk\Core\Events\AfterActionEvent;
11
use Fwk\Core\Events\EndEvent;
12
use Fwk\Core\Events\BootEvent;
13
use Fwk\Core\Events\ErrorEvent;
14
use Fwk\Core\Events\ResponseEvent;
15
use Symfony\Component\HttpFoundation\Response;
16
17
class Application extends Dispatcher implements \ArrayAccess
18
{
19
    /**
20
     * Application name
21
     * @var string
22
     */
23
    protected $name;
24
25
    /**
26
     * List of registered actions
27
     * @var array
28
     */
29
    protected $actions = array();
30
31
    /**
32
     * Services container (Di)
33
     * @var Container
34
     */
35
    protected $services;
36
37
    /**
38
     * The default action (i.e the "homepage")
39
     * @var string
40
     */
41
    protected $defaultAction;
42
43
    /**
44
     * Constructor
45
     *
46
     * @param string    $name     Application name
47
     * @param Container $services Services Container (di)
0 ignored issues
show
Should the type for parameter $services not be null|Container?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
48
     *
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 44
    public function __construct($name, Container $services = null)
52
    {
53 44
        $this->name = $name;
54
55 44
        if (null === $services) {
56 42
            $services = new Container();
57 42
        }
58
59 44
        $this->services = $services;
60 44
    }
61
62
    /**
63
     * Registers an action
64
     *
65
     * @param string      $actionName Name of the action
66
     * @param ActionProxy $proxy      Proxy instance to the action
67
     *
68
     * @return Application
69
     */
70 33
    public function register($actionName, ActionProxy $proxy)
71
    {
72 33
        $this->actions[$actionName] = $proxy;
73
74 33
        return $this;
75
    }
76
77
    /**
78
     * Unregisters an action
79
     *
80
     * @param string $actionName Name of the action
81
     *
82
     * @return Application
83
     * @throws Exception if action is not registered
84
     */
85 2
    public function unregister($actionName)
86
    {
87 2
        if (!array_key_exists($actionName, $this->actions)) {
88 1
            throw new Exception("$actionName is not a registered Action");
89
        }
90
91 1
        unset($this->actions[$actionName]);
92
93 1
        return $this;
94
    }
95
96
    /**
97
     * Returns the ActionProxy of a registered action
98
     *
99
     * @param string $actionName name of the action
100
     *
101
     * @return ActionProxy the proxy instance to the action
102
     * @throws Exception if action is not registered
103
     */
104 25
    public function get($actionName)
105
    {
106 25
        if (!array_key_exists($actionName, $this->actions)) {
107 1
            throw new Exception("$actionName is not a registered Action");
108
        }
109
110 24
        return $this->actions[$actionName];
111
    }
112
113
    /**
114
     * Tells if an action is registered
115
     *
116
     * @param string $actionName Name of the action
117
     *
118
     * @return boolean
119
     */
120 28
    public function exists($actionName)
121
    {
122 28
        return array_key_exists($actionName, $this->actions);
123
    }
124
125
    /**
126
     * Returns the list (array) of all registered actions (keys) and their
127
     * according ActionProxy (values)
128
     *
129
     * @return array
130
     */
131 1
    public function getActions()
132
    {
133 1
        return $this->actions;
134
    }
135
136
    /**
137
     * Instanciates a new Application
138
     * (useful for chaining)
139
     *
140
     * @param string    $name     Application name
141
     * @param Container $services Services Container
0 ignored issues
show
Should the type for parameter $services not be null|Container?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
142
     *
143
     * @return Application App instance
144
     */
145 38
    public static function factory($name, Container $services = null)
146
    {
147 38
        return new self($name, $services);
148
    }
149
150
    /**
151
     * Returns the Application name
152
     *
153
     * @return string
154
     */
155 1
    public function getName()
156
    {
157 1
        return $this->name;
158
    }
159
160
    /**
161
     * Returns the Services Container
162
     *
163
     * @return Container
164
     */
165 35
    public function getServices()
166
    {
167 35
        return $this->services;
168
    }
169
170
    /**
171
     * Defines a Services Container
172
     *
173
     * @param Container $services Services Container (Di)
174
     *
175
     * @return Application
176
     */
177
    public function setServices(Container $services)
178
    {
179
        $this->services = $services;
180
181
        return $this;
182
    }
183
184
    /**
185
     * Runs the Application for a defined (or new) HTTP request
186
     *
187
     * @param Request $request The HTTP request (optional)
0 ignored issues
show
Should the type for parameter $request not be null|Request?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
188
     *
189
     * @return mixed
190
     */
191 27
    public function run(Request $request = null)
192
    {
193 27
        $this->notify(new BootEvent($this));
194
195 26
        if (null === $request) {
196 1
            $request = Request::createFromGlobals();
197 1
        }
198
199 26
        $context = new Context($request);
200 1
        try {
201 26
            $this->notify(new RequestEvent($request, $this, $context));
202
203 26
            if (!$context->isReady()) {
204 6
                $this->notify(new DispatchEvent($this, $context));
205 5
            }
206
207 25
            if (!$context->isReady()) {
208 3
                if (null === $this->defaultAction || $context->isError()) {
209 1
                    throw new Exception('No action found');
210
                }
211 2
                $context->setActionName($this->defaultAction);
212 2
            }
213
214 24
            $result = $this->runAction($context);
215
216 23
            if (!$context->isDone()) {
217 18
                if ($result instanceof Response) {
218 2
                    $context->setResponse($result);
219 18
                } elseif (is_string($result)) {
220 11
                    $context->setResponse(new Response($result));
221 11
                }
222 18
            }
223
224 23
            if ($context->getResponse() instanceof Response) {
225 18
                $this->notify(
226 18
                    new ResponseEvent(
227 18
                        $context->getResponse(),
228 18
                        $this,
229
                        $context
230 18
                    )
231 18
                );
232 18
            }
233 26
        } catch(\Exception $exp) {
234 3
            $event = new ErrorEvent($exp, $this, $context);
235 3
            $this->notify($event);
236
237 3
            if (!$event->isStopped()) {
238 3
                throw $exp;
239
            } else {
240
                return null;
241
            }
242
        }
243
244 23
        $endEvent = new EndEvent($this, $context);
245 23
        $this->notify($endEvent);
246
247 23
        if ($endEvent->isStopped()) {
248
            return null;
249
        }
250
251 23
        if ($context->getResponse() instanceof Response) {
252 18
            return $context->getResponse();
253
        }
254
255 5
        return $context->getResult();
256
    }
257
258
    /**
259
     *
260
     * @param Context $context
261
     *
262
     * @return mixed
263
     */
264 24
    public function runAction(Context $context)
265
    {
266 24
        if (!$context->isReady()) {
267
            throw new Exception('Context is not ready (i.e. no action defined)');
268
        }
269
270 24
        if (!$this->exists($context->getActionName())) {
271 1
            throw new Exception('Unregistered action "'. $context->getActionName() .'"');
272
        }
273
274 23
        $proxy = $this->get($context->getActionName());
275 23
        $this->notify(new BeforeActionEvent($proxy, $this, $context));
276 23
        if ($context->isDone()) {
277
            return $context->getResult();
278
        }
279 23
        $result = $proxy->execute($this, $context);
280 23
        $context->setResult($result);
281 23
        $this->notify(new AfterActionEvent($proxy, $this, $context));
282
283 23
        return $result;
284
    }
285
286
    /**
287
     * Returns the default action name (if any)
288
     *
289
     * @return string
290
     */
291 2
    public function getDefaultAction()
292
    {
293 2
        return $this->defaultAction;
294
    }
295
296
    /**
297
     * Defines a default action. Basically the one which answers on /
298
     *
299
     * @param string $defaultAction Default action name
300
     *
301
     * @return Application
302
     */
303 2
    public function setDefaultAction($defaultAction)
304
    {
305 2
        $this->defaultAction = $defaultAction;
306
307 2
        return $this;
308
    }
309
310 2
    public function offsetExists($actionName)
311
    {
312 2
        return $this->exists($actionName);
313
    }
314
315 1
    public function offsetGet($actionName)
316
    {
317 1
        return $this->get($actionName);
318
    }
319
320 12
    public function offsetSet($actionName, $proxy)
321
    {
322 12
        if (!$proxy instanceof ActionProxy) {
323 12
            $proxy = Action\ProxyFactory::factory($proxy);
324 12
        }
325
326 12
        return $this->register($actionName, $proxy);
327
    }
328
329 1
    public function offsetUnset($actionName)
330
    {
331 1
        return $this->unregister($actionName);
332
    }
333
334
    /**
335
     * Adds a Plugin to the Application.
336
     *
337
     * @param Plugin $plugin The plugin to be loaded
338
     *
339
     * @return Application
340
     */
341 1
    public function plugin(Plugin $plugin)
342
    {
343 1
        $services = $this->getServices();
344
345
        // A Plugin can also be a listener of the Application Events
346 1
        $this->addListener($plugin);
347
348 1
        $plugin->loadServices($services);
349 1
        $plugin->load($this);
350
351 1
        return $this;
352
    }
353
}