Completed
Pull Request — master (#32)
by Lhalaa
03:46
created

PartialFormSubmission::getFields()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 7
ccs 4
cts 4
cp 1
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 0
crap 1
1
<?php
2
3
namespace Firesphere\PartialUserforms\Models;
4
5
use Exception;
6
use SilverStripe\Control\Controller;
7
use SilverStripe\Control\Director;
8
use SilverStripe\Forms\FieldList;
9
use SilverStripe\Forms\GridField\GridField;
10
use SilverStripe\Forms\GridField\GridFieldButtonRow;
11
use SilverStripe\Forms\GridField\GridFieldConfig;
12
use SilverStripe\Forms\GridField\GridFieldDataColumns;
13
use SilverStripe\Forms\GridField\GridFieldExportButton;
14
use SilverStripe\Forms\GridField\GridFieldPrintButton;
15
use SilverStripe\Forms\ReadonlyField;
16
use SilverStripe\ORM\ArrayList;
17
use SilverStripe\ORM\DataList;
18
use SilverStripe\ORM\DataObject;
19
use SilverStripe\Security\Member;
20
use SilverStripe\Security\RandomGenerator;
21
use SilverStripe\UserForms\Model\Submission\SubmittedForm;
22
23
/**
24
 * Class \Firesphere\PartialUserforms\Models\PartialFormSubmission
25
 *
26
 * @property boolean $IsSend
27
 * @property string $TokenSalt
28
 * @property string $Token
29
 * @property int $UserDefinedFormID
30
 * @method DataObject UserDefinedForm()
31
 * @method DataList|PartialFieldSubmission[] PartialFields()
32
 * @method DataList|PartialFileFieldSubmission[] PartialUploads()
33
 */
34
class PartialFormSubmission extends SubmittedForm
35
{
36
    private static $table_name = 'PartialFormSubmission';
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
38
    private static $db = [
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...
39
        'IsSend'    => 'Boolean(false)',
40
        'TokenSalt' => 'Varchar(16)',
41
        'Token'     => 'Varchar(16)',
42
    ];
43
44
    private static $has_one = [
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...
45
        'UserDefinedForm' => DataObject::class
46
    ];
47
48
    private static $has_many = [
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...
49
        'PartialFields'  => PartialFieldSubmission::class,
50
        'PartialUploads' => PartialFileFieldSubmission::class
51
    ];
52
53
    /**
54
     * Don't add PartialUploads to cascade delete, the parent is changed to SubmittedForm on submission
55
     * @var array
56
     */
57
    private static $cascade_deletes = [
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...
58
        'PartialFields'
59
    ];
60
61
    /**
62
     * @var array
63
     */
64
    private static $summary_fields = [
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...
65
        'ID'          => 'ID',
66
        'PartialLink' => 'Link',
67
        'Created'     => 'Created',
68
        'LastEdited'  => 'Last Edited',
69
    ];
70
71 1
    public function getCMSFields()
72
    {
73
        /** @var FieldList $fields */
74 1
        $fields = parent::getCMSFields();
75 1
        $fields->removeByName([
76 1
            'Values',
77
            'IsSend',
78
            'PartialFields',
79
            'TokenSalt',
80
            'Token',
81
            'UserDefinedFormID',
82
            'Submitter',
83
            'PartialUploads'
84
        ]);
85
86 1
        $partialFields = $this->PartialFields();
87 1
        $fileFields = $this->PartialUploads();
88 1
        $list = ArrayList::create();
89 1
        $list->merge($partialFields);
90 1
        $list->merge($fileFields);
91
92 1
        $partialFields = GridField::create(
93 1
            'PartialFields',
94 1
            _t(static::class . '.PARTIALFIELDS', 'Partial fields'),
95 1
            $list->sort('Created', 'ASC')
96
        );
97
98
        $exportColumns = [
99 1
            'Title'       => 'Title',
100
            'ExportValue' => 'Value'
101
        ];
102
103 1
        $config = new GridFieldConfig();
104 1
        $config->addComponent(new GridFieldDataColumns());
105 1
        $config->addComponent(new GridFieldButtonRow('after'));
106 1
        $config->addComponent(new GridFieldExportButton('buttons-after-left', $exportColumns));
107 1
        $config->addComponent(new GridFieldPrintButton('buttons-after-left'));
108 1
        $partialFields->setConfig($config);
109
110 1
        $fields->addFieldsToTab(
111 1
            'Root.Main',
112
            [
113 1
                ReadonlyField::create('ReadonlyPartialLink', 'Partial Link', $this->getPartialLink()),
114 1
                $partialFields
115
            ]
116
        );
117
118 1
        return $fields;
119
    }
120
121 43
    public function getParent()
122
    {
123 43
        return $this->UserDefinedForm();
124
    }
125
126
    /**
127
     * @param Member $member
128
     * @param array $context
129
     * @return bool
130
     */
131 1
    public function canCreate($member = null, $context = [])
132
    {
133 1
        return false;
134
    }
135
136
    /**
137
     * @param Member
138
     *
139
     * @return boolean|string
140
     */
141 43
    public function canView($member = null)
142
    {
143 43
        if ($this->UserDefinedForm()) {
144 40
            return $this->UserDefinedForm()->canView($member);
0 ignored issues
show
Bug Compatibility introduced by
The expression $this->UserDefinedForm()->canView($member); of type boolean|string adds the type string to the return on line 144 which is incompatible with the return type of the parent method SilverStripe\UserForms\M...\SubmittedForm::canView of type boolean.
Loading history...
145
        }
146
147 19
        return parent::canView($member);
148
    }
149
150
    /**
151
     * @param Member
152
     *
153
     * @return boolean|string
154
     */
155 3
    public function canEdit($member = null)
156
    {
157 3
        if ($this->UserDefinedForm()) {
158 3
            return $this->UserDefinedForm()->canEdit($member);
0 ignored issues
show
Bug Compatibility introduced by
The expression $this->UserDefinedForm()->canEdit($member); of type boolean|string adds the type string to the return on line 158 which is incompatible with the return type of the parent method SilverStripe\UserForms\M...\SubmittedForm::canEdit of type boolean.
Loading history...
159
        }
160
161
        return parent::canEdit($member);
162
    }
163
164
    /**
165
     * @param Member
166
     *
167
     * @return boolean|string
168
     */
169 3
    public function canDelete($member = null)
170
    {
171 3
        if ($this->UserDefinedForm()) {
172 3
            return $this->UserDefinedForm()->canDelete($member);
0 ignored issues
show
Bug Compatibility introduced by
The expression $this->UserDefinedForm()->canDelete($member); of type boolean|string adds the type string to the return on line 172 which is incompatible with the return type of the parent method SilverStripe\UserForms\M...ubmittedForm::canDelete of type boolean.
Loading history...
173
        }
174
175
        return parent::canDelete($member);
176
    }
177
178
    /**
179
     * Get the share link of the form
180
     *
181
     * @return string
182
     * @throws Exception
183
     */
184 4
    public function getPartialLink()
185
    {
186 4
        if (!$this->isInDB()) {
187 1
            return '(none)';
188
        }
189
190 4
        return Controller::join_links(
191 4
            Director::absoluteBaseURL(),
192 4
            'partial',
193 4
            $this->generateKey($this->Token),
0 ignored issues
show
Bug introduced by
It seems like $this->Token can also be of type boolean; however, Firesphere\PartialUserfo...bmission::generateKey() does only seem to accept string, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
194 4
            $this->Token
195
        );
196
    }
197
198
    /**
199
     * Generate tokens
200
     * @throws Exception
201
     */
202 40
    protected function onBeforeWrite()
203
    {
204 40
        if (!$this->TokenSalt) {
205 28
            $this->TokenSalt = $this->generateToken();
206 28
            $this->Token = $this->generateToken();
207
        }
208
209 40
        parent::onBeforeWrite();
210 40
    }
211
212
    /**
213
     * Generate a new token
214
     *
215
     * @return bool|string
216
     * @throws Exception
217
     */
218 28
    protected function generateToken()
219
    {
220 28
        $generator = new RandomGenerator();
221
222 28
        return substr($generator->randomToken('sha256'), 0, 16);
223
    }
224
225
    /**
226
     * Generate a key based on the share token salt
227
     *
228
     * @param string $token
229
     * @return string|bool
230
     */
231 6
    public function generateKey($token)
232
    {
233 6
        return hash_pbkdf2('sha256', $token, $this->TokenSalt, 1000, 16);
234
    }
235
236
    /**
237
     * Get all partial fields for loading data into the form
238
     *
239
     * @return array
240
     */
241 2
    public function getFields()
242
    {
243 2
        $formFields = $this->PartialFields()->map('Name', 'Value')->toArray();
244 2
        $fileFields = $this->PartialUploads()->map('Name', 'FileName')->toArray();
245
246 2
        return array_merge($formFields, $fileFields);
247
    }
248
249
    /**
250
     * Validate key/token combination
251
     *
252
     * @param string $key
253
     * @param string $token
254
     * @return bool|PartialFormSubmission
255
     */
256 4
    public static function validateKeyToken($key, $token)
257
    {
258
        /** @var PartialFormSubmission $partial */
259 4
        $partial = PartialFormSubmission::get()->find('Token', $token);
260 4
        if (!$partial ||
261 2
            !$partial->UserDefinedFormID ||
262 4
            !hash_equals($partial->generateKey($token), $key)
263
        ) {
264 3
            return false;
265
        }
266
267 2
        return $partial;
268
    }
269
}
270