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

Normalizer::normalize()   C

Complexity

Conditions 12
Paths 10

Size

Total Lines 66
Code Lines 34

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 26
CRAP Score 12.0071

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 66
ccs 26
cts 27
cp 0.963
rs 5.9123
cc 12
eloc 34
nc 10
nop 4
crap 12.0071

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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