Completed
Push — master ( 11b317...37df4d )
by Lucas
09:27
created

Form::checkJsonRequest()   D

Complexity

Conditions 9
Paths 14

Size

Total Lines 39
Code Lines 24

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 90

Importance

Changes 1
Bugs 0 Features 0
Metric Value
dl 0
loc 39
ccs 0
cts 33
cp 0
rs 4.909
c 1
b 0
f 0
cc 9
eloc 24
nc 14
nop 3
crap 90
1
<?php
2
/**
3
 * base form validator
4
 */
5
6
namespace Graviton\RestBundle\Validator;
7
8
use Graviton\DocumentBundle\Service\FormDataMapperInterface;
9
use Graviton\ExceptionBundle\Exception\InvalidJsonPatchException;
10
use Graviton\ExceptionBundle\Exception\MalformedInputException;
11
use Graviton\ExceptionBundle\Exception\NoInputException;
12
use Graviton\ExceptionBundle\Exception\ValidationException;
13
use Graviton\RestBundle\Model\DocumentModel;
14
use Symfony\Component\Form\FormFactory;
15
use Symfony\Component\Form\FormInterface;
16
use Graviton\DocumentBundle\Form\Type\DocumentType;
17
use Symfony\Component\HttpFoundation\Request;
18
use Symfony\Component\HttpFoundation\Response;
19
use Symfony\Component\Validator\Validator\ValidatorInterface;
20
21
/**
22
 * @author   List of contributors <https://github.com/libgraviton/graviton/graphs/contributors>
23
 * @license  http://opensource.org/licenses/gpl-license.php GNU Public License
24
 * @link     http://swisscom.ch
25
 */
26
class Form
27
{
28
    /**
29
     * @var FormFactory
30
     */
31
    private $formFactory;
32
33
    /**
34
     * @var DocumentType
35
     */
36
    private $formType;
37
38
    /**
39
     * @var ValidatorInterface
40
     */
41
    private $validator;
42
43
    /**
44
     * @param FormFactory        $formFactory Factory, providing different file document instances.
45
     * @param DocumentType       $formType    Type of form to be set
46
     * @param ValidatorInterface $validator   Validator to verify correctness of the provided data
47
     */
48
    public function __construct(
49
        FormFactory $formFactory,
50
        DocumentType $formType,
51
        ValidatorInterface $validator
52
    ) {
53
        $this->formFactory = $formFactory;
54
        $this->formType = $formType;
55
        $this->validator = $validator;
56
    }
57
58
    /**
59
     * @param Request       $request request
60
     * @param DocumentModel $model   model
61
     *
62
     * @return \Symfony\Component\Form\Form
63
     */
64
    public function getForm(Request $request, DocumentModel $model)
65
    {
66
        $this->formType->initialize($model->getEntityClass());
67
        return $this->formFactory->create($this->formType, null, ['method' => $request->getMethod()]);
0 ignored issues
show
Documentation introduced by
$this->formType is of type object<Graviton\Document...Form\Type\DocumentType>, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
68
    }
69
70
    /**
71
     * Validates the provided information against a form.
72
     *
73
     * @param FormInterface           $form           form to check
74
     * @param DocumentModel           $model          Model to determine entity to be used
75
     * @param FormDataMapperInterface $formDataMapper Mapps the entity to form fields
76
     * @param string                  $jsonContent    json data
77
     *
78
     * @throws ValidationException
79
     * @return mixed
80
     */
81
    public function checkForm(
82
        FormInterface $form,
83
        DocumentModel $model,
84
        FormDataMapperInterface $formDataMapper,
85
        $jsonContent
86
    ) {
87
        $document = $formDataMapper->convertToFormData(
88
            $jsonContent,
89
            $model->getEntityClass()
90
        );
91
        $form->submit($document, true);
92
93
        if (!$form->isValid()) {
94
            throw new ValidationException($form->getErrors(true));
95
        } else {
96
            $record = $form->getData();
97
        }
98
99
        return $record;
100
    }
101
102
    /**
103
     * validate raw json input
104
     *
105
     * @param Request  $request  request
106
     * @param Response $response response
107
     * @param string   $content  Alternative request content.
108
     *
109
     * @return void
110
     */
111
    public function checkJsonRequest(Request $request, Response $response, $content = '')
112
    {
113
        if (empty($content)) {
114
            $content = $request->getContent();
115
        }
116
117
        if (is_resource($content)) {
118
            throw new BadRequestHttpException('unexpected resource in validation');
119
        }
120
121
        // is request body empty
122
        if ($content === '') {
123
            $e = new NoInputException();
124
            $e->setResponse($response);
125
            throw $e;
126
        }
127
128
        $input = json_decode($content, true);
129
        if (JSON_ERROR_NONE !== json_last_error()) {
130
            $e = new MalformedInputException($this->getLastJsonErrorMessage());
131
            $e->setErrorType(json_last_error());
132
            $e->setResponse($response);
133
            throw $e;
134
        }
135
        if (!is_array($input)) {
136
            $e = new MalformedInputException('JSON request body must be an object');
137
            $e->setResponse($response);
138
            throw $e;
139
        }
140
141
        if ($request->getMethod() == 'PUT' && array_key_exists('id', $input)) {
142
            // we need to check for id mismatches....
143
            if ($request->attributes->get('id') != $input['id']) {
144
                $e = new MalformedInputException('Record ID in your payload must be the same');
145
                $e->setResponse($response);
146
                throw $e;
147
            }
148
        }
149
    }
150
151
    /**
152
     * Validate JSON patch for any object
153
     *
154
     * @param array $jsonPatch json patch as array
155
     *
156
     * @throws InvalidJsonPatchException
157
     * @return void
158
     */
159
    public function checkJsonPatchRequest(array $jsonPatch)
160
    {
161
        foreach ($jsonPatch as $operation) {
162
            if (!is_array($operation)) {
163
                throw new InvalidJsonPatchException('Patch request should be an array of operations.');
164
            }
165
            if (array_key_exists('path', $operation) && trim($operation['path']) == '/id') {
166
                throw new InvalidJsonPatchException('Change/remove of ID not allowed');
167
            }
168
        }
169
    }
170
    /**
171
     * Used for backwards compatibility to PHP 5.4
172
     *
173
     * @return string
174
     */
175
    private function getLastJsonErrorMessage()
176
    {
177
        $message = 'Unable to decode JSON string';
178
179
        if (function_exists('json_last_error_msg')) {
180
            $message = json_last_error_msg();
181
        }
182
183
        return $message;
184
    }
185
}
186