Completed
Pull Request — master (#92)
by Julien
03:59 queued 01:15
created

SdkClient::createProxy()   B

Complexity

Conditions 10
Paths 3

Size

Total Lines 80
Code Lines 50

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 110

Importance

Changes 13
Bugs 4 Features 2
Metric Value
cc 10
eloc 50
c 13
b 4
f 2
nc 3
nop 1
dl 0
loc 80
ccs 0
cts 42
cp 0
crap 110
rs 7.2242

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
        $this->propertyAccessor = PropertyAccess::createPropertyAccessor();
99 1
    }
100
101
    public function setCacheItemPool(
102
        CacheItemPoolInterface $cacheItemPool,
103
        string $cachePrefix = ''
104
    ): self {
105
        $this->cacheItemPool = $cacheItemPool;
106
        $this->cachePrefix = $cachePrefix;
107
108
        return $this;
109
    }
110
111
    public function getCacheItemPool(): ?CacheItemPoolInterface
112
    {
113
        return $this->cacheItemPool;
114
    }
115
116
    public function getCachePrefix(): string
117
    {
118
        return $this->cachePrefix;
119
    }
120
121
    public function getRepository(string $modelName): EntityRepository
122
    {
123
        // get repository by key
124 1
        $metadata = $this->mapping->getClassMetadataByKey($modelName);
125 1
        if (!$metadata) {
126
            // get by classname
127 1
            $metadata = $this->mapping->getClassMetadata($modelName);
128
        }
129
130 1
        $modelName = $metadata->getModelName();
131
132 1
        if (!isset($this->repositoryList[$modelName])) {
133 1
            $repositoryName = $metadata->getRepositoryName();
134
135 1
            $this->repositoryList[$modelName] = new $repositoryName(
136 1
                $this,
137 1
                $this->restClient,
138 1
                $this->unitOfWork,
139 1
                $modelName
140
            );
141
        }
142
143 1
        return $this->repositoryList[$modelName];
144
    }
145
146
    public function getRestClient(): RestClient
147
    {
148 1
        return $this->restClient;
149
    }
150
151
    public function getMapping(): Mapping
152
    {
153 1
        return $this->mapping;
154
    }
155
156
    public function getSerializer(): Serializer
157
    {
158 1
        return $this->serializer;
159
    }
160
161
    public function getModelHydrator(): ModelHydrator
162
    {
163
        return $this->modelHydrator;
164
    }
165
166
    public function createProxy(string $id): GhostObjectInterface
167
    {
168
        $key = $this->mapping->getKeyFromId($id);
169
        $classMetadata = $this->mapping->getClassMetadataByKey($key);
170
171
        if (null === $classMetadata) {
172
            throw new \RuntimeException(
173
                "Unable to get classMetadata for key {$key}. This should not happen."
174
            );
175
        }
176
177
        $modelName = $classMetadata->getModelName();
178
179
        $sdk = $this;
180
181
        if ($this->proxyManagerConfig) {
182
            $factory = new LazyLoadingGhostFactory($this->proxyManagerConfig);
183
        } else {
184
            $factory = new LazyLoadingGhostFactory();
185
        }
186
187
        $proxyModelName = preg_replace('/^\\\\*/', '', $modelName);
188
189
        $initializer = function (
190
            GhostObjectInterface $proxy,
191
            string $method,
192
            array $parameters,
193
            &$initializer,
194
            array $properties
195
        ) use ($sdk, $classMetadata, $id, $proxyModelName) {
196
            $isAllowedMethod =
197
                'jsonSerialize' === $method ||
198
                '__set' === $method ||
199
                ('__isset' === $method && 'id' === $parameters['name']);
200
201
            if (!$isAllowedMethod) {
202
                $initializer = null; // disable initialization
203
                // load data and modify the object here
204
                if ($id) {
205
                    $repository = $sdk->getRepository(
206
                        $classMetadata->getModelName()
207
                    );
208
                    $model = $repository->find($id);
209
210
                    if (null !== $model) {
211
                        $attributeList = $classMetadata->getAttributeList();
212
213
                        foreach ($attributeList as $attribute) {
214
                            $value = $this->propertyAccessor->getValue(
215
                                $model,
216
                                $attribute->getAttributeName()
217
                            );
218
                            $properties[
219
                                "\0" .
220
                                    $proxyModelName .
221
                                    "\0" .
222
                                    $attribute->getAttributeName()
223
                            ] = $value;
224
                        }
225
                    }
226
                }
227
228
                return true; // confirm that initialization occurred correctly
229
            }
230
        };
231
232
        // initialize the proxy instance
233
        $instance = $factory->createProxy($modelName, $initializer, [
234
            'skippedProperties' => ["\0" . $proxyModelName . "\0id"],
235
        ]);
236
237
        // set the id of the object
238
        $idReflexion = new \ReflectionProperty(
239
            $modelName,
240
            $classMetadata->getIdentifierAttribute()->getAttributeName()
241
        );
242
        $idReflexion->setAccessible(true);
243
        $idReflexion->setValue($instance, $id);
244
245
        return $instance;
246
    }
247
248
    public function setFileCachePath(string $fileCachePath): self
249
    {
250
        $this->proxyManagerConfig = new Configuration();
251
        $this->proxyManagerConfig->setProxiesTargetDir($fileCachePath);
252
253
        return $this;
254
    }
255
}
256