Completed
Pull Request — master (#29)
by Simon
14:44 queued 04:46
created

PartialFormSubmission::generateKey()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 0
cts 0
cp 0
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
crap 2
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
    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...
54
        'PartialFields'
55
    ];
56
57
    /**
58
     * @var array
59
     */
60
    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...
61
        'ID'          => 'ID',
62
        'PartialLink' => 'Link',
63
        'Created'     => 'Created',
64
        'LastEdited'  => 'Last Edited',
65
    ];
66
67 1
    public function getCMSFields()
68
    {
69
        /** @var FieldList $fields */
70 1
        $fields = parent::getCMSFields();
71 1
        $fields->removeByName([
72 1
            'Values',
73
            'IsSend',
74
            'PartialFields',
75
            'TokenSalt',
76
            'Token',
77
            'UserDefinedFormID',
78
            'Submitter',
79
            'PartialUploads'
80
        ]);
81
82 1
        $partialFields = $this->PartialFields();
83 1
        $fileFields = $this->PartialUploads();
84 1
        $list = ArrayList::create();
85 1
        $list->merge($partialFields);
86 1
        $list->merge($fileFields);
87
88 1
        $partialFields = GridField::create(
89 1
            'PartialFields',
90 1
            _t(static::class . '.PARTIALFIELDS', 'Partial fields'),
91 1
            $list->sort('Created', 'ASC')
92
        );
93
94
        $exportColumns = [
95 1
            'Title'       => 'Title',
96
            'ExportValue' => 'Value'
97
        ];
98
99 1
        $config = new GridFieldConfig();
100 1
        $config->addComponent(new GridFieldDataColumns());
101 1
        $config->addComponent(new GridFieldButtonRow('after'));
102 1
        $config->addComponent(new GridFieldExportButton('buttons-after-left', $exportColumns));
103 1
        $config->addComponent(new GridFieldPrintButton('buttons-after-left'));
104 1
        $partialFields->setConfig($config);
105
106 1
        $fields->addFieldsToTab(
107 1
            'Root.Main',
108
            [
109 1
                ReadonlyField::create('ReadonlyPartialLink', 'Partial Link', $this->getPartialLink()),
110 1
                $partialFields
111
            ]
112
        );
113
114 1
        return $fields;
115
    }
116
117 43
    /**
118
     * Check if this partial form already has entries
119 43
     * Used to check if a new form needs to start
120
     * @return bool
121
     */
122
    public function isStarted()
123
    {
124
        return ($this->PartialFields()->count() > 0 || $this->PartialUploads()->count() > 0);
125
    }
126
127 1
    /**
128
     * Return this related Form (Elemental or UserDefinedForm
129 1
     * @return DataObject
130
     */
131
    public function getParent()
132
    {
133
        return $this->UserDefinedForm();
134
    }
135
136
    /**
137 40
     * @param Member $member
138
     * @param array $context
139 40
     * @return bool
140 37
     */
141
    public function canCreate($member = null, $context = [])
142
    {
143 19
        return false;
144
    }
145
146
    /**
147
     * @param Member
148
     *
149
     * @return boolean|string
150
     */
151 3
    public function canView($member = null)
152
    {
153 3
        if ($this->UserDefinedForm()) {
154 3
            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 154 which is incompatible with the return type of the parent method SilverStripe\UserForms\M...\SubmittedForm::canView of type boolean.
Loading history...
155
        }
156
157
        return parent::canView($member);
158
    }
159
160
    /**
161
     * @param Member
162
     *
163
     * @return boolean|string
164
     */
165 3
    public function canEdit($member = null)
166
    {
167 3
        if ($this->UserDefinedForm()) {
168 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 168 which is incompatible with the return type of the parent method SilverStripe\UserForms\M...\SubmittedForm::canEdit of type boolean.
Loading history...
169
        }
170
171
        return parent::canEdit($member);
172
    }
173
174
    /**
175
     * @param Member
176
     *
177
     * @return boolean|string
178
     */
179
    public function canDelete($member = null)
180 2
    {
181
        if ($this->UserDefinedForm()) {
182 2
            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 182 which is incompatible with the return type of the parent method SilverStripe\UserForms\M...ubmittedForm::canDelete of type boolean.
Loading history...
183 1
        }
184
185
        return parent::canDelete($member);
186 2
    }
187
188 2
    /**
189 2
     * Get the share link of the form
190 2
     *
191 2
     * @return string
192 2
     * @throws Exception
193
     */
194
    public function getPartialLink()
195
    {
196
        if (!$this->isInDB()) {
197
            return '(none)';
198
        }
199
200
        $token = $this->getPartialToken();
201
202 3
        return Controller::join_links(
203
            Director::absoluteBaseURL(),
204 3
            'partial',
205 3
            $this->generateKey($token),
0 ignored issues
show
Bug introduced by
It seems like $token defined by $this->getPartialToken() on line 200 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...
206 3
            $token
207 3
        );
208
    }
209
210 3
    /**
211
     * Get the unique token for the share link
212
     *
213
     * @return bool|string|null
214
     * @throws Exception
215
     */
216
    protected function getPartialToken()
217
    {
218
        if (!$this->TokenSalt) {
219 4
            $this->TokenSalt = $this->generateToken();
220
            $this->Token = $this->generateToken();
221 4
            $this->write();
222
        }
223 4
224
        return $this->Token;
225
    }
226
227
    /**
228
     * Generate a new token
229
     *
230
     * @return bool|string
231
     * @throws Exception
232 4
     */
233
    protected function generateToken()
234 4
    {
235
        $generator = new RandomGenerator();
236
237
        return substr($generator->randomToken('sha256'), 0, 16);
238
    }
239
240
    /**
241
     * Generate a key based on the share token salt
242
     *
243
     * @param string $token
244
     * @return string|bool
245
     */
246
    public function generateKey($token)
247
    {
248
        return hash_pbkdf2('sha256', $token, $this->TokenSalt, 1000, 16);
249
    }
250
}
251