Completed
Push — master ( eebc60...bc130b )
by Franco
02:11
created

DMSUploadField::getDMSFileEditActions()   B

Complexity

Conditions 4
Paths 4

Size

Total Lines 22
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 22
rs 8.9197
c 0
b 0
f 0
cc 4
eloc 10
nc 4
nop 1
1
<?php
2
3
/**
4
 * Field for uploading files into a DMSDocument. Replacing the existing file.
5
 * Not ideally suited for the purpose, as the base implementation
6
 * assumes to operate on a {@link File} record. We only use this as
7
 * a temporary container, which gets deleted as soon as the actual
8
 * {@link DMSDocument} is created.
9
 *
10
 * <b>NOTE: this Field will call write() on the supplied record</b>
11
 *
12
 * @author Julian Seidenberg
13
 * @package dms
14
 */
15
class DMSUploadField extends UploadField
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.

You can fix this by adding a namespace to your class:

namespace YourVendor;

class YourClass { }

When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.

Loading history...
16
{
17
    private static $allowed_actions = array(
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...
Unused Code introduced by
The property $allowed_actions is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
18
        "upload",
19
    );
20
21
    protected $folderName = 'DMSTemporaryUploads';
22
23
    public function __construct($name, $title = null, SS_List $items = null)
24
    {
25
        parent::__construct($name, $title, $items);
26
27
        //set default DMS replace template to false
28
        $this->setConfig('useDMSReplaceTemplate', 0);
29
    }
30
31
32
    /**
33
     * Override the default behaviour of the UploadField and take the uploaded file (uploaded to assets) and
34
     * add it into the DMS storage, deleting the old/uploaded file.
35
     * @param File
36
     */
37
    protected function attachFile($file)
38
    {
39
        $dms = DMS::inst();
40
        $record = $this->getRecord();
41
42
        if ($record instanceof DMSDocument) {
43
            // If the edited record is a document,
44
            // assume we're replacing an existing file
45
            $doc = $record;
46
            $doc->ingestFile($file);
47
        } else {
48
            // Otherwise create it
49
            $doc = $dms->storeDocument($file);
50
            $file->delete();
51
            // Relate to the underlying page being edited.
52
            // Not applicable when editing the document itself and replacing it.
53
            $doc->addPage($record);
54
        }
55
56
        return $doc;
57
    }
58
59
    public function validate($validator)
60
    {
61
        return true;
62
    }
63
64
65
    public function isDisabled()
66
    {
67
        return (parent::isDisabled() || !$this->isSaveable());
68
    }
69
70
    public function isSaveable()
71
    {
72
        return (!empty($this->getRecord()->ID));
73
    }
74
75
    /**
76
     * Action to handle upload of a single file
77
     *
78
     * @param SS_HTTPRequest $request
79
     * @return string json
0 ignored issues
show
Documentation introduced by
Should the return type not be SS_HTTPResponse?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
80
     */
81
    public function upload(SS_HTTPRequest $request)
82
    {
83
        if ($this->isDisabled() || $this->isReadonly()) {
84
            return $this->httpError(403);
85
        }
86
87
        // Protect against CSRF on destructive action
88
        $token = $this->getForm()->getSecurityToken();
89
        if (!$token->checkRequest($request)) {
90
            return $this->httpError(400);
91
        }
92
93
        $name = $this->getName();
94
        $tmpfile = $request->postVar($name);
95
        $record = $this->getRecord();
96
97
        // Check if the file has been uploaded into the temporary storage.
98
        if (!$tmpfile) {
99
            $return = array('error' => _t('UploadField.FIELDNOTSET', 'File information not found'));
100
        } else {
101
            $return = array(
102
                'name' => $tmpfile['name'],
103
                'size' => $tmpfile['size'],
104
                'type' => $tmpfile['type'],
105
                'error' => $tmpfile['error']
106
            );
107
        }
108
109
        // Check for constraints on the record to which the file will be attached.
110
        if (!$return['error'] && $this->relationAutoSetting && $record && $record->exists()) {
111
            $tooManyFiles = false;
112
            // Some relationships allow many files to be attached.
113
            if ($this->getConfig('allowedMaxFileNumber') && ($record->has_many($name) || $record->many_many($name))) {
0 ignored issues
show
Deprecated Code introduced by
The method DataObject::has_many() has been deprecated with message: 4.0 Method has been replaced by hasMany() and hasManyComponent()

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
Deprecated Code introduced by
The method DataObject::many_many() has been deprecated with message: 4.0 Method has been renamed to manyMany()

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
114
                if (!$record->isInDB()) {
115
                    $record->write();
116
                }
117
                $tooManyFiles = $record->{$name}()->count() >= $this->getConfig('allowedMaxFileNumber');
118
            // has_one only allows one file at any given time.
119
            } elseif ($record->has_one($name)) {
0 ignored issues
show
Deprecated Code introduced by
The method DataObject::has_one() has been deprecated with message: 4.0 Method has been replaced by hasOne() and hasOneComponent()

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
120
                $tooManyFiles = $record->{$name}() && $record->{$name}()->exists();
121
            }
122
123
            // Report the constraint violation.
124
            if ($tooManyFiles) {
125
                if (!$this->getConfig('allowedMaxFileNumber')) {
126
                    $this->setConfig('allowedMaxFileNumber', 1);
127
                }
128
                $return['error'] = _t(
129
                    'UploadField.MAXNUMBEROFFILES',
130
                    'Max number of {count} file(s) exceeded.',
131
                    array('count' => $this->getConfig('allowedMaxFileNumber'))
0 ignored issues
show
Documentation introduced by
array('count' => $this->...allowedMaxFileNumber')) is of type array<string,*,{"count":"*"}>, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
132
                );
133
            }
134
        }
135
136
        // Process the uploaded file
137
        if (!$return['error']) {
138
            $fileObject = null;
139
140
            if ($this->relationAutoSetting) {
141
                // Search for relations that can hold the uploaded files.
142
                if ($relationClass = $this->getRelationAutosetClass()) {
143
                    // Create new object explicitly. Otherwise rely on Upload::load to choose the class.
144
                    $fileObject = Object::create($relationClass);
145
                }
146
            }
147
148
            // Get the uploaded file into a new file object.
149
            try {
150
                $this->upload->loadIntoFile($tmpfile, $fileObject, $this->folderName);
0 ignored issues
show
Documentation introduced by
$fileObject is of type this<DMSUploadField>|null, but the function expects a object<File>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
Documentation introduced by
$this->folderName is of type string, but the function expects a boolean.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
151
            } catch (Exception $e) {
152
                // we shouldn't get an error here, but just in case
153
                $return['error'] = $e->getMessage();
154
            }
155
156
            if (!$return['error']) {
157
                if ($this->upload->isError()) {
158
                    $return['error'] = implode(' '.PHP_EOL, $this->upload->getErrors());
159
                } else {
160
                    $file = $this->upload->getFile();
161
162
                    // CUSTOM Attach the file to the related record.
163
                    $document = $this->attachFile($file);
164
165
                    // Collect all output data.
166
                    $return = array_merge($return, array(
167
                        'id' => $document->ID,
168
                        'name' => $document->getTitle(),
169
                        'thumbnail_url' => $document->Icon($document->getExtension()),
170
                        'edit_url' => $this->getItemHandler($document->ID)->EditLink(),
171
                        'size' => $document->getFileSizeFormatted(),
172
                        'buttons' => (string) $document->renderWith($this->getTemplateFileButtons()),
173
                        'showeditform' => true
174
                    ));
175
176
                    // CUSTOM END
177
                }
178
            }
179
        }
180
        $response = new SS_HTTPResponse(Convert::raw2json(array($return)));
181
        $response->addHeader('Content-Type', 'text/plain');
182
        return $response;
183
    }
184
185
186
    /**
187
     * Never directly display items uploaded
188
     * @return SS_List
189
     */
190
    public function getItems()
191
    {
192
        return new ArrayList();
193
    }
194
195
    public function Field($properties = array())
196
    {
197
        $fields = parent::Field($properties);
198
199
        // Replace the download template with a new one only when access the upload field through a GridField.
200
        // Needs to be enabled through setConfig('downloadTemplateName', 'ss-dmsuploadfield-downloadtemplate');
201
        Requirements::javascript('dms/javascript/DMSUploadField_downloadtemplate.js');
202
203
        // In the add dialog, add the addtemplate into the set of file that load.
204
        Requirements::javascript('dms/javascript/DMSUploadField_addtemplate.js');
205
206
        return $fields;
207
    }
208
209
    /**
210
     * @param int $itemID
211
     * @return UploadField_ItemHandler
212
     */
213
    public function getItemHandler($itemID)
214
    {
215
        return DMSUploadField_ItemHandler::create($this, $itemID);
216
    }
217
218
219
    /**
220
     * FieldList $fields for the EditForm
221
     * @example 'getCMSFields'
222
     *
223
     * @param File $file File context to generate fields for
224
     * @return FieldList List of form fields
225
     */
226
    public function getDMSFileEditFields($file)
227
    {
228
229
        // Empty actions, generate default
230
        if (empty($this->fileEditFields)) {
231
            $fields = $file->getCMSFields();
232
            // Only display main tab, to avoid overly complex interface
233
            if ($fields->hasTabSet() && ($mainTab = $fields->findOrMakeTab('Root.Main'))) {
234
                $fields = $mainTab->Fields();
235
            }
236
            return $fields;
237
        }
238
239
        // Fields instance
240
        if ($this->fileEditFields instanceof FieldList) {
241
            return $this->fileEditFields;
242
        }
243
244
        // Method to call on the given file
245
        if ($file->hasMethod($this->fileEditFields)) {
246
            return $file->{$this->fileEditFields}();
247
        }
248
249
        user_error("Invalid value for UploadField::fileEditFields", E_USER_ERROR);
250
    }
251
252
    /**
253
     * FieldList $actions or string $name (of a method on File to provide a actions) for the EditForm
254
     * @example 'getCMSActions'
255
     *
256
     * @param File $file File context to generate form actions for
257
     * @return FieldList Field list containing FormAction
258
     */
259
    public function getDMSFileEditActions($file)
260
    {
261
262
        // Empty actions, generate default
263
        if (empty($this->fileEditActions)) {
264
            $actions = new FieldList($saveAction = new FormAction('doEdit', _t('UploadField.DOEDIT', 'Save')));
265
            $saveAction->addExtraClass('ss-ui-action-constructive icon-accept');
266
            return $actions;
267
        }
268
269
        // Actions instance
270
        if ($this->fileEditActions instanceof FieldList) {
271
            return $this->fileEditActions;
272
        }
273
274
        // Method to call on the given file
275
        if ($file->hasMethod($this->fileEditActions)) {
276
            return $file->{$this->fileEditActions}();
277
        }
278
279
        user_error("Invalid value for UploadField::fileEditActions", E_USER_ERROR);
280
    }
281
282
    /**
283
     * Determines the validator to use for the edit form
284
     * @example 'getCMSValidator'
285
     *
286
     * @param File $file File context to generate validator from
287
     * @return Validator Validator object
288
     */
289
    public function getDMSFileEditValidator($file)
290
    {
291
        // Empty validator
292
        if (empty($this->fileEditValidator)) {
293
            return null;
294
        }
295
296
        // Validator instance
297
        if ($this->fileEditValidator instanceof Validator) {
298
            return $this->fileEditValidator;
299
        }
300
301
        // Method to call on the given file
302
        if ($file->hasMethod($this->fileEditValidator)) {
303
            return $file->{$this->fileEditValidator}();
304
        }
305
306
        user_error("Invalid value for UploadField::fileEditValidator", E_USER_ERROR);
307
    }
308
}
309