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

RonasIT / laravel-swagger / 27257748646

10 Jun 2026 06:29AM UTC coverage: 99.317% (-0.4%) from 99.671%
27257748646

Pull #193

github

web-flow
Merge 5a983fdcc into ead648e99
Pull Request #193: feat: name response object by resource class

222 of 226 new or added lines in 13 files covered. (98.23%)

1 existing line in 1 file now uncovered.

1018 of 1025 relevant lines covered (99.32%)

24.5 hits per line

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

97.73
/src/Support/Resolvers/ResourceClassResolver.php
1
<?php
2

3
namespace RonasIT\AutoDoc\Support\Resolvers;
4

5
use Illuminate\Http\Resources\Json\AnonymousResourceCollection;
6
use Illuminate\Http\Resources\Json\JsonResource;
7
use Illuminate\Support\Arr;
8
use Illuminate\Support\Str;
9
use ReflectionFunctionAbstract;
10
use ReflectionNamedType;
11
use ReflectionUnionType;
12
use RonasIT\AutoDoc\DTO\ResolvedResource;
13

14
class ResourceClassResolver
15
{
16
    public function resolve(ReflectionFunctionAbstract $reflection): ?ResolvedResource
17
    {
18
        $returnType = $reflection->getReturnType();
37✔
19

20
        $result = (!empty($returnType))
37✔
21
            ? $this->resolveFromReturnType($returnType)
4✔
22
            : null;
33✔
23

24
        return $result ?? $this->resolveFromSource($reflection);
37✔
25
    }
26

27
    private function resolveFromReturnType(object $returnType): ?ResolvedResource
28
    {
29
        $types = match (get_class($returnType)) {
4✔
30
            ReflectionNamedType::class => [$returnType],
3✔
31
            ReflectionUnionType::class => $returnType->getTypes(),
1✔
NEW
32
            default => [],
×
33
        };
34

35
        foreach ($types as $type) {
4✔
36
            if ($type instanceof ReflectionNamedType && !$type->isBuiltin() && $this->isResourceClass($type->getName())) {
4✔
37
                return new ResolvedResource($type->getName());
2✔
38
            }
39
        }
40

41
        return null;
2✔
42
    }
43

44
    private function resolveFromSource(ReflectionFunctionAbstract $reflection): ?ResolvedResource
45
    {
46
        $fileContent = $this->getFileContent($reflection);
35✔
47
        $code = $this->getFunctionCode($reflection, $fileContent);
35✔
48

49
        $patterns = [
35✔
50
            'single' => '/(?:return\s+|=>\s+)([^\s(]+)::make/',
35✔
51
            'collection' => '/(?:return\s+|=>\s+)([^\s(]+)::collection/',
35✔
52
            'class' => '/(?:return\s+|=>\s+)new\s+([^\s(]+)/',
35✔
53
        ];
35✔
54

55
        foreach ($patterns as $type => $pattern) {
35✔
56
            preg_match($pattern, $code, $matches);
35✔
57

58
            if (empty($matches[1])) {
35✔
59
                continue;
31✔
60
            }
61

62
            $resourceName = class_exists($matches[1])
6✔
63
                ? $matches[1]
1✔
64
                : $this->getClassNameFromImports($matches[1], $fileContent);
5✔
65

66
            if (is_subclass_of($resourceName, JsonResource::class)) {
6✔
67
                return new ResolvedResource($resourceName, $type === 'collection');
6✔
68
            }
69
        }
70

71
        return null;
29✔
72
    }
73

74
    private function isResourceClass(string $className): bool
75
    {
76
        return is_subclass_of($className, JsonResource::class)
4✔
77
            && $className !== AnonymousResourceCollection::class;
4✔
78
    }
79

80
    private function getFileContent(ReflectionFunctionAbstract $reflection): array
81
    {
82
        $fileName = $reflection->getFileName();
35✔
83

84
        return (empty($fileName) || !is_readable($fileName)) ? [] : file($fileName) ?? [];
35✔
85
    }
86

87
    private function getFunctionCode(ReflectionFunctionAbstract $reflection, array $fileContent): string
88
    {
89
        $startLineIndex = $reflection->getStartLine() - 1;
35✔
90
        $methodSlice = array_slice($fileContent, $startLineIndex, $reflection->getEndLine() - $startLineIndex);
35✔
91

92
        return implode('', $methodSlice);
35✔
93
    }
94

95
    private function getClassNameFromImports(string $resourceName, array $fileContent): string
96
    {
97
        $resourceImport = Arr::first(
5✔
98
            array: $fileContent,
5✔
99
            callback: fn (string $line) => Str::startsWith($line, 'use')
5✔
100
                && preg_match('/\b' . preg_quote($resourceName, '/') . '\b/', $line),
5✔
101
        );
5✔
102

103
        preg_match('/^use\s+([^;]+?)(?:\s+as\s+\w+)?;$/', trim($resourceImport), $matches);
5✔
104

105
        return $matches[1] ?? '';
5✔
106
    }
107
}
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