Completed
Pull Request — master (#80)
by John
03:11
created

SwaggerSerializer   A

Complexity

Total Complexity 10

Size/Duplication

Total Lines 93
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 1

Importance

Changes 0
Metric Value
wmc 10
c 0
b 0
f 0
lcom 1
cbo 1
dl 0
loc 93
rs 10

3 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 5 1
A serialize() 0 20 4
B deserialize() 0 36 5
1
<?php declare(strict_types = 1);
2
/*
3
 * This file is part of the KleijnWeb\SwaggerBundle package.
4
 *
5
 * For the full copyright and license information, please view the LICENSE
6
 * file that was distributed with this source code.
7
 */
8
9
namespace KleijnWeb\SwaggerBundle\Serialize\Serializer;
10
11
use KleijnWeb\SwaggerBundle\Serialize\SerializationTypeResolver;
12
use KleijnWeb\SwaggerBundle\Serialize\Serializer;
13
14
/**
15
 * (De-) Serializes objects using JSON Schema
16
 *
17
 * @author John Kleijn <[email protected]>
18
 */
19
class SwaggerSerializer implements Serializer
20
{
21
    /**
22
     * @var SerializationTypeResolver
23
     */
24
    private $serializationTypeResolver;
25
26
    /**
27
     * @var \stdClass
28
     */
29
    private $definitions;
30
31
    /**
32
     * SwaggerSerializer constructor.
33
     *
34
     * @param SerializationTypeResolver $serializationTypeResolver
35
     * @param \stdClass                 $definitions
36
     */
37
    public function __construct(SerializationTypeResolver $serializationTypeResolver, \stdClass $definitions)
38
    {
39
        $this->serializationTypeResolver = $serializationTypeResolver;
40
        $this->definitions               = $definitions;
41
    }
42
43
    /**
44
     * @param mixed $data
45
     *
46
     * @return string
47
     */
48
    public function serialize($data): string
49
    {
50
        $export = function ($object) use (&$export) {
51
            if (!is_object($object)) {
52
                return $object;
53
            }
54
            $class  = get_class($object);
55
            $data   = (array)$object;
56
            $offset = strlen($class) + 2;
57
            $keys   = array_map(function ($k) use ($offset) {
58
                return substr($k, $offset);
59
            }, array_keys($data));
60
61
            return array_map(function ($item) use ($offset, &$export) {
62
                return is_object($item) ? $export($item) : (is_array($item) ? array_map($export, $item) : $item);
63
            }, array_combine($keys, array_values($data)));
64
        };
65
66
        return json_encode($export($data));
67
    }
68
69
    /**
70
     * @param mixed  $data
71
     * @param string $type
72
     *
73
     * @return mixed
74
     */
75
    public function deserialize($data, string $type)
76
    {
77
        $import = function ($item, \stdClass $schema) use (&$import) {
78
            switch ($schema->type) {
79
                case 'array':
80
                    return array_map(function ($value) use (&$import, $schema) {
81
                        return $import($value, $schema->items);
82
                    }, $item);
83
                case 'object':
84
                    $fqcn      = $this->serializationTypeResolver->resolveUsingSchema($schema);
85
                    $object    = unserialize(sprintf('O:%d:"%s":0:{}', strlen($fqcn), $fqcn));
86
                    $reflector = new \ReflectionObject($object);
87
88
                    foreach ($item as $name => $value) {
89
                        $value = isset($schema->properties->$name)
90
                            ? $import($value, $schema->properties->$name)
91
                            : $value;
92
93
                        $attribute = $reflector->getProperty($name);
94
                        $attribute->setAccessible(true);
95
                        $attribute->setValue($object, $value);
96
                    }
97
98
                    return $object;
99
                default:
100
                    settype($item, $schema->type);
101
102
                    return $item;
103
            }
104
        };
105
106
        return $import(
107
            json_decode($data, true),
108
            $this->definitions->{$this->serializationTypeResolver->reverseLookup($type)}
109
        );
110
    }
111
}
112