Completed
Push — master ( 89419d...f547e3 )
by Asmir
28:00 queued 10:26
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\Exception\RuntimeException;
23
use JMS\Serializer\Handler\HandlerRegistryInterface;
24
use JMS\Serializer\EventDispatcher\EventDispatcherInterface;
25
use JMS\Serializer\Exception\UnsupportedFormatException;
26
use JMS\Serializer\ContextFactory\SerializationContextFactoryInterface;
27
use JMS\Serializer\ContextFactory\DeserializationContextFactoryInterface;
28
use JMS\Serializer\ContextFactory\DefaultSerializationContextFactory;
29
use JMS\Serializer\ContextFactory\DefaultDeserializationContextFactory;
30
use Metadata\MetadataFactoryInterface;
31
use PhpCollection\MapInterface;
32
use JMS\Serializer\Expression\ExpressionEvaluatorInterface;
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 376
    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 376
        $this->factory = $factory;
89 376
        $this->handlerRegistry = $handlerRegistry;
90 376
        $this->objectConstructor = $objectConstructor;
91 376
        $this->dispatcher = $dispatcher;
92 376
        $this->typeParser = $typeParser ?: new TypeParser();
93 376
        $this->serializationVisitors = $serializationVisitors;
94 376
        $this->deserializationVisitors = $deserializationVisitors;
95
96 376
        $this->navigator = new GraphNavigator($this->factory, $this->handlerRegistry, $this->objectConstructor, $this->dispatcher, $expressionEvaluator);
97
98 376
        $this->serializationContextFactory = new DefaultSerializationContextFactory();
99 376
        $this->deserializationContextFactory = new DefaultDeserializationContextFactory();
100 376
    }
101
102 334
    public function serialize($data, $format, SerializationContext $context = null)
103
    {
104 334
        if (null === $context) {
105 260
            $context = $this->serializationContextFactory->createSerializationContext();
106 260
        }
107
108 334
        return $this->serializationVisitors->get($format)
109
            ->map(function(VisitorInterface $visitor) use ($context, $data, $format) {
110 333
                $type = $context->getInitialType() !== null ? $this->typeParser->parse($context->getInitialType()) : null;
111
112 333
                $this->visit($visitor, $context, $visitor->prepare($data), $format, $type);
113
114 322
                return $visitor->getResult();
115 334
            })
116 321
            ->getOrThrow(new UnsupportedFormatException(sprintf('The format "%s" is not supported for serialization.', $format)))
117 320
        ;
118
    }
119
120 113
    public function deserialize($data, $type, $format, DeserializationContext $context = null)
121
    {
122 113
        if (null === $context) {
123 109
            $context = $this->deserializationContextFactory->createDeserializationContext();
124 109
        }
125
126 113
        return $this->deserializationVisitors->get($format)
127
            ->map(function(VisitorInterface $visitor) use ($context, $data, $format, $type) {
128 113
                $preparedData = $visitor->prepare($data);
129 110
                $navigatorResult = $this->visit($visitor, $context, $preparedData, $format, $this->typeParser->parse($type));
130
131 107
                return $this->handleDeserializeResult($visitor->getResult(), $navigatorResult);
132 113
            })
133 107
            ->getOrThrow(new UnsupportedFormatException(sprintf('The format "%s" is not supported for deserialization.', $format)))
134 107
        ;
135
    }
136
137
    /**
138
     * {@InheritDoc}
139
     */
140 8
    public function toArray($data, SerializationContext $context = null)
141
    {
142 8
        if (null === $context) {
143 8
            $context = $this->serializationContextFactory->createSerializationContext();
144 8
        }
145
146 8
        return $this->serializationVisitors->get('json')
147
            ->map(function(JsonSerializationVisitor $visitor) use ($context, $data) {
148 8
                $type = $context->getInitialType() !== null ? $this->typeParser->parse($context->getInitialType()) : null;
149
150 8
                $this->visit($visitor, $context, $data, 'json', $type);
151 8
                $result = $this->convertArrayObjects($visitor->getRoot());
152
153 8
                if ( ! is_array($result)) {
154 4
                    throw new RuntimeException(sprintf(
155 4
                        'The input data of type "%s" did not convert to an array, but got a result of type "%s".',
156 4
                        is_object($data) ? get_class($data) : gettype($data),
157 4
                        is_object($result) ? get_class($result) : gettype($result)
158 4
                    ));
159
                }
160
161 4
                return $result;
162 8
            })
163 4
            ->get()
164 4
        ;
165
    }
166
167
    /**
168
     * {@InheritDoc}
169
     */
170 3
    public function fromArray(array $data, $type, DeserializationContext $context = null)
171
    {
172 2
        if (null === $context) {
173 2
            $context = $this->deserializationContextFactory->createDeserializationContext();
174 2
        }
175
176 2
        return $this->deserializationVisitors->get('json')
177 2
            ->map(function(JsonDeserializationVisitor $visitor) use ($data, $type, $context) {
178 2
                $navigatorResult = $this->visit($visitor, $context, $data, 'json', $this->typeParser->parse($type));
179
180 2
                return $this->handleDeserializeResult($visitor->getResult(), $navigatorResult);
181 2
            })
182 3
            ->get()
183 2
        ;
184
    }
185
186 359
    private function visit(VisitorInterface $visitor, Context $context, $data, $format, array $type = null)
187
    {
188 359
        $context->initialize(
189 359
            $format,
190 359
            $visitor,
191 359
            $this->navigator,
192 359
            $this->factory
193 359
        );
194
195 359
        $visitor->setNavigator($this->navigator);
196
197 359
        return $this->navigator->accept($data, $type, $context);
198
    }
199
200 109
    private function handleDeserializeResult($visitorResult, $navigatorResult)
201
    {
202
        // This is a special case if the root is handled by a callback on the object itself.
203 109
        if (null === $visitorResult && null !== $navigatorResult) {
204 10
            return $navigatorResult;
205
        }
206
207 99
        return $visitorResult;
208
    }
209
210 8
    private function convertArrayObjects($data)
211
    {
212 8
        if ($data instanceof \ArrayObject || $data instanceof \stdClass) {
213 2
            $data = (array) $data;
214 2
        }
215 8
        if (is_array($data)) {
216 4
            foreach ($data as $k => $v) {
217 3
                $data[$k] = $this->convertArrayObjects($v);
218 4
            }
219 4
        }
220
221 8
        return $data;
222
    }
223
224
    /**
225
     * @return MetadataFactoryInterface
226
     */
227
    public function getMetadataFactory()
228
    {
229
        return $this->factory;
230
    }
231
232
    /**
233
     * @param SerializationContextFactoryInterface $serializationContextFactory
234
     *
235
     * @return self
236
     */
237 5
    public function setSerializationContextFactory(SerializationContextFactoryInterface $serializationContextFactory)
238
    {
239 5
        $this->serializationContextFactory = $serializationContextFactory;
240
241 5
        return $this;
242
    }
243
244
    /**
245
     * @param DeserializationContextFactoryInterface $deserializationContextFactory
246
     *
247
     * @return self
248
     */
249 3
    public function setDeserializationContextFactory(DeserializationContextFactoryInterface $deserializationContextFactory)
250
    {
251 3
        $this->deserializationContextFactory = $deserializationContextFactory;
252
253 3
        return $this;
254
    }
255
}
256