SdkClient::createProxy()   B
last analyzed

Complexity

Conditions 10
Paths 3

Size

Total Lines 79
Code Lines 49

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 110

Importance

Changes 13
Bugs 4 Features 2
Metric Value
cc 10
eloc 49
c 13
b 4
f 2
nc 3
nop 1
dl 0
loc 79
ccs 0
cts 40
cp 0
crap 110
rs 7.246

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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("Unable to get classMetadata for key {$key}. This should not happen.");
172
        }
173
174
        /** @var class-string $modelName */
175
        $modelName = $classMetadata->getModelName();
176
177
        $sdk = $this;
178
179
        if ($this->proxyManagerConfig) {
180
            $factory = new LazyLoadingGhostFactory($this->proxyManagerConfig);
181
        } else {
182
            $factory = new LazyLoadingGhostFactory();
183
        }
184
185
        $proxyModelName = preg_replace('/^\\\\*/', '', $modelName);
186
187
        $initializer = function (
188
            GhostObjectInterface $proxy,
189
            string $method,
190
            array $parameters,
191
            &$initializer,
192
            array $properties
193
        ) use ($sdk, $classMetadata, $id, $proxyModelName) {
194
            $isAllowedMethod =
195
                'jsonSerialize' === $method ||
196
                '__set' === $method ||
197
                ('__isset' === $method && 'id' === $parameters['name']);
198
199
            if (!$isAllowedMethod) {
200
                $initializer = null; // disable initialization
201
                // load data and modify the object here
202
                if ($id) {
203
                    $repository = $sdk->getRepository(
204
                        $classMetadata->getModelName()
205
                    );
206
                    $model = $repository->find($id);
207
208
                    if (null !== $model) {
209
                        $attributeList = $classMetadata->getAttributeList();
210
211
                        foreach ($attributeList as $attribute) {
212
                            $value = $this->getPropertyAccessor()->getValue(
213
                                $model,
214
                                $attribute->getAttributeName()
215
                            );
216
                            $properties[
217
                                "\0" .
218
                                    $proxyModelName .
219
                                    "\0" .
220
                                    $attribute->getAttributeName()
221
                            ] = $value;
222
                        }
223
                    }
224
                }
225
226
                return true; // confirm that initialization occurred correctly
227
            }
228
        };
229
230
        // initialize the proxy instance
231
        $instance = $factory->createProxy($modelName, $initializer, [
232
            'skippedProperties' => ["\0" . $proxyModelName . "\0id"],
233
        ]);
234
235
        // set the id of the object
236
        $idReflexion = new \ReflectionProperty(
237
            $modelName,
238
            $classMetadata->getIdentifierAttribute()->getAttributeName()
239
        );
240
        $idReflexion->setAccessible(true);
241
        $idReflexion->setValue($instance, $id);
242
243
        return $instance;
244
    }
245
246
    public function setFileCachePath(string $fileCachePath): self
247
    {
248
        $this->proxyManagerConfig = new Configuration();
249
        $this->proxyManagerConfig->setProxiesTargetDir($fileCachePath);
250
251
        return $this;
252
    }
253
254
    private function getPropertyAccessor(): PropertyAccessor
255
    {
256
        if (!isset($this->propertyAccessor)) {
257
            $this->propertyAccessor = PropertyAccess::createPropertyAccessor();
258
        }
259
260
        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...
261
    }
262
}
263