Completed
Pull Request — master (#743)
by Asmir
03:52
created

Serializer::__construct()   B

Complexity

Conditions 5
Paths 16

Size

Total Lines 28
Code Lines 22

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 13
CRAP Score 5

Importance

Changes 0
Metric Value
dl 0
loc 28
ccs 13
cts 13
cp 1
rs 8.439
c 0
b 0
f 0
cc 5
eloc 22
nc 16
nop 10
crap 5

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