-
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
PropertyAccessLite
instead of Symfony's.
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,146 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
/* | ||
* This file is part of rekalogika/mapper package. | ||
* | ||
* (c) Priyadi Iman Nurcahyo <https://rekalogika.dev> | ||
* | ||
* For the full copyright and license information, please view the LICENSE file | ||
* that was distributed with this source code. | ||
*/ | ||
|
||
namespace Rekalogika\Mapper\PropertyAccessLite; | ||
|
||
use Symfony\Component\PropertyAccess\Exception\NoSuchPropertyException; | ||
use Symfony\Component\PropertyAccess\Exception\UninitializedPropertyException; | ||
use Symfony\Component\PropertyAccess\PropertyAccessorInterface; | ||
use Symfony\Component\PropertyAccess\PropertyPathInterface; | ||
|
||
final class PropertyAccessLite implements PropertyAccessorInterface | ||
{ | ||
/** | ||
* @param object|array<array-key,mixed> $objectOrArray | ||
*/ | ||
public function getValue( | ||
object|array $objectOrArray, | ||
string|PropertyPathInterface $propertyPath, | ||
): mixed { | ||
assert(is_string($propertyPath)); | ||
assert(\is_object($objectOrArray)); | ||
|
||
$getter = 'get' . ucfirst($propertyPath); | ||
|
||
try { | ||
/** @psalm-suppress MixedMethodCall */ | ||
return $objectOrArray->{$getter}(); | ||
} catch (\Throwable $e) { | ||
if (!\str_starts_with($e->getMessage(), 'Call to undefined method')) { | ||
if (\str_starts_with($e->getMessage(), 'Typed property')) { | ||
throw new UninitializedPropertyException(\sprintf( | ||
'Property "%s" is not initialized in object "%s"', | ||
$propertyPath, | ||
\get_class($objectOrArray), | ||
), 0, $e); | ||
} | ||
|
||
throw $e; | ||
} | ||
} | ||
|
||
try { | ||
return $objectOrArray->{$propertyPath}; | ||
// @phpstan-ignore-next-line | ||
} catch (\Throwable $e) { | ||
if (\str_starts_with($e->getMessage(), 'Typed property')) { | ||
throw new UninitializedPropertyException(\sprintf( | ||
'Property "%s" is not initialized in object "%s"', | ||
$propertyPath, | ||
\get_class($objectOrArray), | ||
), 0, $e); | ||
} elseif (\str_starts_with($e->getMessage(), 'Cannot access private property')) { | ||
throw new NoSuchPropertyException(\sprintf( | ||
'Property "%s" is not public in object "%s"', | ||
$propertyPath, | ||
\get_class($objectOrArray), | ||
), 0, $e); | ||
} elseif (\str_starts_with($e->getMessage(), 'Undefined property')) { | ||
throw new NoSuchPropertyException(\sprintf( | ||
'Property "%s" is not defined in object "%s"', | ||
$propertyPath, | ||
\get_class($objectOrArray), | ||
), 0, $e); | ||
} | ||
|
||
throw $e; | ||
} | ||
} | ||
|
||
/** | ||
* @param object|array<array-key,mixed> $objectOrArray | ||
*/ | ||
public function setValue( | ||
object|array &$objectOrArray, | ||
string|PropertyPathInterface $propertyPath, | ||
mixed $value | ||
): void { | ||
assert(is_string($propertyPath)); | ||
assert(\is_object($objectOrArray)); | ||
|
||
$setter = 'set' . ucfirst($propertyPath); | ||
|
||
try { | ||
/** @psalm-suppress MixedMethodCall */ | ||
$objectOrArray->{$setter}($value); | ||
return; | ||
} catch (\Throwable $e) { | ||
if (!\str_starts_with($e->getMessage(), 'Call to undefined method')) { | ||
throw $e; | ||
} | ||
} | ||
|
||
try { | ||
if (!\property_exists($objectOrArray, $propertyPath)) { | ||
throw new NoSuchPropertyException(\sprintf( | ||
'Property "%s" is not defined in object "%s"', | ||
$propertyPath, | ||
\get_class($objectOrArray), | ||
)); | ||
} | ||
$objectOrArray->{$propertyPath} = $value; | ||
} catch (NoSuchPropertyException $e) { | ||
throw $e; | ||
} catch (\Throwable $e) { | ||
if (\str_starts_with($e->getMessage(), 'Cannot access private property')) { | ||
throw new NoSuchPropertyException(\sprintf( | ||
'Property "%s" is not public in object "%s"', | ||
$propertyPath, | ||
\get_class($objectOrArray), | ||
), 0, $e); | ||
} | ||
|
||
throw $e; | ||
} | ||
} | ||
|
||
/** | ||
* @param object|array<array-key,mixed> $objectOrArray | ||
*/ | ||
public function isWritable( | ||
object|array $objectOrArray, | ||
string|PropertyPathInterface $propertyPath | ||
): bool { | ||
throw new \RuntimeException('Not implemented'); | ||
} | ||
|
||
/** | ||
* @param object|array<array-key,mixed> $objectOrArray | ||
*/ | ||
public function isReadable( | ||
object|array $objectOrArray, | ||
string|PropertyPathInterface $propertyPath | ||
): bool { | ||
throw new \RuntimeException('Not implemented'); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
/* | ||
* This file is part of rekalogika/mapper package. | ||
* | ||
* (c) Priyadi Iman Nurcahyo <https://rekalogika.dev> | ||
* | ||
* For the full copyright and license information, please view the LICENSE file | ||
* that was distributed with this source code. | ||
*/ | ||
|
||
namespace Rekalogika\Mapper\Tests\Fixtures\AccessMethods; | ||
|
||
class ObjectWithVariousAccessMethods | ||
{ | ||
private string $privatePropertyWithGetterSetter = 'privateProperty'; | ||
// @phpstan-ignore-next-line | ||
private string $privatePropertyWithoutGetterSetter = 'privatePropertyWithoutGetterSetter'; | ||
public string $publicPropertyWithGetterSetter = 'publicProperty'; | ||
public string $publicPropertyWithoutGetterSetter = 'publicPropertyWithoutGetterSetter'; | ||
|
||
|
||
public bool $publicPropertySetterAccessed = false; | ||
public bool $publicPropertyGetterAccessed = false; | ||
|
||
public string $unsetPublicProperty; | ||
Check failure on line 28 in tests/Fixtures/AccessMethods/ObjectWithVariousAccessMethods.php
|
||
|
||
// @phpstan-ignore-next-line | ||
private string $unsetPrivatePropertyWithGetter; | ||
Check failure on line 31 in tests/Fixtures/AccessMethods/ObjectWithVariousAccessMethods.php
|
||
|
||
public function getPrivateProperty(): string | ||
{ | ||
return $this->privatePropertyWithGetterSetter; | ||
} | ||
|
||
public function setPrivateProperty(string $privateProperty): void | ||
{ | ||
$this->privatePropertyWithGetterSetter = $privateProperty; | ||
} | ||
|
||
public function getPublicProperty(): string | ||
{ | ||
$this->publicPropertyGetterAccessed = true; | ||
return $this->publicPropertyWithGetterSetter; | ||
} | ||
|
||
public function setPublicProperty(string $publicProperty): void | ||
{ | ||
$this->publicPropertySetterAccessed = true; | ||
$this->publicPropertyWithGetterSetter = $publicProperty; | ||
} | ||
|
||
public function getUnsetPrivatePropertyWithGetter(): string | ||
{ | ||
return $this->unsetPrivatePropertyWithGetter; | ||
} | ||
} |