Completed
Pull Request — master (#840)
by
unknown
03:40
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 398
    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 398
        $this->factory = $factory;
89 398
        $this->handlerRegistry = $handlerRegistry;
90 398
        $this->objectConstructor = $objectConstructor;
91 398
        $this->dispatcher = $dispatcher;
92 398
        $this->typeParser = $typeParser ?: new TypeParser();
93 398
        $this->serializationVisitors = $serializationVisitors;
94 398
        $this->deserializationVisitors = $deserializationVisitors;
95
96 398
        $this->navigator = new GraphNavigator($this->factory, $this->handlerRegistry, $this->objectConstructor, $this->dispatcher, $expressionEvaluator);
97
98 398
        $this->serializationContextFactory = new DefaultSerializationContextFactory();
99 398
        $this->deserializationContextFactory = new DefaultDeserializationContextFactory();
100 398
    }
101
102 342
    public function serialize($data, $format, SerializationContext $context = null)
103
    {
104 342
        if (null === $context) {
105 268
            $context = $this->serializationContextFactory->createSerializationContext();
106 268
        }
107
108 342
        return $this->serializationVisitors->get($format)
109
            ->map(function (VisitorInterface $visitor) use ($context, $data, $format) {
110 341
                $type = $context->getInitialType() !== null ? $this->typeParser->parse($context->getInitialType()) : null;
111
112 341
                $this->visit($visitor, $context, $visitor->prepare($data), $format, $type);
113
114 330
                return $visitor->getResult();
115 342
            })
116 329
            ->getOrThrow(new UnsupportedFormatException(sprintf('The format "%s" is not supported for serialization.', $format)));
117
    }
118
119 119
    public function deserialize($data, $type, $format, DeserializationContext $context = null)
120
    {
121 119
        if (null === $context) {
122 115
            $context = $this->deserializationContextFactory->createDeserializationContext();
123 115
        }
124
125 119
        return $this->deserializationVisitors->get($format)
126
            ->map(function (VisitorInterface $visitor) use ($context, $data, $format, $type) {
127 119
                $preparedData = $visitor->prepare($data);
128 116
                $navigatorResult = $this->visit($visitor, $context, $preparedData, $format, $this->typeParser->parse($type));
129
130 113
                return $this->handleDeserializeResult($visitor->getResult(), $navigatorResult);
131 119
            })
132 113
            ->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 371
    private function visit(VisitorInterface $visitor, Context $context, $data, $format, array $type = null)
183
    {
184 371
        $context->initialize(
185 371
            $format,
186 371
            $visitor,
187 371
            $this->navigator,
188 371
            $this->factory
189 371
        );
190
191 371
        $visitor->setNavigator($this->navigator);
192
193 371
        return $this->navigator->accept($data, $type, $context);
194
    }
195
196 115
    private function handleDeserializeResult($visitorResult, $navigatorResult)
197 1
    {
198
        // This is a special case if the root is handled by a callback on the object itself.
199 115
        if (null === $visitorResult && null !== $navigatorResult) {
200 10
            return $navigatorResult;
201
        }
202
203 105
        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
    }
219
220
    /**
221
     * @return MetadataFactoryInterface
222
     */
223 1
    public function getMetadataFactory()
224 1
    {
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