Completed
Push — master ( 3d958d...523004 )
by Asmir
12s
created

Serializer::getMetadataFactory()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 1

Importance

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