Completed
Pull Request — master (#771)
by
unknown
41:43
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 395
    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 395
        $this->factory = $factory;
89 395
        $this->handlerRegistry = $handlerRegistry;
90 395
        $this->objectConstructor = $objectConstructor;
91 395
        $this->dispatcher = $dispatcher;
92 395
        $this->typeParser = $typeParser ?: new TypeParser();
93 395
        $this->serializationVisitors = $serializationVisitors;
94 395
        $this->deserializationVisitors = $deserializationVisitors;
95
96 395
        $this->navigator = new GraphNavigator($this->factory, $this->handlerRegistry, $this->objectConstructor, $this->dispatcher, $expressionEvaluator);
97
98 395
        $this->serializationContextFactory = new DefaultSerializationContextFactory();
99 395
        $this->deserializationContextFactory = new DefaultDeserializationContextFactory();
100 395
    }
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 117
    public function deserialize($data, $type, $format, DeserializationContext $context = null)
120
    {
121 117
        if (null === $context) {
122 113
            $context = $this->deserializationContextFactory->createDeserializationContext();
123 113
        }
124
125 117
        return $this->deserializationVisitors->get($format)
126
            ->map(function (VisitorInterface $visitor) use ($context, $data, $format, $type) {
127 117
                $preparedData = $visitor->prepare($data);
128 114
                $navigatorResult = $this->visit($visitor, $context, $preparedData, $format, $this->typeParser->parse($type));
129
130 111
                return $this->handleDeserializeResult($visitor->getResult(), $navigatorResult);
131 117
            })
132 111
            ->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 368
    private function visit(VisitorInterface $visitor, Context $context, $data, $format, array $type = null)
183
    {
184 368
        $context->initialize(
185 368
            $format,
186 368
            $visitor,
187 368
            $this->navigator,
188 368
            $this->factory
189 368
        );
190
191 368
        $visitor->setNavigator($this->navigator);
192
193 368
        return $this->navigator->accept($data, $type, $context);
194
    }
195
196 113
    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 113
        if (null === $visitorResult && null !== $navigatorResult) {
200 10
            return $navigatorResult;
201
        }
202
203 103
        return $visitorResult;
204
    }
205
206 8
    private function convertArrayObjects($data)
207
    {
208 8
        if ($data instanceof \ArrayObject || $data instanceof \stdClass) {
209 2
            $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 1
    }
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