• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

RonasIT / laravel-swagger / 4337150374

pending completion
4337150374

Pull #79

github

GitHub
Merge aa219043f into 7187aa030
Pull Request #79: #78: Added new PhpUnit extension and event subscriber to support PhpUnit v10 and deleted redundant PushDocumentation artisan command

7 of 7 new or added lines in 2 files covered. (100.0%)

446 of 476 relevant lines covered (93.7%)

10.37 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

95.65
/src/Services/SwaggerService.php
1
<?php
2

3
namespace RonasIT\Support\AutoDoc\Services;
4

5
use Illuminate\Container\Container;
6
use Illuminate\Http\Testing\File;
7
use Illuminate\Support\Arr;
8
use Illuminate\Support\Str;
9
use ReflectionClass;
10
use Illuminate\Http\Request;
11
use RonasIT\Support\AutoDoc\Exceptions\LegacyConfigException;
12
use RonasIT\Support\AutoDoc\Exceptions\WrongSecurityConfigException;
13
use RonasIT\Support\AutoDoc\Traits\GetDependenciesTrait;
14
use Symfony\Component\HttpFoundation\Response;
15
use RonasIT\Support\AutoDoc\Interfaces\SwaggerDriverInterface;
16
use RonasIT\Support\AutoDoc\Exceptions\InvalidDriverClassException;
17
use RonasIT\Support\AutoDoc\Exceptions\SwaggerDriverClassNotFoundException;
18

19
/**
20
 * @property SwaggerDriverInterface $driver
21
 */
22
class SwaggerService
23
{
24
    use GetDependenciesTrait;
25

26
    protected $driver;
27

28
    protected $data;
29
    protected $config;
30
    protected $container;
31
    private $uri;
32
    private $method;
33
    /**
34
     * @var Request
35
     */
36
    private $request;
37
    private $item;
38
    private $security;
39

40
    protected $ruleToTypeMap = [
41
        'array' => 'object',
42
        'boolean' => 'boolean',
43
        'date' => 'date',
44
        'digits' => 'integer',
45
        'integer' => 'integer',
46
        'numeric' => 'double',
47
        'string' => 'string',
48
        'int' => 'integer'
49
    ];
50

51
    public function __construct(Container $container)
52
    {
53
        $this->initConfig();
32✔
54

55
        $this->setDriver();
30✔
56

57
        if (config('app.env') == 'testing') {
28✔
58
            $this->container = $container;
28✔
59

60
            $this->security = $this->config['security'];
28✔
61

62
            $this->data = $this->driver->getTmpData();
28✔
63

64
            if (empty($this->data)) {
28✔
65
                $this->data = $this->generateEmptyData();
2✔
66

67
                $this->driver->saveTmpData($this->data);
1✔
68
            }
69
        }
70
    }
71

72
    protected function initConfig()
73
    {
74
        $this->config = config('auto-doc');
32✔
75

76
        $version = Arr::get($this->config, 'config_version');
32✔
77

78
        if (empty($version)) {
32✔
79
            throw new LegacyConfigException();
1✔
80
        }
81

82
        $packageConfigs = require __DIR__ . '/../../config/auto-doc.php';
31✔
83

84
        if (version_compare($packageConfigs['config_version'], $version, '>')) {
31✔
85
            throw new LegacyConfigException();
1✔
86
        }
87
    }
88

89
    protected function setDriver()
90
    {
91
        $driver = $this->config['driver'];
30✔
92
        $className = Arr::get($this->config, "drivers.{$driver}.class");
30✔
93

94
        if (!class_exists($className)) {
30✔
95
            throw new SwaggerDriverClassNotFoundException($className);
1✔
96
        } else {
97
            $this->driver = app($className);
29✔
98
        }
99

100
        if (!$this->driver instanceof SwaggerDriverInterface) {
29✔
101
            throw new InvalidDriverClassException($driver);
1✔
102
        }
103
    }
104

105
    protected function generateEmptyData(): array
106
    {
107
        $data = [
2✔
108
            'swagger' => Arr::get($this->config, 'swagger.version'),
2✔
109
            'host' => $this->getAppUrl(),
2✔
110
            'basePath' => $this->config['basePath'],
2✔
111
            'schemes' => $this->config['schemes'],
2✔
112
            'paths' => [],
2✔
113
            'definitions' => $this->config['definitions']
2✔
114
        ];
2✔
115

116
        $info = $this->prepareInfo($this->config['info']);
2✔
117

118
        if (!empty($info)) {
2✔
119
            $data['info'] = $info;
2✔
120
        }
121

122
        $securityDefinitions = $this->generateSecurityDefinition();
2✔
123

124
        if (!empty($securityDefinitions)) {
1✔
125
            $data['securityDefinitions'] = $securityDefinitions;
×
126
        }
127

128
        if (!empty($data['info']['description'])) {
1✔
129
            $data['info']['description'] = view($data['info']['description'])->render();
1✔
130
        }
131

132
        return $data;
1✔
133
    }
134

135
    protected function getAppUrl()
136
    {
137
        $url = config('app.url');
2✔
138

139
        return str_replace(['http://', 'https://', '/'], '', $url);
2✔
140
    }
141

142
    protected function generateSecurityDefinition()
143
    {
144
        if (empty($this->security)) {
2✔
145
            return '';
1✔
146
        }
147

148
        return [
1✔
149
            $this->security => $this->generateSecurityDefinitionObject($this->security)
1✔
150
        ];
1✔
151
    }
152

153
    protected function generateSecurityDefinitionObject($type): array
154
    {
155
        switch ($type) {
156
            case 'jwt':
1✔
157
                return [
×
158
                    'type' => 'apiKey',
×
159
                    'name' => 'authorization',
×
160
                    'in' => 'header'
×
161
                ];
×
162

163
            case 'laravel':
1✔
164
                return [
×
165
                    'type' => 'apiKey',
×
166
                    'name' => 'Cookie',
×
167
                    'in' => 'header'
×
168
                ];
×
169
            default:
170
                throw new WrongSecurityConfigException();
1✔
171
        }
172
    }
173

174
    public function addData(Request $request, $response)
175
    {
176
        $this->request = $request;
18✔
177

178
        $this->prepareItem();
18✔
179

180
        $this->parseRequest();
18✔
181
        $this->parseResponse($response);
18✔
182

183
        $this->driver->saveTmpData($this->data);
18✔
184
    }
185

186
    protected function prepareItem()
187
    {
188
        $this->uri = "/{$this->getUri()}";
18✔
189
        $this->method = strtolower($this->request->getMethod());
18✔
190

191
        if (empty(Arr::get($this->data, "paths.{$this->uri}.{$this->method}"))) {
18✔
192
            $this->data['paths'][$this->uri][$this->method] = [
18✔
193
                'tags' => [],
18✔
194
                'consumes' => [],
18✔
195
                'produces' => [],
18✔
196
                'parameters' => $this->getPathParams(),
18✔
197
                'responses' => [],
18✔
198
                'security' => [],
18✔
199
                'description' => ''
18✔
200
            ];
18✔
201
        }
202

203
        $this->item = &$this->data['paths'][$this->uri][$this->method];
18✔
204
    }
205

206
    protected function getUri()
207
    {
208
        $uri = $this->request->route()->uri();
18✔
209
        $basePath = preg_replace("/^\//", '', $this->config['basePath']);
18✔
210
        $preparedUri = preg_replace("/^{$basePath}/", '', $uri);
18✔
211

212
        return preg_replace("/^\//", '', $preparedUri);
18✔
213
    }
214

215
    protected function getPathParams(): array
216
    {
217
        $params = [];
18✔
218

219
        preg_match_all('/{.*?}/', $this->uri, $params);
18✔
220

221
        $params = Arr::collapse($params);
18✔
222

223
        $result = [];
18✔
224

225
        foreach ($params as $param) {
18✔
226
            $key = preg_replace('/[{}]/', '', $param);
2✔
227

228
            $result[] = [
2✔
229
                'in' => 'path',
2✔
230
                'name' => $key,
2✔
231
                'description' => '',
2✔
232
                'required' => true,
2✔
233
                'type' => 'string'
2✔
234
            ];
2✔
235
        }
236

237
        return $result;
18✔
238
    }
239

240
    protected function parseRequest()
241
    {
242
        $this->saveConsume();
18✔
243
        $this->saveTags();
18✔
244
        $this->saveSecurity();
18✔
245

246
        $concreteRequest = $this->getConcreteRequest();
18✔
247

248
        if (empty($concreteRequest)) {
18✔
249
            $this->item['description'] = '';
1✔
250

251
            return;
1✔
252
        }
253

254
        $annotations = $this->getClassAnnotations($concreteRequest);
17✔
255

256
        $this->saveParameters($concreteRequest, $annotations);
17✔
257
        $this->saveDescription($concreteRequest, $annotations);
17✔
258
    }
259

260
    protected function parseResponse($response)
261
    {
262
        $produceList = $this->data['paths'][$this->uri][$this->method]['produces'];
18✔
263

264
        $produce = $response->headers->get('Content-type');
18✔
265

266
        if (is_null($produce)) {
18✔
267
            $produce = 'text/plain';
1✔
268
        }
269

270
        if (!in_array($produce, $produceList)) {
18✔
271
            $this->item['produces'][] = $produce;
18✔
272
        }
273

274
        $responses = $this->item['responses'];
18✔
275

276
        $responseExampleLimitCount = config('auto-doc.response_example_limit_count');
18✔
277

278
        $content = json_decode($response->getContent(), true);
18✔
279

280
        if (!empty($responseExampleLimitCount)) {
18✔
281
            if (!empty($content['data'])) {
18✔
282
                $limitedResponseData = array_slice($content['data'], 0, $responseExampleLimitCount, true);
1✔
283
                $content['data'] = $limitedResponseData;
1✔
284
                $content['to'] = count($limitedResponseData);
1✔
285
                $content['total'] = count($limitedResponseData);
1✔
286
            }
287
        }
288

289
        if (!empty($content['exception'])) {
18✔
290
            $uselessKeys = array_keys(Arr::except($content, ['message']));
1✔
291

292
            $content = Arr::except($content, $uselessKeys);
1✔
293
        }
294

295
        $code = $response->getStatusCode();
18✔
296

297
        if (!in_array($code, $responses)) {
18✔
298
            $this->saveExample(
18✔
299
                $code,
18✔
300
                json_encode($content, JSON_PRETTY_PRINT),
18✔
301
                $produce
18✔
302
            );
18✔
303
        }
304
    }
305

306
    protected function saveExample($code, $content, $produce)
307
    {
308
        $description = $this->getResponseDescription($code);
18✔
309
        $availableContentTypes = [
18✔
310
            'application',
18✔
311
            'text'
18✔
312
        ];
18✔
313
        $explodedContentType = explode('/', $produce);
18✔
314

315
        if (in_array($explodedContentType[0], $availableContentTypes)) {
18✔
316
            $this->item['responses'][$code] = $this->makeResponseExample($content, $produce, $description);
17✔
317
        } else {
318
            $this->item['responses'][$code] = '*Unavailable for preview*';
1✔
319
        }
320
    }
321

322
    protected function makeResponseExample($content, $mimeType, $description = ''): array
323
    {
324
        $responseExample = ['description' => $description];
17✔
325

326
        if ($mimeType === 'application/json') {
17✔
327
            $responseExample['schema'] = ['example' => json_decode($content, true)];
14✔
328
        } elseif ($mimeType === 'application/pdf') {
3✔
329
            $responseExample['schema'] = ['example' => base64_encode($content)];
1✔
330
        } else {
331
            $responseExample['examples']['example'] = $content;
2✔
332
        }
333

334
        return $responseExample;
17✔
335
    }
336

337
    protected function saveParameters($request, array $annotations)
338
    {
339
        $formRequest = new $request();
17✔
340
        $formRequest->setUserResolver($this->request->getUserResolver());
17✔
341
        $formRequest->setRouteResolver($this->request->getRouteResolver());
17✔
342
        $rules = method_exists($formRequest, 'rules') ? $formRequest->rules() : [];
17✔
343
        $attributes = method_exists($formRequest, 'attributes') ? $formRequest->attributes() : [];
17✔
344

345
        $actionName = $this->getActionName($this->uri);
17✔
346

347
        if (in_array($this->method, ['get', 'delete'])) {
17✔
348
            $this->saveGetRequestParameters($rules, $attributes, $annotations);
13✔
349
        } else {
350
            $this->savePostRequestParameters($actionName, $rules, $attributes, $annotations);
4✔
351
        }
352
    }
353

354
    protected function saveGetRequestParameters($rules, array $attributes, array $annotations)
355
    {
356
        foreach ($rules as $parameter => $rule) {
13✔
357
            $validation = explode('|', $rule);
13✔
358

359
            $description = Arr::get($annotations, $parameter);
13✔
360

361
            if (empty($description)) {
13✔
362
                $description = Arr::get($attributes, $parameter, implode(', ', $validation));
13✔
363
            }
364

365
            $existedParameter = Arr::first($this->item['parameters'], function ($existedParameter) use ($parameter) {
13✔
366
                return $existedParameter['name'] == $parameter;
1✔
367
            });
13✔
368

369
            if (empty($existedParameter)) {
13✔
370
                $parameterDefinition = [
13✔
371
                    'in' => 'query',
13✔
372
                    'name' => $parameter,
13✔
373
                    'description' => $description,
13✔
374
                    'type' => $this->getParameterType($validation)
13✔
375
                ];
13✔
376
                if (in_array('required', $validation)) {
13✔
377
                    $parameterDefinition['required'] = true;
13✔
378
                }
379

380
                $this->item['parameters'][] = $parameterDefinition;
13✔
381
            }
382
        }
383
    }
384

385
    protected function savePostRequestParameters($actionName, $rules, array $attributes, array $annotations)
386
    {
387
        if ($this->requestHasMoreProperties($actionName)) {
4✔
388
            if ($this->requestHasBody()) {
4✔
389
                $this->item['parameters'][] = [
4✔
390
                    'in' => 'body',
4✔
391
                    'name' => 'body',
4✔
392
                    'description' => '',
4✔
393
                    'required' => true,
4✔
394
                    'schema' => [
4✔
395
                        "\$ref" => "#/definitions/{$actionName}Object"
4✔
396
                    ]
4✔
397
                ];
4✔
398
            }
399

400
            $this->saveDefinitions($actionName, $rules, $attributes, $annotations);
4✔
401
        }
402
    }
403

404
    protected function saveDefinitions($objectName, $rules, $attributes, array $annotations)
405
    {
406
        $data = [
4✔
407
            'type' => 'object',
4✔
408
            'properties' => []
4✔
409
        ];
4✔
410

411
        foreach ($rules as $parameter => $rule) {
4✔
412
            $rulesArray = (is_array($rule)) ? $rule : explode('|', $rule);
4✔
413
            $parameterType = $this->getParameterType($rulesArray);
4✔
414
            $this->saveParameterType($data, $parameter, $parameterType);
4✔
415

416
            $uselessRules = $this->ruleToTypeMap;
4✔
417
            $uselessRules['required'] = 'required';
4✔
418

419
            if (in_array('required', $rulesArray)) {
4✔
420
                $data['required'][] = $parameter;
4✔
421
            }
422

423
            $rulesArray = array_flip(array_diff_key(array_flip($rulesArray), $uselessRules));
4✔
424

425
            $this->saveParameterDescription($data, $parameter, $rulesArray, $attributes, $annotations);
4✔
426
        }
427

428
        $data['example'] = $this->generateExample($data['properties']);
4✔
429
        $this->data['definitions'][$objectName . 'Object'] = $data;
4✔
430
    }
431

432
    protected function getParameterType(array $validation): string
433
    {
434
        $validationRules = $this->ruleToTypeMap;
17✔
435
        $validationRules['email'] = 'string';
17✔
436

437
        $parameterType = 'string';
17✔
438

439
        foreach ($validation as $item) {
17✔
440
            if (in_array($item, array_keys($validationRules))) {
17✔
441
                return $validationRules[$item];
16✔
442
            }
443
        }
444

445
        return $parameterType;
1✔
446
    }
447

448
    protected function saveParameterType(&$data, $parameter, $parameterType)
449
    {
450
        $data['properties'][$parameter] = [
4✔
451
            'type' => $parameterType
4✔
452
        ];
4✔
453
    }
454

455
    protected function saveParameterDescription(&$data, $parameter, array $rulesArray, array $attributes, array $annotations)
456
    {
457
        $description = Arr::get($annotations, $parameter);
4✔
458

459
        if (empty($description)) {
4✔
460
            $description = Arr::get($attributes, $parameter, implode(', ', $rulesArray));
4✔
461
        }
462

463
        $data['properties'][$parameter]['description'] = $description;
4✔
464
    }
465

466
    protected function requestHasMoreProperties($actionName): bool
467
    {
468
        $requestParametersCount = count($this->request->all());
4✔
469

470
        if (isset($this->data['definitions'][$actionName . 'Object']['properties'])) {
4✔
471
            $objectParametersCount = count($this->data['definitions'][$actionName . 'Object']['properties']);
1✔
472
        } else {
473
            $objectParametersCount = 0;
3✔
474
        }
475

476
        return $requestParametersCount > $objectParametersCount;
4✔
477
    }
478

479
    protected function requestHasBody(): bool
480
    {
481
        $parameters = $this->data['paths'][$this->uri][$this->method]['parameters'];
4✔
482

483
        $bodyParamExisted = Arr::where($parameters, function ($value) {
4✔
484
            return $value['name'] == 'body';
1✔
485
        });
4✔
486

487
        return empty($bodyParamExisted);
4✔
488
    }
489

490
    public function getConcreteRequest()
491
    {
492
        $controller = $this->request->route()->getActionName();
18✔
493

494
        if ($controller == 'Closure') {
18✔
495
            return null;
1✔
496
        }
497

498
        $explodedController = explode('@', $controller);
17✔
499

500
        $class = $explodedController[0];
17✔
501
        $method = $explodedController[1];
17✔
502

503
        $instance = app($class);
17✔
504
        $route = $this->request->route();
17✔
505

506
        $parameters = $this->resolveClassMethodDependencies(
17✔
507
            $route->parametersWithoutNulls(),
17✔
508
            $instance,
17✔
509
            $method
17✔
510
        );
17✔
511

512
        return Arr::first($parameters, function ($key) {
17✔
513
            return preg_match('/Request/', $key);
17✔
514
        });
17✔
515
    }
516

517
    public function saveConsume()
518
    {
519
        $consumeList = $this->data['paths'][$this->uri][$this->method]['consumes'];
18✔
520
        $consume = $this->request->header('Content-Type');
18✔
521

522
        if (!empty($consume) && !in_array($consume, $consumeList)) {
18✔
523
            $this->item['consumes'][] = $consume;
14✔
524
        }
525
    }
526

527
    public function saveTags()
528
    {
529
        $tagIndex = 1;
18✔
530

531
        $explodedUri = explode('/', $this->uri);
18✔
532

533
        $tag = Arr::get($explodedUri, $tagIndex);
18✔
534

535
        $this->item['tags'] = [$tag];
18✔
536
    }
537

538
    public function saveDescription($request, array $annotations)
539
    {
540
        $this->item['summary'] = $this->getSummary($request, $annotations);
17✔
541

542
        $description = Arr::get($annotations, 'description');
17✔
543

544
        if (!empty($description)) {
17✔
545
            $this->item['description'] = $description;
1✔
546
        }
547
    }
548

549
    protected function saveSecurity()
550
    {
551
        if ($this->requestSupportAuth()) {
18✔
552
            $this->addSecurityToOperation();
3✔
553
        }
554
    }
555

556
    protected function addSecurityToOperation()
557
    {
558
        $security = &$this->data['paths'][$this->uri][$this->method]['security'];
3✔
559

560
        if (empty($security)) {
3✔
561
            $security[] = [
3✔
562
                "{$this->security}" => []
3✔
563
            ];
3✔
564
        }
565
    }
566

567
    protected function getSummary($request, array $annotations)
568
    {
569
        $summary = Arr::get($annotations, 'summary');
17✔
570

571
        if (empty($summary)) {
17✔
572
            $summary = $this->parseRequestName($request);
16✔
573
        }
574

575
        return $summary;
17✔
576
    }
577

578
    protected function requestSupportAuth(): bool
579
    {
580
        switch ($this->security) {
18✔
581
            case 'jwt':
18✔
582
                $header = $this->request->header('authorization');
5✔
583
                break;
5✔
584
            case 'laravel':
13✔
585
                $header = $this->request->cookie('__ym_uid');
2✔
586
                break;
2✔
587
        }
588

589
        return !empty($header);
18✔
590
    }
591

592
    protected function parseRequestName($request)
593
    {
594
        $explodedRequest = explode('\\', $request);
16✔
595
        $requestName = array_pop($explodedRequest);
16✔
596
        $summaryName = str_replace('Request', '', $requestName);
16✔
597

598
        $underscoreRequestName = $this->camelCaseToUnderScore($summaryName);
16✔
599

600
        return preg_replace('/[_]/', ' ', $underscoreRequestName);
16✔
601
    }
602

603
    protected function getResponseDescription($code)
604
    {
605
        $defaultDescription = Response::$statusTexts[$code];
18✔
606

607
        $request = $this->getConcreteRequest();
18✔
608

609
        if (empty($request)) {
18✔
610
            return $defaultDescription;
1✔
611
        }
612

613
        $annotations = $this->getClassAnnotations($request);
17✔
614

615
        $localDescription = Arr::get($annotations, "_{$code}");
17✔
616

617
        if (!empty($localDescription)) {
17✔
618
            return $localDescription;
1✔
619
        }
620

621
        return Arr::get($this->config, "defaults.code-descriptions.{$code}", $defaultDescription);
16✔
622
    }
623

624
    protected function getActionName($uri): string
625
    {
626
        $action = preg_replace('[\/]', '', $uri);
17✔
627

628
        return Str::camel($action);
17✔
629
    }
630

631
    protected function saveTempData()
632
    {
633
        $exportFile = Arr::get($this->config, 'files.temporary');
×
634
        $data = json_encode($this->data);
×
635

636
        file_put_contents($exportFile, $data);
×
637
    }
638

639
    public function saveProductionData()
640
    {
641
        $this->driver->saveData();
×
642
    }
643

644
    public function getDocFileContent()
645
    {
646
        $documentation = $this->driver->getDocumentation();
3✔
647

648
        $additionalDocs = config('auto-doc.additional_paths', []);
3✔
649

650
        foreach ($additionalDocs as $filePath) {
3✔
651
            $fileContent = json_decode(file_get_contents(base_path($filePath)), true);
1✔
652

653
            $paths = array_keys($fileContent['paths']);
1✔
654

655
            foreach ($paths as $path) {
1✔
656
                $additionalDocPath =  $fileContent['paths'][$path];
1✔
657

658
                if (empty($documentation['paths'][$path])) {
1✔
659
                    $documentation['paths'][$path] = $additionalDocPath;
1✔
660
                } else {
661
                    $methods = array_keys($documentation['paths'][$path]);
1✔
662
                    $additionalDocMethods = array_keys($additionalDocPath);
1✔
663

664
                    foreach ($additionalDocMethods as $method) {
1✔
665
                        if (!in_array($method, $methods)) {
1✔
666
                            $documentation['paths'][$path][$method] = $additionalDocPath[$method];
1✔
667
                        }
668
                    }
669
                }
670
            }
671

672
            $definitions = array_keys($fileContent['definitions']);
1✔
673

674
            foreach ($definitions as $definition) {
1✔
675
                if (empty($documentation['definitions'][$definition])) {
1✔
676
                    $documentation['definitions'][$definition] = $fileContent['definitions'][$definition];
1✔
677
                }
678
            }
679
        }
680

681
        return $documentation;
3✔
682
    }
683

684
    protected function camelCaseToUnderScore($input): string
685
    {
686
        preg_match_all('!([A-Z][A-Z0-9]*(?=$|[A-Z][a-z0-9])|[A-Za-z][a-z0-9]+)!', $input, $matches);
16✔
687
        $ret = $matches[0];
16✔
688

689
        foreach ($ret as &$match) {
16✔
690
            $match = $match == strtoupper($match) ? strtolower($match) : lcfirst($match);
16✔
691
        }
692

693
        return implode('_', $ret);
16✔
694
    }
695

696
    protected function generateExample($properties): array
697
    {
698
        $parameters = $this->replaceObjectValues($this->request->all());
4✔
699
        $example = [];
4✔
700

701
        $this->replaceNullValues($parameters, $properties, $example);
4✔
702

703
        return $example;
4✔
704
    }
705

706
    protected function replaceObjectValues($parameters): array
707
    {
708
        $classNamesValues = [
4✔
709
            File::class => '[uploaded_file]',
4✔
710
        ];
4✔
711

712
        $parameters = Arr::dot($parameters);
4✔
713
        $returnParameters = [];
4✔
714

715
        foreach ($parameters as $parameter => $value) {
4✔
716
            if (is_object($value)) {
4✔
717
                $class = get_class($value);
1✔
718

719
                $value = Arr::get($classNamesValues, $class, $class);
1✔
720
            }
721

722
            Arr::set($returnParameters, $parameter, $value);
4✔
723
        }
724

725
        return $returnParameters;
4✔
726
    }
727

728
    protected function getClassAnnotations($class): array
729
    {
730
        $reflection = new ReflectionClass($class);
17✔
731

732
        $annotations = $reflection->getDocComment();
17✔
733

734
        $blocks = explode("\n", $annotations);
17✔
735

736
        $result = [];
17✔
737

738
        foreach ($blocks as $block) {
17✔
739
            if (Str::contains($block, '@')) {
17✔
740
                $index = strpos($block, '@');
1✔
741
                $block = substr($block, $index);
1✔
742
                $exploded = explode(' ', $block);
1✔
743

744
                $paramName = str_replace('@', '', array_shift($exploded));
1✔
745
                $paramValue = implode(' ', $exploded);
1✔
746

747
                $result[$paramName] = $paramValue;
1✔
748
            }
749
        }
750

751
        return $result;
17✔
752
    }
753

754
    /**
755
     * NOTE: All functions below are temporary solution for
756
     * this issue: https://github.com/OAI/OpenAPI-Specification/issues/229
757
     * We hope swagger developers will resolve this problem in next release of Swagger OpenAPI
758
     * */
759
    protected function replaceNullValues($parameters, $types, &$example)
760
    {
761
        foreach ($parameters as $parameter => $value) {
4✔
762
            if (is_null($value) && array_key_exists($parameter, $types)) {
4✔
763
                $example[$parameter] = $this->getDefaultValueByType($types[$parameter]['type']);
3✔
764
            } elseif (is_array($value)) {
4✔
765
                $this->replaceNullValues($value, $types, $example[$parameter]);
1✔
766
            } else {
767
                $example[$parameter] = $value;
4✔
768
            }
769
        }
770
    }
771

772
    protected function getDefaultValueByType($type)
773
    {
774
        $values = [
3✔
775
            'object' => 'null',
3✔
776
            'boolean' => false,
3✔
777
            'date' => "0000-00-00",
3✔
778
            'integer' => 0,
3✔
779
            'string' => '',
3✔
780
            'double' => 0
3✔
781
        ];
3✔
782

783
        return $values[$type];
3✔
784
    }
785

786
    /**
787
     * @param $info
788
     * @return mixed
789
     */
790
    protected function prepareInfo($info)
791
    {
792
        if (empty($info)) {
2✔
793
            return $info;
×
794
        }
795

796
        foreach ($info['license'] as $key => $value) {
2✔
797
            if (empty($value)) {
2✔
798
                unset($info['license'][$key]);
2✔
799
            }
800
        }
801
        if (empty($info['license'])) {
2✔
802
            unset($info['license']);
2✔
803
        }
804

805
        return $info;
2✔
806
    }
807
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc