AbstractSerializer   A
last analyzed

Complexity

Total Complexity 21

Size/Duplication

Total Lines 194
Duplicated Lines 0 %

Coupling/Cohesion

Components 2
Dependencies 10

Importance

Changes 0
Metric Value
wmc 21
lcom 2
cbo 10
dl 0
loc 194
rs 10
c 0
b 0
f 0

13 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 7 1
A setSerializer() 0 8 3
A getSerializationMetadataCollection() 0 4 1
A getSerializationMetadata() 0 6 1
A hasSerializationMetadata() 0 6 1
A getEntityMetadata() 0 7 1
A getPropertyPath() 0 11 1
A buildPath() 0 11 1
A getEntityFields() 0 12 3
A getEntityEmbeddables() 0 13 3
A getEntityAssociations() 0 10 2
A getRealClass() 0 6 1
A getEntityManager() 0 8 2
1
<?php
2
/*
3
 * WellCommerce Open-Source E-Commerce Platform
4
 * 
5
 * This file is part of the WellCommerce package.
6
 *
7
 * (c) Adam Piotrowski <[email protected]>
8
 * 
9
 * For the full copyright and license information,
10
 * please view the LICENSE file that was distributed with this source code.
11
 */
12
13
namespace WellCommerce\Component\Serializer;
14
15
use Doctrine\Common\Persistence\ManagerRegistry;
16
use Doctrine\Common\Persistence\Mapping\ClassMetadata;
17
use Doctrine\Common\Persistence\ObjectManager;
18
use Doctrine\Common\Util\ClassUtils;
19
use Doctrine\Common\Util\Inflector;
20
use Symfony\Component\PropertyAccess\PropertyAccess;
21
use Symfony\Component\PropertyAccess\PropertyPath;
22
use Symfony\Component\Serializer\Exception\LogicException;
23
use Symfony\Component\Serializer\Normalizer\DenormalizerInterface;
24
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
25
use Symfony\Component\Serializer\Serializer;
26
use Symfony\Component\Serializer\SerializerAwareInterface;
27
use Symfony\Component\Serializer\SerializerInterface;
28
use WellCommerce\Component\Serializer\Metadata\Collection\SerializationMetadataCollection;
29
use WellCommerce\Component\Serializer\Metadata\Loader\SerializationMetadataLoaderInterface;
30
use WellCommerce\Component\Serializer\Metadata\SerializationClassMetadataInterface;
31
32
/**
33
 * Class AbstractSerializer
34
 *
35
 * @author  Adam Piotrowski <[email protected]>
36
 */
37
abstract class AbstractSerializer implements SerializerAwareInterface
38
{
39
    /**
40
     * @var ManagerRegistry
41
     */
42
    protected $managerRegistry;
43
    
44
    /**
45
     * @var \Symfony\Component\PropertyAccess\PropertyAccessor
46
     */
47
    protected $propertyAccessor;
48
    
49
    /**
50
     * @var Serializer
51
     */
52
    protected $serializer;
53
    
54
    /**
55
     * @var SerializationMetadataLoaderInterface
56
     */
57
    protected $serializationMetadataLoader;
58
    
59
    /**
60
     * @var \WellCommerce\Component\Serializer\Metadata\Collection\SerializationMetadataCollection
61
     */
62
    protected $serializationMetadataCollection;
63
    
64
    /**
65
     * @var array
66
     */
67
    protected $context = [];
68
    
69
    /**
70
     * @var string
71
     */
72
    protected $format;
73
    
74
    public function __construct(ManagerRegistry $managerRegistry, SerializationMetadataLoaderInterface $serializationMetadataLoader)
75
    {
76
        $this->managerRegistry                 = $managerRegistry;
77
        $this->serializationMetadataLoader     = $serializationMetadataLoader;
78
        $this->propertyAccessor                = PropertyAccess::createPropertyAccessor();
79
        $this->serializationMetadataCollection = $this->getSerializationMetadataCollection();
80
    }
81
    
82
    public function setSerializer(SerializerInterface $serializer)
83
    {
84
        if (!$serializer instanceof NormalizerInterface || !$serializer instanceof DenormalizerInterface) {
85
            throw new LogicException('Injected serializer must implement both NormalizerInterface and DenormalizerInterface');
86
        }
87
        
88
        $this->serializer = $serializer;
89
    }
90
    
91
    protected function getSerializationMetadataCollection(): SerializationMetadataCollection
92
    {
93
        return $this->serializationMetadataLoader->loadMetadata();
94
    }
95
    
96
    protected function getSerializationMetadata($entity): SerializationClassMetadataInterface
97
    {
98
        $className = $this->getRealClass($entity);
99
        
100
        return $this->serializationMetadataCollection->get($className);
101
    }
102
    
103
    protected function hasSerializationMetadata($entity): bool
104
    {
105
        $className = $this->getRealClass($entity);
106
        
107
        return $this->serializationMetadataCollection->has($className);
108
    }
109
    
110
    protected function getEntityMetadata($entity): ClassMetadata
111
    {
112
        $class   = $this->getRealClass($entity);
113
        $manager = $this->getEntityManager($class);
114
        
115
        return $manager->getClassMetadata($class);
116
    }
117
    
118
    /**
119
     * Builds property path in array-notation style from given attribute's name
120
     *
121
     * @param $attributeName
122
     *
123
     * @return PropertyPath
124
     */
125
    protected function getPropertyPath(string $attributeName): PropertyPath
126
    {
127
        $elements = explode('.', $attributeName);
128
        
129
        $wrapped = array_map(function ($element) {
130
            
131
            return "[{$element}]";
132
        }, $elements);
133
        
134
        return new PropertyPath(implode('', $wrapped));
135
    }
136
    
137
    /**
138
     * Builds a property path from string
139
     *
140
     * @param $propertyName
141
     *
142
     * @return PropertyPath
143
     */
144
    protected function buildPath(string $propertyName): PropertyPath
145
    {
146
        $elements = explode('.', $propertyName);
147
        $wrapped  = array_map(function ($element) {
148
            $name = Inflector::classify($element);
149
            
150
            return Inflector::camelize($name);
151
        }, $elements);
152
        
153
        return new PropertyPath(implode('.', $wrapped));
154
    }
155
    
156
    /**
157
     * Returns the entity fields
158
     *
159
     * @param ClassMetadata $metadata
160
     *
161
     * @return array
162
     */
163
    protected function getEntityFields(ClassMetadata $metadata): array
164
    {
165
        $entityFields = $metadata->getFieldNames();
166
        $fields       = [];
167
        foreach ($entityFields as $field) {
168
            if (false === strpos($field, '.')) {
169
                $fields[$field] = $field;
170
            }
171
        }
172
        
173
        return $fields;
174
    }
175
    
176
    /**
177
     * Returns the entity embeddable fields
178
     *
179
     * @param ClassMetadata $metadata
180
     *
181
     * @return array
182
     */
183
    protected function getEntityEmbeddables(ClassMetadata $metadata): array
184
    {
185
        $entityFields = $metadata->getFieldNames();
186
        $embeddables  = [];
187
        foreach ($entityFields as $embeddableField) {
188
            if (false !== strpos($embeddableField, '.')) {
189
                list($embeddablePropertyName,) = explode('.', $embeddableField);
190
                $embeddables[$embeddablePropertyName] = $embeddablePropertyName;
191
            }
192
        }
193
        
194
        return $embeddables;
195
    }
196
    
197
    /**
198
     * Returns the entity fields
199
     *
200
     * @param ClassMetadata $metadata
201
     *
202
     * @return array
203
     */
204
    protected function getEntityAssociations(ClassMetadata $metadata): array
205
    {
206
        $entityAssociations = $metadata->getAssociationNames();
207
        $associations       = [];
208
        foreach ($entityAssociations as $association) {
209
            $associations[$association] = $association;
210
        }
211
        
212
        return $associations;
213
    }
214
    
215
    protected function getRealClass($object): string
216
    {
217
        $className = get_class($object);
218
        
219
        return ClassUtils::getRealClass($className);
220
    }
221
    
222
    protected function getEntityManager(string $class = null): ObjectManager
223
    {
224
        if (null === $class) {
225
            return $this->managerRegistry->getManager();
226
        }
227
        
228
        return $this->managerRegistry->getManagerForClass($class);
229
    }
230
}
231