Completed
Pull Request — master (#925)
by Asmir
02:40
created

Serializer::__construct()   B

Complexity

Conditions 5
Paths 1

Size

Total Lines 27
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 27
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
56
    private $deserializationVisitors = array();
57
58
    private $serializationNavigator;
0 ignored issues
show
introduced by
The private property $serializationNavigator is not used, and could be removed.
Loading history...
59
    private $deserializationNavigator;
0 ignored issues
show
introduced by
The private property $deserializationNavigator is not used, and could be removed.
Loading history...
60
61
    /**
62
     * @var SerializationContextFactoryInterface
63
     */
64
    private $serializationContextFactory;
65
66
    /**
67
     * @var DeserializationContextFactoryInterface
68
     */
69
    private $deserializationContextFactory;
70
    /**
71
     * @var AccessorStrategyInterface
72
     */
73
    private $accessorStrategy;
74
75
    private $expressionEvaluator;
76
    /**
77
     * @param \Metadata\MetadataFactoryInterface $factory
78
     * @param Handler\HandlerRegistryInterface $handlerRegistry
79
     * @param Construction\ObjectConstructorInterface $objectConstructor
80
     * @param SerializationVisitorFactory[] $serializationVisitors
81
     * @param DeserializationVisitorFactory[] $deserializationVisitors
82
     * @param AccessorStrategyInterface $accessorStrategy
83
     * @param EventDispatcherInterface|null $dispatcher
84
     * @param AbstractParser|null $typeParser
85
     * @param ExpressionEvaluatorInterface|null $expressionEvaluator
86
     * @param SerializationContextFactoryInterface|null $serializationContextFactory
87
     * @param DeserializationContextFactoryInterface|null $deserializationContextFactory
88
     */
89 314
    public function __construct(
90
        MetadataFactoryInterface $factory,
91
        HandlerRegistryInterface $handlerRegistry,
92
        ObjectConstructorInterface $objectConstructor,
93
        array $serializationVisitors,
94
        array $deserializationVisitors,
95
        AccessorStrategyInterface $accessorStrategy,
96
        EventDispatcherInterface $dispatcher = null,
97
        AbstractParser $typeParser = null,
98
        ExpressionEvaluatorInterface $expressionEvaluator = null,
99
        SerializationContextFactoryInterface $serializationContextFactory = null,
100
        DeserializationContextFactoryInterface $deserializationContextFactory = null
101
    )
102
    {
103 314
        $this->factory = $factory;
104 314
        $this->handlerRegistry = $handlerRegistry;
105 314
        $this->objectConstructor = $objectConstructor;
106 314
        $this->dispatcher = $dispatcher ?: new EventDispatcher();
107 314
        $this->typeParser = $typeParser ?: new TypeParser();
108 314
        $this->serializationVisitors = $serializationVisitors;
109 314
        $this->deserializationVisitors = $deserializationVisitors;
110 314
        $this->accessorStrategy = $accessorStrategy;
111
112 314
        $this->expressionEvaluator = $expressionEvaluator;
113
114 314
        $this->serializationContextFactory = $serializationContextFactory ?: new DefaultSerializationContextFactory();
115 314
        $this->deserializationContextFactory = $deserializationContextFactory ?: new DefaultDeserializationContextFactory();
116 314
    }
117
118
    /**
119
     * Parses a direction string to one of the direction constants.
120
     *
121
     * @param string $dirStr
122
     *
123
     * @return integer
124
     */
125
    public static function parseDirection(string $dirStr) : int
126
    {
127
        switch (strtolower($dirStr)) {
128
            case 'serialization':
129
                return GraphNavigatorInterface::DIRECTION_SERIALIZATION;
130
131
            case 'deserialization':
132
                return GraphNavigatorInterface::DIRECTION_DESERIALIZATION;
133
134
            default:
135
                throw new InvalidArgumentException(sprintf('The direction "%s" does not exist.', $dirStr));
136
        }
137
    }
138
139 272
    private function findInitialType($type, SerializationContext $context)
140
    {
141 272
        if ($type !== null) {
142
            return $this->typeParser->parse($type);
143 272
        } elseif ($context->hasAttribute('initial_type')) {
144 27
            return $this->typeParser->parse($context->getAttribute('initial_type'));
145
        }
146 245
        return null;
147
    }
148
149 272
    private function getSerializationNavigator() : GraphNavigatorInterface
150
    {
151 272
        return new SerializationGraphNavigator($this->factory, $this->handlerRegistry, $this->accessorStrategy, $this->dispatcher, $this->expressionEvaluator);
152
    }
153
154 132
    private function getDeserializationNavigator(): GraphNavigatorInterface
155
    {
156 132
        return new DeserializationGraphNavigator($this->factory, $this->handlerRegistry, $this->objectConstructor, $this->accessorStrategy, $this->dispatcher, $this->expressionEvaluator);
157
    }
158
159 265
    public function serialize($data, string $format, SerializationContext $context = null, string $type = null):string
160
    {
161 265
        if (null === $context) {
162 182
            $context = $this->serializationContextFactory->createSerializationContext();
163
        }
164
165 265
        if (!isset($this->serializationVisitors[$format])) {
166 1
            throw new UnsupportedFormatException(sprintf('The format "%s" is not supported for serialization.', $format));
167
        }
168
169 264
        $type = $this->findInitialType($type, $context);
170
171 264
        $visitor = $this->serializationVisitors[$format]->getVisitor();
172 264
        $navigator = $this->getSerializationNavigator();
173
174 264
        $result = $this->visit($navigator, $visitor, $context, $data, $format, $type);
175 244
        return $visitor->getResult($result);
176
    }
177
178 130
    public function deserialize(string $data, string $type, string $format, DeserializationContext $context = null)
179
    {
180 130
        if (null === $context) {
181 126
            $context = $this->deserializationContextFactory->createDeserializationContext();
182
        }
183
184 130
        if (!isset($this->deserializationVisitors[$format])) {
185
            throw new UnsupportedFormatException(sprintf('The format "%s" is not supported for deserialization.', $format));
186
        }
187
188 130
        $visitor = $this->deserializationVisitors[$format]->getVisitor();
189 130
        $navigator = $this->getDeserializationNavigator();
190
191 130
        $result = $this->visit($navigator, $visitor, $context, $data, $format, $this->typeParser->parse($type));
192
193 124
        return $visitor->getResult($result);
194
    }
195
196
    /**
197
     * {@InheritDoc}
198
     */
199 8
    public function toArray($data, SerializationContext $context = null, string $type = null):array
200
    {
201 8
        if (null === $context) {
202 8
            $context = $this->serializationContextFactory->createSerializationContext();
203
        }
204
205 8
        if (!isset($this->serializationVisitors['json'])) {
206
            throw new UnsupportedFormatException(sprintf('The format "%s" is not supported for fromArray.', 'json'));
207
        }
208
209 8
        $type = $this->findInitialType($type, $context);
210
211 8
        $visitor = $this->serializationVisitors['json']->getVisitor();
212 8
        $navigator = $this->getSerializationNavigator();
213
214 8
        $result = $this->visit($navigator, $visitor, $context, $data, 'json', $type);
215 8
        $result = $this->convertArrayObjects($result);
216
217 8
        if (!\is_array($result)) {
218 4
            throw new RuntimeException(sprintf(
219 4
                'The input data of type "%s" did not convert to an array, but got a result of type "%s".',
220 4
                \is_object($data) ? \get_class($data) : \gettype($data),
221 4
                \is_object($result) ? \get_class($result) : \gettype($result)
222
            ));
223
        }
224
225 4
        return $result;
226
    }
227
228
    /**
229
     * {@InheritDoc}
230
     */
231 2
    public function fromArray(array $data, string $type, DeserializationContext $context = null)
232
    {
233 2
        if (null === $context) {
234 2
            $context = $this->deserializationContextFactory->createDeserializationContext();
235
        }
236
237 2
        if (!isset($this->deserializationVisitors['json'])) {
238
            throw new UnsupportedFormatException(sprintf('The format "%s" is not supported for fromArray.', 'json'));
239
        }
240
241 2
        $visitor = $this->deserializationVisitors['json']->getVisitor();
242 2
        $navigator = $this->getDeserializationNavigator();
243
244 2
        return $this->visit($navigator, $visitor, $context, $data, 'json', $this->typeParser->parse($type), false);
245
    }
246
247 297
    private function visit(GraphNavigatorInterface $navigator, VisitorInterface $visitor, Context $context, $data, $format, array $type = null, $prepare = true)
248
    {
249 297
        $context->initialize(
250 297
            $format,
251 297
            $visitor,
252 297
            $navigator,
253 297
            $this->factory
254
        );
255
256 297
        $visitor->setNavigator($navigator);
257 297
        $navigator->initialize($visitor, $context);
258
259 297
        if ($prepare) {
260 295
            $data = $visitor->prepare($data);
261
        }
262 294
        return $navigator->accept($data, $type);
263
    }
264
265 8
    private function convertArrayObjects($data)
266
    {
267 8
        if ($data instanceof \ArrayObject || $data instanceof \stdClass) {
268 2
            $data = (array)$data;
269
        }
270 8
        if (\is_array($data)) {
271 4
            foreach ($data as $k => $v) {
272 3
                $data[$k] = $this->convertArrayObjects($v);
273
            }
274
        }
275
276 8
        return $data;
277
    }
278
279
    /**
280
     * @return MetadataFactoryInterface
281
     */
282
    public function getMetadataFactory()
283
    {
284
        return $this->factory;
285
    }
286
}
287