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