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

GollumSF / rest-doc-bundle / 23619610488

26 Mar 2026 09:43PM UTC coverage: 96.735% (-3.3%) from 100.0%
23619610488

push

github

Smeagolworms4
Update to SF 7.* and 8.0 Coverage

7 of 7 new or added lines in 1 file covered. (100.0%)

32 existing lines in 1 file now uncovered.

948 of 980 relevant lines covered (96.73%)

7.15 hits per line

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

13.51
/src/TypeDiscover/Handler/PropertyInfosHandler.php
1
<?php
2

3
namespace GollumSF\RestDocBundle\TypeDiscover\Handler;
4

5
use GollumSF\RestDocBundle\Builder\ModelBuilder\ModelBuilderInterface;
6
use GollumSF\RestDocBundle\TypeDiscover\Models\ArrayType;
7
use GollumSF\RestDocBundle\TypeDiscover\Models\DateTimeType;
8
use GollumSF\RestDocBundle\TypeDiscover\Models\NativeType;
9
use GollumSF\RestDocBundle\TypeDiscover\Models\TypeInterface;
10
use Symfony\Component\PropertyInfo\PropertyInfoExtractorInterface;
11

12
class PropertyInfosHandler implements HandlerInterface {
13

14
        /** @var PropertyInfoExtractorInterface */
15
        private $propertyInfoExtractor;
16

17
        /** @var ModelBuilderInterface */
18
        private $modelBuilder;
19

20
        public function __construct(
21
                PropertyInfoExtractorInterface $propertyInfoExtractor,
22
                ModelBuilderInterface $modelBuilder
23
        ) {
24
                $this->propertyInfoExtractor = $propertyInfoExtractor;
26✔
25
                $this->modelBuilder = $modelBuilder;
26✔
26
        }
27

28
        public function getType(string $class, string $targetName): ?TypeInterface {
29
                try {
30
                        if (method_exists($this->propertyInfoExtractor, 'getType')) { // @codeCoverageIgnoreStart
31
                                // Symfony 7.1+ / 8.0+ with TypeInfo component
32
                                $type = $this->propertyInfoExtractor->getType($class, $targetName);
33
                                if ($type) {
34
                                        return $this->createTypeFromTypeInfo($type);
35
                                } // @codeCoverageIgnoreEnd
UNCOV
36
                        } elseif (method_exists($this->propertyInfoExtractor, 'getTypes')) {
×
37
                                // Symfony 6.4 / 7.0 with legacy PropertyInfo Type
UNCOV
38
                                $types = $this->propertyInfoExtractor->getTypes($class, $targetName);
×
UNCOV
39
                                if ($types) {
×
40
                                        return $this->createTypeLegacy($types);
1✔
41
                                }
42
                        }
43
                } catch (\Throwable $e) {
1✔
44
                }
45
                return null;
2✔
46
        }
47

48
        /**
49
         * Create type from Symfony TypeInfo component (Symfony 7.1+/8.0+)
50
         * @codeCoverageIgnore
51
         */
52
        protected function createTypeFromTypeInfo(object $type): ?TypeInterface {
53
                $typeString = (string) $type;
54

55
                // Handle nullable types - unwrap nullable wrapper
56
                if (method_exists($type, 'isNullable') && $type->isNullable()) {
57
                        // For nullable types like ?int, get the non-null type
58
                        if (method_exists($type, 'getTypes')) {
59
                                foreach ($type->getTypes() as $innerType) {
60
                                        $innerString = (string) $innerType;
61
                                        if ($innerString !== 'null') {
62
                                                return $this->createTypeFromTypeInfo($innerType);
63
                                        }
64
                                }
65
                        }
66
                }
67

68
                // Handle collection/list/array types
69
                if (method_exists($type, 'getCollectionValueType')) {
70
                        try {
71
                                $valueType = $type->getCollectionValueType();
72
                                return new ArrayType(
73
                                        $valueType ? $this->createTypeFromTypeInfo($valueType) : null
74
                                );
75
                        } catch (\Throwable $e) {
76
                                return new ArrayType(null);
77
                        }
78
                }
79

80
                if ($typeString === 'array' || str_starts_with($typeString, 'list<') || str_starts_with($typeString, 'array<')) {
81
                        return new ArrayType(null);
82
                }
83

84
                // Map native types
85
                $nativeMap = [
86
                        'int' => 'integer',
87
                        'bool' => 'boolean',
88
                        'float' => 'number',
89
                        'double' => 'number',
90
                        'string' => 'string',
91
                ];
92
                if (isset($nativeMap[$typeString])) {
93
                        return new NativeType($nativeMap[$typeString]);
94
                }
95
                if (in_array($typeString, ['integer', 'boolean', 'number', 'string'])) {
96
                        return new NativeType($typeString);
97
                }
98

99
                // Handle object types
100
                if (class_exists($typeString) || interface_exists($typeString)) {
101
                        if ($typeString === \DateTime::class || is_subclass_of($typeString, \DateTime::class)) {
102
                                return new DateTimeType();
103
                        }
104
                        return $this->modelBuilder->getModel($typeString);
105
                }
106

107
                // Try to get class from object type
108
                if (method_exists($type, 'getClassName')) {
109
                        $class = $type->getClassName();
110
                        if ($class) {
111
                                if ($class === \DateTime::class || is_subclass_of($class, \DateTime::class)) {
112
                                        return new DateTimeType();
113
                                }
114
                                return $this->modelBuilder->getModel($class);
115
                        }
116
                }
117

118
                return null;
119
        }
120

121
        /**
122
         * Create type from legacy PropertyInfo Type (Symfony 6.4/7.0)
123
         */
124
        protected function createTypeLegacy(array $types): ?TypeInterface {
UNCOV
125
                foreach ($types as $type) {
×
UNCOV
126
                        $builtin = $type->getBuiltinType();
×
127
                        switch ($builtin) {
UNCOV
128
                                case 'int':
×
UNCOV
129
                                        $builtin = 'integer'; break;
×
UNCOV
130
                                case 'bool':
×
UNCOV
131
                                        $builtin = 'boolean'; break;
×
UNCOV
132
                                case 'float':
×
UNCOV
133
                                case 'double':
×
UNCOV
134
                                        $builtin = 'number'; break;
×
UNCOV
135
                                default: break;
×
136
                        }
UNCOV
137
                        if (in_array($builtin, [
×
UNCOV
138
                                'integer',
×
UNCOV
139
                                'float',
×
UNCOV
140
                                'number',
×
UNCOV
141
                                'string',
×
UNCOV
142
                                'boolean',
×
UNCOV
143
                        ])) {
×
UNCOV
144
                                return new NativeType($builtin);
×
145
                        }
UNCOV
146
                        if ($builtin === 'object') {
×
UNCOV
147
                                $class = $type->getClassName();
×
UNCOV
148
                                if ($class === \DateTime::class || is_subclass_of($class, \DateTime::class)) {
×
UNCOV
149
                                        return new DateTimeType();
×
150
                                }
UNCOV
151
                                return $this->modelBuilder->getModel($class);
×
152
                        }
UNCOV
153
                        if ($type->isCollection()) {
×
UNCOV
154
                                $valueType = $type->getCollectionValueTypes();
×
UNCOV
155
                                return new ArrayType(
×
UNCOV
156
                                        $valueType ? $this->createTypeLegacy($valueType) : null
×
UNCOV
157
                                );
×
158
                        }
159
                }
UNCOV
160
                return null;
×
161
        }
162
}
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