diff --git a/data-access-kit/src/Repository/Compiler.php b/data-access-kit/src/Repository/Compiler.php index 6af0ecc..3d234f5 100644 --- a/data-access-kit/src/Repository/Compiler.php +++ b/data-access-kit/src/Repository/Compiler.php @@ -71,8 +71,8 @@ public function prepare(ReflectionClass|string $repositoryInterface): Result if (!$repositoryInterface->isInterface()) { throw new CompilerException(sprintf( - "The provided class name must be an interface, %s is not an interface.", - $repositoryInterface, + "The provided class name must be an interface, [%s] is not an interface.", + $repositoryInterface->getName(), )); } @@ -147,7 +147,7 @@ public function compile(Result $result): Result $returnType = $rm->getReturnType(); if (!$returnType instanceof ReflectionNamedType || !in_array($returnType->getName(), ["array", "iterable", $result->repository->class], true)) { throw new CompilerException(sprintf( - "Method [%s::%s] must return array, iterable, or [%s] to able to be generated. Either change the return type, add an attribute, or remove the method.", + "Find method [%s::%s] must return array, iterable, or [%s] to able to be generated. Either change the return type, add an attribute, or remove the method.", $result->reflection->getName(), $rm->getName(), $result->repository->class, @@ -161,7 +161,7 @@ public function compile(Result $result): Result $returnType = $rm->getReturnType(); if (!$returnType instanceof ReflectionNamedType || $returnType->getName() !== "int") { throw new CompilerException(sprintf( - "Method [%s::%s] must return int to able to be generated. Either change the return type, add an attribute, or remove the method.", + "Count method [%s::%s] must return int to able to be generated. Either change the return type, add an attribute, or remove the method.", $result->reflection->getName(), $rm->getName(), )); diff --git a/data-access-kit/src/Repository/Method/BuildWhereTrait.php b/data-access-kit/src/Repository/Method/BuildWhereTrait.php index d7dd286..9a33e6c 100644 --- a/data-access-kit/src/Repository/Method/BuildWhereTrait.php +++ b/data-access-kit/src/Repository/Method/BuildWhereTrait.php @@ -26,10 +26,10 @@ private function buildWhere(ResultMethod $method, Table $table, Result $result, } if ($column === null) { throw new CompilerException(sprintf( - "Method [%s::%s] parameter [%s] does not match any property of [%s], and therefore cannot be used as a query condition.", + "Parameter [%s] of method [%s::%s] does not match any property of [%s], and therefore cannot be used as a query condition.", + $parameter->getName(), $result->reflection->getName(), $method->reflection->getName(), - $parameter->getName(), $result->repository->class, )); } diff --git a/data-access-kit/src/Repository/Method/DelegateMethodCompiler.php b/data-access-kit/src/Repository/Method/DelegateMethodCompiler.php index 8a96fa2..236fa82 100644 --- a/data-access-kit/src/Repository/Method/DelegateMethodCompiler.php +++ b/data-access-kit/src/Repository/Method/DelegateMethodCompiler.php @@ -4,12 +4,16 @@ use DataAccessKit\Repository\Attribute\Delegate; use DataAccessKit\Repository\Compiler; +use DataAccessKit\Repository\Exception\CompilerException; use DataAccessKit\Repository\MethodCompilerInterface; use DataAccessKit\Repository\Result; use DataAccessKit\Repository\ResultMethod; use ReflectionClass; +use ReflectionException; use ReflectionNamedType; +use function class_exists; use function lcfirst; +use function sprintf; use function ucfirst; /** @@ -19,7 +23,21 @@ class DelegateMethodCompiler implements MethodCompilerInterface { public function compile(Result $result, ResultMethod $method, $attribute): void { - $delegateRC = new ReflectionClass($attribute->class); + try { + $delegateRC = new ReflectionClass($attribute->class); + } catch (ReflectionException $e) { + throw new CompilerException( + sprintf( + "Delegate class [%s] referenced by method [%s::%s] does not exist. Please fix the class, interface, or trait reference.", + $attribute->class, + $result->reflection->getName(), + $method->reflection->getName(), + ), + 0, + $e, + ); + } + $alias = $result->use($delegateRC->getName()); $propertyName = lcfirst($alias); @@ -54,6 +72,17 @@ public function compile(Result $result, ResultMethod $method, $attribute): void } $delegateMethodName = $attribute->method ?? $method->name; + if (!$delegateRC->hasMethod($delegateMethodName)) { + throw new CompilerException( + sprintf( + "Delegate method [%s::%s] referenced by method [%s::%s] does not exist. Please fix the method name.", + $delegateRC->getName(), + $delegateMethodName, + $result->reflection->getName(), + $method->reflection->getName(), + ), + ); + } $returnType = $method->reflection->getReturnType(); $void = $returnType instanceof ReflectionNamedType && $returnType->getName() === "void"; $method->line((!$void ? "return " : "") . "\$this->{$propertyName}->{$delegateMethodName}(...func_get_args());"); diff --git a/data-access-kit/src/Repository/Method/SQLFileMethodCompiler.php b/data-access-kit/src/Repository/Method/SQLFileMethodCompiler.php index daf4523..a7132f0 100644 --- a/data-access-kit/src/Repository/Method/SQLFileMethodCompiler.php +++ b/data-access-kit/src/Repository/Method/SQLFileMethodCompiler.php @@ -42,7 +42,7 @@ public function compile(Result $result, ResultMethod $method, $attribute): void $file = dirname($result->reflection->getFileName()) . DIRECTORY_SEPARATOR . $file; } - $contents = file_get_contents($file); + $contents = @file_get_contents($file); if ($contents === false) { throw new CompilerException(sprintf( "SQL file for method [%s::%s] does not exist or is not readable.", diff --git a/data-access-kit/test/Repository/CompilerTest.php b/data-access-kit/test/Repository/CompilerTest.php index 8f223c4..8339260 100644 --- a/data-access-kit/test/Repository/CompilerTest.php +++ b/data-access-kit/test/Repository/CompilerTest.php @@ -6,10 +6,21 @@ use DataAccessKit\Registry; use DataAccessKit\Repository\Exception\CompilerException; use DataAccessKit\Repository\Fixture\AbsoluteSQLFileRepositoryInterface; +use DataAccessKit\Repository\Fixture\CountBadParameterNameRepositoryInterface; +use DataAccessKit\Repository\Fixture\CountBadReturnTypeRepositoryInterface; +use DataAccessKit\Repository\Fixture\DelegateClassDoesNotExistRepositoryInterface; +use DataAccessKit\Repository\Fixture\DelegateMethodDoesNotExistRepositoryInterface; +use DataAccessKit\Repository\Fixture\EmptyFileNameSQLFileRepositoryInterface; +use DataAccessKit\Repository\Fixture\FileDoesNotExistSQLFileRepositoryInterface; +use DataAccessKit\Repository\Fixture\FindBadParameterNameRepositoryInterface; +use DataAccessKit\Repository\Fixture\FindBadReturnTypeRepositoryInterface; +use DataAccessKit\Repository\Fixture\MacroColumnsExceptAllColumnRepositoryInterface; use DataAccessKit\Repository\Fixture\MacroColumnsExceptFromRepositoryInterface; use DataAccessKit\Repository\Fixture\MacroColumnsExceptMultipleFromRepositoryInterface; use DataAccessKit\Repository\Fixture\MacroColumnsExceptMultipleRepositoryInterface; use DataAccessKit\Repository\Fixture\MacroColumnsExceptRepositoryInterface; +use DataAccessKit\Repository\Fixture\MacroUnknownRepositoryInterface; +use DataAccessKit\Repository\Fixture\MacroColumnsExceptUnknownColumnRepositoryInterface; use DataAccessKit\Repository\Fixture\MacroColumnsFromRepositoryInterface; use DataAccessKit\Repository\Fixture\MacroColumnsRepositoryInterface; use DataAccessKit\Repository\Fixture\CountRepositoryInterface; @@ -31,6 +42,12 @@ use DataAccessKit\Repository\Fixture\SimpleSQLNullableObjectRepositoryInterface; use DataAccessKit\Repository\Fixture\SimpleSQLObjectRepositoryInterface; use DataAccessKit\Repository\Fixture\MacroTableSQLRepositoryInterface; +use DataAccessKit\Repository\Fixture\UnhandledMethodRepositoryInterface; +use DataAccessKit\Repository\Fixture\UnknownVariableSQLRepositoryInterface; +use DataAccessKit\Repository\Fixture\UnsupportedReturnTypeIntersectRepositoryInterface; +use DataAccessKit\Repository\Fixture\UnsupportedReturnTypeMixedRepositoryInterface; +use DataAccessKit\Repository\Fixture\UnsupportedReturnTypeObjectRepositoryInterface; +use DataAccessKit\Repository\Fixture\UnsupportedReturnTypeUnionRepositoryInterface; use DataAccessKit\Repository\Fixture\UnusedVariableSQLRepositoryInterface; use DataAccessKit\Repository\Fixture\VariableSQLRepositoryInterface; use DataAccessKit\Repository\Fixture\VoidSQLRepositoryInterface; @@ -56,20 +73,6 @@ protected function setUp(): void $this->compiler = new Compiler(new Registry(new DefaultNameConverter())); } - public function testCompileAcceptsOnlyInterface() - { - $this->expectException(CompilerException::class); - $this->expectExceptionMessage("must be an interface"); - $this->compiler->compile($this->compiler->prepare(CompilerTest::class)); - } - - public function testCompileAcceptsOnlyInterfaceWithAttribute() - { - $this->expectException(CompilerException::class); - $this->expectExceptionMessage("must have a #[\\DataAccessKit\\Repository\\Attribute\\Repository] attribute"); - $this->compiler->compile($this->compiler->prepare(NoAttributeInterface::class)); - } - #[DataProvider("provideCompile")] public function testCompile(string $interfaceName) { @@ -113,7 +116,7 @@ public static function provideCompile() public function testCompileError(string $interfaceName): void { try { - $this->compiler->compile($this->compiler->prepare(UnusedVariableSQLRepositoryInterface::class)); + $this->compiler->compile($this->compiler->prepare($interfaceName)); } catch (CompilerException $e) { $this->assertMatchesSnapshot($e->getMessage()); } @@ -122,7 +125,26 @@ public function testCompileError(string $interfaceName): void public static function provideCompileError(): iterable { return static::provideRepositoryClasses([ + CompilerTest::class, + NoAttributeInterface::class, UnusedVariableSQLRepositoryInterface::class, + FindBadReturnTypeRepositoryInterface::class, + CountBadReturnTypeRepositoryInterface::class, + UnhandledMethodRepositoryInterface::class, + FindBadParameterNameRepositoryInterface::class, + CountBadParameterNameRepositoryInterface::class, + DelegateClassDoesNotExistRepositoryInterface::class, + DelegateMethodDoesNotExistRepositoryInterface::class, + FileDoesNotExistSQLFileRepositoryInterface::class, + EmptyFileNameSQLFileRepositoryInterface::class, + UnsupportedReturnTypeUnionRepositoryInterface::class, + UnsupportedReturnTypeIntersectRepositoryInterface::class, + UnsupportedReturnTypeMixedRepositoryInterface::class, + UnsupportedReturnTypeObjectRepositoryInterface::class, + UnknownVariableSQLRepositoryInterface::class, + MacroColumnsExceptUnknownColumnRepositoryInterface::class, + MacroColumnsExceptAllColumnRepositoryInterface::class, + MacroUnknownRepositoryInterface::class, ]); } diff --git a/data-access-kit/test/Repository/Fixture/Bar.php b/data-access-kit/test/Repository/Fixture/Bar.php new file mode 100644 index 0000000..93d63f4 --- /dev/null +++ b/data-access-kit/test/Repository/Fixture/Bar.php @@ -0,0 +1,16 @@ + + xsi:noNamespaceSchemaLocation="vendor/phpunit/phpunit/phpunit.xsd" + failOnWarning="true" + displayDetailsOnTestsThatTriggerWarnings="true" + failOnNotice="true" + displayDetailsOnTestsThatTriggerNotices="true"> data-access-kit/test