Completed
Push — standalone ( 5a4b99...a217df )
by Philip
04:06
created

Normalizer   A

Complexity

Total Complexity 27

Size/Duplication

Total Lines 149
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 6

Test Coverage

Coverage 96.49%

Importance

Changes 0
Metric Value
wmc 27
c 0
b 0
f 0
lcom 1
cbo 6
dl 0
loc 149
ccs 55
cts 57
cp 0.9649
rs 10

5 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 5 1
C normalize() 0 66 12
A isIncluded() 0 14 4
A appendPath() 0 8 3
C normalizeField() 0 31 7
1
<?php
2
3
namespace Dontdrinkandroot\RestBundle\Service;
4
5
use Doctrine\Common\Collections\Collection;
6
use Doctrine\Common\Util\ClassUtils;
7
use Dontdrinkandroot\RestBundle\Metadata\ClassMetadata;
8
use Dontdrinkandroot\RestBundle\Metadata\PropertyMetadata;
9
use Metadata\MetadataFactoryInterface;
10
use Symfony\Component\PropertyAccess\PropertyAccessorInterface;
11
12
class Normalizer
13
{
14
    /**
15
     * @var MetadataFactoryInterface
16
     */
17
    private $metadataFactory;
18
19
    /**
20
     * @var PropertyAccessorInterface
21
     */
22
    private $propertyAccessor;
23
24 24
    function __construct(MetadataFactoryInterface $metadataFactory, PropertyAccessorInterface $propertyAccessor)
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
25
    {
26 24
        $this->metadataFactory = $metadataFactory;
27 24
        $this->propertyAccessor = $propertyAccessor;
28 24
    }
29
30
    /**
31
     * @param mixed    $data
32
     * @param string[] $includes
33
     * @param int      $depth
34
     * @param string   $path
35
     *
36
     * @return array
37
     */
38 24
    public function normalize($data, $includes = [], int $depth = 0, string $path = '')
39
    {
40 24
        if (is_array($data)) {
41 14
            $normalizedData = [];
42 14
            foreach ($data as $datum) {
43 14
                $normalizedData[] = $this->normalize($datum, $includes, $depth + 1, $path);
44
            }
45
46 14
            return $normalizedData;
47
        }
48
49 24
        if (is_object($data)) {
50
51 24
            $normalizedData = [];
52
53
            /** @var ClassMetadata $classMetadata */
54 24
            $classMetadata = $this->metadataFactory->getMetadataForClass(ClassUtils::getClass($data));
55
56
            /** @var PropertyMetadata $propertyMetadatum */
57 24
            foreach ($classMetadata->propertyMetadata as $propertyMetadatum) {
58
59 24
                if ($propertyMetadatum->isExcluded()) {
60 12
                    continue;
61
                }
62
63 24
                if ($propertyMetadatum->isAssociation()) {
64
65
                    /* Inlude if includable AND it is on include path */
66 18
                    if ($propertyMetadatum->isIncludable() && $this->isIncluded(
67
                            $path,
68 18
                            $propertyMetadatum->getIncludablePaths(),
69
                            $includes
70
                        )
71
                    ) {
72 4
                        $value = $this->propertyAccessor->getValue($data, $propertyMetadatum->name);
73 4
                        if ($propertyMetadatum->isCollection()) {
74
                            /** @var Collection $value */
75 2
                            $value = $value->getValues();
76
                        }
77 4
                        $normalizedData[$propertyMetadatum->name] = $this->normalize(
78
                            $value,
79
                            $includes,
80 4
                            $depth + 1,
81 18
                            $this->appendPath($path, $propertyMetadatum->name)
82
                        );
83
                    }
84
                } else {
85
86
                    /* Inlude if includable is missing OR it is on include path */
87 24
                    if (!$propertyMetadatum->isIncludable() || $this->isIncluded(
88
                            $path,
89 24
                            $propertyMetadatum->getIncludablePaths(),
90
                            $includes
91
                        )
92
                    ) {
93 24
                        $value = $this->propertyAccessor->getValue($data, $propertyMetadatum->name);
94 24
                        $normalizedData[$propertyMetadatum->name] = $this->normalizeField($value, $propertyMetadatum);
95
                    }
96
                }
97
            }
98
99 24
            return $normalizedData;
100
        }
101
102
        return null;
103
    }
104
105 18
    private function isIncluded($currentPath, array $paths, ?array $includes): bool
106
    {
107 18
        if (null === $includes) {
108
            return false;
109
        }
110
111 18
        foreach ($paths as $path) {
112 18
            if (in_array($this->appendPath($currentPath, $path), $includes)) {
113 18
                return true;
114
            }
115
        }
116
117 18
        return false;
118
    }
119
120 18
    private function appendPath($path, $name)
121
    {
122 18
        if (null === $path || '' === $path) {
123 18
            return $name;
124
        }
125
126 4
        return $path . '.' . $name;
127
    }
128
129 24
    private function normalizeField($value, PropertyMetadata $propertyMetadata)
130
    {
131 24
        switch ($propertyMetadata->getType()) {
132 24
            case 'datetime':
133 10
                if (null === $value) {
134 4
                    return null;
135
                }
136
137
                /** @var $value \DateTime */
138 8
                return $value->format('Y-m-d H:i:s');
139
140 24
            case 'date':
141 10
                if (null === $value) {
142 4
                    return null;
143
                }
144
145
                /** @var $value \DateTime */
146 8
                return $value->format('Y-m-d');
147
148 24
            case 'time':
149 10
                if (null === $value) {
150 4
                    return null;
151
                }
152
153
                /** @var $value \DateTime */
154 8
                return $value->format('H:i:s');
155
156
            default:
157 24
                return $value;
158
        }
159
    }
160
}
161