Skip to content

Commit c598a97

Browse files
ClassMetadata::fullyQualifiedClassNameOfDataTypeSpecification() implemented.
1 parent 38c1b8b commit c598a97

2 files changed

Lines changed: 112 additions & 3 deletions

File tree

src/Metadata/ClassMetadata.php

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,9 @@ private function throwOnInvalidUseStatement(string $useStatement)
8787
);
8888
}
8989

90+
/**
91+
* NOTE: Does not resolve "$this" or "self" to a fully qualified class name, but keeps them.
92+
*/
9093
public function fullyQualifiedDataTypeSpecification(?string $originalSpecification) : ?string
9194
{
9295
if (is_null($originalSpecification)) {
@@ -135,11 +138,11 @@ public function fullyQualifiedDataTypeSpecification(?string $originalSpecificati
135138
/**
136139
* Returns if the data type specification corresponds to an object.
137140
*
138-
* Union types and interfaces are not supported.
141+
* NOTE: Union types and interfaces are not supported.
139142
*/
140-
public function isDataTypeSpecificationAnObject(?string $originalSpecification) : bool
143+
public function isDataTypeSpecificationAnObject(?string $specification) : bool
141144
{
142-
$fullyQualified = $this->fullyQualifiedDataTypeSpecification($originalSpecification);
145+
$fullyQualified = $this->fullyQualifiedDataTypeSpecification($specification);
143146

144147
if ('[]' === substr($fullyQualified, -2)) {
145148
$fullyQualified = substr($fullyQualified, 0, -2);
@@ -155,6 +158,36 @@ public function isDataTypeSpecificationAnObject(?string $originalSpecification)
155158
return class_exists($fullyQualified);
156159
}
157160

161+
/**
162+
* NOTES:
163+
*
164+
* - Throws an exception if the specification is not an object. (Check using self::isDataTypeSpecificationAnObject()
165+
* before).
166+
*
167+
* - Union types and interfaces are not supported.
168+
*/
169+
public function fullyQualifiedClassNameOfDataTypeSpecification(string $specification) : string
170+
{
171+
if (! $this->isDataTypeSpecificationAnObject($specification))
172+
{
173+
throw new \RuntimeException(
174+
sprintf(
175+
"Data type specification '%s' is not an object. (Interfaces and union types are not supported.)",
176+
$specification
177+
)
178+
);
179+
}
180+
181+
if (
182+
'self' === $specification ||
183+
'$this' === $specification
184+
) {
185+
return $this->name;
186+
}
187+
188+
return $this->fullyQualifiedDataTypeSpecification($specification);
189+
}
190+
158191
public function serialize() : string
159192
{
160193
return serialize(

tests/PhpUnit/Metadata/ClassMetadataTest.php

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,4 +216,80 @@ public function it_checks_if_a_data_type_specification_is_an_object(?string $spe
216216
// then the result is as expected as provided by the test's parameter
217217
$this->assertSame($expectedIsObject, $isObject);
218218
}
219+
220+
public function provides_data_type_specification_and_expected_class_name() : array
221+
{
222+
return [
223+
[\DateTime::class, \DateTime::class],
224+
['ClassMetadata', ClassMetadata::class],
225+
['self', ClassForTesting::class],
226+
['$this', ClassForTesting::class],
227+
];
228+
}
229+
230+
/**
231+
* @test
232+
* @dataProvider provides_data_type_specification_and_expected_class_name
233+
* @covers ::fullyQualifiedClassNameOfDataTypeSpecification()
234+
*/
235+
public function it_resolves_a_data_type_specification_to_a_fully_qualified_class_name(
236+
string $dataTypeSpecification,
237+
string $expectedClassName
238+
)
239+
{
240+
// given some ClassMetadata
241+
$classMetadata = new ClassMetadata(
242+
ClassForTesting::class,
243+
[
244+
'ScaleUpStack\Metadata\Metadata\ClassMetadata',
245+
],
246+
new Annotations()
247+
);
248+
// and a data type specification as provided by the test's parameter
249+
250+
// when resolving the specification to a fully qualified class name
251+
$className = $classMetadata->fullyQualifiedClassNameOfDataTypeSpecification($dataTypeSpecification);
252+
253+
// then the result is the expected class name as provided by the test's parameter
254+
$this->assertSame($className, $expectedClassName);
255+
}
256+
257+
public function provides_non_object_data_type_specifications() : array
258+
{
259+
return [
260+
[\DateTimeInterface::class], // interfaces are not supported
261+
['int'],
262+
[\DateTime::class . '|' . \Exception::class], // union types are not supported
263+
];
264+
}
265+
266+
/**
267+
* @test
268+
* @dataProvider provides_non_object_data_type_specifications
269+
* @covers ::fullyQualifiedClassNameOfDataTypeSpecification()
270+
*/
271+
public function it_throws_an_exception_if_data_type_specification_is_no_object(string $specification)
272+
{
273+
// given some ClassMetadata
274+
$classMetadata = new ClassMetadata(
275+
ClassForTesting::class,
276+
[
277+
'ScaleUpStack\Metadata\Metadata\ClassMetadata',
278+
],
279+
new Annotations()
280+
);
281+
// and a data type specification that is not object as provided by the test's parameter
282+
283+
// when resolving the specification to a fully qualified class name
284+
// then an exception is thrown
285+
$this->expectException(\RuntimeException::class);
286+
$this->expectExceptionMessage(
287+
sprintf(
288+
"Data type specification '%s' is not an object. (Interfaces and union types are not supported.)",
289+
$specification
290+
)
291+
);
292+
293+
$classMetadata->fullyQualifiedClassNameOfDataTypeSpecification($specification);
294+
}
219295
}

0 commit comments

Comments
 (0)