Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
90.32% covered (success)
90.32%
28 / 31
80.00% covered (warning)
80.00%
12 / 15
CRAP
0.00% covered (danger)
0.00%
0 / 1
ApieFacade
90.32% covered (success)
90.32%
28 / 31
80.00% covered (warning)
80.00%
12 / 15
21.40
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getBoundedContext
66.67% covered (warning)
66.67%
2 / 3
0.00% covered (danger)
0.00%
0 / 1
2.15
 all
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
2
 find
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 removeExisting
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 persistNew
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 persistExisting
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 normalize
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 denormalizeNewObject
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 denormalizeOnExistingObject
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 denormalizeOnMethodCall
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getAction
80.00% covered (warning)
80.00%
4 / 5
0.00% covered (danger)
0.00%
0 / 1
3.07
 createAction
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
2
 getActionsForBoundedContext
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
2
 upsert
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2namespace Apie\Common;
3
4use Apie\Common\Interfaces\ApieFacadeInterface;
5use Apie\Common\Interfaces\RouteDefinitionProviderInterface;
6use Apie\Common\RouteDefinitions\ActionHashmap;
7use Apie\Core\Actions\ActionInterface;
8use Apie\Core\BoundedContext\BoundedContext;
9use Apie\Core\BoundedContext\BoundedContextHashmap;
10use Apie\Core\BoundedContext\BoundedContextId;
11use Apie\Core\Context\ApieContext;
12use Apie\Core\ContextConstants;
13use Apie\Core\Datalayers\ApieDatalayer;
14use Apie\Core\Datalayers\Lists\EntityListInterface;
15use Apie\Core\Entities\EntityInterface;
16use Apie\Core\Identifiers\IdentifierInterface;
17use Apie\Core\Lists\ItemHashmap;
18use Apie\Core\Lists\ItemList;
19use Apie\Serializer\Serializer;
20use LogicException;
21use ReflectionClass;
22use ReflectionMethod;
23
24final class ApieFacade implements ApieFacadeInterface
25{
26    public function __construct(
27        private RouteDefinitionProviderInterface $routeDefinitionProvider,
28        private BoundedContextHashmap $boundedContextHashmap,
29        private Serializer $serializer,
30        private ApieDatalayer $apieDatalayer
31    ) {
32    }
33
34    private function getBoundedContext(BoundedContext|BoundedContextId $boundedContext): BoundedContextId
35    {
36        if ($boundedContext instanceof BoundedContext) {
37            return $boundedContext->getId();
38        }
39        return $boundedContext;
40    }
41
42    /**
43     * @template T of EntityInterface
44     * @param class-string<T>|ReflectionClass<T> $class
45     * @return EntityListInterface<T>
46     */
47    public function all(string|ReflectionClass $class, BoundedContext|BoundedContextId $boundedContext): EntityListInterface
48    {
49        if (is_string($class)) {
50            $class = new ReflectionClass($class);
51        }
52
53        return $this->apieDatalayer->all($class, $this->getBoundedContext($boundedContext));
54    }
55
56    /**
57     * @template T of EntityInterface
58     * @param IdentifierInterface<T> $identifier
59     * @return T
60     */
61    public function find(IdentifierInterface $identifier, BoundedContext|BoundedContextId $boundedContext): EntityInterface
62    {
63        return $this->apieDatalayer->find($identifier, $this->getBoundedContext($boundedContext));
64    }
65
66    public function removeExisting(EntityInterface $entity, BoundedContext|BoundedContextId $boundedContext): void
67    {
68        $this->apieDatalayer->removeExisting($entity, $this->getBoundedContext($boundedContext));
69    }
70
71    /**
72     * @template T of EntityInterface
73     * @param T $entity
74     * @return T
75     */
76    public function persistNew(EntityInterface $entity, BoundedContext|BoundedContextId $boundedContext): EntityInterface
77    {
78        return $this->apieDatalayer->persistNew($entity, $this->getBoundedContext($boundedContext));
79    }
80
81    /**
82     * @template T of EntityInterface
83     * @param T $entity
84     * @return T
85     */
86    public function persistExisting(EntityInterface $entity, BoundedContext|BoundedContextId $boundedContext): EntityInterface
87    {
88        return $this->apieDatalayer->persistExisting($entity, $this->getBoundedContext($boundedContext));
89    }
90
91    public function normalize(mixed $object, ApieContext $apieContext): string|int|float|bool|ItemList|ItemHashmap|null
92    {
93        return $this->serializer->normalize($object, $apieContext);
94    }
95
96    public function denormalizeNewObject(string|int|float|bool|ItemList|ItemHashmap|array|null $object, string $desiredType, ApieContext $apieContext): mixed
97    {
98        return $this->serializer->denormalizeNewObject($object, $desiredType, $apieContext);
99    }
100
101    public function denormalizeOnExistingObject(ItemHashmap $object, object $existingObject, ApieContext $apieContext): mixed
102    {
103        return $this->serializer->denormalizeOnExistingObject($object, $existingObject, $apieContext);
104    }
105
106    public function denormalizeOnMethodCall(string|int|float|bool|ItemList|ItemHashmap|array|null $input, ?object $object, ReflectionMethod $method, ApieContext $apieContext): mixed
107    {
108        return $this->serializer->denormalizeOnMethodCall($input, $object, $method, $apieContext);
109    }
110
111    /**
112     * @deprecated use createAction instead
113     */
114    public function getAction(string $boundedContextId, string $operationId, ApieContext $apieContext): ActionInterface
115    {
116        $actions = $this->getActionsForBoundedContext(new BoundedContextId($boundedContextId), $apieContext);
117        foreach ($actions as $action) {
118            if ($action->getOperationId() === $operationId) {
119                return new($action->getAction())($this);
120            }
121        }
122        throw new LogicException(sprintf('"%s" operation id not found!', $operationId));
123    }
124
125    public function createAction(ApieContext $apieContext): ActionInterface
126    {
127        if ($apieContext->hasContext(ContextConstants::APIE_ACTION)) {
128            return new ($apieContext->getContext(ContextConstants::APIE_ACTION))($this);
129        }
130
131        return $this->getAction(
132            $apieContext->getContext(ContextConstants::BOUNDED_CONTEXT_ID),
133            $apieContext->getContext(ContextConstants::OPERATION_ID),
134            $apieContext,
135        );
136    }
137
138    public function getActionsForBoundedContext(BoundedContextId|BoundedContext $boundedContext, ApieContext $apieContext): ActionHashmap
139    {
140        if ($boundedContext instanceof BoundedContextId) {
141            $boundedContext = $this->boundedContextHashmap[$boundedContext->toNative()];
142        }
143
144        return $this->routeDefinitionProvider->getActionsForBoundedContext($boundedContext, $apieContext);
145    }
146
147    public function upsert(EntityInterface $entity, BoundedContextId|BoundedContext $boundedContext): EntityInterface
148    {
149        return $this->apieDatalayer->upsert($entity, $this->getBoundedContext($boundedContext));
150    }
151}