diff --git a/data-access-kit/src/Repository/Attribute/Update.php b/data-access-kit/src/Repository/Attribute/Update.php index c2d093f..39ab968 100644 --- a/data-access-kit/src/Repository/Attribute/Update.php +++ b/data-access-kit/src/Repository/Attribute/Update.php @@ -7,4 +7,9 @@ #[Attribute(Attribute::TARGET_METHOD)] class Update { + public function __construct( + public readonly ?array $columns = null, + ) + { + } } diff --git a/data-access-kit/src/Repository/Compiler.php b/data-access-kit/src/Repository/Compiler.php index 69c74a7..cbb382a 100644 --- a/data-access-kit/src/Repository/Compiler.php +++ b/data-access-kit/src/Repository/Compiler.php @@ -59,8 +59,8 @@ public function __construct( $this->registerMethodCompiler(Delegate::class, new DelegateMethodCompiler()); $this->registerMethodCompiler(Insert::class, $manipulationMethodCompiler = new ManipulationMethodCompiler()); $this->registerMethodCompiler(Upsert::class, $manipulationMethodCompiler); - $this->registerMethodCompiler(Update::class, new UpdateMethodCompiler()); - $this->registerMethodCompiler(Delete::class, new DeleteMethodCompiler()); + $this->registerMethodCompiler(Update::class, $manipulationMethodCompiler); + $this->registerMethodCompiler(Delete::class, $manipulationMethodCompiler); } /** diff --git a/data-access-kit/src/Repository/Method/DeleteMethodCompiler.php b/data-access-kit/src/Repository/Method/DeleteMethodCompiler.php deleted file mode 100644 index 6e0aca4..0000000 --- a/data-access-kit/src/Repository/Method/DeleteMethodCompiler.php +++ /dev/null @@ -1,56 +0,0 @@ - - */ -class DeleteMethodCompiler implements MethodCompilerInterface -{ - use CreateConstructorTrait; - - public function compile(Result $result, ResultMethod $method, $attribute): void - { - if (!$method->reflection->getReturnType() instanceof ReflectionNamedType || $method->reflection->getReturnType()->getName() !== "void") { - throw new CompilerException(sprintf( - "Delete method [%s::%s] must have void return type.", - $result->reflection->getName(), - $method->reflection->getName(), - )); - } - - if ($method->reflection->getNumberOfParameters() !== 1) { - throw new CompilerException(sprintf( - "Delete method [%s::%s] must have exactly one parameter.", - $result->reflection->getName(), - $method->reflection->getName(), - )); - } - - $rp = $method->reflection->getParameters()[0]; - if (!$rp->getType() instanceof ReflectionNamedType || !in_array($rp->getType()->getName(), ["array", $result->repository->class], true)) { - throw new CompilerException(sprintf( - "Delete method [%s::%s] must have exactly one parameter with type [%s] or array.", - $result->reflection->getName(), - $method->reflection->getName(), - $result->repository->class, - )); - } - - $this->createConstructorWithPersistenceProperty($result); - - if ($rp->getType()->getName() === "array") { - $method->line("\$this->persistence->deleteAll(\${$rp->getName()});"); - } else { - $method->line("\$this->persistence->delete(\${$rp->getName()});"); - } - } -} diff --git a/data-access-kit/src/Repository/Method/ManipulationMethodCompiler.php b/data-access-kit/src/Repository/Method/ManipulationMethodCompiler.php index 78f6afc..d187a08 100644 --- a/data-access-kit/src/Repository/Method/ManipulationMethodCompiler.php +++ b/data-access-kit/src/Repository/Method/ManipulationMethodCompiler.php @@ -2,7 +2,9 @@ namespace DataAccessKit\Repository\Method; +use DataAccessKit\Repository\Attribute\Delete; use DataAccessKit\Repository\Attribute\Insert; +use DataAccessKit\Repository\Attribute\Update; use DataAccessKit\Repository\Attribute\Upsert; use DataAccessKit\Repository\Compiler; use DataAccessKit\Repository\Exception\CompilerException; @@ -11,13 +13,12 @@ use DataAccessKit\Repository\ResultMethod; use ReflectionNamedType; use function get_class; -use function in_array; use function property_exists; use function sprintf; use function ucfirst; /** - * @implements MethodCompilerInterface + * @implements MethodCompilerInterface */ class ManipulationMethodCompiler implements MethodCompilerInterface { @@ -28,6 +29,8 @@ public function compile(Result $result, ResultMethod $method, $attribute): void $persistenceMethod = match (true) { $attribute instanceof Insert => "insert", $attribute instanceof Upsert => "upsert", + $attribute instanceof Update => "update", + $attribute instanceof Delete => "delete", default => throw new CompilerException(sprintf( "Unexpected attribute of type [%s].", get_class($attribute), @@ -53,13 +56,19 @@ public function compile(Result $result, ResultMethod $method, $attribute): void } $rp = $method->reflection->getParameters()[0]; - if (!$rp->getType() instanceof ReflectionNamedType || !in_array($rp->getType()->getName(), ["array", $result->repository->class], true)) { + if (!$rp->getType() instanceof ReflectionNamedType || + !( + $rp->getType()->getName() === $result->repository->class || + ($rp->getType()->getName() === "array" && !$attribute instanceof Update) + ) + ) { throw new CompilerException(sprintf( - "%s method [%s::%s] must have exactly one parameter with type [%s] or array.", + "%s method [%s::%s] must have exactly one parameter with type [%s]%s.", ucfirst($persistenceMethod), $result->reflection->getName(), $method->reflection->getName(), $result->repository->class, + $attribute instanceof Update ? "" : " or array", )); } diff --git a/data-access-kit/src/Repository/Method/UpdateMethodCompiler.php b/data-access-kit/src/Repository/Method/UpdateMethodCompiler.php deleted file mode 100644 index 69c4b5a..0000000 --- a/data-access-kit/src/Repository/Method/UpdateMethodCompiler.php +++ /dev/null @@ -1,52 +0,0 @@ - - */ -class UpdateMethodCompiler implements MethodCompilerInterface -{ - use CreateConstructorTrait; - - public function compile(Result $result, ResultMethod $method, $attribute): void - { - if (!$method->reflection->getReturnType() instanceof ReflectionNamedType || $method->reflection->getReturnType()->getName() !== "void") { - throw new CompilerException(sprintf( - "Update method [%s::%s] must have void return type.", - $result->reflection->getName(), - $method->reflection->getName(), - )); - } - - if ($method->reflection->getNumberOfParameters() !== 1) { - throw new CompilerException(sprintf( - "Update method [%s::%s] must have exactly one parameter.", - $result->reflection->getName(), - $method->reflection->getName(), - )); - } - - $rp = $method->reflection->getParameters()[0]; - if (!$rp->getType() instanceof ReflectionNamedType || $rp->getType()->getName() !== $result->repository->class) { - throw new CompilerException(sprintf( - "Update method [%s::%s] must have exactly one parameter with type [%s].", - $result->reflection->getName(), - $method->reflection->getName(), - $result->repository->class, - )); - } - - $this->createConstructorWithPersistenceProperty($result); - - $method->line("\$this->persistence->update(\${$rp->getName()});"); - } - -} diff --git a/data-access-kit/test/Repository/CompilerTest.php b/data-access-kit/test/Repository/CompilerTest.php index ad366bd..083b440 100644 --- a/data-access-kit/test/Repository/CompilerTest.php +++ b/data-access-kit/test/Repository/CompilerTest.php @@ -74,6 +74,7 @@ use Spatie\Snapshots\MatchesSnapshots; use function dirname; use function lcfirst; +use function sprintf; use function str_replace; use function strrpos; use function substr; @@ -138,6 +139,7 @@ public function testCompileError(string $interfaceName): void { try { $this->compiler->compile($this->compiler->prepare($interfaceName)); + $this->fail(sprintf("Expected [%s] to be thrown.", CompilerException::class)); } catch (CompilerException $e) { $this->assertMatchesSnapshot($e->getMessage()); } diff --git a/data-access-kit/test/Repository/Fixture/UpdateRepositoryInterface.php b/data-access-kit/test/Repository/Fixture/UpdateRepositoryInterface.php index 8b876ed..343fead 100644 --- a/data-access-kit/test/Repository/Fixture/UpdateRepositoryInterface.php +++ b/data-access-kit/test/Repository/Fixture/UpdateRepositoryInterface.php @@ -3,9 +3,12 @@ namespace DataAccessKit\Repository\Fixture; use DataAccessKit\Repository\Attribute\Repository; +use DataAccessKit\Repository\Attribute\Update; #[Repository(Foo::class)] interface UpdateRepositoryInterface { public function update(Foo $foo): void; + #[Update(["title"])] + public function updateTitleOnly(Foo $foo): void; } diff --git a/data-access-kit/test/Repository/Snapshot/CompilerTest.testCompile.update.txt b/data-access-kit/test/Repository/Snapshot/CompilerTest.testCompile.update.txt index b3f4e6c..11d6e6e 100644 --- a/data-access-kit/test/Repository/Snapshot/CompilerTest.testCompile.update.txt +++ b/data-access-kit/test/Repository/Snapshot/CompilerTest.testCompile.update.txt @@ -18,4 +18,11 @@ final class UpdateRepository implements UpdateRepositoryInterface { $this->persistence->update($foo); } + + public function updateTitleOnly( + Foo $foo, + ): void + { + $this->persistence->update($foo, ['title']); + } }