Skip to content

Commit

Permalink
Merge pull request #56 from patchlevel/class-not-found-exception
Browse files Browse the repository at this point in the history
throw exception if class not found
  • Loading branch information
DavidBadura authored Oct 15, 2024
2 parents b8951b3 + 8f50b95 commit b2cc966
Show file tree
Hide file tree
Showing 10 changed files with 95 additions and 3 deletions.
18 changes: 17 additions & 1 deletion baseline.xml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<files psalm-version="5.23.1@8471a896ccea3526b26d082f4461eeea467f10a4">
<files psalm-version="5.26.1@d747f6500b38ac4f7dfc5edbcae6e4b637d7add0">
<file src="src/Cryptography/Cipher/OpensslCipherKeyFactory.php">
<ArgumentTypeCoercion>
<code><![CDATA[openssl_random_pseudo_bytes($this->ivLength)]]></code>
Expand Down Expand Up @@ -45,4 +45,20 @@
<code><![CDATA[$return]]></code>
</MixedAssignment>
</file>
<file src="tests/Unit/Metadata/AttributeMetadataFactoryTest.php">
<ArgumentTypeCoercion>
<code><![CDATA['Unknown']]></code>
</ArgumentTypeCoercion>
<UndefinedClass>
<code><![CDATA['Unknown']]></code>
</UndefinedClass>
</file>
<file src="tests/Unit/MetadataHydratorTest.php">
<ArgumentTypeCoercion>
<code><![CDATA['Unknown']]></code>
</ArgumentTypeCoercion>
<UndefinedClass>
<code><![CDATA['Unknown']]></code>
</UndefinedClass>
</file>
</files>
5 changes: 5 additions & 0 deletions phpstan-baseline.neon
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@ parameters:
count: 1
path: src/Cryptography/PersonalDataPayloadCryptographer.php

-
message: "#^Dead catch \\- ReflectionException is never thrown in the try block\\.$#"
count: 1
path: src/Metadata/AttributeMetadataFactory.php

-
message: "#^Property Patchlevel\\\\Hydrator\\\\Metadata\\\\ClassMetadata\\<T of object\\>\\:\\:\\$reflection \\(ReflectionClass\\<T of object\\>\\) does not accept ReflectionClass\\<object\\>\\.$#"
count: 1
Expand Down
19 changes: 19 additions & 0 deletions src/ClassNotSupported.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?php

declare(strict_types=1);

namespace Patchlevel\Hydrator;

use RuntimeException;
use Throwable;

use function sprintf;

final class ClassNotSupported extends RuntimeException implements HydratorException
{
/** @param class-string $className */
public function __construct(string $className, Throwable|null $previous = null)
{
parent::__construct(sprintf('Class %s not supported', $className), 0, $previous);

Check warning on line 17 in src/ClassNotSupported.php

View workflow job for this annotation

GitHub Actions / Mutation tests (locked, 8.3, ubuntu-latest)

Escaped Mutant for Mutator "DecrementInteger": --- Original +++ New @@ @@ /** @param class-string $className */ public function __construct(string $className, Throwable|null $previous = null) { - parent::__construct(sprintf('Class %s not supported', $className), 0, $previous); + parent::__construct(sprintf('Class %s not supported', $className), -1, $previous); } }

Check warning on line 17 in src/ClassNotSupported.php

View workflow job for this annotation

GitHub Actions / Mutation tests (locked, 8.3, ubuntu-latest)

Escaped Mutant for Mutator "IncrementInteger": --- Original +++ New @@ @@ /** @param class-string $className */ public function __construct(string $className, Throwable|null $previous = null) { - parent::__construct(sprintf('Class %s not supported', $className), 0, $previous); + parent::__construct(sprintf('Class %s not supported', $className), 1, $previous); } }

Check warning on line 17 in src/ClassNotSupported.php

View workflow job for this annotation

GitHub Actions / Mutation tests (locked, 8.3, ubuntu-latest)

Escaped Mutant for Mutator "MethodCallRemoval": --- Original +++ New @@ @@ /** @param class-string $className */ public function __construct(string $className, Throwable|null $previous = null) { - parent::__construct(sprintf('Class %s not supported', $className), 0, $previous); + } }
}
}
2 changes: 2 additions & 0 deletions src/Hydrator.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ interface Hydrator
*
* @return T
*
* @throws ClassNotSupported if the class is not supported or not found.
*
* @template T of object
*/
public function hydrate(string $class, array $data): object;
Expand Down
7 changes: 6 additions & 1 deletion src/Metadata/AttributeMetadataFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
use Patchlevel\Hydrator\Normalizer\ReflectionTypeAwareNormalizer;
use ReflectionAttribute;
use ReflectionClass;
use ReflectionException;
use ReflectionNamedType;
use ReflectionProperty;

Expand Down Expand Up @@ -52,7 +53,11 @@ public function metadata(string $class): ClassMetadata
return $classMetadata;
}

$reflectionClass = new ReflectionClass($class);
try {
$reflectionClass = new ReflectionClass($class);
} catch (ReflectionException) {
throw new ClassNotFound($class);
}

$classMetadata = $this->getClassMetadata($reflectionClass);

Expand Down
18 changes: 18 additions & 0 deletions src/Metadata/ClassNotFound.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php

declare(strict_types=1);

namespace Patchlevel\Hydrator\Metadata;

use RuntimeException;

use function sprintf;

final class ClassNotFound extends RuntimeException implements MetadataException
{
/** @param class-string $className */
public function __construct(string $className)
{
parent::__construct(sprintf('Class %s not found', $className));

Check warning on line 16 in src/Metadata/ClassNotFound.php

View workflow job for this annotation

GitHub Actions / Mutation tests (locked, 8.3, ubuntu-latest)

Escaped Mutant for Mutator "MethodCallRemoval": --- Original +++ New @@ @@ /** @param class-string $className */ public function __construct(string $className) { - parent::__construct(sprintf('Class %s not found', $className)); + } }
}
}
2 changes: 2 additions & 0 deletions src/Metadata/MetadataFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ interface MetadataFactory
*
* @return ClassMetadata<T>
*
* @throws ClassNotFound if the class does not exist.
*
* @template T of object
*/
public function metadata(string $class): ClassMetadata;
Expand Down
7 changes: 6 additions & 1 deletion src/MetadataHydrator.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use Patchlevel\Hydrator\Cryptography\PayloadCryptographer;
use Patchlevel\Hydrator\Metadata\AttributeMetadataFactory;
use Patchlevel\Hydrator\Metadata\ClassMetadata;
use Patchlevel\Hydrator\Metadata\ClassNotFound;
use Patchlevel\Hydrator\Metadata\MetadataFactory;
use Patchlevel\Hydrator\Normalizer\HydratorAwareNormalizer;
use ReflectionParameter;
Expand Down Expand Up @@ -39,7 +40,11 @@ public function __construct(
*/
public function hydrate(string $class, array $data): object
{
$metadata = $this->metadataFactory->metadata($class);
try {
$metadata = $this->metadataFactory->metadata($class);
} catch (ClassNotFound $e) {
throw new ClassNotSupported($class, $e);
}

if ($this->cryptographer) {
$data = $this->cryptographer->decrypt($metadata, $data);
Expand Down
9 changes: 9 additions & 0 deletions tests/Unit/Metadata/AttributeMetadataFactoryTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
use Patchlevel\Hydrator\Attribute\PostHydrate;
use Patchlevel\Hydrator\Attribute\PreExtract;
use Patchlevel\Hydrator\Metadata\AttributeMetadataFactory;
use Patchlevel\Hydrator\Metadata\ClassNotFound;
use Patchlevel\Hydrator\Metadata\DuplicatedFieldNameInMetadata;
use Patchlevel\Hydrator\Metadata\MissingDataSubjectId;
use Patchlevel\Hydrator\Metadata\MultipleDataSubjectId;
Expand Down Expand Up @@ -77,6 +78,14 @@ public function testWithProperties(): void
self::assertNull($propertyMetadata->normalizer());
}

public function testUnknownClass(): void
{
$this->expectException(ClassNotFound::class);

$metadataFactory = new AttributeMetadataFactory();
$metadataFactory->metadata('Unknown');
}

public function testSkipStaticProperties(): void
{
$object = new class {
Expand Down
11 changes: 11 additions & 0 deletions tests/Unit/MetadataHydratorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
use DateTimeImmutable;
use DateTimeZone;
use Patchlevel\Hydrator\CircularReference;
use Patchlevel\Hydrator\ClassNotSupported;
use Patchlevel\Hydrator\Cryptography\PayloadCryptographer;
use Patchlevel\Hydrator\DenormalizationFailure;
use Patchlevel\Hydrator\Metadata\AttributeMetadataFactory;
Expand Down Expand Up @@ -139,6 +140,16 @@ public function testHydrate(): void
self::assertEquals($expected, $event);
}

public function testHydrateUnknownClass(): void
{
$this->expectException(ClassNotSupported::class);

$this->hydrator->hydrate(
'Unknown',
['profileId' => '1', 'email' => '[email protected]'],
);
}

public function testHydrateWithDefaults(): void
{
$object = $this->hydrator->hydrate(
Expand Down

0 comments on commit b2cc966

Please sign in to comment.