GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.

Issues (164)

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.

src/Application.php (5 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 PhpBoot;
3
4
use DI\Container;
5
use DI\FactoryInterface;
6
use Doctrine\Common\Cache\ApcCache;
7
use Doctrine\Common\Cache\Cache;
8
use Doctrine\Common\Cache\FilesystemCache;
9
use FastRoute\DataGenerator\GroupCountBased as GroupCountBasedDataGenerator;
10
use FastRoute\Dispatcher\GroupCountBased as GroupCountBasedDispatcher;
11
use FastRoute\Dispatcher;
12
use FastRoute\RouteCollector;
13
use FastRoute\RouteParser\Std;
14
use Invoker\Exception\InvocationException;
15
use Invoker\Exception\NotCallableException;
16
use Invoker\Exception\NotEnoughParametersException;
17
use PhpBoot\Controller\ControllerContainerBuilder;
18
use PhpBoot\Cache\CheckableCache;
19
use PhpBoot\Cache\ClassModifiedChecker;
20
use PhpBoot\Controller\ControllerContainer;
21
use PhpBoot\Controller\ExceptionRenderer;
22
use PhpBoot\Controller\HookInterface;
23
use PhpBoot\Controller\Route;
24
use PhpBoot\DB\DB;
25
use PhpBoot\DI\DIContainerBuilder;
26
use PhpBoot\DI\Traits\EnableDIAnnotations;
27
use PhpBoot\Lock\LocalAutoLock;
28
use PhpBoot\Utils\Logger;
29
use Psr\Container\ContainerExceptionInterface;
30
use Psr\Container\ContainerInterface;
31
use Psr\Container\NotFoundExceptionInterface;
32
use Psr\Log\LoggerInterface;
33
use Symfony\Component\HttpFoundation\ParameterBag;
34
use Symfony\Component\HttpFoundation\Request;
35
use Symfony\Component\HttpFoundation\Response;
36
use Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException;
37
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
38
39
class Application implements ContainerInterface, FactoryInterface, \DI\InvokerInterface
40
{
41
    use EnableDIAnnotations;
42
43
    /**
44
     * @param string|array
45
     * .php file
46
     * ```
47
     * return
48
     * [
49
     *      'App.name'  => 'App', //The App's name, default is "App", use by \Monolog\Logger as the logging channel
50
     *      'App.uriPrefix' => '/',  // The prefix of api uri path, default is "/"
51
     *
52
     *       //DB.* are the params for PDO::__construct, @see http://php.net/manual/en/pdo.construct.php
53
     *      'DB.connection' => 'mysql:dbname=default;host=localhost',
54
     *      'DB.username' => 'root',
55
     *      'DB.password' => 'root',
56
     *      'DB.options' => [],
57
     *
58
     *
59
     *      LoggerInterface::class => \DI\object(\Monolog\Logger::class)
60
     *          ->constructor(\DI\get('App.name')),
61
     *      // 注意, 系统缓存, 只使用 apc、文件缓存等本地缓存, 不要使用 redis 等分布式缓存
62
     *      Cache::class => \DI\object(FilesystemCache::class)
63
     *          ->constructorParameter('directory', sys_get_temp_dir())
64
     * ];
65
     * ```
66
     * or just the array
67
     * @return self
68
     */
69 89
    static public function createByDefault($conf = [])
70
    {
71 89
        $builder = new DIContainerBuilder();
72
73
        $default = [
74
75 89
            'App.name' => 'App',
76 89
            'App.uriPrefix' => '/',
77
78 89
            'DB.connection' => 'mysql:dbname=default;host=localhost',
79 89
            'DB.username' => 'root',
80 89
            'DB.password' => 'root',
81 89
            'DB.options' => [],
82
83 89
            Application::class => \DI\object()
84 89
                ->method('setUriPrefix', \DI\get('App.uriPrefix')),
85
86 89
            DB::class => \DI\factory([DB::class, 'connect'])
87 89
                ->parameter('dsn', \DI\get('DB.connection'))
88 89
                ->parameter('username', \DI\get('DB.username'))
89 89
                ->parameter('password', \DI\get('DB.password'))
90 89
                ->parameter('options', \DI\get('DB.options')),
91
92 89
            LoggerInterface::class => \DI\object(\Monolog\Logger::class)
93 89
                ->constructor(\DI\get('App.name')),
94
95 89
            Request::class => \DI\factory([Application::class, 'createRequestFromGlobals']),
96 89
        ];
97 89
        if(function_exists('apc_fetch')){
98
            $default += [
99 89
                Cache::class => \DI\object(ApcCache::class)
100 89
            ];
101 89
        }else{
102
            $default += [
103
                Cache::class => \DI\object(FilesystemCache::class)
104
                    ->constructorParameter('directory', sys_get_temp_dir())
105
            ];
106
        }
107
108
109 89
        $builder->addDefinitions($default);
110 89
        $builder->addDefinitions($conf);
111
112 89
        $container = $builder->build();
113
114 89
        Logger::setDefaultLogger($container->get(LoggerInterface::class));
115
116 89
        $app = $container->make(self::class);
117 89
        return $app;
118
    }
119
120
    /**
121
     * @return Cache
122
     */
123 1
    public function getCache()
124
    {
125 1
        return $this->cache;
126
    }
127
128
    /**
129
     * @param Cache $localCache
130
     */
131
    public function setCache(Cache $localCache)
132
    {
133
        $this->cache = $localCache;
134
    }
135
136
    /**
137
     * load routes from class
138
     *
139
     * @param string $className
140
     * @param string[] $hooks hook class names
141
     * @return void
142
     */
143 2
    public function loadRoutesFromClass($className, $hooks=[])
144
    {
145 2
        $cache = new CheckableCache($this->cache);
146
147 2
        $key = 'loadRoutesFromClass:' . md5(__CLASS__ . ':' . $className);
148 2
        $routes = $cache->get($key, $this);
149
150 2
        $controller = null;
151 2
        if ($routes == $this) { //not cached
152 2
            $routes = [];
153 2
            $controller = $this->controllerContainerBuilder->build($className);
154 2
            foreach ($controller->getRoutes() as $actionName => $route) {
155 2
                $routes[] = [$route->getMethod(), $route->getUri(), $actionName];
156 2
            }
157 2
            $cache->set($key, $routes, 0, new ClassModifiedChecker($className));
158 2
        }
159 2
        foreach ($routes as $route) {
160 2
            list($method, $uri, $actionName) = $route;
161 2
            $this->routes[] = [
162 2
                $method,
163 2
                $uri,
164
                function (Application $app, Request $request) use ($cache, $className, $actionName, $controller) {
165
166 1
                    $key = 'loadRoutesFromClass:route:' . md5(__CLASS__ . ':' . $className . ':' . $actionName);
167
168 1
                    $routeInstance = $cache->get($key, $this);
169 1
                    if ($routeInstance == $this) {
170 1
                        if (!$controller) {
171
                            $controller = $app->controllerContainerBuilder->build($className);
0 ignored issues
show
Consider using a different name than the imported variable $controller, or did you forget to import by reference?

It seems like you are assigning to a variable which was imported through a use statement which was not imported by reference.

For clarity, we suggest to use a different name or import by reference depending on whether you would like to have the change visibile in outer-scope.

Change not visible in outer-scope

$x = 1;
$callable = function() use ($x) {
    $x = 2; // Not visible in outer scope. If you would like this, how
            // about using a different variable name than $x?
};

$callable();
var_dump($x); // integer(1)

Change visible in outer-scope

$x = 1;
$callable = function() use (&$x) {
    $x = 2;
};

$callable();
var_dump($x); // integer(2)
Loading history...
172
                        }
173 1
                        $routeInstance = $controller->getRoute($actionName) or
174
                        abort(new NotFoundHttpException("action $actionName not found"));
175 1
                        $cache->set($key, $routeInstance, 0, new ClassModifiedChecker($className));
176 1
                    }
177 1
                    return ControllerContainer::dispatch($this, $className, $actionName, $routeInstance, $request);
178 2
                },
179
                $hooks
180 2
            ];
181 2
        }
182 2
        $this->controllers[] = $className;
183 2
    }
184
185
    /**
186
     * load routes from path
187
     *
188
     * 被加载的文件必须以: 类名.php的形式命名
189
     * @param string $fromPath
190
     * @param string $namespace
191
     * @param string[] $hooks
192
     * @return void
193
     */
194 View Code Duplication
    public function loadRoutesFromPath($fromPath, $namespace = '', $hooks=[])
0 ignored issues
show
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
195
    {
196
        $dir = @dir($fromPath) or abort("dir $fromPath not exist");
197
198
        $getEach = function () use ($dir) {
199
            $name = $dir->read();
200
            if (!$name) {
201
                return $name;
202
            }
203
            return $name;
204
        };
205
206
        while (!!($entry = $getEach())) {
207
            if ($entry == '.' || $entry == '..') {
208
                continue;
209
            }
210
            $path = $fromPath . '/' . str_replace('\\', '/', $entry);
211
            if (is_file($path) && substr_compare($entry, '.php', strlen($entry) - 4, 4, true) == 0) {
212
                $class_name = $namespace . '\\' . substr($entry, 0, strlen($entry) - 4);
213
                $this->loadRoutesFromClass($class_name, $hooks);
214
            } else {
215
                //\Log::debug($path.' ignored');
216
            }
217
        }
218
    }
219
220
    /**
221
     * Add route
222
     * @param string $method
223
     * @param string $uri
224
     * @param callable $handler function(Application $app, Request $request):Response
225
     * @param string[] $hooks
226
     */
227 1
    public function addRoute($method, $uri, callable $handler, $hooks=[])
228
    {
229 1
        $this->routes[] = [$method, $uri, $handler, $hooks];
230 1
    }
231
232
    /**
233
     * @return ControllerContainer[]
234
     */
235 1
    public function getControllers()
236
    {
237 1
        $controllers = [];
238 1
        foreach ($this->controllers as $name) {
239 1
            $controllers[] = $this->controllerContainerBuilder->build($name);
240 1
        }
241 1
        return $controllers;
242
    }
243
244
    /**
245
     * @param Request|null $request
246
     * @param bool $send
247
     * @return Response
248
     */
249 3
    public function dispatch(Request $request = null, $send = true)
250
    {
251
        //  TODO 把 Route里的异常处理 ExceptionRenderer 移到这里更妥?
252 2
        $renderer = $this->get(ExceptionRenderer::class);
253
        try{
254 2
            if ($request == null) {
255
                $request = $this->make(Request::class);
256
            }
257 2
            $uri = $request->getRequestUri();
258 2
            if (false !== $pos = strpos($uri, '?')) {
259
                $uri = substr($uri, 0, $pos);
260
            }
261 2
            $uri = rawurldecode($uri);
262
263
            $next = function (Request $request)use($uri){
264 3
                $dispatcher = $this->getDispatcher();
265 2
                $res = $dispatcher->dispatch($request->getMethod(), $uri);
266 2
                if ($res[0] == Dispatcher::FOUND) {
267
268 2
                    if (count($res[2])) {
269
                        $request->attributes->add($res[2]);
270
                    }
271 2
                    list($handler, $hooks) = $res[1];
272
                    $next = function (Request $request)use($handler){
273 2
                        return $handler($this, $request);
274 2
                    };
275 2 View Code Duplication
                    foreach (array_reverse($hooks) as $hookName){
0 ignored issues
show
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
276
                        $next = function($request)use($hookName, $next){
277 1
                            $hook = $this->get($hookName);
278
                            /**@var $hook HookInterface*/
279 1
                            return $hook->handle($request, $next);
280 1
                        };
281 2
                    }
282 2
                    return $next($request);
283
284
                }elseif ($res[0] == Dispatcher::NOT_FOUND) {
285
                    \PhpBoot\abort(new NotFoundHttpException(), [$request->getMethod(), $uri]);
286
                } elseif ($res[0] == Dispatcher::METHOD_NOT_ALLOWED) {
287
                    \PhpBoot\abort(new MethodNotAllowedHttpException($res[1]), [$request->getMethod(), $uri]);
288
                } else {
289
                    \PhpBoot\abort("unknown dispatch return {$res[0]}");
290
                }
291 2
            };
292
293 2 View Code Duplication
            foreach (array_reverse($this->getGlobalHooks()) as $hookName){
0 ignored issues
show
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
294
                $next = function($request)use($hookName, $next){
295
                    $hook = $this->get($hookName);
296
                    /**@var $hook HookInterface*/
297
                    return $hook->handle($request, $next);
298
                };
299 2
            }
300 2
            $response = $next($request);
301
302
            /** @var Response $response */
303 2
            if ($send) {
304
                $response->send();
305
            }
306 2
            return $response;
307
308
        }catch (\Exception $e){
309
            $renderer->render($e);
310
        }
311
312
    }
313
314
    /**
315
     * @return GroupCountBasedDispatcher
316
     */
317 2
    private function getDispatcher()
318
    {
319 2
        $routeCollector = new RouteCollector(new Std(), new GroupCountBasedDataGenerator());
320 2
        foreach ($this->routes as $route) {
321 2
            list($method, $uri, $handler, $hooks) = $route;
322 2
            $uri = $this->getFullUri($uri);
323 2
            $routeCollector->addRoute($method, $uri, [$handler, $hooks]);
324 2
        }
325 2
        return new GroupCountBasedDispatcher($routeCollector->getData());
326
    }
327
328
    /**
329
     * Finds an entry of the container by its identifier and returns it.
330
     *
331
     * @param string $id Identifier of the entry to look for.
332
     *
333
     * @throws NotFoundExceptionInterface  No entry was found for **this** identifier.
334
     * @throws ContainerExceptionInterface Error while retrieving the entry.
335
     *
336
     * @return mixed Entry.
337
     */
338 18
    public function get($id)
339
    {
340 18
        return $this->container->get($id);
341
    }
342
343
    /**
344
     * Returns true if the container can return an entry for the given identifier.
345
     * Returns false otherwise.
346
     *
347
     * `has($id)` returning true does not mean that `get($id)` will not throw an exception.
348
     * It does however mean that `get($id)` will not throw a `NotFoundExceptionInterface`.
349
     *
350
     * @param string $id Identifier of the entry to look for.
351
     *
352
     * @return bool
353
     */
354
    public function has($id)
355
    {
356
        return $this->container->has($id);
357
    }
358
359
    /**
360
     * Call the given function using the given parameters.
361
     *
362
     * @param callable $callable Function to call.
363
     * @param array $parameters Parameters to use.
364
     *
365
     * @return mixed Result of the function.
366
     *
367
     * @throws InvocationException Base exception class for all the sub-exceptions below.
368
     * @throws NotCallableException
369
     * @throws NotEnoughParametersException
370
     */
371
    public function call($callable, array $parameters = array())
372
    {
373
        return $this->container->call($callable, $parameters);
374
    }
375
376 23
    public function make($name, array $parameters = [])
377
    {
378 23
        return $this->container->make($name, $parameters);
379
    }
380
381
    /**
382
     * @param \string[] $globalHooks
383
     */
384
    public function setGlobalHooks($globalHooks)
385
    {
386
        $this->globalHooks = $globalHooks;
0 ignored issues
show
Documentation Bug introduced by
It seems like $globalHooks of type array<integer,object<string>> is incompatible with the declared type array<integer,string> of property $globalHooks.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
387
    }
388
389
    /**
390
     * @return \string[]
391
     */
392 2
    public function getGlobalHooks()
393
    {
394 2
        return $this->globalHooks;
395
    }
396
397
    public static function createRequestFromGlobals()
398
    {
399
        $request = Request::createFromGlobals();
400
        if (0 === strpos($request->headers->get('CONTENT_TYPE'), 'application/json')
401
            && in_array(strtoupper($request->server->get('REQUEST_METHOD', 'GET')), array('POST', 'PUT', 'DELETE', 'PATCH'))
402
        ) {
403
            $data = json_decode($request->getContent(), true);
404
            $request->request = new ParameterBag($data);
405
        }
406
407
        return $request;
408
    }
409
410 3
    public function getFullUri($uri)
411
    {
412 3
        return rtrim($this->getUriPrefix(), '/').'/'.ltrim($uri, '/');
413
    }
414
    /**
415
     * @return string
416
     */
417 3
    public function getUriPrefix()
418
    {
419 3
        return $this->uriPrefix;
420
    }
421
422
    /**
423
     * @param string $uriPrefix
424
     */
425 89
    public function setUriPrefix($uriPrefix)
426
    {
427 89
        $this->uriPrefix = $uriPrefix;
428 89
    }
429
    /**
430
     * @var string
431
     */
432
    protected $uriPrefix = '/';
433
    /**
434
     * @inject
435
     * @var Container
436
     */
437
    protected $container;
438
439
    /**
440
     * @inject
441
     * @var ControllerContainerBuilder
442
     */
443
    protected $controllerContainerBuilder;
444
445
    /**
446
     * @inject
447
     * @var Cache
448
     */
449
    protected $cache;
450
451
    /**
452
     * [
453
     *      [method, uri, handler, hooks]
454
     * ]
455
     * @var array
456
     */
457
    protected $routes = [];
458
459
    /**
460
     * @var string[]
461
     */
462
    protected $controllers = [];
463
464
    /**
465
     * @var string[]
466
     */
467
    protected $globalHooks = [];
468
469
}