Completed
Pull Request — master (#16)
by Simon
11:00
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 Firesphere\PartialUserforms\Models\PartialFieldSubmission;
6
use Firesphere\PartialUserforms\Models\PartialFormSubmission;
7
use SilverStripe\Assets\File;
8
use SilverStripe\Assets\Upload;
9
use SilverStripe\CMS\Controllers\ContentController;
10
use SilverStripe\Control\HTTPRequest;
11
use SilverStripe\ORM\DataObject;
12
use SilverStripe\ORM\ValidationException;
13
use SilverStripe\UserForms\Model\EditableFormField;
14
15
/**
16
 * Class PartialSubmissionController
17
 * @package Firesphere\PartialUserforms\Controllers
18
 */
19
class PartialSubmissionController extends ContentController
20
{
21
    /**
22
     * Session key name
23
     */
24
    public const SESSION_KEY = 'PartialSubmissionID';
25
26
    /**
27
     * @var array
28
     */
29
    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...
30
        'save' => 'savePartialSubmission',
31
    ];
32
33
    /**
34
     * @var array
35
     */
36
    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...
37
        'savePartialSubmission',
38
    ];
39
40
    /**
41
     * @param HTTPRequest $request
42
     * @return bool|void
43
     * @throws ValidationException
44
     * @throws \SilverStripe\Control\HTTPResponse_Exception
45
     */
46
    public function savePartialSubmission(HTTPRequest $request)
47
    {
48
        if (!$request->isPOST()) {
49
            return $this->httpError(404);
50
        }
51
52
        $postVars = $request->postVars();
53
        $editableField = null;
54
55
        // We don't want SecurityID and/or the process Action stored as a thing
56
        unset($postVars['SecurityID'], $postVars['action_process']);
57
        $submissionID = $request->getSession()->get(self::SESSION_KEY);
58
59
        /** @var PartialFormSubmission $partialSubmission */
60
        $partialSubmission = PartialFormSubmission::get()->byID($submissionID);
61
62
        if (!$submissionID || !$partialSubmission) {
63
            $partialSubmission = PartialFormSubmission::create();
64
            // TODO: Set the Parent ID and Parent Class before write, this issue will create new submissions
65
            // every time the session expires when the user proceeds to the next step.
66
            // Also, saving a new submission without a parent creates an "AccordionItems" as parent class (first DataObject found)
67
            $submissionID = $partialSubmission->write();
68
        }
69
        $request->getSession()->set(self::SESSION_KEY, $submissionID);
70
        foreach ($postVars as $field => $value) {
71
            /** @var EditableFormField $editableField */
72
            $editableField = $this->createOrUpdateSubmission([
73
                'Name'            => $field,
74
                'Value'           => $value,
75
                'SubmittedFormID' => $submissionID
76
            ]);
77
        }
78
79
        if ($editableField instanceof EditableFormField && !$partialSubmission->UserDefinedFormID) {
80
            // Updates parent class to the correct DataObject
81
            $partialSubmission->update([
82
                'UserDefinedFormID'    => $editableField->Parent()->ID,
83
                'ParentID'             => $editableField->Parent()->ID,
84
                'ParentClass'          => $editableField->Parent()->ClassName,
85
                'UserDefinedFormClass' => $editableField->Parent()->ClassName
86
            ]);
87
            $partialSubmission->write();
88
        }
89
90
        return $partialSubmission->exists();
91
    }
92
93
    /**
94
     * @param $formData
95
     * @return DataObject|EditableFormField
96
     * @throws ValidationException
97
     */
98
    protected function createOrUpdateSubmission($formData)
99
    {
100
        $filter = [
101
            'Name'            => $formData['Name'],
102
            'SubmittedFormID' => $formData['SubmittedFormID'],
103
        ];
104
105
        /** @var EditableFormField $editableField */
106
        $editableField = EditableFormField::get()->filter(['Name' => $formData['Name']])->first();
107
        if ($editableField instanceof EditableFormField\EditableFileField) {
108
            $this->savePartialFile($formData, $filter, $editableField);
109
        } elseif ($editableField instanceof EditableFormField) {
110
            $this->savePartialField($formData, $filter, $editableField);
111
        }
112
113
        // Return the ParentID to link the PartialSubmission to it's proper thingy
114
        return $editableField;
115
    }
116
117
    /**
118
     * @param $formData
119
     * @param array $filter
120
     * @param EditableFormField $editableField
121
     * @throws ValidationException
122
     */
123
    protected function savePartialField($formData, array $filter, EditableFormField $editableField)
124
    {
125
        $exists = PartialFieldSubmission::get()->filter($filter)->first();
126
        if (is_array($formData['Value'])) {
127
            $formData['Value'] = implode(', ', $formData['Value']);
128
        }
129
        if ($editableField) {
130
            $formData['Title'] = $editableField->Title;
131
            $formData['ParentClass'] = $editableField->Parent()->ClassName;
132
        }
133
        if (!$exists) {
134
            $exists = PartialFieldSubmission::create($formData);
135
        } else {
136
            $exists->update($formData);
137
        }
138
        $exists->write();
139
    }
140
141
    /**
142
     * @param $formData
143
     * @param array $filter
144
     * @param EditableFormField\EditableFileField $editableField
145
     * @throws ValidationException
146
     * @throws Exception
147
     */
148
    protected function savePartialFile($formData, array $filter, EditableFormField\EditableFileField $editableField)
149
    {
150
        $partialFileSubmission = PartialFileFieldSubmission::get()->filter($filter)->first();
151
        $partialData = [];
152
        if (!$partialFileSubmission && $editableField) {
153
            $partialData['Title'] = $editableField->Title;
154
            $partialData['ParentClass'] = $editableField->Parent()->ClassName;
155
        }
156
        // Don't overwrite existing uploads
157
        if (!$partialFileSubmission ||
158
            (!$partialFileSubmission->UploadedFileID && is_array($formData['Value']))
159
        ) {
160
            $file = $this->uploadFile($partialData, $editableField);
161
            $formData['UploadedFileID'] = $file->ID ?? 0;
162
            $partialFileSubmission = PartialFileFieldSubmission::create($partialData);
163
        }
164
        $partialFileSubmission->write();
165
    }
166
167
    /**
168
     * @param array $formData
169
     * @param EditableFormField\EditableFileField $field
170
     * @return bool|File
171
     * @throws \Exception
172
     */
173
    protected function uploadFile($formData, $field)
174
    {
175
        if (!empty($formData['Value']['name'])) {
176
            $foldername = $field->getFormField()->getFolderName();
177
178
            // create the file from post data
179
            $upload = Upload::create();
180
            $file = File::create();
181
            $file->ShowInSearch = 0;
182
            if ($upload->loadIntoFile($formData['Value'], $file, $foldername)) {
183
                return $file;
184
            }
185
        }
186
187
        return false;
188
    }
189
190
}
191