Completed
Push — master ( df1f12...4872e5 )
by Lucas
05:42
created

Form::checkForm()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 20
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 10
CRAP Score 2
Metric Value
dl 0
loc 20
ccs 10
cts 10
cp 1
rs 9.4285
cc 2
eloc 14
nc 2
nop 4
crap 2
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\HttpKernel\Exception\BadRequestHttpException;
20
use Symfony\Component\Validator\Validator\ValidatorInterface;
21
22
/**
23
 * @author   List of contributors <https://github.com/libgraviton/graviton/graphs/contributors>
24
 * @license  http://opensource.org/licenses/gpl-license.php GNU Public License
25
 * @link     http://swisscom.ch
26
 */
27
class Form
28
{
29
    /**
30
     * @var FormFactory
31
     */
32
    private $formFactory;
33
34
    /**
35
     * @var DocumentType
36
     */
37
    private $formType;
38
39
    /**
40
     * @var ValidatorInterface
41
     */
42
    private $validator;
43
44
    /**
45
     * @param FormFactory        $formFactory Factory, providing different file document instances.
46
     * @param DocumentType       $formType    Type of form to be set
47
     * @param ValidatorInterface $validator   Validator to verify correctness of the provided data
48
     */
49 189
    public function __construct(
50
        FormFactory $formFactory,
51
        DocumentType $formType,
52
        ValidatorInterface $validator
53
    ) {
54 189
        $this->formFactory = $formFactory;
55 189
        $this->formType = $formType;
56 189
        $this->validator = $validator;
57 189
    }
58
59
    /**
60
     * @param Request       $request request
61
     * @param DocumentModel $model   model
62
     *
63
     * @return \Symfony\Component\Form\Form
64
     */
65 67
    public function getForm(Request $request, DocumentModel $model)
66
    {
67 67
        $this->formType->initialize($model->getEntityClass());
68 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...
69
    }
70
71
    /**
72
     * Validates the provided information against a form.
73
     *
74
     * @param FormInterface           $form           form to check
75
     * @param DocumentModel           $model          Model to determine entity to be used
76
     * @param FormDataMapperInterface $formDataMapper Mapps the entity to form fields
77
     * @param string                  $jsonContent    json data
78
     *
79
     * @throws ValidationException
80
     * @return mixed
81
     */
82 67
    public function checkForm(
83
        FormInterface $form,
84
        DocumentModel $model,
85
        FormDataMapperInterface $formDataMapper,
86
        $jsonContent
87
    ) {
88 67
        $document = $formDataMapper->convertToFormData(
89 1
            $jsonContent,
90 67
            $model->getEntityClass()
91 1
        );
92 67
        $form->submit($document, true);
93
94 67
        if (!$form->isValid()) {
95 22
            throw new ValidationException($form->getErrors(true));
96
        } else {
97 48
            $record = $form->getData();
98
        }
99
100 48
        return $record;
101
    }
102
103
    /**
104
     * validate raw json input
105
     *
106
     * @param Request  $request  request
107
     * @param Response $response response
108
     * @param string   $content  Alternative request content.
109
     *
110
     * @return void
111
     */
112 74
    public function checkJsonRequest(Request $request, Response $response, $content = '')
113
    {
114 74
        if (empty($content)) {
115 72
            $content = $request->getContent();
116
        }
117
118 74
        if (is_resource($content)) {
119
            throw new BadRequestHttpException('unexpected resource in validation');
120
        }
121
122
        // is request body empty
123 74
        if ($content === '') {
124 1
            $e = new NoInputException();
125 1
            $e->setResponse($response);
126 1
            throw $e;
127
        }
128
129 73
        $input = json_decode($content, true);
130 73
        if (JSON_ERROR_NONE !== json_last_error()) {
131 1
            $e = new MalformedInputException($this->getLastJsonErrorMessage());
132 1
            $e->setErrorType(json_last_error());
133 1
            $e->setResponse($response);
134 1
            throw $e;
135
        }
136 72
        if (!is_array($input)) {
137 1
            $e = new MalformedInputException('JSON request body must be an object');
138 1
            $e->setResponse($response);
139 1
            throw $e;
140
        }
141
142 71
        if ($request->getMethod() == 'PUT' && array_key_exists('id', $input)) {
143
            // we need to check for id mismatches....
144 31
            if ($request->attributes->get('id') != $input['id']) {
145 1
                throw new BadRequestHttpException('Record ID in your payload must be the same');
146
            }
147
        }
148 70
    }
149
150
    /**
151
     * Validate JSON patch for any object
152
     *
153
     * @param array $jsonPatch json patch as array
154
     *
155
     * @throws InvalidJsonPatchException
156
     * @return void
157
     */
158 14
    public function checkJsonPatchRequest(array $jsonPatch)
159
    {
160 14
        foreach ($jsonPatch as $operation) {
161 14
            if (!is_array($operation)) {
162 1
                throw new InvalidJsonPatchException('Patch request should be an array of operations.');
163
            }
164 13
            if (array_key_exists('path', $operation) && trim($operation['path']) == '/id') {
165 13
                throw new InvalidJsonPatchException('Change/remove of ID not allowed');
166
            }
167
        }
168 12
    }
169
    /**
170
     * Used for backwards compatibility to PHP 5.4
171
     *
172
     * @return string
173
     */
174 1
    private function getLastJsonErrorMessage()
175
    {
176 1
        $message = 'Unable to decode JSON string';
177
178 1
        if (function_exists('json_last_error_msg')) {
179 1
            $message = json_last_error_msg();
180
        }
181
182 1
        return $message;
183
    }
184
}
185