Passed
Pull Request — master (#25)
by Jacques
08:40 queued 03:46
created

ModalController::submitAction()   D

Complexity

Conditions 19
Paths 22

Size

Total Lines 68
Code Lines 39

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 39
c 1
b 0
f 0
dl 0
loc 68
rs 4.5166
cc 19
nc 22
nop 1

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
declare(strict_types=1);
3
4
namespace MonsieurBiz\SyliusRichEditorPlugin\Controller;
5
6
use MonsieurBiz\SyliusRichEditorPlugin\Exception\UiElementNotFoundException;
7
use MonsieurBiz\SyliusRichEditorPlugin\Factory\UiElementFactoryInterface;
8
use MonsieurBiz\SyliusRichEditorPlugin\Form\Type\NameableTypeInterface;
9
use MonsieurBiz\SyliusRichEditorPlugin\UiElement\NameableInterface;
10
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
11
use Symfony\Bundle\FrameworkBundle\Templating\EngineInterface;
12
use Symfony\Component\HttpFoundation\File\UploadedFile;
13
use Symfony\Component\HttpFoundation\JsonResponse;
14
use Symfony\Component\HttpFoundation\Request;
15
use Symfony\Component\HttpFoundation\Response;
16
use Symfony\Contracts\Translation\TranslatorInterface;
17
18
class ModalController extends AbstractController
19
{
20
    /** @var EngineInterface */
21
    private $templatingEngine;
22
23
    /** @var UiElementFactoryInterface */
24
    private $uiElementFactory;
25
26
    /** @var TranslatorInterface */
27
    private $translator;
28
29
    /**
30
     * ModalController constructor.
31
     *
32
     * @param EngineInterface $templatingEngine
33
     * @param UiElementFactoryInterface $uiElementFactory
34
     * @param TranslatorInterface $translator
35
     */
36
    public function __construct(
37
        EngineInterface $templatingEngine,
38
        UiElementFactoryInterface $uiElementFactory,
39
        TranslatorInterface $translator
40
    ) {
41
        $this->templatingEngine = $templatingEngine;
42
        $this->uiElementFactory = $uiElementFactory;
43
        $this->translator = $translator;
44
    }
45
46
    /**
47
     * Generate the form and render the edit markup
48
     *
49
     * @param Request $request
50
     * @return Response
51
     */
52
    public function formAction(Request $request): Response
53
    {
54
        // Check request
55
        $data = $request->query->get('data') ?? null;
56
        if (empty($data)) {
57
            throw $this->createNotFoundException();
58
        }
59
60
        // Correct JSON decode data
61
        $data = json_decode($data, true);
62
        if (!isset($data['type']) || !isset($data['fields'])) {
63
            throw $this->createNotFoundException();
64
        }
65
66
        // Find UI Element from type
67
        try {
68
            $uiElement = $this->uiElementFactory->getUiElementByType($data['type']);
69
        } catch (UiElementNotFoundException $exception) {
70
            throw $this->createNotFoundException($exception->getMessage());
71
        }
72
73
        // Create form depending on UI Element with data
74
        $form = $this->createForm($uiElement->getFormClass());//, $data['fields']);
75
76
        $innerType = $form->getConfig()->getType()->getInnerType();
77
        $formData = $data['fields'];
78
        if ($innerType instanceof NameableTypeInterface && isset($data['name'])) {
79
            $formData[$innerType->getUiElementNameName()] = $data['name'];
80
        }
81
82
        $form->setData($formData);
83
84
        return $this->templatingEngine->renderResponse('@MonsieurBizSyliusRichEditorPlugin/Admin/Modal/edit.html.twig', [
85
            'form' => $form->createView(),
86
            'uiElement' => $uiElement,
87
            'data' => $data['fields'],
88
        ]);
89
    }
90
91
    /**
92
     * Validate submitted data and return an UI Element JSON if everything is OK
93
     *
94
     * @param Request $request
95
     * @return Response
96
     */
97
    public function submitAction(Request $request): Response
98
    {
99
        $uiElementType = $request->request->get('uiElementType');
100
        if (!$request->isXmlHttpRequest() || empty($uiElementType)) {
101
            throw $this->createNotFoundException();
102
        }
103
104
        // Find UI Element from type
105
        try {
106
            $uiElement = $this->uiElementFactory->getUiElementByType($uiElementType);
107
        } catch (UiElementNotFoundException $exception) {
108
            throw $this->createNotFoundException($exception->getMessage());
109
        }
110
111
        // Create and validate form
112
        $data = $request->request->get($uiElement->getType());
113
        $form = $this->createForm($uiElement->getFormClass(), $data);
114
        $form->handleRequest($request);
115
        if (!$form->isSubmitted()) {
116
            throw $this->createNotFoundException();
117
        }
118
119
        // Generate array of errors with field name
120
        if (!$form->isValid()) {
121
            $errors = [];
122
            foreach ($form as $child) {
123
                if (!$child->isValid()) {
124
                    foreach ($child->getErrors() as $error) {
125
                        $childLabel = $this->translator->trans(sprintf('monsieurbiz_richeditor_plugin.ui_element.%s.field.%s', $uiElementType, $child->getName()));
126
                        $errors[$childLabel][] = $error->getMessage();
127
                    }
128
                }
129
            }
130
            return new JsonResponse(['errors' => $errors], Response::HTTP_NOT_ACCEPTABLE);
131
        }
132
133
        // Create object with UiElement data
134
        $element = new \stdClass();
135
        $element->type = $uiElement->getType();
136
        $element->fields = new \stdClass();
137
        $element->name = null;
138
        foreach ($uiElement->getFields() as $field) {
139
            // If file, upload it and retrieve the path
140
            if (($file = $request->files->get($uiElementType)) && isset($file[$field])) {
141
                $element->fields->{$field} = $this->uploadAndReturnPath($file[$field]);
142
            // Value in form exists, we take it
143
            } elseif (($value = $request->request->get($uiElementType)) && isset($value[$field])) {
144
                // Allow array if choices inputs
145
                if (is_array($value[$field])) {
146
                    $element->fields->{$field} = $value[$field];
147
                } else {
148
                    $element->fields->{$field} = (string) $value[$field];
149
                }
150
            // Value is not set, set an empty one
151
            } else {
152
                $element->fields->{$field} = '';
153
            }
154
        }
155
156
        // UI Element's name
157
        $innerType = $form->getConfig()->getType()->getInnerType();
158
        if ($uiElement instanceof NameableInterface && $innerType instanceof NameableTypeInterface) {
159
            if (($value = $request->request->get($uiElementType)) && isset($value[$innerType->getUiElementNameName()])) {
160
                $element->name = $value[$innerType->getUiElementNameName()];
161
            }
162
        }
163
164
        return new JsonResponse(['element' => $element]);
165
    }
166
167
    /**
168
     * Upload file in folder in config and return the path from public folder
169
     *
170
     * @param UploadedFile $file
171
     * @return mixed
172
     */
173
    private function uploadAndReturnPath(UploadedFile $file)
174
    {
175
        $originalFilename = pathinfo($file->getClientOriginalName(), PATHINFO_FILENAME);
176
        // this is needed to safely include the file name as part of the URL
177
        $safeFilename = transliterator_transliterate('Any-Latin; Latin-ASCII; [^A-Za-z0-9_] remove; Lower()', $originalFilename);
178
        $newFilename = $safeFilename . '-' . uniqid() . '.' . $file->guessExtension();
179
180
        // Move the file to the directory where brochures are stored
181
        $file = $file->move(
182
            $this->getParameter('monsieur_biz_sylius_rich_editor.upload_directory'),
183
            $newFilename
184
        );
185
186
        // Generate path from public folder
187
        $relativePath = str_replace($this->getParameter('kernel.project_dir'), '', $file->getPathname());
188
        $relativePath = str_replace('/public', '', $relativePath);
189
190
        return $relativePath;
191
    }
192
}
193