Completed
Push — master ( a11a2f...a1ae8b )
by Asmir
03:55
created

Serializer::__construct()   B

Complexity

Conditions 2
Paths 2

Size

Total Lines 24
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 12
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 24
ccs 12
cts 12
cp 1
rs 8.9713
c 0
b 0
f 0
cc 2
eloc 19
nc 2
nop 8
crap 2

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\EventDispatcherInterface;
27
use JMS\Serializer\Exception\RuntimeException;
28
use JMS\Serializer\Exception\UnsupportedFormatException;
29
use JMS\Serializer\Expression\ExpressionEvaluatorInterface;
30
use JMS\Serializer\Handler\HandlerRegistryInterface;
31
use Metadata\MetadataFactoryInterface;
32
use PhpCollection\MapInterface;
33
34
/**
35
 * Serializer Implementation.
36
 *
37
 * @author Johannes M. Schmitt <[email protected]>
38
 */
39
class Serializer implements SerializerInterface, ArrayTransformerInterface
40
{
41
    private $factory;
42
    private $handlerRegistry;
43
    private $objectConstructor;
44
    private $dispatcher;
45
    private $typeParser;
46
47
    /** @var \PhpCollection\MapInterface */
48
    private $serializationVisitors;
49
50
    /** @var \PhpCollection\MapInterface */
51
    private $deserializationVisitors;
52
53
    private $navigator;
54
55
    /**
56
     * @var SerializationContextFactoryInterface
57
     */
58
    private $serializationContextFactory;
59
60
    /**
61
     * @var DeserializationContextFactoryInterface
62
     */
63
    private $deserializationContextFactory;
64
65
    /**
66
     * Constructor.
67
     *
68
     * @param \Metadata\MetadataFactoryInterface $factory
69
     * @param Handler\HandlerRegistryInterface $handlerRegistry
70
     * @param Construction\ObjectConstructorInterface $objectConstructor
71
     * @param \PhpCollection\MapInterface $serializationVisitors of VisitorInterface
72
     * @param \PhpCollection\MapInterface $deserializationVisitors of VisitorInterface
73
     * @param EventDispatcher\EventDispatcherInterface $dispatcher
74
     * @param TypeParser $typeParser
75
     * @param ExpressionEvaluatorInterface|null $expressionEvaluator
76
     */
77 392
    public function __construct(
78
        MetadataFactoryInterface $factory,
79
        HandlerRegistryInterface $handlerRegistry,
80
        ObjectConstructorInterface $objectConstructor,
81
        MapInterface $serializationVisitors,
82
        MapInterface $deserializationVisitors,
83
        EventDispatcherInterface $dispatcher = null,
84
        TypeParser $typeParser = null,
85
        ExpressionEvaluatorInterface $expressionEvaluator = null
86
    )
87
    {
88 392
        $this->factory = $factory;
89 392
        $this->handlerRegistry = $handlerRegistry;
90 392
        $this->objectConstructor = $objectConstructor;
91 392
        $this->dispatcher = $dispatcher;
92 392
        $this->typeParser = $typeParser ?: new TypeParser();
93 392
        $this->serializationVisitors = $serializationVisitors;
94 392
        $this->deserializationVisitors = $deserializationVisitors;
95
96 392
        $this->navigator = new GraphNavigator($this->factory, $this->handlerRegistry, $this->objectConstructor, $this->dispatcher, $expressionEvaluator);
97
98 392
        $this->serializationContextFactory = new DefaultSerializationContextFactory();
99 392
        $this->deserializationContextFactory = new DefaultDeserializationContextFactory();
100 392
    }
101
102 340
    public function serialize($data, $format, SerializationContext $context = null)
103
    {
104 340
        if (null === $context) {
105 266
            $context = $this->serializationContextFactory->createSerializationContext();
106 266
        }
107
108 340
        return $this->serializationVisitors->get($format)
109
            ->map(function (VisitorInterface $visitor) use ($context, $data, $format) {
110 339
                $type = $context->getInitialType() !== null ? $this->typeParser->parse($context->getInitialType()) : null;
111
112 339
                $this->visit($visitor, $context, $visitor->prepare($data), $format, $type);
113
114 328
                return $visitor->getResult();
115 340
            })
116 327
            ->getOrThrow(new UnsupportedFormatException(sprintf('The format "%s" is not supported for serialization.', $format)));
117
    }
118
119 115
    public function deserialize($data, $type, $format, DeserializationContext $context = null)
120
    {
121 115
        if (null === $context) {
122 111
            $context = $this->deserializationContextFactory->createDeserializationContext();
123 111
        }
124
125 115
        return $this->deserializationVisitors->get($format)
126
            ->map(function (VisitorInterface $visitor) use ($context, $data, $format, $type) {
127 115
                $preparedData = $visitor->prepare($data);
128 112
                $navigatorResult = $this->visit($visitor, $context, $preparedData, $format, $this->typeParser->parse($type));
129
130 109
                return $this->handleDeserializeResult($visitor->getResult(), $navigatorResult);
131 115
            })
132 109
            ->getOrThrow(new UnsupportedFormatException(sprintf('The format "%s" is not supported for deserialization.', $format)));
133
    }
134
135
    /**
136
     * {@InheritDoc}
137
     */
138 8
    public function toArray($data, SerializationContext $context = null)
139
    {
140 8
        if (null === $context) {
141 8
            $context = $this->serializationContextFactory->createSerializationContext();
142 8
        }
143
144 8
        return $this->serializationVisitors->get('json')
145
            ->map(function (JsonSerializationVisitor $visitor) use ($context, $data) {
146 8
                $type = $context->getInitialType() !== null ? $this->typeParser->parse($context->getInitialType()) : null;
147
148 8
                $this->visit($visitor, $context, $data, 'json', $type);
149 8
                $result = $this->convertArrayObjects($visitor->getRoot());
150
151 8
                if (!is_array($result)) {
152 4
                    throw new RuntimeException(sprintf(
153 4
                        'The input data of type "%s" did not convert to an array, but got a result of type "%s".',
154 4
                        is_object($data) ? get_class($data) : gettype($data),
155 4
                        is_object($result) ? get_class($result) : gettype($result)
156 4
                    ));
157
                }
158
159 4
                return $result;
160 8
            })
161 4
            ->get();
162
    }
163
164
    /**
165
     * {@InheritDoc}
166
     */
167 2
    public function fromArray(array $data, $type, DeserializationContext $context = null)
168
    {
169 2
        if (null === $context) {
170 2
            $context = $this->deserializationContextFactory->createDeserializationContext();
171 2
        }
172
173 2
        return $this->deserializationVisitors->get('json')
174 2
            ->map(function (JsonDeserializationVisitor $visitor) use ($data, $type, $context) {
175 2
                $navigatorResult = $this->visit($visitor, $context, $data, 'json', $this->typeParser->parse($type));
176
177 2
                return $this->handleDeserializeResult($visitor->getResult(), $navigatorResult);
178 2
            })
179 2
            ->get();
180
    }
181
182 366
    private function visit(VisitorInterface $visitor, Context $context, $data, $format, array $type = null)
183
    {
184 366
        $context->initialize(
185 366
            $format,
186 366
            $visitor,
187 366
            $this->navigator,
188 366
            $this->factory
189 366
        );
190
191 366
        $visitor->setNavigator($this->navigator);
192
193 366
        return $this->navigator->accept($data, $type, $context);
194
    }
195
196 111
    private function handleDeserializeResult($visitorResult, $navigatorResult)
197
    {
198
        // This is a special case if the root is handled by a callback on the object itself.
199 111
        if (null === $visitorResult && null !== $navigatorResult) {
200 10
            return $navigatorResult;
201
        }
202
203 101
        return $visitorResult;
204
    }
205
206 8
    private function convertArrayObjects($data)
207
    {
208 8
        if ($data instanceof \ArrayObject || $data instanceof \stdClass) {
209 3
            $data = (array)$data;
210 2
        }
211 8
        if (is_array($data)) {
212 4
            foreach ($data as $k => $v) {
213 3
                $data[$k] = $this->convertArrayObjects($v);
214 4
            }
215 4
        }
216
217 8
        return $data;
218
    }
219
220
    /**
221
     * @return MetadataFactoryInterface
222
     */
223
    public function getMetadataFactory()
224
    {
225
        return $this->factory;
226
    }
227
228
    /**
229
     * @param SerializationContextFactoryInterface $serializationContextFactory
230
     *
231
     * @return self
232
     */
233 5
    public function setSerializationContextFactory(SerializationContextFactoryInterface $serializationContextFactory)
234
    {
235 5
        $this->serializationContextFactory = $serializationContextFactory;
236
237 5
        return $this;
238
    }
239
240
    /**
241
     * @param DeserializationContextFactoryInterface $deserializationContextFactory
242
     *
243
     * @return self
244
     */
245 3
    public function setDeserializationContextFactory(DeserializationContextFactoryInterface $deserializationContextFactory)
246
    {
247 3
        $this->deserializationContextFactory = $deserializationContextFactory;
248
249 3
        return $this;
250
    }
251
}
252