Passed
Push — master ( f59089...907e2e )
by Julien
01:19 queued 12s
created

SdkClient::getMapping()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 1
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 1
c 1
b 0
f 0
nc 1
nop 0
dl 0
loc 3
ccs 1
cts 1
cp 1
crap 1
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Mapado\RestClientSdk;
6
7
use Mapado\RestClientSdk\Model\ModelHydrator;
8
use Mapado\RestClientSdk\Model\Serializer;
9
use ProxyManager\Configuration;
10
use ProxyManager\Factory\LazyLoadingGhostFactory;
11
use ProxyManager\Proxy\GhostObjectInterface;
12
use Psr\Cache\CacheItemPoolInterface;
13
use Symfony\Component\PropertyAccess\PropertyAccess;
14
use Symfony\Component\PropertyAccess\PropertyAccessor;
15
16
/**
17
 * Sdk Client
18
 */
19
class SdkClient
20
{
21
    /**
22
     * @var RestClient
23
     */
24
    protected $restClient;
25
26
    /**
27
     * Cache item pool.
28
     *
29
     * @var ?CacheItemPoolInterface
30
     */
31
    protected $cacheItemPool;
32
33
    /**
34
     * Cache prefix.
35
     *
36
     * @var string
37
     */
38
    protected $cachePrefix;
39
40
    /**
41
     * @var Mapping
42
     */
43
    private $mapping;
44
45
    /**
46
     * @var Serializer
47
     */
48
    private $serializer;
49
50
    /**
51
     * @var ModelHydrator
52
     */
53
    private $modelHydrator;
54
55
    /**
56
     * @var array
57
     */
58
    private $repositoryList = [];
59
60
    /**
61
     * proxyManagerConfig
62
     *
63
     * @var ?Configuration
64
     */
65
    private $proxyManagerConfig;
66
67
    /**
68
     * unitOfWork
69
     *
70
     * @var UnitOfWork
71
     */
72
    private $unitOfWork;
73
74
    /**
75
     * @var ?PropertyAccessor
76
     */
77
    private $propertyAccessor;
78
79
    public function __construct(
80
        RestClient $restClient,
81
        Mapping $mapping,
82
        ?UnitOfWork $unitOfWork = null,
83
        ?Serializer $serializer = null
84
    ) {
85 1
        $this->restClient = $restClient;
86 1
        $this->mapping = $mapping;
87 1
        if (null === $unitOfWork) {
88
            $unitOfWork = new UnitOfWork($this->mapping);
89
        }
90 1
        $this->unitOfWork = $unitOfWork;
91 1
        if (null === $serializer) {
92
            $serializer = new Serializer($this->mapping, $this->unitOfWork);
93
        }
94 1
        $this->serializer = $serializer;
95 1
        $this->serializer->setSdk($this);
96
97 1
        $this->modelHydrator = new ModelHydrator($this);
98 1
    }
99
100
    public function setCacheItemPool(
101
        CacheItemPoolInterface $cacheItemPool,
102
        string $cachePrefix = ''
103
    ): self {
104
        $this->cacheItemPool = $cacheItemPool;
105
        $this->cachePrefix = $cachePrefix;
106
107
        return $this;
108
    }
109
110
    public function getCacheItemPool(): ?CacheItemPoolInterface
111
    {
112
        return $this->cacheItemPool;
113
    }
114
115
    public function getCachePrefix(): string
116
    {
117
        return $this->cachePrefix;
118
    }
119
120
    public function getRepository(string $modelName): EntityRepository
121
    {
122
        // get repository by key
123 1
        $metadata = $this->mapping->getClassMetadataByKey($modelName);
124 1
        if (!$metadata) {
125
            // get by classname
126 1
            $metadata = $this->mapping->getClassMetadata($modelName);
127
        }
128
129 1
        $modelName = $metadata->getModelName();
130
131 1
        if (!isset($this->repositoryList[$modelName])) {
132 1
            $repositoryName = $metadata->getRepositoryName();
133
134 1
            $this->repositoryList[$modelName] = new $repositoryName(
135 1
                $this,
136 1
                $this->restClient,
137 1
                $this->unitOfWork,
138
                $modelName
139
            );
140
        }
141
142 1
        return $this->repositoryList[$modelName];
143
    }
144
145
    public function getRestClient(): RestClient
146
    {
147 1
        return $this->restClient;
148
    }
149
150
    public function getMapping(): Mapping
151
    {
152 1
        return $this->mapping;
153
    }
154
155
    public function getSerializer(): Serializer
156
    {
157 1
        return $this->serializer;
158
    }
159
160
    public function getModelHydrator(): ModelHydrator
161
    {
162
        return $this->modelHydrator;
163
    }
164
165
    public function createProxy(string $id): GhostObjectInterface
166
    {
167
        $key = $this->mapping->getKeyFromId($id);
168
        $classMetadata = $this->mapping->getClassMetadataByKey($key);
169
170
        if (null === $classMetadata) {
171
            throw new \RuntimeException(
172
                "Unable to get classMetadata for key {$key}. This should not happen."
173
            );
174
        }
175
176
        $modelName = $classMetadata->getModelName();
177
178
        $sdk = $this;
179
180
        if ($this->proxyManagerConfig) {
181
            $factory = new LazyLoadingGhostFactory($this->proxyManagerConfig);
182
        } else {
183
            $factory = new LazyLoadingGhostFactory();
184
        }
185
186
        $proxyModelName = preg_replace('/^\\\\*/', '', $modelName);
187
188
        $initializer = function (
189
            GhostObjectInterface $proxy,
190
            string $method,
191
            array $parameters,
192
            &$initializer,
193
            array $properties
194
        ) use ($sdk, $classMetadata, $id, $proxyModelName) {
195
            $isAllowedMethod =
196
                'jsonSerialize' === $method ||
197
                '__set' === $method ||
198
                ('__isset' === $method && 'id' === $parameters['name']);
199
200
            if (!$isAllowedMethod) {
201
                $initializer = null; // disable initialization
202
                // load data and modify the object here
203
                if ($id) {
204
                    $repository = $sdk->getRepository(
205
                        $classMetadata->getModelName()
206
                    );
207
                    $model = $repository->find($id);
208
209
                    if (null !== $model) {
210
                        $attributeList = $classMetadata->getAttributeList();
211
212
                        foreach ($attributeList as $attribute) {
213
                            $value = $this->getPropertyAccessor()->getValue(
214
                                $model,
215
                                $attribute->getAttributeName()
216
                            );
217
                            $properties[
218
                                "\0" .
219
                                    $proxyModelName .
220
                                    "\0" .
221
                                    $attribute->getAttributeName()
222
                            ] = $value;
223
                        }
224
                    }
225
                }
226
227
                return true; // confirm that initialization occurred correctly
228
            }
229
        };
230
231
        // initialize the proxy instance
232
        $instance = $factory->createProxy($modelName, $initializer, [
233
            'skippedProperties' => ["\0" . $proxyModelName . "\0id"],
234
        ]);
235
236
        // set the id of the object
237
        $idReflexion = new \ReflectionProperty(
238
            $modelName,
239
            $classMetadata->getIdentifierAttribute()->getAttributeName()
240
        );
241
        $idReflexion->setAccessible(true);
242
        $idReflexion->setValue($instance, $id);
243
244
        return $instance;
245
    }
246
247
    public function setFileCachePath(string $fileCachePath): self
248
    {
249
        $this->proxyManagerConfig = new Configuration();
250
        $this->proxyManagerConfig->setProxiesTargetDir($fileCachePath);
251
252
        return $this;
253
    }
254
255
    private function getPropertyAccessor(): PropertyAccessor
256
    {
257
        if (!isset($this->propertyAccessor)) {
258
            $this->propertyAccessor = PropertyAccess::createPropertyAccessor();
259
        }
260
261
        return $this->propertyAccessor;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->propertyAccessor could return the type null which is incompatible with the type-hinted return Symfony\Component\PropertyAccess\PropertyAccessor. Consider adding an additional type-check to rule them out.
Loading history...
262
    }
263
}
264