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

DoclerLabs / api-client-generator / 21418891888

27 Jan 2026 11:51PM UTC coverage: 86.69% (-0.3%) from 86.973%
21418891888

Pull #131

github

web-flow
Bump phpunit/phpunit from 9.5.9 to 9.6.33

Bumps [phpunit/phpunit](https://github.com/sebastianbergmann/phpunit) from 9.5.9 to 9.6.33.
- [Release notes](https://github.com/sebastianbergmann/phpunit/releases)
- [Changelog](https://github.com/sebastianbergmann/phpunit/blob/9.6.33/ChangeLog-9.6.md)
- [Commits](https://github.com/sebastianbergmann/phpunit/compare/9.5.9...9.6.33)

---
updated-dependencies:
- dependency-name: phpunit/phpunit
  dependency-version: 9.6.33
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>
Pull Request #131: Bump phpunit/phpunit from 9.5.9 to 9.6.33

3465 of 3997 relevant lines covered (86.69%)

7.11 hits per line

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

95.95
/src/Generator/RequestGenerator.php
1
<?php
2

3
declare(strict_types=1);
4

5
namespace DoclerLabs\ApiClientGenerator\Generator;
6

7
use DateTimeInterface;
8
use DoclerLabs\ApiClientGenerator\Ast\Builder\CodeBuilder;
9
use DoclerLabs\ApiClientGenerator\Ast\Builder\ParameterBuilder;
10
use DoclerLabs\ApiClientGenerator\Ast\ParameterNode;
11
use DoclerLabs\ApiClientGenerator\Ast\PhpVersion;
12
use DoclerLabs\ApiClientGenerator\Entity\Field;
13
use DoclerLabs\ApiClientGenerator\Entity\Operation;
14
use DoclerLabs\ApiClientGenerator\Entity\Request;
15
use DoclerLabs\ApiClientGenerator\Generator\Security\SecurityStrategyInterface;
16
use DoclerLabs\ApiClientGenerator\Input\InvalidSpecificationException;
17
use DoclerLabs\ApiClientGenerator\Input\Specification;
18
use DoclerLabs\ApiClientGenerator\Naming\CopiedNamespace;
19
use DoclerLabs\ApiClientGenerator\Naming\RequestNaming;
20
use DoclerLabs\ApiClientGenerator\Output\Copy\Schema\SerializableInterface;
21
use DoclerLabs\ApiClientGenerator\Output\Php\PhpFileCollection;
22
use PhpParser\Node\Expr\FuncCall;
23
use PhpParser\Node\Stmt\ClassMethod;
24

25
class RequestGenerator extends MutatorAccessorClassGeneratorAbstract
26
{
27
    public const NAMESPACE_SUBPATH = '\\Request';
28

29
    public const SUBDIRECTORY = 'Request/';
30

31
    private const CONTENT_TYPE_PARAMETER_NAME = 'contentType';
32

33
    /** @var SecurityStrategyInterface[] */
34
    private array $securityStrategies;
35

36
    private bool $isContentTypeEnum = false;
37

38
    public function __construct(
39
        string $baseNamespace,
40
        CodeBuilder $builder,
41
        PhpVersion $phpVersion,
42
        SecurityStrategyInterface ...$securityStrategies
43
    ) {
44
        parent::__construct($baseNamespace, $builder, $phpVersion);
38✔
45

46
        $this->securityStrategies = $securityStrategies;
38✔
47
    }
48

49
    public function generate(Specification $specification, PhpFileCollection $fileRegistry): void
50
    {
51
        foreach ($specification->getOperations() as $operation) {
38✔
52
            $this->isContentTypeEnum = false;
38✔
53
            $this->generateRequest($fileRegistry, $operation, $specification);
38✔
54
        }
55
    }
56

57
    protected function generateRequest(
58
        PhpFileCollection $fileRegistry,
59
        Operation $operation,
60
        Specification $specification
61
    ): void {
62
        $className = RequestNaming::getClassName($operation);
38✔
63
        $request   = $operation->request;
38✔
64

65
        $classBuilder = $this
38✔
66
            ->builder
38✔
67
            ->class($className)
38✔
68
            ->implement('RequestInterface')
38✔
69
            ->addStmts($this->generateEnums($request))
38✔
70
            ->addStmts($this->generateProperties($request, $operation, $specification))
38✔
71
            ->addStmt($this->generateConstructor($request, $operation, $specification))
38✔
72
            ->addStmt($this->generateGetContentType())
38✔
73
            ->addStmts($this->generateSetters($request))
38✔
74
            ->addStmt($this->generateGetMethod($request))
38✔
75
            ->addStmt($this->generateGetRoute($request))
38✔
76
            ->addStmts($this->generateGetParametersMethods($request, $operation, $specification));
38✔
77

78
        foreach ($this->securityStrategies as $securityStrategy) {
38✔
79
            $this->getImports()->append($securityStrategy->getImports($this->baseNamespace));
38✔
80
        }
81

82
        $this->registerFile($fileRegistry, $classBuilder, self::SUBDIRECTORY, self::NAMESPACE_SUBPATH);
38✔
83
    }
84

85
    protected function generateEnums(Request $request): array
86
    {
87
        $statements = [];
38✔
88
        foreach ($request->fields as $field) {
38✔
89
            foreach ($this->generateEnumStatements($field) as $statement) {
38✔
90
                $statements[] = $statement;
16✔
91
            }
92
        }
93

94
        return $statements;
38✔
95
    }
96

97
    protected function generateProperties(Request $request, Operation $operation, Specification $specification): array
98
    {
99
        $statements = [];
38✔
100
        $fieldNames = [];
38✔
101

102
        foreach ($request->fields as $field) {
38✔
103
            if ($field->isComposite()) {
38✔
104
                $this->addImport(
34✔
105
                    sprintf(
34✔
106
                        '%s%s\\%s',
34✔
107
                        $this->baseNamespace,
34✔
108
                        SchemaGenerator::NAMESPACE_SUBPATH,
34✔
109
                        $field->getPhpClassName()
34✔
110
                    )
34✔
111
                );
34✔
112
            }
113
            if ($field->isDate()) {
38✔
114
                $this->addImport(DateTimeInterface::class);
8✔
115
            } elseif ($field->isEnum() && $this->phpVersion->isEnumSupported()) {
38✔
116
                $this->addImport($this->fqdn($this->withSubNamespace(SchemaGenerator::NAMESPACE_SUBPATH), $field->getPhpClassName()));
14✔
117
            }
118
            if (
119
                $field->isRequired()
38✔
120
                && $this->phpVersion->isConstructorPropertyPromotionSupported()
38✔
121
            ) {
122
                continue;
21✔
123
            }
124

125
            $statements[] = $this->generateProperty($field);
35✔
126
            $fieldNames[] = $field->getPhpVariableName();
35✔
127
        }
128

129
        $default               = null;
38✔
130
        $bodyContentTypesCount = count($request->bodyContentTypes);
38✔
131
        if ($bodyContentTypesCount < 2) {
38✔
132
            $default = $this->builder->val($request->bodyContentTypes[0] ?? '');
34✔
133
        }
134

135
        if (
136
            ($bodyContentTypesCount < 2 || !$this->phpVersion->isConstructorPropertyPromotionSupported())
38✔
137
            && !in_array(self::CONTENT_TYPE_PARAMETER_NAME, $fieldNames, true)
38✔
138
        ) {
139
            $statements[] = $this->builder->localProperty(self::CONTENT_TYPE_PARAMETER_NAME, 'string', 'string', false, $default);
34✔
140
        }
141

142
        foreach ($this->securityStrategies as $securityStrategy) {
38✔
143
            array_push($statements, ...$securityStrategy->getProperties($operation, $specification));
38✔
144
        }
145

146
        return $statements;
38✔
147
    }
148

149
    protected function generateConstructor(
150
        Request $request,
151
        Operation $operation,
152
        Specification $specification
153
    ): ?ClassMethod {
154
        $paramNames  = [];
38✔
155
        $params      = [];
38✔
156
        $paramInits  = [];
38✔
157
        $validations = [];
38✔
158
        foreach ($request->fields as $field) {
38✔
159
            if ($field->isRequired()) {
38✔
160
                array_push($validations, ...$this->generateValidationStmts($field));
30✔
161

162
                $param = $this
30✔
163
                    ->builder
30✔
164
                    ->param($field->getPhpVariableName())
30✔
165
                    ->setType($field->getPhpTypeHint(), $field->isNullable());
30✔
166

167
                if (($default = $field->getDefault()) !== null) {
30✔
168
                    if ($field->isEnum() && $this->phpVersion->isEnumSupported() && (
16✔
169
                        is_string($default)
16✔
170
                        || is_integer($default)
16✔
171
                    )) {
172
                        $param->setDefault($this->builder->classConstFetch(
8✔
173
                            $field->getPhpClassName(),
8✔
174
                            EnumGenerator::getCaseName((string)$default)
8✔
175
                        ));
8✔
176
                    } else {
177
                        $param->setDefault($field->getDefault());
8✔
178
                    }
179
                }
180

181
                $params[]     = $param;
30✔
182
                $paramNames[] = $field->getPhpVariableName();
30✔
183

184
                if (
185
                    $field->isEnum()
30✔
186
                    && $this->phpVersion->isEnumSupported()
30✔
187
                    && $field->getPhpVariableName() === self::CONTENT_TYPE_PARAMETER_NAME
30✔
188
                ) {
189
                    $this->isContentTypeEnum = true;
2✔
190
                }
191

192
                $paramInits[] = $this->builder->assign(
30✔
193
                    $this->builder->localPropertyFetch($field->getPhpVariableName()),
30✔
194
                    $this->builder->var($field->getPhpVariableName())
30✔
195
                );
30✔
196
            }
197
        }
198

199
        foreach ($this->securityStrategies as $securityStrategy) {
38✔
200
            array_push($params, ...$securityStrategy->getConstructorParams($operation, $specification));
38✔
201
            array_push($paramInits, ...$securityStrategy->getConstructorParamInits($operation, $specification));
38✔
202
        }
203

204
        if (count($request->bodyContentTypes) > 1 && !in_array(self::CONTENT_TYPE_PARAMETER_NAME, $paramNames, true)) {
38✔
205
            $params[] = $this->builder->param(self::CONTENT_TYPE_PARAMETER_NAME)->setType('string');
2✔
206

207
            $paramInits[] = $this->builder->assign(
2✔
208
                $this->builder->localPropertyFetch(self::CONTENT_TYPE_PARAMETER_NAME),
2✔
209
                $this->builder->var(self::CONTENT_TYPE_PARAMETER_NAME)
2✔
210
            );
2✔
211
        }
212

213
        if (empty($params)) {
38✔
214
            return null;
2✔
215
        }
216

217
        if ($this->phpVersion->isConstructorPropertyPromotionSupported()) {
38✔
218
            foreach ($params as $param) {
27✔
219
                $param->makePrivate();
27✔
220
            }
221
        }
222
        if ($this->phpVersion->isReadonlyPropertySupported()) {
38✔
223
            foreach ($params as $param) {
18✔
224
                $param->makeReadonly();
18✔
225
            }
226
        }
227

228
        $params = array_map(
38✔
229
            static fn (ParameterBuilder $param): ParameterNode => $param->getNode(),
38✔
230
            $params
38✔
231
        );
38✔
232

233
        $params = $this->sortParameters(...$params);
38✔
234

235
        $constructor = $this->builder
38✔
236
            ->method('__construct')
38✔
237
            ->makePublic()
38✔
238
            ->addParams($params)
38✔
239
            ->addStmts($validations)
38✔
240
            ->composeDocBlock($params);
38✔
241

242
        if (!$this->phpVersion->isConstructorPropertyPromotionSupported()) {
38✔
243
            $constructor->addStmts($paramInits);
11✔
244
        }
245

246
        return $constructor->getNode();
38✔
247
    }
248

249
    private function generateSetters(Request $request): array
250
    {
251
        $statements = [];
38✔
252
        foreach ($request->fields as $field) {
38✔
253
            if ($field->isRequired()) {
38✔
254
                continue;
30✔
255
            }
256
            if ($field->isNullable()) {
34✔
257
                throw new InvalidSpecificationException('Nullable optional parameter is not supported');
×
258
            }
259
            $statements[] = $this->generateSet($field);
34✔
260
        }
261

262
        return $statements;
38✔
263
    }
264

265
    private function generateGetContentType(): ClassMethod
266
    {
267
        $localProperty = $this->builder->localPropertyFetch(self::CONTENT_TYPE_PARAMETER_NAME);
38✔
268
        $returnType    = 'string';
38✔
269

270
        if ($this->isContentTypeEnum) {
38✔
271
            $localProperty = $this->builder->propertyFetch($localProperty, 'value');
2✔
272
        }
273

274
        $return = $this->builder->return($localProperty);
38✔
275

276
        return $this
38✔
277
            ->builder
38✔
278
            ->method('getContentType')
38✔
279
            ->makePublic()
38✔
280
            ->addStmt($return)
38✔
281
            ->setReturnType($returnType)
38✔
282
            ->composeDocBlock([], $returnType)
38✔
283
            ->getNode();
38✔
284
    }
285

286
    private function generateGetMethod(Request $request): ClassMethod
287
    {
288
        $return     = $this->builder->return($this->builder->val($request->method));
38✔
289
        $returnType = 'string';
38✔
290

291
        return $this
38✔
292
            ->builder
38✔
293
            ->method('getMethod')
38✔
294
            ->makePublic()
38✔
295
            ->addStmt($return)
38✔
296
            ->setReturnType($returnType)
38✔
297
            ->composeDocBlock([], $returnType)
38✔
298
            ->getNode();
38✔
299
    }
300

301
    private function generateGetRoute(Request $request): ClassMethod
302
    {
303
        $values     = [];
38✔
304
        $returnType = 'string';
38✔
305

306
        foreach ($request->fields->getPathFields() as $field) {
38✔
307
            /** @var Field $field */
308
            $key = sprintf('{%s}', $field->getName());
14✔
309
            if (
310
                $this->phpVersion->isEnumSupported()
14✔
311
                && $field->isEnum()
14✔
312
            ) {
313
                $values[$key] = $this->builder->propertyFetch(
2✔
314
                    $this->builder->localPropertyFetch($field->getPhpVariableName()),
2✔
315
                    'value'
2✔
316
                );
2✔
317
            } else {
318
                $values[$key] = $this->builder->localPropertyFetch($field->getPhpVariableName());
12✔
319
            }
320
        }
321

322
        if (empty($values)) {
38✔
323
            $return = $this->builder->return($this->builder->val($request->path));
26✔
324

325
            return $this
26✔
326
                ->builder
26✔
327
                ->method('getRoute')
26✔
328
                ->makePublic()
26✔
329
                ->addStmt($return)
26✔
330
                ->setReturnType($returnType)
26✔
331
                ->composeDocBlock([], $returnType)
26✔
332
                ->getNode();
26✔
333
        }
334

335
        $map    = $this->builder->array($values);
14✔
336
        $return = $this->builder->return(
14✔
337
            $this->builder->funcCall('strtr', [$this->builder->val($request->path), $map])
14✔
338
        );
14✔
339

340
        return $this
14✔
341
            ->builder
14✔
342
            ->method('getRoute')
14✔
343
            ->makePublic()
14✔
344
            ->addStmt($return)
14✔
345
            ->setReturnType($returnType)
14✔
346
            ->composeDocBlock([], $returnType)
14✔
347
            ->getNode();
14✔
348
    }
349

350
    private function generateGetParametersMethods(
351
        Request $request,
352
        Operation $operation,
353
        Specification $specification
354
    ): array {
355
        $methods = [];
38✔
356
        $fields  = $request->fields;
38✔
357

358
        $securityQueryFields = $this->getSecurityQueryParameters($operation, $specification);
38✔
359
        $securityCookies     = $this->getSecurityCookies($operation, $specification);
38✔
360

361
        $methods[] = $this->generateGetParametersMethod('getQueryParameters', $fields->getQueryFields(), $securityQueryFields);
38✔
362
        $methods[] = $this->generateGetRawParametersMethod('getRawQueryParameters', $fields->getQueryFields(), $securityQueryFields);
38✔
363
        $methods[] = $this->generateGetParametersMethod('getCookies', $fields->getCookieFields(), $securityCookies);
38✔
364
        $methods[] = $this->generateGetHeadersMethod($request, $fields->getHeaderFields(), $operation, $specification);
38✔
365
        $methods[] = $this->generateGetBody($fields->getBody());
38✔
366

367
        return $methods;
38✔
368
    }
369

370
    private function generateGetParametersMethod(string $methodName, array $fields, array $securityFields): ClassMethod
371
    {
372
        $returnVal  = $this->builder->array([]);
38✔
373
        $fieldsArr  = $this->generateFieldsArray($fields);
38✔
374
        $returnType = 'array';
38✔
375

376
        if (!empty($fieldsArr)) {
38✔
377
            if (empty($securityFields)) {
34✔
378
                $returnVal = $this->generateParametersFromFields($fieldsArr);
18✔
379
            } else {
380
                $returnVal = $this->builder->funcCall(
16✔
381
                    'array_merge',
16✔
382
                    [
16✔
383
                        $this->generateParametersFromFields($fieldsArr),
16✔
384
                        $securityFields,
16✔
385
                    ]
16✔
386
                );
16✔
387
            }
388
        } else {
389
            $returnVal = $this->builder->array($securityFields);
30✔
390
        }
391

392
        return $this
38✔
393
            ->builder
38✔
394
            ->method($methodName)
38✔
395
            ->makePublic()
38✔
396
            ->addStmt($this->builder->return($returnVal))
38✔
397
            ->setReturnType($returnType)
38✔
398
            ->composeDocBlock([], $returnType)
38✔
399
            ->getNode();
38✔
400
    }
401

402
    private function generateGetRawParametersMethod(string $methodName, array $fields, array $securityFields): ClassMethod
403
    {
404
        $fieldsArr  = $this->generateFieldsArray($fields);
38✔
405
        $returnType = 'array';
38✔
406

407
        return $this
38✔
408
            ->builder
38✔
409
            ->method($methodName)
38✔
410
            ->makePublic()
38✔
411
            ->addStmt($this->builder->return($this->builder->array(array_merge($fieldsArr, $securityFields))))
38✔
412
            ->setReturnType($returnType)
38✔
413
            ->composeDocBlock([], $returnType)
38✔
414
            ->getNode();
38✔
415
    }
416

417
    private function generateFieldsArray(array $fields): array
418
    {
419
        $fieldsArr = [];
38✔
420
        foreach ($fields as $field) {
38✔
421
            /** @var Field $field */
422
            $fieldsArr[$field->getName()] = $this->builder->localPropertyFetch($field->getPhpVariableName());
34✔
423

424
            if ($this->phpVersion->isEnumSupported()) {
34✔
425
                if ($field->isEnum()) {
16✔
426
                    if ($field->isNullable() || $field->isOptional()) {
4✔
427
                        $fieldsArr[$field->getName()] = $this->builder->nullsafePropertyFetch($fieldsArr[$field->getName()], 'value');
4✔
428
                    } else {
429
                        $fieldsArr[$field->getName()] = $this->builder->propertyFetch($fieldsArr[$field->getName()], 'value');
4✔
430
                    }
431
                } elseif ($field->isArrayOfEnums()) {
16✔
432
                    $enumField = $field->getArrayItem();
×
433
                    $this->addImport($this->fqdn($this->withSubNamespace(SchemaGenerator::NAMESPACE_SUBPATH), $enumField->getPhpClassName()));
×
434
                    $fieldsArr[$field->getName()] = $this->builder->funcCall(
×
435
                        'array_map',
×
436
                        [
×
437
                            $this->builder->arrowFunction(
×
438
                                $this->builder->propertyFetch($this->builder->var('enum'), 'value'),
×
439
                                [$this->builder->param('enum')->setType($enumField->getPhpClassName())->getNode()],
×
440
                                $enumField->getType()->toPhpType()
×
441
                            ),
×
442
                            $fieldsArr[$field->getName()],
×
443
                        ]
×
444
                    );
×
445
                }
446
            }
447
        }
448

449
        return $fieldsArr;
38✔
450
    }
451

452
    private function generateGetBody(?Field $body): ClassMethod
453
    {
454
        if ($body !== null) {
38✔
455
            $returnType = $body->getPhpTypeHint();
26✔
456

457
            return $this
26✔
458
                ->builder
26✔
459
                ->method('getBody')
26✔
460
                ->makePublic()
26✔
461
                ->addStmt($this->builder->return($this->builder->localPropertyFetch($body->getPhpVariableName())))
26✔
462
                ->composeDocBlock([], $returnType)
26✔
463
                ->getNode();
26✔
464
        }
465

466
        return $this
14✔
467
            ->builder
14✔
468
            ->method('getBody')
14✔
469
            ->makePublic()
14✔
470
            ->addStmt($this->builder->return($this->builder->val(null)))
14✔
471
            ->getNode();
14✔
472
    }
473

474
    private function generateGetHeadersMethod(
475
        Request $request,
476
        array $fields,
477
        Operation $operation,
478
        Specification $specification
479
    ): ClassMethod {
480
        $stmts   = $this->getSecurityHeadersStmts($operation, $specification);
38✔
481
        $headers = $this->getSecurityHeaders($operation, $specification);
38✔
482
        if (!empty($request->bodyContentTypes)) {
38✔
483
            $contentType = $this->builder->localPropertyFetch('contentType');
26✔
484

485
            if ($this->isContentTypeEnum) {
26✔
486
                $contentType = $this->builder->propertyFetch($contentType, 'value');
2✔
487
            }
488

489
            $headers['Content-Type'] = $contentType;
26✔
490
        }
491

492
        $returnVal  = $this->builder->array($headers);
38✔
493
        $fieldsArr  = [];
38✔
494
        $returnType = 'array';
38✔
495
        foreach ($fields as $field) {
38✔
496
            $fieldsArr[$field->getName()] = $this->builder->localPropertyFetch($field->getPhpVariableName());
26✔
497
        }
498

499
        if (!empty($fieldsArr)) {
38✔
500
            $returnVal = $this->builder->funcCall(
26✔
501
                'array_merge',
26✔
502
                [$returnVal, $this->generateParametersFromFields($fieldsArr)]
26✔
503
            );
26✔
504
        }
505

506
        return $this
38✔
507
            ->builder
38✔
508
            ->method('getHeaders')
38✔
509
            ->makePublic()
38✔
510
            ->addStmts($stmts)
38✔
511
            ->addStmt($this->builder->return($returnVal))
38✔
512
            ->setReturnType($returnType)
38✔
513
            ->composeDocBlock([], $returnType)
38✔
514
            ->getNode();
38✔
515
    }
516

517
    private function getSecurityHeadersStmts(Operation $operation, Specification $specification): array
518
    {
519
        $stmts = [];
38✔
520

521
        foreach ($this->securityStrategies as $securityStrategy) {
38✔
522
            $stmts = array_merge($stmts, $securityStrategy->getSecurityHeadersStmts($operation, $specification));
38✔
523
        }
524

525
        return $stmts;
38✔
526
    }
527

528
    private function getSecurityHeaders(Operation $operation, Specification $specification): array
529
    {
530
        $headers = [];
38✔
531

532
        foreach ($this->securityStrategies as $securityStrategy) {
38✔
533
            $headers += $securityStrategy->getSecurityHeaders($operation, $specification);
38✔
534
        }
535

536
        return $headers;
38✔
537
    }
538

539
    private function getSecurityCookies(Operation $operation, Specification $specification): array
540
    {
541
        $cookies = [];
38✔
542

543
        foreach ($this->securityStrategies as $securityStrategy) {
38✔
544
            $cookies += $securityStrategy->getSecurityCookies($operation, $specification);
38✔
545
        }
546

547
        return $cookies;
38✔
548
    }
549

550
    private function getSecurityQueryParameters(Operation $operation, Specification $specification): array
551
    {
552
        $queryParameters = [];
38✔
553

554
        foreach ($this->securityStrategies as $securityStrategy) {
38✔
555
            $queryParameters += $securityStrategy->getSecurityQueryParameters($operation, $specification);
38✔
556
        }
557

558
        return $queryParameters;
38✔
559
    }
560

561
    private function generateParametersFromFields(array $fields): FuncCall
562
    {
563
        $filterCallbackBody = $this->builder->return(
34✔
564
            $this->builder->notEquals($this->builder->val(null), $this->builder->var('value'))
34✔
565
        );
34✔
566

567
        $filterCallback = $this->builder->closure(
34✔
568
            [$filterCallbackBody],
34✔
569
            [$this->builder->param('value')->getNode()]
34✔
570
        );
34✔
571

572
        $filter = $this->builder->funcCall(
34✔
573
            'array_filter',
34✔
574
            [$this->builder->array($fields), $filterCallback]
34✔
575
        );
34✔
576

577
        $this->addImport(CopiedNamespace::getImport($this->baseNamespace, SerializableInterface::class));
34✔
578
        $closureVariable = $this->builder->var('value');
34✔
579
        $closureBody     = $this->builder->return(
34✔
580
            $this->builder->ternary(
34✔
581
                $this->builder->instanceOf(
34✔
582
                    $closureVariable,
34✔
583
                    $this->builder->className('SerializableInterface')
34✔
584
                ),
34✔
585
                $this->builder->methodCall(
34✔
586
                    $closureVariable,
34✔
587
                    'toArray'
34✔
588
                ),
34✔
589
                $closureVariable
34✔
590
            )
34✔
591
        );
34✔
592

593
        return $this->builder->funcCall(
34✔
594
            'array_map',
34✔
595
            [
34✔
596
                $this->builder->closure(
34✔
597
                    [$closureBody],
34✔
598
                    [$this->builder->param('value')->getNode()]
34✔
599
                ),
34✔
600
                $filter,
34✔
601
            ]
34✔
602
        );
34✔
603
    }
604

605
    private function sortParameters(ParameterNode ...$parameterNodes): array
606
    {
607
        usort(
38✔
608
            $parameterNodes,
38✔
609
            static fn (ParameterNode $paramA, ParameterNode $paramB) => $paramA->default <=> $paramB->default
38✔
610
        );
38✔
611

612
        return $parameterNodes;
38✔
613
    }
614
}
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

© 2026 Coveralls, Inc