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

PartialUserFormController   A

Complexity

Total Complexity 17

Size/Duplication

Total Lines 151
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 11

Importance

Changes 0
Metric Value
wmc 17
lcom 1
cbo 11
dl 0
loc 151
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace Firesphere\PartialUserforms\Controllers;
4
5
use Firesphere\PartialUserforms\Models\PartialFieldSubmission;
6
use Firesphere\PartialUserforms\Models\PartialFileFieldSubmission;
7
use Firesphere\PartialUserforms\Models\PartialFormSubmission;
8
use SilverStripe\Assets\File;
9
use SilverStripe\Assets\Upload;
10
use SilverStripe\CMS\Controllers\ContentController;
11
use SilverStripe\Control\Controller;
12
use SilverStripe\Control\HTTPRequest;
13
use SilverStripe\ORM\DataObject;
14
use SilverStripe\ORM\ValidationException;
15
<<<<<<< HEAD
0 ignored issues
show
Bug introduced by
This code did not parse for me. Apparently, there is an error somewhere around this line:

Syntax error, unexpected T_SL
Loading history...
16
use SilverStripe\UserForms\Control\UserDefinedFormController;
17
=======
18
use SilverStripe\ORM\ValidationResult;
19
>>>>>>> Safe files to partial submissions
20
use SilverStripe\UserForms\Model\EditableFormField;
21
use SilverStripe\View\Requirements;
22
23
/**
24
 * Class PartialUserFormController
25
 * @package Firesphere\PartialUserforms\Controllers
26
 */
27
class PartialUserFormController extends ContentController
28
{
29
    /**
30
     * Session key name
31
     */
32
    const SESSION_KEY = 'PartialSubmissionID';
33
34
    /**
35
     * @var array
36
     */
37
    private static $url_handlers = [
38
        'save' => 'savePartialSubmission',
39
        '$Key/$Token' => 'partial',
40
    ];
41
42
    /**
43
     * @var array
44
     */
45
    private static $allowed_actions = [
46
        'savePartialSubmission',
47
        'partial',
48
    ];
49
50
    /**
51
     * @param HTTPRequest $request
52
     * @return int|mixed|void
53
     * @throws ValidationException
54
     * @throws \SilverStripe\Control\HTTPResponse_Exception
55
     */
56
    public function savePartialSubmission(HTTPRequest $request)
57
    {
58
        if (!$request->isPOST()) {
59
            return $this->httpError(404);
60
        }
61
62
        $postVars = $request->postVars();
63
        $editableField = null;
64
65
        // We don't want SecurityID and/or the process Action stored as a thing
66
        unset($postVars['SecurityID'], $postVars['action_process']);
67
        $submissionID = $request->getSession()->get(self::SESSION_KEY);
68
69
        /** @var PartialFormSubmission $partialSubmission */
70
        $partialSubmission = PartialFormSubmission::get()->byID($submissionID);
71
72
        if (!$submissionID || !$partialSubmission) {
73
            $partialSubmission = PartialFormSubmission::create();
74
            $submissionID = $partialSubmission->write();
75
        }
76
        $request->getSession()->set(self::SESSION_KEY, $submissionID);
77
        foreach ($postVars as $field => $value) {
78
            /** @var EditableFormField $editableField */
79
            $editableField = $this->createOrUpdateSubmission([
80
                'Name'            => $field,
81
                'Value'           => $value,
82
                'SubmittedFormID' => $submissionID
83
            ]);
84
        }
85
86
        if ($editableField instanceof EditableFormField && !$partialSubmission->UserDefinedFormID) {
87
            $partialSubmission->update([
88
                'UserDefinedFormID'    => $editableField->Parent()->ID,
89
                'ParentID'             => $editableField->Parent()->ID,
90
                'ParentClass'          => $editableField->Parent()->ClassName,
91
                'UserDefinedFormClass' => $editableField->Parent()->ClassName
92
            ]);
93
            $partialSubmission->write();
94
        }
95
96
        return $submissionID;
97
    }
98
99
    /**
100
     * @param $formData
101
     * @return DataObject|EditableFormField
102
     * @throws ValidationException
103
     */
104
    protected function createOrUpdateSubmission($formData)
105
    {
106
        $filter = [
107
            'Name'            => $formData['Name'],
108
            'SubmittedFormID' => $formData['SubmittedFormID'],
109
        ];
110
111
        // Set the title
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\EditableFileField $editableField
128
     * @throws ValidationException
129
     * @throws \Exception
130
     */
131
    protected function savePartialFile($formData, array $filter, EditableFormField\EditableFileField $editableField)
132
    {
133
        $partialFileSubmission = PartialFileFieldSubmission::get()->filter($filter)->first();
134
        $partialData = [];
135
        // Don't overwrite existing uploads
136
        if (!$partialFileSubmission) {
137
            if ($editableField) {
138
                $partialData['Title'] = $editableField->Title;
139
                $partialData['ParentClass'] = $editableField->Parent()->ClassName;
140
            }
141
        }
142
        if (is_array($formData['Value']) && !$partialFileSubmission->UploadedFileID) {
143
            $file = $this->uploadFile($partialData, $editableField);
144
            $formData['UploadedFileID'] = $file->ID ?? 0;
145
            $partialFileSubmission = PartialFileFieldSubmission::create($partialData);
146
        }
147
        $partialFileSubmission->write();
148
    }
149
150
    /**
151
     * @param $formData
152
     * @param array $filter
153
     * @param EditableFormField $editableField
154
     * @throws ValidationException
155
     */
156
    protected function savePartialField($formData, array $filter, EditableFormField $editableField)
157
    {
158
        $exists = PartialFieldSubmission::get()->filter($filter)->first();
159
        if (is_array($formData['Value'])) {
160
            $formData['Value'] = implode(', ', $formData['Value']);
161
        }
162
        if ($editableField) {
163
            $formData['Title'] = $editableField->Title;
164
            $formData['ParentClass'] = $editableField->Parent()->ClassName;
165
        }
166
        if (!$exists) {
167
            $exists = PartialFieldSubmission::create($formData);
168
        } else {
169
            $exists->update($formData);
170
        }
171
        $exists->write();
172
    }
173
174
    /**
175
     * @param array $formData
176
     * @param EditableFormField\EditableFileField $field
177
     * @return File|void
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
            try {
190
                $upload->loadIntoFile($formData['Value'], $file, $foldername);
191
            } catch (ValidationException $e) {
192
                $validationResult = $e->getResult();
193
                foreach ($validationResult->getMessages() as $message) {
194
                    $field->Parent()->sessionMessage($message['message'], ValidationResult::TYPE_ERROR);
195
                }
196
                Controller::curr()->redirectBack();
197
                return;
198
            }
199
200
            return $file;
201
        }
202
    }
203
204
    /**
205
     * Partial form
206
     *
207
     * @param HTTPRequest $request
208
     * @return \SilverStripe\ORM\FieldType\DBHTMLText|void
209
     * @throws \SilverStripe\Control\HTTPResponse_Exception
210
     */
211
    public function partial(HTTPRequest $request)
212
    {
213
        $key = $request->param('Key');
214
        $token = $request->param('Token');
215
216
        $partial = PartialFormSubmission::get()->find('Token', $token);
217
        if (!$token || !$partial || !$partial->UserDefinedFormID) {
218
            return $this->httpError(404);
219
        }
220
221
        if ($partial->generateKey($token) === $key) {
222
            // Set the session if the last session has expired
223
            if (!$request->getSession()->get(self::SESSION_KEY)) {
224
                $request->getSession()->set(self::SESSION_KEY, $partial->ID);
225
            }
226
227
            // TODO: Recognize visitor with the password
228
            // TODO: Populate form values
229
230
            $record = DataObject::get_by_id($partial->UserDefinedFormClass, $partial->UserDefinedFormID);
231
            $controller = new UserDefinedFormController($record);
232
            $controller->init();
233
234
            Requirements::javascript('firesphere/partialuserforms:client/dist/main.js');
235
236
            return $this->customise([
237
                'Title' => $record->Title,
238
                'Breadcrumbs' => $record->Breadcrumbs(),
239
                'Content' => $this->obj('Content'),
240
                'Form' => $controller->Form(),
241
                'Link' => $partial->getPartialLink()
242
            ])->renderWith(['PartialUserForm', 'Page']);
243
        } else {
244
            return $this->httpError(404);
245
        }
246
    }
247
}
248