Passed
Push — master ( 622cfa...f34591 )
by Asmir
31:36 queued 28:57
created

Serializer::__construct()   B

Complexity

Conditions 5
Paths 1

Size

Total Lines 26
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 12
CRAP Score 5

Importance

Changes 0
Metric Value
cc 5
eloc 11
nc 1
nop 11
dl 0
loc 26
ccs 12
cts 12
cp 1
crap 5
rs 8.439
c 0
b 0
f 0

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * Copyright 2016 Johannes M. Schmitt <[email protected]>
7
 *
8
 * Licensed under the Apache License, Version 2.0 (the "License");
9
 * you may not use this file except in compliance with the License.
10
 * You may obtain a copy of the License at
11
 *
12
 *     http://www.apache.org/licenses/LICENSE-2.0
13
 *
14
 * Unless required by applicable law or agreed to in writing, software
15
 * distributed under the License is distributed on an "AS IS" BASIS,
16
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17
 * See the License for the specific language governing permissions and
18
 * limitations under the License.
19
 */
20
21
namespace JMS\Serializer;
22
23
use JMS\Parser\AbstractParser;
24
use JMS\Serializer\Accessor\AccessorStrategyInterface;
25
use JMS\Serializer\Construction\ObjectConstructorInterface;
26
use JMS\Serializer\ContextFactory\DefaultDeserializationContextFactory;
27
use JMS\Serializer\ContextFactory\DefaultSerializationContextFactory;
28
use JMS\Serializer\ContextFactory\DeserializationContextFactoryInterface;
29
use JMS\Serializer\ContextFactory\SerializationContextFactoryInterface;
30
use JMS\Serializer\EventDispatcher\EventDispatcher;
31
use JMS\Serializer\EventDispatcher\EventDispatcherInterface;
32
use JMS\Serializer\Exception\InvalidArgumentException;
33
use JMS\Serializer\Exception\RuntimeException;
34
use JMS\Serializer\Exception\UnsupportedFormatException;
35
use JMS\Serializer\Expression\ExpressionEvaluatorInterface;
36
use JMS\Serializer\Handler\HandlerRegistryInterface;
37
use JMS\Serializer\VisitorFactory\DeserializationVisitorFactory;
38
use JMS\Serializer\VisitorFactory\SerializationVisitorFactory;
39
use Metadata\MetadataFactoryInterface;
40
41
/**
42
 * Serializer Implementation.
43
 *
44
 * @author Johannes M. Schmitt <[email protected]>
45
 */
46
final class Serializer implements SerializerInterface, ArrayTransformerInterface
47
{
48
    private $factory;
49
    private $handlerRegistry;
50
    private $objectConstructor;
51
    private $dispatcher;
52
    private $typeParser;
53
54
    private $serializationVisitors = array();
55
    private $deserializationVisitors = array();
56
57
    /**
58
     * @var SerializationContextFactoryInterface
59
     */
60
    private $serializationContextFactory;
61
62
    /**
63
     * @var DeserializationContextFactoryInterface
64
     */
65
    private $deserializationContextFactory;
66
    /**
67
     * @var AccessorStrategyInterface
68
     */
69
    private $accessorStrategy;
70
71
    private $expressionEvaluator;
72
    /**
73
     * @param \Metadata\MetadataFactoryInterface $factory
74
     * @param Handler\HandlerRegistryInterface $handlerRegistry
75
     * @param Construction\ObjectConstructorInterface $objectConstructor
76
     * @param SerializationVisitorFactory[] $serializationVisitors
77
     * @param DeserializationVisitorFactory[] $deserializationVisitors
78
     * @param AccessorStrategyInterface $accessorStrategy
79
     * @param EventDispatcherInterface|null $dispatcher
80
     * @param AbstractParser|null $typeParser
81
     * @param ExpressionEvaluatorInterface|null $expressionEvaluator
82
     * @param SerializationContextFactoryInterface|null $serializationContextFactory
83
     * @param DeserializationContextFactoryInterface|null $deserializationContextFactory
84
     */
85 315
    public function __construct(
86
        MetadataFactoryInterface $factory,
87
        HandlerRegistryInterface $handlerRegistry,
88
        ObjectConstructorInterface $objectConstructor,
89
        array $serializationVisitors,
90
        array $deserializationVisitors,
91
        AccessorStrategyInterface $accessorStrategy,
92
        EventDispatcherInterface $dispatcher = null,
93
        AbstractParser $typeParser = null,
94
        ExpressionEvaluatorInterface $expressionEvaluator = null,
95
        SerializationContextFactoryInterface $serializationContextFactory = null,
96
        DeserializationContextFactoryInterface $deserializationContextFactory = null
97
    )
98
    {
99 315
        $this->factory = $factory;
100 315
        $this->handlerRegistry = $handlerRegistry;
101 315
        $this->objectConstructor = $objectConstructor;
102 315
        $this->dispatcher = $dispatcher ?: new EventDispatcher();
103 315
        $this->typeParser = $typeParser ?: new TypeParser();
104 315
        $this->serializationVisitors = $serializationVisitors;
105 315
        $this->deserializationVisitors = $deserializationVisitors;
106 315
        $this->accessorStrategy = $accessorStrategy;
107 315
        $this->expressionEvaluator = $expressionEvaluator;
108
109 315
        $this->serializationContextFactory = $serializationContextFactory ?: new DefaultSerializationContextFactory();
110 315
        $this->deserializationContextFactory = $deserializationContextFactory ?: new DefaultDeserializationContextFactory();
111 315
    }
112
113
    /**
114
     * Parses a direction string to one of the direction constants.
115
     *
116
     * @param string $dirStr
117
     *
118
     * @return integer
119
     */
120
    public static function parseDirection(string $dirStr) : int
121
    {
122
        switch (strtolower($dirStr)) {
123
            case 'serialization':
124
                return GraphNavigatorInterface::DIRECTION_SERIALIZATION;
125
126
            case 'deserialization':
127
                return GraphNavigatorInterface::DIRECTION_DESERIALIZATION;
128
129
            default:
130
                throw new InvalidArgumentException(sprintf('The direction "%s" does not exist.', $dirStr));
131
        }
132
    }
133
134 273
    private function findInitialType($type, SerializationContext $context)
135
    {
136 273
        if ($type !== null) {
137
            return $this->typeParser->parse($type);
138 273
        } elseif ($context->hasAttribute('initial_type')) {
139 27
            return $this->typeParser->parse($context->getAttribute('initial_type'));
140
        }
141 246
        return null;
142
    }
143
144 273
    private function getSerializationNavigator() : GraphNavigatorInterface
145
    {
146 273
        return new SerializationGraphNavigator($this->factory, $this->handlerRegistry, $this->accessorStrategy, $this->dispatcher, $this->expressionEvaluator);
147
    }
148
149 133
    private function getDeserializationNavigator(): GraphNavigatorInterface
150
    {
151 133
        return new DeserializationGraphNavigator($this->factory, $this->handlerRegistry, $this->objectConstructor, $this->accessorStrategy, $this->dispatcher, $this->expressionEvaluator);
152
    }
153
154 266
    public function serialize($data, string $format, SerializationContext $context = null, string $type = null):string
155
    {
156 266
        if (null === $context) {
157 183
            $context = $this->serializationContextFactory->createSerializationContext();
158
        }
159
160 266
        if (!isset($this->serializationVisitors[$format])) {
161 1
            throw new UnsupportedFormatException(sprintf('The format "%s" is not supported for serialization.', $format));
162
        }
163
164 265
        $type = $this->findInitialType($type, $context);
165
166 265
        $visitor = $this->serializationVisitors[$format]->getVisitor();
167 265
        $navigator = $this->getSerializationNavigator();
168
169 265
        $result = $this->visit($navigator, $visitor, $context, $data, $format, $type);
170 245
        return $visitor->getResult($result);
171
    }
172
173 131
    public function deserialize(string $data, string $type, string $format, DeserializationContext $context = null)
174
    {
175 131
        if (null === $context) {
176 127
            $context = $this->deserializationContextFactory->createDeserializationContext();
177
        }
178
179 131
        if (!isset($this->deserializationVisitors[$format])) {
180
            throw new UnsupportedFormatException(sprintf('The format "%s" is not supported for deserialization.', $format));
181
        }
182
183 131
        $visitor = $this->deserializationVisitors[$format]->getVisitor();
184 131
        $navigator = $this->getDeserializationNavigator();
185
186 131
        $result = $this->visit($navigator, $visitor, $context, $data, $format, $this->typeParser->parse($type));
187
188 125
        return $visitor->getResult($result);
189
    }
190
191
    /**
192
     * {@InheritDoc}
193
     */
194 8
    public function toArray($data, SerializationContext $context = null, string $type = null):array
195
    {
196 8
        if (null === $context) {
197 8
            $context = $this->serializationContextFactory->createSerializationContext();
198
        }
199
200 8
        if (!isset($this->serializationVisitors['json'])) {
201
            throw new UnsupportedFormatException(sprintf('The format "%s" is not supported for fromArray.', 'json'));
202
        }
203
204 8
        $type = $this->findInitialType($type, $context);
205
206 8
        $visitor = $this->serializationVisitors['json']->getVisitor();
207 8
        $navigator = $this->getSerializationNavigator();
208
209 8
        $result = $this->visit($navigator, $visitor, $context, $data, 'json', $type);
210 8
        $result = $this->convertArrayObjects($result);
211
212 8
        if (!\is_array($result)) {
213 4
            throw new RuntimeException(sprintf(
214 4
                'The input data of type "%s" did not convert to an array, but got a result of type "%s".',
215 4
                \is_object($data) ? \get_class($data) : \gettype($data),
216 4
                \is_object($result) ? \get_class($result) : \gettype($result)
217
            ));
218
        }
219
220 4
        return $result;
221
    }
222
223
    /**
224
     * {@InheritDoc}
225
     */
226 2
    public function fromArray(array $data, string $type, DeserializationContext $context = null)
227
    {
228 2
        if (null === $context) {
229 2
            $context = $this->deserializationContextFactory->createDeserializationContext();
230
        }
231
232 2
        if (!isset($this->deserializationVisitors['json'])) {
233
            throw new UnsupportedFormatException(sprintf('The format "%s" is not supported for fromArray.', 'json'));
234
        }
235
236 2
        $visitor = $this->deserializationVisitors['json']->getVisitor();
237 2
        $navigator = $this->getDeserializationNavigator();
238
239 2
        return $this->visit($navigator, $visitor, $context, $data, 'json', $this->typeParser->parse($type), false);
240
    }
241
242 298
    private function visit(GraphNavigatorInterface $navigator, VisitorInterface $visitor, Context $context, $data, $format, array $type = null, $prepare = true)
243
    {
244 298
        $context->initialize(
245 298
            $format,
246 298
            $visitor,
247 298
            $navigator,
248 298
            $this->factory
249
        );
250
251 298
        $visitor->setNavigator($navigator);
252 298
        $navigator->initialize($visitor, $context);
253
254 298
        if ($prepare) {
255 296
            $data = $visitor->prepare($data);
256
        }
257 295
        return $navigator->accept($data, $type);
258
    }
259
260 8
    private function convertArrayObjects($data)
261
    {
262 8
        if ($data instanceof \ArrayObject || $data instanceof \stdClass) {
263 2
            $data = (array)$data;
264
        }
265 8
        if (\is_array($data)) {
266 4
            foreach ($data as $k => $v) {
267 3
                $data[$k] = $this->convertArrayObjects($v);
268
            }
269
        }
270
271 8
        return $data;
272
    }
273
274
    /**
275
     * @return MetadataFactoryInterface
276
     */
277
    public function getMetadataFactory()
278
    {
279
        return $this->factory;
280
    }
281
}
282