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

PartialFormSubmission::getParent()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 0
1
<?php
2
3
namespace Firesphere\PartialUserforms\Models;
4
5
use SilverStripe\Control\Controller;
6
use SilverStripe\Control\Director;
7
use SilverStripe\Forms\FieldList;
8
use SilverStripe\Forms\GridField\GridField;
9
use SilverStripe\Forms\GridField\GridFieldButtonRow;
10
use SilverStripe\Forms\GridField\GridFieldConfig;
11
use SilverStripe\Forms\GridField\GridFieldDataColumns;
12
use SilverStripe\Forms\GridField\GridFieldExportButton;
13
use SilverStripe\Forms\GridField\GridFieldPrintButton;
14
use SilverStripe\Forms\ReadonlyField;
15
use SilverStripe\ORM\DataList;
16
use SilverStripe\ORM\DataObject;
17
use SilverStripe\Security\Member;
18
use SilverStripe\Security\RandomGenerator;
19
use SilverStripe\UserForms\Model\Submission\SubmittedForm;
20
use SilverStripe\UserForms\Model\UserDefinedForm;
21
22
/**
23
 * Class \Firesphere\PartialUserforms\Models\PartialFormSubmission
24
 *
25
 * @property boolean $IsSend
26
 * @property string $TokenSalt
27
 * @property string $Token
28
 * @property string $Password
29
 * @property int $UserDefinedFormID
30
 * @method DataObject UserDefinedForm()
31
 * @method DataList|PartialFieldSubmission[] PartialFields()
32
 */
33
class PartialFormSubmission extends SubmittedForm
34
{
35
    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...
36
37
    /**
38
     * @var array
39
     */
40
    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...
41
        'IsSend'    => 'Boolean(false)',
42
        'TokenSalt' => 'Varchar(16)',
43
        'Token'     => 'Varchar(16)',
44
        'Password' => 'Varchar(64)',
45
    ];
46
47
    /**
48
     * @var array
49
     */
50
    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...
51
        'UserDefinedForm' => DataObject::class
52
    ];
53
54
    /**
55
     * @var array
56
     */
57
    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...
58
        'PartialFields' => PartialFieldSubmission::class
59
    ];
60
61
    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...
62
        'PartialFields'
63
    ];
64
65
    /**
66
     * @var array
67
     */
68
    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...
69
        'ID'            => 'ID',
70
        'PartialLink'   => 'Link',
71
        'Created'       => 'Created',
72
        'LastEdited'    => 'Last Edited',
73
    ];
74
75
    private static $special_characters = [
76
        '!',
77
        '@',
78
        '#',
79
        '$',
80
        '%',
81
        '^',
82
        '&',
83
        '*',
84
        '(',
85
        ')',
86
        '_',
87
        '-',
88
        '=',
89
        '+',
90
        ';',
91
        ':',
92
        ',',
93
        '.',
94
        '?'
95
    ];
96
97
    /**
98
     * @return FieldList
99
     */
100
    public function getCMSFields()
101
    {
102
        /** @var FieldList $fields */
103
        $fields = parent::getCMSFields();
104
        $fields->removeByName(['Values', 'IsSend', 'PartialFields', 'TokenSalt', 'Token', 'UserDefinedFormID', 'Submitter']);
105
106
        $partialFields = GridField::create(
107
            'PartialFields',
108
            _t(static::class . '.PARTIALFIELDS', 'Partial fields'),
109
            $this->PartialFields()->sort('Created', 'ASC')
110
        );
111
112
        $exportColumns =[
113
            'Title'       => 'Title',
114
            'ExportValue' => 'Value'
115
        ];
116
117
        $config = new GridFieldConfig();
118
        $config->addComponent(new GridFieldDataColumns());
119
        $config->addComponent(new GridFieldButtonRow('after'));
120
        $config->addComponent(new GridFieldExportButton('buttons-after-left', $exportColumns));
121
        $config->addComponent(new GridFieldPrintButton('buttons-after-left'));
122
        $partialFields->setConfig($config);
123
124
        $fields->addFieldsToTab(
125
            'Root.Main',
126
            [
127
                ReadonlyField::create('ReadonlyPartialLink', 'Partial Link', $this->getPartialLink()),
128
                $partialFields
129
            ]
130
        );
131
132
        return $fields;
133
    }
134
135
    /**
136
     * @return DataObject|UserDefinedForm
137
     */
138
    public function getParent()
139
    {
140
        return $this->UserDefinedForm();
141
    }
142
143
    /**
144
     * If the submission is password protected, generate a password.
145
     */
146
    public function onBeforeWrite()
147
    {
148
        parent::onBeforeWrite();
149
        if (!$this->Password &&
150
            $this->getParent() &&
151
            $this->getParent()->PasswordProtected
152
        ) {
153
            $chars = range('A', 'Z');
154
            $chars = array_merge($chars, range('a', 'z'));
155
            $chars = array_merge($chars, range(0, 9));
156
            $chars = array_merge($chars, self::$special_characters);
157
            shuffle($chars);
158
            $pwd = implode(array_slice($chars, 0, 10));
159
            $this->Password = hash('SHA256', $pwd);
160
            Controller::curr()->getRequest()->getSession()->set('FormPassword', $pwd);
161
        }
162
    }
163
164
    /**
165
     * @param Member
166
     *
167
     * @return boolean|string
168
     */
169
    public function canCreate($member = null, $context = [])
170
    {
171
        if ($this->UserDefinedForm()) {
172
            return $this->UserDefinedForm()->canCreate($member, $context);
0 ignored issues
show
Bug Compatibility introduced by
The expression $this->UserDefinedForm()...ate($member, $context); 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::canCreate of type boolean.
Loading history...
173
        }
174
175
        return parent::canCreate($member);
176
    }
177
178
    /**
179
     * @param Member
180
     *
181
     * @return boolean|string
182
     */
183
    public function canView($member = null)
184
    {
185
        if ($this->UserDefinedForm()) {
186
            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 186 which is incompatible with the return type of the parent method SilverStripe\UserForms\M...\SubmittedForm::canView of type boolean.
Loading history...
187
        }
188
189
        return parent::canView($member);
190
    }
191
192
    /**
193
     * @param Member
194
     *
195
     * @return boolean|string
196
     */
197
    public function canEdit($member = null)
198
    {
199
        if ($this->UserDefinedForm()) {
200
            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 200 which is incompatible with the return type of the parent method SilverStripe\UserForms\M...\SubmittedForm::canEdit of type boolean.
Loading history...
201
        }
202
203
        return parent::canEdit($member);
204
    }
205
206
    /**
207
     * @param Member
208
     *
209
     * @return boolean|string
210
     */
211
    public function canDelete($member = null)
212
    {
213
        if ($this->UserDefinedForm()) {
214
            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 214 which is incompatible with the return type of the parent method SilverStripe\UserForms\M...ubmittedForm::canDelete of type boolean.
Loading history...
215
        }
216
217
        return parent::canDelete($member);
218
    }
219
220
    /**
221
     * Get the share link of the form
222
     *
223
     * @return string
224
     * @throws \Exception
225
     */
226
    public function getPartialLink()
227
    {
228
        if (!$this->isInDB()) {
229
            return '(none)';
230
        }
231
232
        $token = $this->getPartialToken();
233
234
        return Controller::join_links(
235
            Director::absoluteBaseURL(),
236
            'partial',
237
            $this->generateKey($token),
0 ignored issues
show
Bug introduced by
It seems like $token defined by $this->getPartialToken() on line 232 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...
238
            $token
239
        );
240
    }
241
242
    /**
243
     * Get the unique token for the share link
244
     *
245
     * @return bool|string|null
246
     * @throws \Exception
247
     */
248
    protected function getPartialToken()
249
    {
250
        if (!$this->TokenSalt) {
251
            $this->TokenSalt = $this->generateToken();
252
            $this->Token = $this->generateToken();
253
            $this->write();
254
        }
255
256
        return $this->Token;
257
    }
258
259
    /**
260
     * Generate a new token
261
     *
262
     * @return bool|string
263
     * @throws \Exception
264
     */
265
    protected function generateToken()
266
    {
267
        $generator = new RandomGenerator();
268
269
        return substr($generator->randomToken('sha256'), 0, 16);
270
    }
271
272
    /**
273
     * Generate a key based on the share token salt
274
     *
275
     * @param string $token
276
     * @return mixed
277
     */
278
    public function generateKey($token)
279
    {
280
        return hash_pbkdf2('sha256', $token, $this->TokenSalt, 1000, 16);
281
    }
282
}
283