Completed
Push — master ( c0fbe9...e7535a )
by Robbie
13s
created

code/cms/DMSUploadField.php (3 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

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
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
    /**
22
     * The temporary folder name to store files in during upload
23
     * @var string
24
     */
25
    protected $folderName = 'DMSTemporaryUploads';
26
27
    /**
28
     * Override the default behaviour of the UploadField and take the uploaded file (uploaded to assets) and
29
     * add it into the DMS storage, deleting the old/uploaded file.
30
     * @param File
31
     */
32
    protected function attachFile($file)
33
    {
34
        $dms = DMS::inst();
35
        $record = $this->getRecord();
36
37
        if ($record instanceof DMSDocument) {
38
            // If the edited record is a document,
39
            // assume we're replacing an existing file
40
            $doc = $record;
41
            $doc->ingestFile($file);
42
        } else {
43
            // Otherwise create it
44
            $doc = $dms->storeDocument($file);
45
            $file->delete();
46
        }
47
48
        // Relate to the underlying document set being edited.
49
        // Not applicable when editing the document itself and replacing it, or uploading from the ModelAdmin
50
        if ($record instanceof DMSDocumentSet) {
51
            $record->Documents()->add($doc, array('ManuallyAdded' => 1));
52
        }
53
54
        return $doc;
55
    }
56
57
    public function validate($validator)
58
    {
59
        return true;
60
    }
61
62
    /**
63
     * Action to handle upload of a single file
64
     *
65
     * @param SS_HTTPRequest $request
66
     * @return string json
67
     */
68
    public function upload(SS_HTTPRequest $request)
69
    {
70
        if ($recordId = $request->postVar('ID')) {
71
            $this->setRecord(DMSDocumentSet::get()->byId($recordId));
72
        }
73
74
        if ($this->isDisabled() || $this->isReadonly()) {
75
            return $this->httpError(403);
76
        }
77
78
        // Protect against CSRF on destructive action
79
        $token = $this->getForm()->getSecurityToken();
80
        if (!$token->checkRequest($request)) {
81
            return $this->httpError(400);
82
        }
83
84
        $name = $this->getName();
85
        $tmpfile = $request->postVar($name);
86
        $record = $this->getRecord();
87
88
        // Check if the file has been uploaded into the temporary storage.
89
        if (!$tmpfile) {
90
            $return = array('error' => _t('UploadField.FIELDNOTSET', 'File information not found'));
91
        } else {
92
            $return = array(
93
                'name' => $tmpfile['name'],
94
                'size' => $tmpfile['size'],
95
                'type' => $tmpfile['type'],
96
                'error' => $tmpfile['error']
97
            );
98
        }
99
100
        // Check for constraints on the record to which the file will be attached.
101
        if (!$return['error'] && $this->relationAutoSetting && $record && $record->exists()) {
102
            $tooManyFiles = false;
103
            // Some relationships allow many files to be attached.
104
            if ($this->getConfig('allowedMaxFileNumber') && ($record->hasMany($name) || $record->manyMany($name))) {
105
                if (!$record->isInDB()) {
106
                    $record->write();
107
                }
108
                $tooManyFiles = $record->{$name}()->count() >= $this->getConfig('allowedMaxFileNumber');
109
            // has_one only allows one file at any given time.
110
            } elseif ($record->hasOne($name)) {
111
                $tooManyFiles = $record->{$name}() && $record->{$name}()->exists();
112
            }
113
114
            // Report the constraint violation.
115
            if ($tooManyFiles) {
116
                if (!$this->getConfig('allowedMaxFileNumber')) {
117
                    $this->setConfig('allowedMaxFileNumber', 1);
118
                }
119
                $return['error'] = _t(
120
                    'UploadField.MAXNUMBEROFFILES',
121
                    'Max number of {count} file(s) exceeded.',
122
                    array('count' => $this->getConfig('allowedMaxFileNumber'))
123
                );
124
            }
125
        }
126
127
        // Process the uploaded file
128
        if (!$return['error']) {
129
            $fileObject = null;
130
131
            if ($this->relationAutoSetting) {
132
                // Search for relations that can hold the uploaded files.
133
                if ($relationClass = $this->getRelationAutosetClass()) {
134
                    // Create new object explicitly. Otherwise rely on Upload::load to choose the class.
135
                    $fileObject = Object::create($relationClass);
136
                }
137
            }
138
139
            // Get the uploaded file into a new file object.
140
            try {
141
                $this->upload->loadIntoFile($tmpfile, $fileObject, $this->getFolderName());
0 ignored issues
show
$fileObject is of type object<Object>|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...
142
            } catch (Exception $e) {
143
                // we shouldn't get an error here, but just in case
144
                $return['error'] = $e->getMessage();
145
            }
146
147
            if (!$return['error']) {
148
                if ($this->upload->isError()) {
149
                    $return['error'] = implode(' ' . PHP_EOL, $this->upload->getErrors());
150
                } else {
151
                    $file = $this->upload->getFile();
152
153
                    // CUSTOM Attach the file to the related record.
154
                    $document = $this->attachFile($file);
155
156
                    // Collect all output data.
157
                    $return = array_merge($return, array(
158
                        'id' => $document->ID,
159
                        'name' => $document->getTitle(),
160
                        'thumbnail_url' => $document->Icon($document->getExtension()),
161
                        'edit_url' => $this->getItemHandler($document->ID)->EditLink(),
162
                        'size' => $document->getFileSizeFormatted(),
163
                        'buttons' => (string) $document->renderWith($this->getTemplateFileButtons()),
164
                        'showeditform' => true
165
                    ));
166
167
                    // CUSTOM END
168
                }
169
            }
170
        }
171
        $response = new SS_HTTPResponse(Convert::raw2json(array($return)));
172
        $response->addHeader('Content-Type', 'text/plain');
173
        return $response;
174
    }
175
176
177
    /**
178
     * Never directly display items uploaded
179
     * @return SS_List
180
     */
181
    public function getItems()
182
    {
183
        return new ArrayList();
184
    }
185
186
    public function Field($properties = array())
187
    {
188
        $fields = parent::Field($properties);
189
190
        // Replace the download template with a new one only when access the upload field through a GridField.
191
        // Needs to be enabled through setConfig('downloadTemplateName', 'ss-dmsuploadfield-downloadtemplate');
192
        Requirements::javascript(DMS_DIR . '/javascript/DMSUploadField_downloadtemplate.js');
193
194
        // In the add dialog, add the addtemplate into the set of file that load.
195
        Requirements::javascript(DMS_DIR . '/javascript/DMSUploadField_addtemplate.js');
196
197
        return $fields;
198
    }
199
200
    /**
201
     * @param int $itemID
202
     * @return UploadField_ItemHandler
203
     */
204
    public function getItemHandler($itemID)
205
    {
206
        return DMSUploadField_ItemHandler::create($this, $itemID);
207
    }
208
209
210
    /**
211
     * FieldList $fields for the EditForm
212
     * @example 'getCMSFields'
213
     *
214
     * @param File $file File context to generate fields for
215
     * @return FieldList List of form fields
216
     */
217
    public function getDMSFileEditFields($file)
218
    {
219
220
        // Empty actions, generate default
221
        if (empty($this->fileEditFields)) {
222
            $fields = $file->getCMSFields();
223
            // Only display main tab, to avoid overly complex interface
224
            if ($fields->hasTabSet() && ($mainTab = $fields->findOrMakeTab('Root.Main'))) {
225
                $fields = $mainTab->Fields();
226
            }
227
            return $fields;
228
        }
229
230
        // Fields instance
231
        if ($this->fileEditFields instanceof FieldList) {
232
            return $this->fileEditFields;
233
        }
234
235
        // Method to call on the given file
236
        if ($file->hasMethod($this->fileEditFields)) {
237
            return $file->{$this->fileEditFields}();
238
        }
239
240
        user_error("Invalid value for UploadField::fileEditFields", E_USER_ERROR);
241
    }
242
243
    /**
244
     * FieldList $actions or string $name (of a method on File to provide a actions) for the EditForm
245
     * @example 'getCMSActions'
246
     *
247
     * @param File $file File context to generate form actions for
248
     * @return FieldList Field list containing FormAction
249
     */
250
    public function getDMSFileEditActions($file)
251
    {
252
253
        // Empty actions, generate default
254
        if (empty($this->fileEditActions)) {
255
            $actions = new FieldList($saveAction = new FormAction('doEdit', _t('UploadField.DOEDIT', 'Save')));
256
            $saveAction->addExtraClass('ss-ui-action-constructive icon-accept');
257
            return $actions;
258
        }
259
260
        // Actions instance
261
        if ($this->fileEditActions instanceof FieldList) {
262
            return $this->fileEditActions;
263
        }
264
265
        // Method to call on the given file
266
        if ($file->hasMethod($this->fileEditActions)) {
267
            return $file->{$this->fileEditActions}();
268
        }
269
270
        user_error("Invalid value for UploadField::fileEditActions", E_USER_ERROR);
271
    }
272
273
    /**
274
     * Determines the validator to use for the edit form
275
     * @example 'getCMSValidator'
276
     *
277
     * @param File $file File context to generate validator from
278
     * @return Validator Validator object
279
     */
280
    public function getDMSFileEditValidator($file)
281
    {
282
        // Empty validator
283
        if (empty($this->fileEditValidator)) {
284
            return null;
285
        }
286
287
        // Validator instance
288
        if ($this->fileEditValidator instanceof Validator) {
289
            return $this->fileEditValidator;
290
        }
291
292
        // Method to call on the given file
293
        if ($file->hasMethod($this->fileEditValidator)) {
294
            return $file->{$this->fileEditValidator}();
295
        }
296
297
        user_error("Invalid value for UploadField::fileEditValidator", E_USER_ERROR);
298
    }
299
300
    /**
301
     * Set the folder name to store DMS files in
302
     *
303
     * @param  string $folderName
304
     * @return $this
305
     */
306
    public function setFolderName($folderName)
307
    {
308
        $this->folderName = (string) $folderName;
309
        return $this;
310
    }
311
312
    /**
313
     * Get the folder name for storing the document
314
     *
315
     * @return string
316
     */
317
    public function getFolderName()
318
    {
319
        return $this->folderName;
320
    }
321
}
322