From 86bdf6105ef5baf0b8e57c7e77ee5fb51d41aedf Mon Sep 17 00:00:00 2001 From: Margus Kaidja Date: Thu, 10 Nov 2022 11:52:53 +0200 Subject: [PATCH] Make Accessible trait as minimal as possible and hide as much of the implementation as possible to internal classes. --- src/Accessible.php | 15 +++----- src/ClassConf.php | 76 +++++++++++++++++++++++------------------ src/Format/Method.php | 1 + src/Format/Standard.php | 1 + 4 files changed, 50 insertions(+), 43 deletions(-) diff --git a/src/Accessible.php b/src/Accessible.php index c2077b2..9b2eeb1 100644 --- a/src/Accessible.php +++ b/src/Accessible.php @@ -26,8 +26,7 @@ trait Accessible */ public function __call(string $method, array $args): mixed { - return ClassConf::findConf(static::class) - ->handleMagicCall($this, $method, $args); + return ClassConf::handleMagicCall($this, $method, $args); } /** @@ -38,8 +37,7 @@ public function __call(string $method, array $args): mixed */ public function __get(string $propertyName): mixed { - return ClassConf::findConf(static::class) - ->handleMagicGet($this, $propertyName); + return ClassConf::handleMagicGet($this, $propertyName); } /** @@ -51,8 +49,7 @@ public function __get(string $propertyName): mixed */ public function __set(string $propertyName, mixed $propertyValue): void { - ClassConf::findConf(static::class) - ->handleMagicSet($this, $propertyName, $propertyValue); + ClassConf::handleMagicSet($this, $propertyName, $propertyValue); } /** @@ -63,8 +60,7 @@ public function __set(string $propertyName, mixed $propertyValue): void */ public function __isset(string $propertyName): bool { - return ClassConf::findConf(static::class) - ->handleMagicIsset($this, $propertyName); + return ClassConf::handleMagicIsset($this, $propertyName); } /** @@ -75,7 +71,6 @@ public function __isset(string $propertyName): bool */ public function __unset(string $propertyName): void { - ClassConf::findConf(static::class) - ->handleMagicUnset($this, $propertyName); + ClassConf::handleMagicUnset($this, $propertyName); } } diff --git a/src/ClassConf.php b/src/ClassConf.php index 099e938..9c1c1b9 100644 --- a/src/ClassConf.php +++ b/src/ClassConf.php @@ -26,6 +26,7 @@ use function call_user_func; use function count; use function current; +use function get_class; use function get_parent_class; use function in_array; use function is_string; @@ -171,7 +172,7 @@ private function __construct( * @return ClassConf * @throws ReflectionException */ - public static function findConf(string $name): ClassConf + private static function findConf(string $name): ClassConf { if (!isset(self::$classes[$name])) { self::$classes[$name] = new self($name); @@ -343,10 +344,12 @@ private function isClassUsingAccessibleTrait(ReflectionClass $rfClass): array * * @return mixed */ - public function handleMagicCall(object $object, string $method, array $args): mixed + public static function handleMagicCall(object $object, string $method, array $args): mixed { + $classConf = self::findConf(get_class($object)); + /** @var Format $attr */ - $attr = $this->attributes->get(Format::class); + $attr = $classConf->attributes->get(Format::class); $format = $attr->instance(); if (null !== ($parsedMethod = $format->matchCalled($method))) { @@ -376,7 +379,7 @@ public function handleMagicCall(object $object, string $method, array $args): mi ) { if ($nArgs > 1) { throw InvalidArgumentException::dueMultiPropertyAccessorCanHaveExactlyOneArgument( - self::class, + $classConf->name, $method ); } @@ -386,7 +389,7 @@ public function handleMagicCall(object $object, string $method, array $args): mi } elseif ( // Check if whole method name is property name like $obj->somePropertyName('somevalue') null === $accessorMethod - && null !== $this->properties->findConf($propertyName, true) + && null !== $classConf->properties->findConf($propertyName, true) && $format->allowPropertyNameOnly() ) { // If there are zero arguments, then interpret the call as Getter @@ -401,7 +404,7 @@ public function handleMagicCall(object $object, string $method, array $args): mi // Accessor method must be resolved at this point, or we fail if (null === $accessorMethod) { - throw BadMethodCallException::dueUnknownAccessorMethod(self::class, $method); + throw BadMethodCallException::dueUnknownAccessorMethod($classConf->name, $method); } $propertyNameCI = false; @@ -411,14 +414,14 @@ public function handleMagicCall(object $object, string $method, array $args): mi if (0 === count($propertiesList)) { if ('' === $propertyName) { if (!count($args)) { - throw InvalidArgumentException::dueMethodIsMissingPropertyNameArgument(self::class, $method); + throw InvalidArgumentException::dueMethodIsMissingPropertyNameArgument($classConf->name, $method); } $propertyName = array_shift($args); if (!is_string($propertyName)) { throw InvalidArgumentException::duePropertyNameArgumentMustBeString( - self::class, + $classConf->name, $method, count($args) + 1 ); @@ -433,7 +436,7 @@ public function handleMagicCall(object $object, string $method, array $args): mi if ($accessorMethodIsSetOrWith) { if (!count($args)) { throw InvalidArgumentException::dueMethodIsMissingPropertyValueArgument( - self::class, + $classConf->name, $method, $nArgs + 1 ); @@ -445,7 +448,7 @@ public function handleMagicCall(object $object, string $method, array $args): mi // Fail if there are more arguments specified than we are willing to process if (count($args)) { throw InvalidArgumentException::dueMethodHasMoreArgumentsThanExpected( - self::class, + $classConf->name, $method, $nArgs - count($args) ); @@ -466,18 +469,18 @@ public function handleMagicCall(object $object, string $method, array $args): mi $result = clone $result; } - $accessorImpl = $this->setter; + $accessorImpl = $classConf->setter; foreach ($propertiesList as $propertyName => $propertyValue) { if (!is_string($propertyName)) { throw InvalidArgumentException::dueMultiPropertyArrayContainsNonStringProperty( - self::class, + $classConf->name, $method, $propertyName ); } - $propertyConf = $this->properties->findConf($propertyName, $propertyNameCI); + $propertyConf = $classConf->properties->findConf($propertyName, $propertyNameCI); $immutable = ($propertyConf?->isImmutable()) ?? false; // Check if mutable/immutable property was called using correct method: @@ -489,12 +492,12 @@ public function handleMagicCall(object $object, string $method, array $args): mi ) { if ($immutable) { throw BadMethodCallException::dueImmutablePropertiesMustBeCalledUsingWith( - self::class, + $classConf->name, $propertyName ); } else { throw BadMethodCallException::dueMutablePropertiesMustBeCalledUsingSet( - self::class, + $classConf->name, $propertyName ); } @@ -505,21 +508,21 @@ public function handleMagicCall(object $object, string $method, array $args): mi } else { /** @var 'get'|'isset'|'unset' $accessorMethod */ $accessorImpl = match ($accessorMethod) { - Method::TYPE_GET => $this->getter, - Method::TYPE_ISSET => $this->isSetter, - Method::TYPE_UNSET => $this->unSetter + Method::TYPE_GET => $classConf->getter, + Method::TYPE_ISSET => $classConf->isSetter, + Method::TYPE_UNSET => $classConf->unSetter }; foreach ($propertiesList as $propertyName) { if (!is_string($propertyName)) { throw InvalidArgumentException::dueMultiPropertyArrayContainsNonStringProperty( - self::class, + $classConf->name, $method, $propertyName ); } - $propertyConf = $this->properties->findConf($propertyName, $propertyNameCI); + $propertyConf = $classConf->properties->findConf($propertyName, $propertyNameCI); $result = $accessorImpl($result, $propertyName, $propertyConf); } } @@ -527,37 +530,42 @@ public function handleMagicCall(object $object, string $method, array $args): mi return $result; } - public function handleMagicGet(object $object, string $propertyName): mixed + public static function handleMagicGet(object $object, string $propertyName): mixed { - return ($this->getter)( + $classConf = self::findConf(get_class($object)); + + return ($classConf->getter)( $object, $propertyName, - $this->properties->findConf($propertyName) + $classConf->properties->findConf($propertyName) ); } - public function handleMagicIsset(object $object, string $propertyName): bool + public static function handleMagicIsset(object $object, string $propertyName): bool { - return ($this->isSetter)( + $classConf = self::findConf(get_class($object)); + + return ($classConf->isSetter)( $object, $propertyName, - $this->properties->findConf($propertyName) + $classConf->properties->findConf($propertyName) ); } - public function handleMagicSet(object $object, string $propertyName, mixed $propertyValue): void + public static function handleMagicSet(object $object, string $propertyName, mixed $propertyValue): void { - $propertyConf = $this->properties->findConf($propertyName); + $classConf = self::findConf(get_class($object)); + $propertyConf = $classConf->properties->findConf($propertyName); $immutable = $propertyConf?->isImmutable(); if ($immutable) { throw BadMethodCallException::dueImmutablePropertiesCantBeSetUsingAssignmentOperator( - $this->name, + $classConf->name, $propertyName ); } - ($this->setter)( + ($classConf->setter)( $object, 'set', $propertyName, @@ -566,12 +574,14 @@ public function handleMagicSet(object $object, string $propertyName, mixed $prop ); } - public function handleMagicUnset(object $object, string $propertyName): void + public static function handleMagicUnset(object $object, string $propertyName): void { - ($this->unSetter)( + $classConf = self::findConf(get_class($object)); + + ($classConf->unSetter)( $object, $propertyName, - $this->properties->findConf($propertyName) + $classConf->properties->findConf($propertyName) ); } } diff --git a/src/Format/Method.php b/src/Format/Method.php index fe6e049..f01605d 100644 --- a/src/Format/Method.php +++ b/src/Format/Method.php @@ -12,6 +12,7 @@ namespace margusk\Accessors\Format; +/** @api */ final class Method { public const TYPE_GET = 'get'; diff --git a/src/Format/Standard.php b/src/Format/Standard.php index ad433a3..a2c76fe 100644 --- a/src/Format/Standard.php +++ b/src/Format/Standard.php @@ -31,6 +31,7 @@ * $value = $foo->bar(); // Same as $value = $foo->bar; * $foo->bar('new value'); // Same as $foo->bar = `new value`; * ``` + * @api */ class Standard implements FormatContract {