Completed
Push — master ( 9e9a0d...740d0f )
by Rafael
04:13
created

AbstractMutationResolver::preValidate()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 2
Code Lines 0

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 1
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 0
nc 1
nop 1
dl 0
loc 2
ccs 1
cts 1
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
<?php
2
/*******************************************************************************
3
 *  This file is part of the GraphQL Bundle package.
4
 *
5
 *  (c) YnloUltratech <[email protected]>
6
 *
7
 *  For the full copyright and license information, please view the LICENSE
8
 *  file that was distributed with this source code.
9
 ******************************************************************************/
10
11
namespace Ynlo\GraphQLBundle\Mutation;
12
13
use Symfony\Component\Form\FormBuilderInterface;
14
use Symfony\Component\Form\FormInterface;
15
use Symfony\Component\Validator\ConstraintViolation as SymfonyConstraintViolation;
16
use Ynlo\GraphQLBundle\Form\DataTransformer\DataWithIdToNodeTransformer;
17
use Ynlo\GraphQLBundle\Model\ConstraintViolation;
18
use Ynlo\GraphQLBundle\Resolver\AbstractResolver;
19
use Ynlo\GraphQLBundle\Validator\ConstraintViolationList;
20
21
/**
22
 * Base class for mutations
23
 * Implement the method "process()" and "returnPayload()" is enough in many scenarios
24
 */
25
abstract class AbstractMutationResolver extends AbstractResolver
26
{
27
    /**
28
     * @param array $input
29
     *
30
     * @return mixed
31
     */
32 7
    public function __invoke($input)
33
    {
34 7
        $formBuilder = $this->createDefinitionForm($input);
35
36 7
        $form = null;
37 7
        if ($formBuilder) {
38 7
            $form = $formBuilder->getForm();
39
        }
40
41 7
        $this->preValidate($input);
42 7
        if ($form) {
43 7
            $form->submit($input, false);
44 7
            $data = $form->getData();
45
        } else {
46
            $data = $input;
47
        }
48
49 7
        $this->onSubmit($input, $data);
50
51 7
        $violations = new ConstraintViolationList();
52 7
        if ($form) {
53 7
            $this->extractFormErrors($form, $violations);
54
        }
55 7
        $this->postValidation($data, $violations);
56
57 7
        $dryRun = $input['dryRun'] ?? false;
58
59 7
        if ($dryRun) {
60
            $data = null;
61
        } else {
62 7
            if ((!$form && !$violations->count())
63 7
                || ($form->isSubmitted() && $form->isValid() && !$violations->count())
64
            ) {
65
66 6
                $this->process($data);
67
            }
68
        }
69
70 7
        return $this->returnPayload($data, $violations, $input);
71
    }
72
73
    /**
74
     * Actions to process
75
     * the result processed data is given to payload
76
     *
77
     * @param mixed $data
78
     */
79
    abstract protected function process(&$data);
80
81
    /**
82
     * The payload object or array matching the GraphQL definition
83
     *
84
     * @param mixed                   $data        normalized data, its the input data processed by the form
85
     * @param ConstraintViolationList $violations  violations returned by the form validation process
86
     * @param array                   $inputSource the original submitted data in array
87
     *
88
     * @return mixed
89
     */
90
    abstract protected function returnPayload($data, ConstraintViolationList $violations, $inputSource);
91
92
    /**
93
     * @param mixed $data
94
     *
95
     * @return FormBuilderInterface|null
96
     */
97 7
    protected function createDefinitionForm($data): ?FormBuilderInterface
98
    {
99 7
        if (!$this->context->getDefinition()->hasMeta('form')) {
100
            return null;
101
        }
102
103 7
        $formConfig = $this->context->getDefinition()->getMeta('form') ?? [];
104 7
        $formType = $formConfig['type'] ?? null;
105 7
        if (!$formConfig || !$formType) {
106
            throw new \RuntimeException(sprintf('Can`t find a valid form for %s', $this->context->getDefinition()->getName()));
107
        }
108
109
        $options = [
110 7
            'csrf_protection' => false,
111
            'allow_extra_fields' => true,
112
        ];
113
114 7
        $options = array_merge($options, $formConfig['options'] ?? []);
115 7
        $form = $this->createFormBuilder($formType, $data, $options);
116 7
        $viewTransformer = new DataWithIdToNodeTransformer($this->getManager(), $this->context->getEndpoint());
117 7
        $form->addViewTransformer($viewTransformer);
118
119 7
        return $form;
120
    }
121
122
    /**
123
     * @param FormInterface           $form
124
     * @param ConstraintViolationList $violations
125
     * @param null|string             $parentName
126
     */
127 7
    protected function extractFormErrors(FormInterface $form, ConstraintViolationList $violations, ?string $parentName = null)
128
    {
129 7
        $errors = $form->getErrors();
130 7
        foreach ($errors as $error) {
131 1
            $violation = new ConstraintViolation();
132
133 1
            $path = null;
134 1
            if ($form->getParent()) {
135 1
                $path = $form->getName();
136
            }
137 1
            if ($parentName) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $parentName of type null|string is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
138 1
                $path = $parentName.'.'.$form->getName();
139
            }
140
141 1
            $violation->setPropertyPath($path);
142 1
            $violation->setMessage($error->getMessage());
0 ignored issues
show
Bug introduced by
The method getMessage() does not exist on Symfony\Component\Form\FormErrorIterator. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

142
            $violation->setMessage($error->/** @scrutinizer ignore-call */ getMessage());

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
143 1
            $violation->setMessageTemplate($error->getMessageTemplate());
0 ignored issues
show
Bug introduced by
The method getMessageTemplate() does not exist on Symfony\Component\Form\FormErrorIterator. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

143
            $violation->setMessageTemplate($error->/** @scrutinizer ignore-call */ getMessageTemplate());

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
144 1
            foreach ($error->getMessageParameters() as $key => $value) {
0 ignored issues
show
Bug introduced by
The method getMessageParameters() does not exist on Symfony\Component\Form\FormErrorIterator. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

144
            foreach ($error->/** @scrutinizer ignore-call */ getMessageParameters() as $key => $value) {

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
145 1
                $violation->addParameter($key, $value);
146
            }
147
148 1
            $cause = $error->getCause();
0 ignored issues
show
Bug introduced by
The method getCause() does not exist on Symfony\Component\Form\FormErrorIterator. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

148
            /** @scrutinizer ignore-call */ 
149
            $cause = $error->getCause();

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
149 1
            if ($cause instanceof SymfonyConstraintViolation) {
150 1
                $violation->setCode($cause->getCode());
151 1
                $violation->setInvalidValue($cause->getInvalidValue());
152 1
                $violation->setPlural($cause->getPlural());
153
            }
154
155 1
            $violations->addViolation($violation);
156
        }
157 7
        if ($form->all()) {
158 7
            foreach ($form->all() as $child) {
159 7
                $parentName = $form->getName();
160
161
                //avoid set the name of the form
162 7
                if ($form->getName() === $parentName && !$form->getParent()) {
163 7
                    $parentName = null;
164
                }
165
166 7
                $this->extractFormErrors($child, $violations, $parentName);
167
            }
168
        }
169 7
    }
170
171
    /**
172
     * Can use this method to verify if submitted data is valid
173
     * otherwise can trow a error
174
     *
175
     * @param mixed $inputSource contain the original submitted input data
176
     * @param mixed $normData    contains the processed and normalized data by the form
177
     */
178 3
    protected function onSubmit($inputSource, &$normData)
0 ignored issues
show
Unused Code introduced by
The parameter $normData is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

178
    protected function onSubmit($inputSource, /** @scrutinizer ignore-unused */ &$normData)

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

Loading history...
Unused Code introduced by
The parameter $inputSource is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

178
    protected function onSubmit(/** @scrutinizer ignore-unused */ $inputSource, &$normData)

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

Loading history...
179
    {
180
        //override in child
181 3
    }
182
183
    /**
184
     * Can do something before validate the submitted data
185
     *
186
     * @param mixed $data
187
     */
188 7
    protected function preValidate(&$data)
0 ignored issues
show
Unused Code introduced by
The parameter $data is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

188
    protected function preValidate(/** @scrutinizer ignore-unused */ &$data)

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

Loading history...
189
    {
190
        //override in child
191 7
    }
192
193
    /**
194
     * Can use this to add your custom validations errors
195
     *
196
     * @param mixed                   $data
197
     * @param ConstraintViolationList $violations
198
     */
199 6
    protected function postValidation($data, ConstraintViolationList $violations)
0 ignored issues
show
Unused Code introduced by
The parameter $violations is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

199
    protected function postValidation($data, /** @scrutinizer ignore-unused */ ConstraintViolationList $violations)

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

Loading history...
Unused Code introduced by
The parameter $data is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

199
    protected function postValidation(/** @scrutinizer ignore-unused */ $data, ConstraintViolationList $violations)

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

Loading history...
200
    {
201
        //override in child
202 6
    }
203
}
204