Completed
Pull Request — master (#16)
by Simon
01:15
created

PartialSubmissionController::savePartialField()   A

Complexity

Conditions 4
Paths 8

Size

Total Lines 17

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 17
rs 9.7
c 0
b 0
f 0
cc 4
nc 8
nop 3
1
<?php
2
3
namespace Firesphere\PartialUserforms\Controllers;
4
5
use Exception;
6
use Firesphere\PartialUserforms\Models\PartialFieldSubmission;
7
use Firesphere\PartialUserforms\Models\PartialFileFieldSubmission;
8
use Firesphere\PartialUserforms\Models\PartialFormSubmission;
9
use SilverStripe\Assets\File;
10
use SilverStripe\Assets\Upload;
11
use SilverStripe\CMS\Controllers\ContentController;
12
use SilverStripe\Control\HTTPRequest;
13
use SilverStripe\Control\HTTPResponse;
14
use SilverStripe\ORM\DataObject;
15
use SilverStripe\ORM\ValidationException;
16
use SilverStripe\UserForms\Model\EditableFormField;
17
18
/**
19
 * Class PartialSubmissionController
20
 *
21
 * @package Firesphere\PartialUserforms\Controllers
22
 */
23
class PartialSubmissionController extends ContentController
24
{
25
    /**
26
     * Session key name
27
     */
28
    public const SESSION_KEY = 'PartialSubmissionID';
29
30
    /**
31
     * @var array
32
     */
33
    private static $url_handlers = [
0 ignored issues
show
Comprehensibility introduced by
Consider using a different property name as you override a private property of the parent class.
Loading history...
34
        'save' => 'savePartialSubmission',
35
    ];
36
37
    /**
38
     * @var array
39
     */
40
    private static $allowed_actions = [
0 ignored issues
show
Comprehensibility introduced by
Consider using a different property name as you override a private property of the parent class.
Loading history...
41
        'savePartialSubmission',
42
    ];
43
44
    /**
45
     * @param HTTPRequest $request
46
     * @return HTTPResponse
47
     * @throws ValidationException
48
     * @throws \SilverStripe\Control\HTTPResponse_Exception
49
     */
50
    public function savePartialSubmission(HTTPRequest $request)
51
    {
52
        if (!$request->isPOST()) {
53
            return $this->httpError(404);
54
        }
55
56
        $postVars = $request->postVars();
57
        $editableField = null;
58
59
        // We don't want SecurityID and/or the process Action stored as a thing
60
        unset($postVars['SecurityID'], $postVars['action_process']);
61
        $submissionID = $request->getSession()->get(self::SESSION_KEY);
62
63
        /** @var PartialFormSubmission $partialSubmission */
64
        $partialSubmission = PartialFormSubmission::get()->byID($submissionID);
65
66
        if (!$submissionID || !$partialSubmission) {
67
            $partialSubmission = PartialFormSubmission::create();
68
            // TODO: Set the Parent ID and Parent Class before write, this issue will create new submissions
69
            // every time the session expires when the user proceeds to the next step.
70
            // Also, saving a new submission without a parent creates an
71
            // "AccordionItems" as parent class (first DataObject found)
72
            $submissionID = $partialSubmission->write();
73
        }
74
        $request->getSession()->set(self::SESSION_KEY, $submissionID);
75
        foreach ($postVars as $field => $value) {
76
            /** @var EditableFormField $editableField */
77
            $editableField = $this->createOrUpdateSubmission([
78
                'Name'            => $field,
79
                'Value'           => $value,
80
                'SubmittedFormID' => $submissionID
81
            ]);
82
        }
83
84
        if ($editableField instanceof EditableFormField && !$partialSubmission->UserDefinedFormID) {
85
            // Updates parent class to the correct DataObject
86
            $partialSubmission->update([
87
                'UserDefinedFormID'    => $editableField->Parent()->ID,
88
                'ParentID'             => $editableField->Parent()->ID,
89
                'ParentClass'          => $editableField->Parent()->ClassName,
90
                'UserDefinedFormClass' => $editableField->Parent()->ClassName
91
            ]);
92
            $partialSubmission->write();
93
        }
94
95
        $return = $partialSubmission->exists();
96
97
        return new HTTPResponse($return, $return ? 201 : 400);
0 ignored issues
show
Documentation introduced by
$return is of type boolean, but the function expects a string|null.

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...
98
    }
99
100
    /**
101
     * @param $formData
102
     * @return DataObject|EditableFormField
103
     * @throws ValidationException
104
     */
105
    protected function createOrUpdateSubmission($formData)
106
    {
107
        $filter = [
108
            'Name'            => $formData['Name'],
109
            'SubmittedFormID' => $formData['SubmittedFormID'],
110
        ];
111
112
        /** @var EditableFormField $editableField */
113
        $editableField = EditableFormField::get()->filter(['Name' => $formData['Name']])->first();
114
        if ($editableField instanceof EditableFormField\EditableFileField) {
115
            $this->savePartialFile($formData, $filter, $editableField);
116
        } elseif ($editableField instanceof EditableFormField) {
117
            $this->savePartialField($formData, $filter, $editableField);
118
        }
119
120
        // Return the ParentID to link the PartialSubmission to it's proper thingy
121
        return $editableField;
122
    }
123
124
    /**
125
     * @param $formData
126
     * @param array $filter
127
     * @param EditableFormField $editableField
128
     * @throws ValidationException
129
     */
130
    protected function savePartialField($formData, array $filter, EditableFormField $editableField)
131
    {
132
        $exists = PartialFieldSubmission::get()->filter($filter)->first();
133
        if (is_array($formData['Value'])) {
134
            $formData['Value'] = implode(', ', $formData['Value']);
135
        }
136
        if ($editableField) {
137
            $formData['Title'] = $editableField->Title;
138
            $formData['ParentClass'] = $editableField->Parent()->ClassName;
139
        }
140
        if (!$exists) {
141
            $exists = PartialFieldSubmission::create($formData);
142
        } else {
143
            $exists->update($formData);
144
        }
145
        $exists->write();
146
    }
147
148
    /**
149
     * @param $formData
150
     * @param array $filter
151
     * @param EditableFormField\EditableFileField $editableField
152
     * @throws ValidationException
153
     * @throws Exception
154
     */
155
    protected function savePartialFile($formData, array $filter, EditableFormField\EditableFileField $editableField)
156
    {
157
        $partialFileSubmission = PartialFileFieldSubmission::get()->filter($filter)->first();
158
        $partialData = [];
159
        if (!$partialFileSubmission && $editableField) {
160
            $partialData['Title'] = $editableField->Title;
161
            $partialData['ParentClass'] = $editableField->Parent()->ClassName;
162
        }
163
        // Don't overwrite existing uploads
164
        if (!$partialFileSubmission ||
165
            (!$partialFileSubmission->UploadedFileID && is_array($formData['Value']))
166
        ) {
167
            $file = $this->uploadFile($partialData, $editableField);
168
            $formData['UploadedFileID'] = $file->ID ?? 0;
169
            $partialFileSubmission = PartialFileFieldSubmission::create($partialData);
170
        }
171
        $partialFileSubmission->write();
172
    }
173
174
    /**
175
     * @param array $formData
176
     * @param EditableFormField\EditableFileField $field
177
     * @return bool|File
178
     * @throws \Exception
179
     */
180
    protected function uploadFile($formData, $field)
181
    {
182
        if (!empty($formData['Value']['name'])) {
183
            $foldername = $field->getFormField()->getFolderName();
184
185
            // create the file from post data
186
            $upload = Upload::create();
187
            $file = File::create();
188
            $file->ShowInSearch = 0;
189
            if ($upload->loadIntoFile($formData['Value'], $file, $foldername)) {
190
                return $file;
191
            }
192
        }
193
194
        return false;
195
    }
196
}
197