Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
90.20% covered (success)
90.20%
46 / 51
60.00% covered (warning)
60.00%
6 / 10
CRAP
0.00% covered (danger)
0.00%
0 / 1
DecryptedAuthenticatedUser
90.20% covered (success)
90.20%
46 / 51
60.00% covered (warning)
60.00%
6 / 10
13.16
0.00% covered (danger)
0.00%
0 / 1
 createFromEntity
100.00% covered (success)
100.00%
9 / 9
100.00% covered (success)
100.00%
1 / 1
1
 getIdentifierClassName
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getEntityClassName
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 isExpired
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getExpireTime
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getBoundedContextId
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getId
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 refresh
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
1
 convert
89.47% covered (warning)
89.47%
17 / 19
0.00% covered (danger)
0.00%
0 / 1
3.01
 createRandom
92.86% covered (success)
92.86%
13 / 14
0.00% covered (danger)
0.00%
0 / 1
2.00
1<?php
2namespace Apie\Common\ValueObjects;
3
4use Apie\Core\Attributes\FakeMethod;
5use Apie\Core\BoundedContext\BoundedContextId;
6use Apie\Core\Entities\EntityInterface;
7use Apie\Core\Identifiers\IdentifierInterface;
8use Apie\Core\ValueObjects\Exceptions\InvalidStringForValueObjectException;
9use Apie\Core\ValueObjects\Interfaces\StringValueObjectInterface;
10use Apie\Core\ValueObjects\IsStringValueObject;
11use Apie\Fixtures\Identifiers\CollectionItemOwnedIdentifier;
12use Apie\Fixtures\Identifiers\ImageFileIdentifier;
13use Apie\Fixtures\Identifiers\OrderIdentifier;
14use Apie\Fixtures\Identifiers\UserAutoincrementIdentifier;
15use Apie\Fixtures\Identifiers\UserWithAddressIdentifier;
16use Faker\Generator;
17use ReflectionClass;
18use ReflectionException;
19
20/**
21 * @template T of EntityInterface
22 */
23#[FakeMethod('createRandom')]
24final class DecryptedAuthenticatedUser implements StringValueObjectInterface
25{
26    use IsStringValueObject;
27
28    /** @var class-string<IdentifierInterface<T>> */
29    private string $className;
30
31    private BoundedContextId $boundedContextId;
32
33    /** @var IdentifierInterface<T> */
34    private IdentifierInterface $id;
35
36    private int $expireTime;
37
38    /**
39     * @template U of EntityInterface
40     * @param U $entity
41     * @return DecryptedAuthenticatedUser<U>
42     */
43    public static function createFromEntity(
44        EntityInterface  $entity,
45        BoundedContextId $boundedContextId,
46        int              $time
47    ): self {
48        return new self(
49            get_class($entity->getId())
50            . '/'
51            . $boundedContextId
52            . '/'
53            . $entity->getId()
54            . '/'
55            . $time
56        );
57    }
58
59    /**
60     * @return class-string<IdentifierInterface<T>>
61     */
62    public function getIdentifierClassName(): string
63    {
64        return $this->className;
65    }
66
67    /**
68     * @return class-string<T>
69     */
70    public function getEntityClassName(): string
71    {
72        return $this->className::getReferenceFor()->name;
73    }
74
75    public function isExpired(): bool
76    {
77        return $this->expireTime <= time();
78    }
79
80    public function getExpireTime(): int
81    {
82        return $this->expireTime;
83    }
84
85    public function getBoundedContextId(): BoundedContextId
86    {
87        return $this->boundedContextId;
88    }
89
90    /**
91     * @return IdentifierInterface<T>
92     */
93    public function getId(): IdentifierInterface
94    {
95        return $this->id;
96    }
97
98    /**
99     * @return DecryptedAuthenticatedUser<T>
100     */
101    public function refresh(int $expireTime): self
102    {
103        $res = clone $this;
104        $res->expireTime = $expireTime;
105        return $res;
106    }
107
108    protected function convert(string $input): string
109    {
110        list($className, $boundedContextId, $id, $expireTime) = array_pad(
111            explode(
112                '/',
113                $input,
114                4
115            ),
116            4,
117            null
118        );
119        try {
120            $refl = new ReflectionClass($className);
121            if (!in_array(IdentifierInterface::class, $refl->getInterfaceNames(), true)) {
122                throw new InvalidStringForValueObjectException($input, $this);
123            }
124        } catch (ReflectionException $previous) {
125            throw new InvalidStringForValueObjectException($input, $this, $previous);
126        }
127        $this->className = $className;
128        $this->boundedContextId = new BoundedContextId($boundedContextId);
129        $this->id = new $className($id);
130        $this->expireTime = (int)$expireTime;
131
132        return $input;
133    }
134
135    public static function createRandom(Generator $factory): static
136    {
137        $classes = [
138            CollectionItemOwnedIdentifier::class,
139            ImageFileIdentifier::class,
140            OrderIdentifier::class,
141            UserAutoincrementIdentifier::class,
142            UserWithAddressIdentifier::class,
143        ];
144        $class = $factory->randomElement($classes);
145        if (!class_exists($class)) {
146            throw new \LogicException('I need apie/fixtures to be able to make a random instance!');
147        }
148        $identifier = $class::createRandom($factory);
149        return new static(
150            get_class($identifier) . '/' . $factory->fakeClass(BoundedContextId::class) . '/' . $identifier->toNative() . '/' . (time() + 3600)
151        );
152    }
153}