Code Coverage  | 
      ||||||||||
Lines  | 
       Functions and Methods  | 
       Classes and Traits  | 
      ||||||||
| Total |         | 
       72.73%  | 
       24 / 33  | 
               | 
       42.86%  | 
       3 / 7  | 
       CRAP |         | 
       0.00%  | 
       0 / 1  | 
      
| IdentifierUtils |         | 
       72.73%  | 
       24 / 33  | 
               | 
       42.86%  | 
       3 / 7  | 
       16.43 |         | 
       0.00%  | 
       0 / 1  | 
      
| __construct |         | 
       0.00%  | 
       0 / 1  | 
               | 
       0.00%  | 
       0 / 1  | 
       2 | |||
| identifierToEntityClass |         | 
       100.00%  | 
       3 / 3  | 
               | 
       100.00%  | 
       1 / 1  | 
       2 | |||
| idStringToIdentifier |         | 
       100.00%  | 
       6 / 6  | 
               | 
       100.00%  | 
       1 / 1  | 
       2 | |||
| entityClassToIdentifier |         | 
       66.67%  | 
       4 / 6  | 
               | 
       0.00%  | 
       0 / 1  | 
       3.33 | |||
| classNameToUnderscore |         | 
       100.00%  | 
       4 / 4  | 
               | 
       100.00%  | 
       1 / 1  | 
       1 | |||
| propertyToUnderscore |         | 
       0.00%  | 
       0 / 4  | 
               | 
       0.00%  | 
       0 / 1  | 
       2 | |||
| injectIdentifier |         | 
       77.78%  | 
       7 / 9  | 
               | 
       0.00%  | 
       0 / 1  | 
       3.10 | |||
| 1 | <?php | 
| 2 | namespace Apie\Core; | 
| 3 | |
| 4 | use Apie\Core\Context\ApieContext; | 
| 5 | use Apie\Core\Entities\EntityInterface; | 
| 6 | use Apie\Core\Exceptions\InvalidTypeException; | 
| 7 | use Apie\Core\Identifiers\IdentifierInterface; | 
| 8 | use Apie\Serializer\Serializer; | 
| 9 | use LogicException; | 
| 10 | use ReflectionClass; | 
| 11 | use ReflectionNamedType; | 
| 12 | use ReflectionProperty; | 
| 13 | |
| 14 | final class IdentifierUtils | 
| 15 | { | 
| 16 | private function __construct() | 
| 17 | { | 
| 18 | } | 
| 19 | |
| 20 | /** | 
| 21 | * @template T of EntityInterface | 
| 22 | * @param ReflectionClass<IdentifierInterface<T>>|IdentifierInterface<T> $identifier | 
| 23 | * @return ReflectionClass<T> | 
| 24 | */ | 
| 25 | public static function identifierToEntityClass(ReflectionClass|IdentifierInterface $identifier): ReflectionClass | 
| 26 | { | 
| 27 | if ($identifier instanceof IdentifierInterface) { | 
| 28 | $identifier = new ReflectionClass($identifier); | 
| 29 | } | 
| 30 | return $identifier->getMethod('getReferenceFor')->invoke(null); | 
| 31 | } | 
| 32 | |
| 33 | /** | 
| 34 | * @return IdentifierInterface<EntityInterface> | 
| 35 | */ | 
| 36 | public static function idStringToIdentifier(string $id, ApieContext $context): IdentifierInterface | 
| 37 | { | 
| 38 | $resourceClass = new ReflectionClass($context->getContext(ContextConstants::RESOURCE_NAME)); | 
| 39 | $idClass = self::entityClassToIdentifier($resourceClass); | 
| 40 | /** @var IdentifierInterface<EntityInterface> $idObject */ | 
| 41 | $idObject = $context->hasContext(Serializer::class) | 
| 42 | ? $context->getContext(Serializer::class)->denormalizeNewObject($id, $idClass->name, $context) | 
| 43 | : $idClass->newInstance($id); | 
| 44 | return $idObject; | 
| 45 | } | 
| 46 | |
| 47 | /** | 
| 48 | * @template T of EntityInterface | 
| 49 | * @param ReflectionClass<T>|T $identifier | 
| 50 | * @return ReflectionClass<IdentifierInterface<T>> | 
| 51 | */ | 
| 52 | public static function entityClassToIdentifier(ReflectionClass|EntityInterface $identifier): ReflectionClass | 
| 53 | { | 
| 54 | if ($identifier instanceof EntityInterface) { | 
| 55 | $identifier = new ReflectionClass($identifier); | 
| 56 | } | 
| 57 | $returnType = $identifier->getMethod('getId')->getReturnType(); | 
| 58 | if (!($returnType instanceof ReflectionNamedType)) { | 
| 59 | throw new InvalidTypeException($returnType, 'ReflectionNamedType'); | 
| 60 | } | 
| 61 | return new ReflectionClass($returnType->getName()); | 
| 62 | } | 
| 63 | |
| 64 | /** | 
| 65 | * @param ReflectionClass<object> $class | 
| 66 | */ | 
| 67 | public static function classNameToUnderscore(ReflectionClass $class): string | 
| 68 | { | 
| 69 | $str = $class->getShortName(); | 
| 70 | $str = lcfirst($str); | 
| 71 | $str = preg_replace("/[A-Z]/", '_$0', $str); | 
| 72 | return strtolower($str); | 
| 73 | } | 
| 74 | |
| 75 | public static function propertyToUnderscore(ReflectionProperty $property): string | 
| 76 | { | 
| 77 | // TODO check visibility with private properties | 
| 78 | $str = $property->name; | 
| 79 | $str = lcfirst($str); | 
| 80 | $str = preg_replace("/[A-Z]/", '_$0', $str); | 
| 81 | return strtolower($str); | 
| 82 | } | 
| 83 | |
| 84 | /** | 
| 85 | * @template T of EntityInterface | 
| 86 | * @param T $entity | 
| 87 | * @param IdentifierInterface<T> $identifier | 
| 88 | */ | 
| 89 | public static function injectIdentifier(EntityInterface $entity, IdentifierInterface $identifier): void | 
| 90 | { | 
| 91 | $refl = new ReflectionClass($entity); | 
| 92 | while ($refl) { | 
| 93 | if ($refl->hasProperty('id')) { | 
| 94 | $prop = $refl->getProperty('id'); | 
| 95 | $prop->setAccessible(true); | 
| 96 | $prop->setValue($entity, $identifier); | 
| 97 | return; | 
| 98 | } | 
| 99 | $refl = $refl->getParentClass(); | 
| 100 | } | 
| 101 | throw new LogicException('I could not find an "id" property!'); | 
| 102 | } | 
| 103 | } |