Completed
Push — standalone ( 6b9ae2...5a4b99 )
by Philip
03:07
created

RestRequestParser::parseEntity()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 22
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 9
CRAP Score 3.009

Importance

Changes 1
Bugs 0 Features 0
Metric Value
dl 0
loc 22
ccs 9
cts 10
cp 0.9
rs 9.2
c 1
b 0
f 0
cc 3
eloc 13
nc 3
nop 3
crap 3.009
1
<?php
2
3
namespace Dontdrinkandroot\RestBundle\Service;
4
5
use Doctrine\Common\Util\ClassUtils;
6
use Dontdrinkandroot\RestBundle\Metadata\PropertyMetadata;
7
use Metadata\MetadataFactory;
8
use Symfony\Component\HttpFoundation\Request;
9
10
class RestRequestParser
11
{
12
    /**
13
     * @var MetadataFactory
14
     */
15
    private $ddrRestMetadataFactory;
16
17 4
    public function __construct(MetadataFactory $ddrRestMetadataFactory)
18
    {
19 4
        $this->ddrRestMetadataFactory = $ddrRestMetadataFactory;
20 4
    }
21
22
    /**
23
     * @param Request     $request
24
     * @param string      $entityClass
25
     * @param object|null $entity
26
     *
27
     * @return object
28
     */
29 4
    public function parseEntity(
30
        Request $request,
31
        $entityClass,
32
        $entity = null
33
    ) {
34 4
        $method = $request->getMethod();
35 4
        $format = $request->getRequestFormat();
36
37 4
        if ('json' !== $format) {
38
            throw new \RuntimeException(sprintf('Unsupported format "%s"', $format));
39
        }
40
41 4
        $data = $this->getRequestContent($request);
42
43 4
        if (null === $entity) {
44 2
            $entity = new $entityClass;
45
        }
46
47 4
        $this->updateObject($entity, $method, $data);
48
49 4
        return $entity;
50
    }
51
52
    /**
53
     * @param Request $request
54
     *
55
     * @return array
56
     */
57 4
    protected function getRequestContent(Request $request)
58
    {
59 4
        $content = $request->getContent();
60 4
        if ('' !== $content) {
61 4
            return json_decode($content, true);
62
        }
63
64
        return $request->request->all();
65
    }
66
67
    /**
68
     * @param object $object Access by reference.
69
     * @param string $method
70
     * @param array  $data
71
     */
72 4
    protected function updateObject(
73
        &$object,
74
        $method,
75
        $data
76
    ) {
77
78 4
        $classMetadata = $this->ddrRestMetadataFactory->getMetadataForClass(ClassUtils::getClass($object));
79
80 4
        foreach ($data as $key => $value) {
81 2
            if (!array_key_exists($key, $classMetadata->propertyMetadata)) {
82
                continue;
83
                //throw new \RuntimeException(sprintf('No field %s for Class %s', $key, get_class($object)));
84
            }
85
            /** @var PropertyMetadata $propertyMetadata */
86 2
            $propertyMetadata = $classMetadata->propertyMetadata[$key];
87 2
            if ($this->isUpdateable($method, $propertyMetadata)) {
88 2
                $this->updateProperty($object, $method, $key, $value, $propertyMetadata);
89
            }
90
        }
91 4
    }
92
93
    /**
94
     * @param object           $object Access by reference.
95
     * @param string           $method
96
     * @param string           $propertyName
97
     * @param mixed            $value
98
     * @param PropertyMetadata $propertyMetadata
99
     */
100 2
    protected function updateProperty(
101
        &$object,
102
        $method,
0 ignored issues
show
Unused Code introduced by
The parameter $method is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
103
        $propertyName,
0 ignored issues
show
Unused Code introduced by
The parameter $propertyName is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
104
        $value,
105
        PropertyMetadata $propertyMetadata
106
    ) {
107
108
        // TODO: Reenable embedded
109
//        if (array_key_exists($propertyName, $doctrineClassMetadata->embeddedClasses)) {
110
//            $embeddedClass = $doctrineClassMetadata->embeddedClasses[$propertyName]['class'];
111
//            $this->updatePropertyObject($object, $method, $embeddedClass, $propertyName, $value);
112
//
113
//            return;
114
//        }
115
116
        //TODO: Reenable associations
117
//        if (array_key_exists($propertyName, $doctrineClassMetadata->associationMappings)) {
118
//            $associatedClass = $doctrineClassMetadata->associationMappings[$propertyName]['targetEntity'];
119
//            $this->updatePropertyObject($object, $method, $associatedClass, $propertyName, $value);
120
//
121
//            return;
122
//        }
123
124 2
        $convertedValue = $this->convert($propertyMetadata->getType(), $value);
125 2
        $propertyMetadata->setValue($object, $convertedValue);
126 2
    }
127
128
//    /**
129
//     * @param object $object Access by reference.
130
//     * @param string $method
131
//     * @param string $propertyName
132
//     * @param [] $value
133
//     */
134
//    protected function updatePropertyObject(
135
//        &$object,
136
//        $method,
137
//        $class,
138
//        $propertyName,
139
//        $value
140
//    ) {
141
//        $propertyObject = $this->propertyAccessor->getValue($object, $propertyName);
142
//        if (null === $propertyObject) {
143
//            $propertyObject = new $class;
144
//        }
145
//
146
//        $this->updateObject($propertyObject, $method, $value);
147
//        $this->propertyAccessor->setValue($object, $propertyName, $propertyObject);
148
//    }
149
150
    /**
151
     * @param string           $method
152
     * @param PropertyMetadata $propertyMetadata
153
     *
154
     * @return bool
155
     */
156 2
    protected function isUpdateable(
157
        $method,
158
        PropertyMetadata $propertyMetadata
159
    ) {
160 2
        if (Request::METHOD_PUT === $method || Request::METHOD_PATCH === $method) {
161 2
            return $propertyMetadata->isPuttable();
162
        }
163
        if (Request:: METHOD_POST === $method) {
164
            return $propertyMetadata->isPostable();
165
        }
166
167
        return false;
168
    }
169
170 2
    private function convert(?string $type, $value)
171
    {
172 2
        if (null === $value) {
173
            return $value;
174
        }
175
176
        switch ($type) {
177 2
            case 'datetime':
178 2
            case 'date':
179 2
            case 'time':
180 2
                return new \DateTime($value);
181
            default:
182
                return $value;
183
        }
184
    }
185
}
186