Skip to content

Commit

Permalink
ClassMetadata::fullyQualifiedClassNameOfDataTypeSpecification() imple…
Browse files Browse the repository at this point in the history
…mented.
  • Loading branch information
ThomasNunninger committed Sep 7, 2019
1 parent 38c1b8b commit c598a97
Show file tree
Hide file tree
Showing 2 changed files with 112 additions and 3 deletions.
39 changes: 36 additions & 3 deletions src/Metadata/ClassMetadata.php
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,9 @@ private function throwOnInvalidUseStatement(string $useStatement)
);
}

/**
* NOTE: Does not resolve "$this" or "self" to a fully qualified class name, but keeps them.
*/
public function fullyQualifiedDataTypeSpecification(?string $originalSpecification) : ?string
{
if (is_null($originalSpecification)) {
Expand Down Expand Up @@ -135,11 +138,11 @@ public function fullyQualifiedDataTypeSpecification(?string $originalSpecificati
/**
* Returns if the data type specification corresponds to an object.
*
* Union types and interfaces are not supported.
* NOTE: Union types and interfaces are not supported.
*/
public function isDataTypeSpecificationAnObject(?string $originalSpecification) : bool
public function isDataTypeSpecificationAnObject(?string $specification) : bool
{
$fullyQualified = $this->fullyQualifiedDataTypeSpecification($originalSpecification);
$fullyQualified = $this->fullyQualifiedDataTypeSpecification($specification);

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

/**
* NOTES:
*
* - Throws an exception if the specification is not an object. (Check using self::isDataTypeSpecificationAnObject()
* before).
*
* - Union types and interfaces are not supported.
*/
public function fullyQualifiedClassNameOfDataTypeSpecification(string $specification) : string
{
if (! $this->isDataTypeSpecificationAnObject($specification))
{
throw new \RuntimeException(
sprintf(
"Data type specification '%s' is not an object. (Interfaces and union types are not supported.)",
$specification
)
);
}

if (
'self' === $specification ||
'$this' === $specification
) {
return $this->name;
}

return $this->fullyQualifiedDataTypeSpecification($specification);
}

public function serialize() : string
{
return serialize(
Expand Down
76 changes: 76 additions & 0 deletions tests/PhpUnit/Metadata/ClassMetadataTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -216,4 +216,80 @@ public function it_checks_if_a_data_type_specification_is_an_object(?string $spe
// then the result is as expected as provided by the test's parameter
$this->assertSame($expectedIsObject, $isObject);
}

public function provides_data_type_specification_and_expected_class_name() : array
{
return [
[\DateTime::class, \DateTime::class],
['ClassMetadata', ClassMetadata::class],
['self', ClassForTesting::class],
['$this', ClassForTesting::class],
];
}

/**
* @test
* @dataProvider provides_data_type_specification_and_expected_class_name
* @covers ::fullyQualifiedClassNameOfDataTypeSpecification()
*/
public function it_resolves_a_data_type_specification_to_a_fully_qualified_class_name(
string $dataTypeSpecification,
string $expectedClassName
)
{
// given some ClassMetadata
$classMetadata = new ClassMetadata(
ClassForTesting::class,
[
'ScaleUpStack\Metadata\Metadata\ClassMetadata',
],
new Annotations()
);
// and a data type specification as provided by the test's parameter

// when resolving the specification to a fully qualified class name
$className = $classMetadata->fullyQualifiedClassNameOfDataTypeSpecification($dataTypeSpecification);

// then the result is the expected class name as provided by the test's parameter
$this->assertSame($className, $expectedClassName);
}

public function provides_non_object_data_type_specifications() : array
{
return [
[\DateTimeInterface::class], // interfaces are not supported
['int'],
[\DateTime::class . '|' . \Exception::class], // union types are not supported
];
}

/**
* @test
* @dataProvider provides_non_object_data_type_specifications
* @covers ::fullyQualifiedClassNameOfDataTypeSpecification()
*/
public function it_throws_an_exception_if_data_type_specification_is_no_object(string $specification)
{
// given some ClassMetadata
$classMetadata = new ClassMetadata(
ClassForTesting::class,
[
'ScaleUpStack\Metadata\Metadata\ClassMetadata',
],
new Annotations()
);
// and a data type specification that is not object as provided by the test's parameter

// when resolving the specification to a fully qualified class name
// then an exception is thrown
$this->expectException(\RuntimeException::class);
$this->expectExceptionMessage(
sprintf(
"Data type specification '%s' is not an object. (Interfaces and union types are not supported.)",
$specification
)
);

$classMetadata->fullyQualifiedClassNameOfDataTypeSpecification($specification);
}
}

0 comments on commit c598a97

Please sign in to comment.