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/Docgen/Swagger/Swagger.php (14 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\Docgen\Swagger;
3
4
use PhpBoot\Application;
5
use PhpBoot\Controller\ControllerContainer;
6
use PhpBoot\Controller\ExceptionRenderer;
7
use PhpBoot\Controller\Route;
8
use PhpBoot\Docgen\Swagger\Schemas\ArraySchemaObject;
9
use PhpBoot\Docgen\Swagger\Schemas\BodyParameterObject;
10
use PhpBoot\Docgen\Swagger\Schemas\OperationObject;
11
use PhpBoot\Docgen\Swagger\Schemas\OtherParameterObject;
12
use PhpBoot\Docgen\Swagger\Schemas\PrimitiveSchemaObject;
13
use PhpBoot\Docgen\Swagger\Schemas\RefSchemaObject;
14
use PhpBoot\Docgen\Swagger\Schemas\ResponseObject;
15
use PhpBoot\Docgen\Swagger\Schemas\SimpleModelSchemaObject;
16
use PhpBoot\Docgen\Swagger\Schemas\SwaggerObject;
17
use PhpBoot\Docgen\Swagger\Schemas\TagObject;
18
use PhpBoot\Entity\ArrayContainer;
19
use PhpBoot\Entity\EntityContainer;
20
use PhpBoot\Entity\ScalarTypeContainer;
21
use PhpBoot\Entity\TypeContainerInterface;
22
use PhpBoot\Metas\ParamMeta;
23
use PhpBoot\Metas\ReturnMeta;
24
use PhpBoot\Utils\ArrayHelper;
25
use PhpBoot\Validator\Validator;
26
use Symfony\Component\HttpKernel\Exception\HttpException;
27
28
class Swagger extends SwaggerObject
29
{
30
31
    /**
32
     * @param Application $app
33
     * @param ControllerContainer[] $controllers
34
     */
35 1
    public function appendControllers(Application $app, $controllers)
36
    {
37 1
        foreach ($controllers as $controller) {
38 1
            $this->appendController($app, $controller);
39 1
        }
40 1
    }
41
42
    /**
43
     * @param Application $app
44
     * @param ControllerContainer $controller
45
     */
46 1
    public function appendController(Application $app, ControllerContainer $controller)
47
    {
48
        //tags
49 1
        $tag = new TagObject();
50 1
        $tag->name = $controller->getSummary();
51 1
        $tag->description = $controller->getDescription();
52 1
        $this->tags[] = $tag;
53
54 1
        foreach ($controller->getRoutes() as $action => $route) {
55 1
            $op = new OperationObject();
56 1
            $op->tags = [$controller->getSummary()];
57 1
            $op->summary = $route->getSummary();
58 1
            $op->description = $route->getDescription();
59
60 1
            $op->parameters = $this->getParamsSchema($app, $controller, $action, $route);
61 1
            if($this->hasFileParam($route)){
62 1
                $op->consumes = ['multipart/form-data'];
63 1
            }
64
65 1
            if ($returnSchema = $this->getReturnSchema($app, $controller, $action, $route)) {
66 1
                $op->responses['200'] = $returnSchema;
67 1
            }
68 1
            $op->responses += $this->getExceptionsSchema($app, $controller, $action, $route);
69 1
            $uri = $app->getFullUri($route->getUri());
70 1
            if (!isset($this->paths[$uri])) {
71 1
                $this->paths[$uri] = [];
72 1
            }
73 1
            $method = strtolower($route->getMethod());
74 1
            $this->paths[$uri][$method] = $op;
75 1
        }
76 1
    }
77
78
    /**
79
     * @return string
80
     */
81
    public function toJson()
82
    {
83
        $json = $this->toArray();
84
        return json_encode($json, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
85
    }
86
87
    /**
88
     * @return array
89
     */
90 1
    public function toArray()
91
    {
92 1
        return self::objectToArray($this);
93
    }
94
95
    /**
96
     * @param $object
97
     * @return array
98
     */
99 1
    static public function objectToArray($object)
100
    {
101 1
        if (is_object($object)) {
102 1
            $object = get_object_vars($object);
103 1
        }
104 1
        $res = [];
105 1
        foreach ($object as $k => $v) {
106 1
            if ($v === null) {
107 1
                continue;
108
            }
109 1
            if (is_array($v) || is_object($v)) {
110 1
                $res[$k] = self::objectToArray($v);
111 1
            } else {
112 1
                $res[$k] = $v;
113
            }
114 1
        }
115 1
        return $res;
116
    }
117
118
    /**
119
     * @param Application $app
120
     * @param ControllerContainer $controller
121
     * @param $action
122
     * @param Route $route
123
     * @return array
124
     */
125 1
    public function getExceptionsSchema(Application $app,
126
                                        ControllerContainer $controller,
0 ignored issues
show
The parameter $controller is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
127
                                        $action,
0 ignored issues
show
The parameter $action is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
128
                                        Route $route)
129
    {
130 1
        $handler = $route->getExceptionHandler();
131 1
        if (!$handler) {
132
            return [];
133
        }
134 1
        $schemas = [];
135 1
        foreach ($handler->getExceptions() as $exception) {
136 1
            list($name, $desc) = $exception;
137
138 1
            $ins = null;
139
            try{
140 1
                $ins = $app->make($name);
141 1
            }catch (\Exception $e){
142
                try{
143
                    $ins = new $name("");
144
                }catch (\Exception $e){
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
145
146
                }
147
            }
148
149
            //TODO status 重复怎么办
150 1
            if ($ins instanceof HttpException) {
151 1
                $status = $ins->getStatusCode();
152 1
            } else {
153
                $status = 500;
154
            }
155 1
            if (isset($schemas[$status])) {
156
                //$this->warnings[] = "status response $status has been used for $name, $desc";
157
                $res = $schemas[$status];
158
            } else {
159 1
                $res = new ResponseObject();
160
            }
161 1
            $shortName = self::getShortClassName($name);
162 1
            $desc = "$shortName: $desc";
163 1
            $res->description = self::implode("\n", [$res->description, $desc]);
164 1
            if($ins){
165 1
                $error = $app->get(ExceptionRenderer::class)->render($ins)->getContent();
166 1
                if($error){
167
                    $res->examples = [$shortName => $error];
168
                }
169 1
            }
170
            //$res->schema = new RefSchemaObject("#/definitions/$name");
171 1
            $schemas[$status] = $res;
172
173 1
        }
174 1
        return $schemas;
175
    }
176
177
    /**
178
     * @param Application $app
179
     * @param ControllerContainer $controller
180
     * @param $action
181
     * @param Route $route
182
     * @return null|ResponseObject
183
     */
184 1
    public function getReturnSchema(Application $app,
185
                                    ControllerContainer $controller,
186
                                    $action,
187
                                    Route $route)
188
    {
189 1
        $response = $route->getResponseHandler();
190 1
        if (!$response) {
191
            return null;
192
        }
193 1
        $mappings = $response->getMappings();
194 1
        $output = [];
195 1
        $schema = new ResponseObject();
196 1
        foreach ($mappings as $key => $map) {
197 1 View Code Duplication
            if (substr($key, 0, strlen('response.')) == 'response.') {
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...
198 1
                $key = substr($key, strlen('response.'));
199 1
            }
200 1
            ArrayHelper::set($output, $key, $map);
201 1
        }
202
        //TODO 支持 header、status 等
203 1
        if (isset($output['content'])) {
204 1
            $content = $output['content'];
205 1
            if ($content instanceof ReturnMeta) {
206 1
                $schema->description = $content->description;
207 1
                $schema->schema = $this->getAnySchema($app, $controller, $action, $route, $content->container);
0 ignored issues
show
It seems like $content->container can be null; however, getAnySchema() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
208 1
            } elseif (is_array($content)) {
209 1
                $tmpSchema = $this->makeTempSchema($app, $controller, $action, $route, $content, 'Res');
210 1
                $schema->schema = $tmpSchema;
211
212 1
            }
213
            //$schema->examples = ['application/json'=>$this->makeExample($content)];
214 1
            return $schema;
215
        }
216
        return null;
217
    }
218
219
    /**
220
     * @param $content
221
     */
222
    public function makeExample($content)
223
    {
224
        if ($content instanceof ReturnMeta || $content instanceof ParamMeta) {
225
            return $this->makeExample($content->container);
226
        }elseif ($content instanceof TypeContainerInterface){
227
            return $content->makeExample();
228
        }elseif(is_array($content)) {
229
            $res = [];
230
            foreach ($content as $k => $v) {
231
                $res[$k] = $this->makeExample($v);
232
            }
233
            return $res;
234
        }
235
        return null;
236
    }
237
    /**
238
     * @param Application $app
239
     * @param ControllerContainer $controller
240
     * @param $action
241
     * @param Route $route
242
     * @param array $arr
243
     * @param string $suffix
244
     * @return RefSchemaObject
245
     */
246 1
    public function makeTempSchema(Application $app,
247
                                   ControllerContainer $controller,
248
                                   $action,
249
                                   Route $route,
250
                                   array $arr, $suffix)
251
    {
252 1
        $className = self::getShortClassName($controller->getClassName());
253 1
        $name = $className . ucfirst($action) . $suffix;
254
255 1
        $schema = new SimpleModelSchemaObject();
256
257 1
        foreach ($arr as $k => $v) {
258 1
            if (is_array($v)) {
259 1
                $schema->properties[$k] = $this->makeTempSchema($app, $controller, $action, $route, $v, $suffix);
260 1
            } elseif ($v instanceof ReturnMeta) {
261 1
                $sub = $this->getAnySchema($app, $controller, $action, $route, $v->container);
0 ignored issues
show
It seems like $v->container can be null; however, getAnySchema() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
262 1
                if($sub){
263 1
                    $sub->description = $v->description;
264 1
                }
265 1
                $schema->properties[$k] = $sub;
266 1
            } elseif ($v instanceof ParamMeta) {
267 1 View Code Duplication
                if ($v->container instanceof ArrayContainer) {
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...
268 1
                    $sub = $this->getArraySchema($app, $controller, $action, $route, $v->container);
269
                    //TODO array for validation
270 1
                } elseif ($v->container instanceof EntityContainer) {
271 1
                    $sub = $this->getRefSchema($app, $controller, $action, $route, $v->container);
272
                    //TODO array for validation
273 1
                } else {
274 1
                    $sub = new PrimitiveSchemaObject();
275 1
                    $sub->type = self::mapType($v->type);
276 1
                    self::mapValidation($v->validation, $sub);
277 1
                    unset($sub->required);
278
                }
279 1
                if($sub){
280 1
                    $sub->description = $v->description;
281 1
                    $sub->default = $v->default;
282 1
                }
283 1
                if (!$v->isOptional) {
284 1
                    $schema->required[] = $k;
285 1
                }
286 1
                $schema->properties[$k] = $sub;
287 1
            } else {
288
                //TODO how to do?
289
            }
290 1
        }
291 1
        $unused = $name;
292 1
        $tempId = 0;
293 1
        while (isset($this->definitions[$unused])) {
294 1
            $unused = $name . $tempId;
295 1
            $tempId++;
296 1
        }
297 1
        $this->definitions[$unused] = $schema;
298 1
        return new RefSchemaObject("#/definitions/$unused");
299
    }
300
301
    /**
302
     * @param Application $app
303
     * @param ControllerContainer $controller
304
     * @param $action
305
     * @param Route $route
306
     * @param EntityContainer $container
307
     * @return RefSchemaObject
308
     */
309 1
    public function getRefSchema(Application $app,
310
                                 ControllerContainer $controller,
311
                                 $action,
312
                                 Route $route,
313
                                 EntityContainer $container)
314
    {
315 1
        $name = $container->getClassName();
316 1
        if (!isset($this->definitions[$name])) {
317 1
            $this->definitions[$name] = $this->getObjectSchema($app, $controller, $action, $route, $container);
318 1
        }
319 1
        return new RefSchemaObject("#/definitions/$name");
320
    }
321
322 1
    public function getParamsSchema(Application $app,
323
                                    ControllerContainer $controller,
324
                                    $action,
325
                                    Route $route)
326
    {
327 1
        $params = $route->getRequestHandler()->getParamMetas();
328 1
        $parameters = [];
329 1
        $body = [];
330 1
        $in = 'query';
331
332 1
        $bodyType = 'body'; // 当有文件上传时, 必须是formData方式
333 1
        if($this->hasFileParam($route)){
334 1
            $bodyType = 'formData';
335 1
        }
336
337 1
        foreach ($params as $name => $param) {
338 1
            $isFile = false;
339 1
            if ($param->isPassedByReference) {
340 1
                continue;
341
            }
342 1
            if ($param->source == 'request.request') {
343
                $in = $bodyType;
344
                $name = '';
345 1 View Code Duplication
            } elseif (strpos($param->source, 'request.request.') === 0
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...
346 1
                || $param->source == 'request.request'
347 1
            ) {
348 1
                $in = $bodyType;
349 1
                $name = substr($param->source, strlen('request.request.'));
350 1
            } elseif (strpos($param->source, 'request.query.') === 0) {
351 1
                $in = 'query';
352 1
                $name = substr($param->source, strlen('request.query.'));
353 1
            } elseif (strpos($param->source, 'request.cookies.') === 0) {
354 1
                $in = 'cookie';
355 1
                $name = substr($param->source, strlen('request.cookies.'));
356 1
            } elseif (strpos($param->source, 'request.headers.') === 0) {
357 1
                $in = 'header';
358 1
                $name = substr($param->source, strlen('request.headers.'));
359 1 View Code Duplication
            } elseif (strpos($param->source, 'request.files.') === 0) {
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...
360 1
                $isFile = true;
361 1
                $in = $bodyType;
362 1
                $name = substr($param->source, strlen('request.files.'));
363 1
            } elseif (strpos($param->source, 'request.') === 0) {
364 1
                $name = substr($param->source, strlen('request.'));
365 1
                if ($route->hasPathParam($param->name)) {
366 1
                    $in = 'path';
367 1
                } elseif ($route->getMethod() == 'POST'
368 1
                    || $route->getMethod() == 'PUT'
369 1
                    || $route->getMethod() == 'PATCH'
370 1
                ) {
371 1
                    $in = $bodyType;
372 1
                } else {
373 1
                    $in = 'query';
374
                }
375 1
            }
376 1
            if ($in != 'body') {
377 1 View Code Duplication
                if ($param->container instanceof ArrayContainer) {
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...
378 1
                    $paramSchema = $this->getArraySchema($app, $controller, $action, $route, $param->container);
379
                    //TODO array for validation
380 1
                } elseif ($param->container instanceof EntityContainer) {
381 1
                    $paramSchema = $this->getRefSchema($app, $controller, $action, $route, $param->container);
382
                    //TODO array for validation
383 1
                } else {
384 1
                    $paramSchema = new PrimitiveSchemaObject();
385 1
                    if($isFile){
386 1
                        $paramSchema->type = 'file';
387 1
                    }else{
388 1
                        $paramSchema->type = self::mapType($param->type);
389 1
                        self::mapValidation($param->validation, $paramSchema);
390
                    }
391
392
                }
393 1
                $paramSchema->in = $in;
394 1
                $paramSchema->name = $name;
395 1
                $paramSchema->description = $param->description;
396 1
                $paramSchema->default = $param->default;
397 1
                $paramSchema->required = !$param->isOptional;
398 1
                $parameters[] = $paramSchema;
399 1
            } else {
400 1
                if (!$name) {
401
                    $body = $param;
402
                } else {
403 1
                    ArrayHelper::set($body, $name, $param);
0 ignored issues
show
It seems like $body defined by $param on line 401 can also be of type object<PhpBoot\Metas\ParamMeta>; however, PhpBoot\Utils\ArrayHelper::set() does only seem to accept array|object<ArrayAccess>, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
404
                }
405
406
            }
407 1
        }
408 1
        if ($body && $bodyType == 'body') {
409
410 1
            $paramSchema = new BodyParameterObject();
411 1
            $paramSchema->name = 'body';
412 1
            $paramSchema->in = 'body';
413 1
            if (is_array($body)) {
414 1
                $paramSchema->schema = $this->makeTempSchema($app, $controller, $action, $route, $body, 'Req');
415 1
            } else {
416
                $paramSchema->schema = $this->getAnySchema($app, $controller, $action, $route, $body->container);
417
            }
418
419 1
            $parameters[] = $paramSchema;
420 1
        }
421
422 1
        return $parameters;
423
    }
424
425
    /**
426
     * @param Application $app
427
     * @param ControllerContainer $controller
428
     * @param $action
429
     * @param Route $route
430
     * @param TypeContainerInterface $container
431
     * @return ArraySchemaObject|PrimitiveSchemaObject|RefSchemaObject
432
     */
433 1
    public function getAnySchema(Application $app, ControllerContainer $controller, $action, Route $route, $container)
434
    {
435 1
        if ($container instanceof EntityContainer) {
436 1
            $schema = $this->getRefSchema($app, $controller, $action, $route, $container);
437 1
        } elseif ($container instanceof ArrayContainer) {
438 1
            $schema = $this->getArraySchema($app, $controller, $action, $route, $container);
439 1
        } elseif ($container instanceof ScalarTypeContainer) {
440 1
            $schema = new PrimitiveSchemaObject();
441 1
            $schema->type = self::mapType($container->getType());
442 1
        } elseif($container == null){
443
            $schema = null ;//new PrimitiveSchemaObject();
444
            //$schema->type = null;
445
        }else {
446 1
            $schema = new PrimitiveSchemaObject();
447
            //$schema->type = 'mixed';
448
        }
449 1
        return $schema;
450
    }
451
452
    /**
453
     * @param Application $app
454
     * @param ControllerContainer $controller
455
     * @param $action
456
     * @param Route $route
457
     * @param ArrayContainer $container
458
     * @return ArraySchemaObject
459
     */
460 1
    public function getArraySchema(Application $app,
461
                                   ControllerContainer $controller,
462
                                   $action,
463
                                   Route $route,
464
                                   ArrayContainer $container)
465
    {
466 1
        $schema = new ArraySchemaObject();
467 1
        $itemContainer = $container->getContainer();
468 1
        if ($itemContainer instanceof EntityContainer) {
469 1
            $itemSchema = $this->getRefSchema($app, $controller, $action, $route, $itemContainer);
470 1
        } elseif ($itemContainer instanceof ArrayContainer) {
471
            $itemSchema = $this->getArraySchema($app, $controller, $action, $route, $itemContainer);
472 1
        } elseif ($itemContainer instanceof ScalarTypeContainer) {
473 1
            $itemSchema = new PrimitiveSchemaObject();
474 1
            $itemSchema->type = self::mapType($itemContainer->getType());
475 1
        } else {
476
            $itemSchema = new PrimitiveSchemaObject();
477
            //$itemSchema->type = 'mixed';
478
        }
479 1
        $schema->items = $itemSchema;
480 1
        return $schema;
481
    }
482
483 1
    public function getObjectSchema(Application $app,
484
                                    ControllerContainer $controller,
485
                                    $action,
486
                                    Route $route,
487
                                    EntityContainer $container)
488
    {
489 1
        $schema = new SimpleModelSchemaObject();
490 1
        $schema->description = self::implode("\n", [$container->getSummary(), $container->getDescription()]);
491
492 1
        foreach ($container->getProperties() as $property) {
493
494 1
            if (!$property->isOptional) {
495 1
                $schema->required[] = $property->name;
496 1
            }
497 1
            if ($property->container instanceof EntityContainer) {
498 1
                $propertySchema = $this->getRefSchema($app, $controller, $action, $route, $property->container);
499 1
            } elseif ($property->container instanceof ArrayContainer) {
500 1
                $propertySchema = $this->getArraySchema($app, $controller, $action, $route, $property->container);
501 1
            } else {
502 1
                $propertySchema = new PrimitiveSchemaObject();
503 1
                $propertySchema->type = self::mapType($property->type);
504 1
                $propertySchema->description = self::implode("\n", [$property->summary, $property->description]);
505 1
                self::mapValidation($property->validation, $propertySchema);
0 ignored issues
show
It seems like $property->validation can also be of type array; however, PhpBoot\Docgen\Swagger\Swagger::mapValidation() does only seem to accept string, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
506 1
                unset($propertySchema->required);
507
            }
508 1
            $schema->properties[$property->name] = $propertySchema;
509 1
        }
510
511 1
        return $schema;
512
    }
513
514 1
    public function hasFileParam(Route $route)
515
    {
516 1
        $params = $route->getRequestHandler()->getParamMetas();
517 1
        foreach ($params as $name => $param) {
518 1
            if(strpos($param->source, 'request.files.')===0){
519 1
                return true;
520
            }
521 1
        }
522 1
        return false;
523
    }
524
    /**
525
     * @param string $v
526
     * @param PrimitiveSchemaObject $schemaObject
527
     * @return PrimitiveSchemaObject
528
     */
529 1
    static public function mapValidation($v, PrimitiveSchemaObject $schemaObject)
530
    {
531 1
        if(!$v){
532 1
            return $schemaObject;
533
        }
534 1
        $rules = explode('|', $v);
535 1
        foreach ($rules as $r) {
536 1
            $params = explode(':', trim($r));
537 1
            $rule = $params[0];
538 1
            $params = isset($params[1]) ? explode(',', $params[1]) : [];
539
540 1
            if ($rule == 'required') {
541
                $schemaObject->required = true;
542 1
            } elseif ($rule == 'in') {
543
                $schemaObject->enum = $params;
544 1
            } elseif ($rule == 'lengthBetween' && isset($params[0]) && isset($params[1])) {
545
                $schemaObject->minLength = intval($params[0]);
546
                $schemaObject->maxLength = intval($params[1]);
547 1
            } elseif ($rule == 'lengthMin'&& isset($params[0])) {
548
                $schemaObject->minLength = intval($params[0]);
549 1
            } elseif ($rule == 'lengthMax'&& isset($params[0])) {
550
                $schemaObject->maxLength = intval($params[0]);
551 1
            } elseif ($rule == 'min'&& isset($params[0])) {
552 1
                $schemaObject->minimum = floatval($params[0]);
0 ignored issues
show
Documentation Bug introduced by
The property $minimum was declared of type integer, but floatval($params[0]) is of type double. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
553 1
            } elseif ($rule == 'max'&& isset($params[0])) {
554 1
                $schemaObject->maximum = floatval($params[0]);
0 ignored issues
show
Documentation Bug introduced by
The property $maximum was declared of type integer, but floatval($params[0]) is of type double. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
555 1
            } elseif ($rule == 'regex'&& isset($params[0])) {
556
                $schemaObject->pattern = $params[0];
557
            } elseif ($rule == 'optional') {
558
                $schemaObject->required = false;
559
            }
560 1
        }
561 1
        return $schemaObject;
562
    }
563
564
    /**
565
     * @param string $type
566
     * @return string
567
     */
568 1
    static public function mapType($type)
569
    {
570
        //TODO 如何处理 file、mixed 类型
571
        $map = [
572 1
            'int' => 'integer',
573 1
            'bool' => 'boolean',
574 1
            'float' => 'number',
575 1
            'mixed' => null,
576 1
        ];
577 1
        if (array_key_exists($type, $map)) {
578 1
            return $map[$type];
579
        }
580 1
        return $type;
581
    }
582
583
    /**
584
     * @param $className
585
     * @return string
586
     */
587 1
    static public function getShortClassName($className)
588
    {
589 1
        $className = explode('\\', $className);
590 1
        $className = $className[count($className) - 1];
591 1
        return $className;
592
    }
593
594
    static public function implode($glue , array $pieces )
595
    {
596
        $pieces = array_filter($pieces, function($i){return trim($i) !== '';});
597 1
        return implode($glue, $pieces);
598
    }
599
}