Completed
Pull Request — master (#81)
by John
03:37
created

ObjectSerializer::serialize()   D

Complexity

Conditions 9
Paths 1

Size

Total Lines 45
Code Lines 30

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 45
rs 4.909
cc 9
eloc 30
nc 1
nop 2
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\Document\Specification;
12
use KleijnWeb\SwaggerBundle\Request\ParameterCoercer;
13
use KleijnWeb\SwaggerBundle\Serialize\Serializer;
14
use KleijnWeb\SwaggerBundle\Serialize\TypeResolver\ClassNameResolver;
15
use KleijnWeb\SwaggerBundle\Serialize\TypeResolver\SerializerTypeDefinitionMap;
16
17
/**
18
 * (De-) Serializes objects using JSON Schema
19
 *
20
 * @author John Kleijn <[email protected]>
21
 */
22
class ObjectSerializer implements Serializer
23
{
24
    /**
25
     * @param mixed                       $data
26
     * @param SerializerTypeDefinitionMap $definitionMap
27
     *
28
     * @return string
29
     */
30
    public function serialize($data, SerializerTypeDefinitionMap $definitionMap): string
31
    {
32
        $export = function ($item, \stdClass $schema) use (&$export) {
33
            if ($item instanceof \DateTimeInterface) {
34
                if ($schema->format == 'date') {
35
                    return $item->format('Y-m-d');
36
                }
37
                if ($schema->format == 'date-time') {
38
                    return $item->format(\DateTime::ISO8601);
39
                }
40
                throw new \UnexpectedValueException;
41
            }
42
            switch ($schema->type) {
43
                case 'array':
44
                    return array_map(function ($value) use (&$export, $schema) {
45
                        return $export($value, $schema->items);
46
                    }, $item);
47
                case 'object':
48
                    $class  = get_class($item);
49
                    $data   = (array)$item;
50
                    $offset = strlen($class) + 2;
51
52
                    $array = array_filter(array_combine(array_map(function ($k) use ($offset) {
53
                        return substr($k, $offset);
54
                    }, array_keys($data)), array_values($data)));
55
56
                    foreach ($array as $name => $value) {
57
                        $array[$name] = isset($schema->properties->$name)
58
                            ? $export($value, $schema->properties->$name)
59
                            : $value;
60
                    }
61
62
                    return $array;
63
                default:
64
                    if (!is_scalar($item)) {
65
                        throw new \UnexpectedValueException;
66
                    }
67
68
                    return $item;
69
            }
70
71
        };
72
73
        return json_encode($export($data, $definitionMap->getDefinitionByFqcn(get_class($data))));
74
    }
75
76
    /**
77
     * @param mixed                       $data
78
     * @param string                      $fqdn
79
     * @param SerializerTypeDefinitionMap $definitionMap
80
     *
81
     * @return mixed
82
     */
83
    public function deserialize($data, string $fqdn, SerializerTypeDefinitionMap $definitionMap)
84
    {
85
        $import = function ($item, \stdClass $schema) use (&$import) {
86
            switch ($schema->type) {
87
                case 'array':
88
                    return array_map(function ($value) use (&$import, $schema) {
89
                        return $import($value, $schema->items);
90
                    }, $item);
91
                case 'object':
92
                    $fqcn      = $schema->{'x-class'};
93
                    $object    = unserialize(sprintf('O:%d:"%s":0:{}', strlen($fqcn), $fqcn));
94
                    $reflector = new \ReflectionObject($object);
95
96
                    foreach ($item as $name => $value) {
97
                        if (!$reflector->hasProperty($name)) {
98
                            continue;
99
                        }
100
                        $value = isset($schema->properties->$name)
101
                            ? $import($value, $schema->properties->$name)
102
                            : $value;
103
104
                        $attribute = $reflector->getProperty($name);
105
                        $attribute->setAccessible(true);
106
                        $attribute->setValue($object, $value);
107
                    }
108
109
                    return $object;
110
                default:
111
                    return ParameterCoercer::coerceParameter($schema, $item);
112
            }
113
        };
114
115
        return $import(
116
            json_decode($data, true),
117
            $definitionMap->getDefinitionByFqcn($fqdn)
118
        );
119
    }
120
}
121