Completed
Pull Request — master (#6442)
by Robbie
09:26
created

UploadTest::getTemporaryFileContent()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 1
dl 0
loc 4
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace SilverStripe\Assets\Tests;
4
5
use SilverStripe\Assets\File;
6
use SilverStripe\Assets\Upload;
7
use SilverStripe\Assets\Tests\Storage\AssetStoreTest\TestAssetStore;
8
use SilverStripe\Core\Config\Config;
9
use SilverStripe\Dev\SapphireTest;
10
use SilverStripe\ORM\Versioning\Versioned;
11
12
class UploadTest extends SapphireTest
13
{
14
    /**
15
     * {@inheritDoc}
16
     * @var bool
17
     */
18
    protected $usesDatabase = true;
19
20
    /**
21
     * The temporary file path used for upload tests
22
     * @var string
23
     */
24
    protected $tmpFilePath;
25
26
    /**
27
     * {@inheritDoc}
28
     */
29
    public function setUp()
30
    {
31
        parent::setUp();
32
        Versioned::set_stage(Versioned::DRAFT);
33
        TestAssetStore::activate('UploadTest');
34
    }
35
36
    /**
37
     * {@inheritDoc}
38
     */
39
    public function tearDown()
40
    {
41
        TestAssetStore::reset();
42
        parent::tearDown();
43
44
        if (file_exists($this->tmpFilePath)) {
45
            unlink($this->tmpFilePath);
46
        }
47
    }
48
49
    public function testUpload()
50
    {
51
        // create tmp file
52
        $tmpFileName = 'UploadTest-testUpload.txt';
53
        $this->tmpFilePath = TEMP_FOLDER . '/' . $tmpFileName;
54
        $tmpFileContent = $this->getTemporaryFileContent();
55
        file_put_contents($this->tmpFilePath, $tmpFileContent);
56
57
        // emulates the $_FILES array
58
        $tmpFile = array(
59
            'name' => $tmpFileName,
60
            'type' => 'text/plaintext',
61
            'size' => filesize($this->tmpFilePath),
62
            'tmp_name' => $this->tmpFilePath,
63
            'extension' => 'txt',
64
            'error' => UPLOAD_ERR_OK,
65
        );
66
67
        $v = new UploadTest\Validator();
68
69
        // test upload into default folder
70
        $u1 = new Upload();
71
        $u1->setValidator($v);
72
        $u1->loadIntoFile($tmpFile);
73
        $file1 = $u1->getFile();
74
        $this->assertEquals(
75
            'Uploads/UploadTest-testUpload.txt',
76
            $file1->getFilename()
77
        );
78
        $this->assertEquals(
79
            BASE_PATH . '/assets/UploadTest/.protected/Uploads/315ae4c3d4/UploadTest-testUpload.txt',
80
            TestAssetStore::getLocalPath($file1)
81
        );
82
        $this->assertFileExists(
83
            TestAssetStore::getLocalPath($file1),
84
            'File upload to standard directory in /assets'
85
        );
86
87
        // test upload into custom folder
88
        $customFolder = 'UploadTest-testUpload';
89
        $u2 = new Upload();
90
        $u2->loadIntoFile($tmpFile, null, $customFolder);
91
        $file2 = $u2->getFile();
92
        $this->assertEquals(
93
            'UploadTest-testUpload/UploadTest-testUpload.txt',
94
            $file2->getFilename()
95
        );
96
        $this->assertEquals(
97
            BASE_PATH . '/assets/UploadTest/.protected/UploadTest-testUpload/315ae4c3d4/UploadTest-testUpload.txt',
98
            TestAssetStore::getLocalPath($file2)
99
        );
100
        $this->assertFileExists(
101
            TestAssetStore::getLocalPath($file2),
102
            'File upload to custom directory in /assets'
103
        );
104
    }
105
106
    public function testAllowedFilesize()
107
    {
108
        // create tmp file
109
        $tmpFileName = 'UploadTest-testUpload.txt';
110
        $this->tmpFilePath = TEMP_FOLDER . '/' . $tmpFileName;
111
        $tmpFileContent = $this->getTemporaryFileContent();
112
        file_put_contents($this->tmpFilePath, $tmpFileContent);
113
114
        // emulates the $_FILES array
115
        $tmpFile = array(
116
            'name' => $tmpFileName,
117
            'type' => 'text/plaintext',
118
            'size' => filesize($this->tmpFilePath),
119
            'tmp_name' => $this->tmpFilePath,
120
            'extension' => 'txt',
121
            'error' => UPLOAD_ERR_OK,
122
        );
123
124
        // test upload into default folder
125
        $u1 = new Upload();
126
        $v = new UploadTest\Validator();
127
128
        $v->setAllowedMaxFileSize(array('txt' => 10));
129
        $u1->setValidator($v);
130
        $result = $u1->loadIntoFile($tmpFile);
131
        $this->assertFalse($result, 'Load failed because size was too big');
132
133
        $v->setAllowedMaxFileSize(array('[document]' => 10));
134
        $u1->setValidator($v);
135
        $result = $u1->loadIntoFile($tmpFile);
136
        $this->assertFalse($result, 'Load failed because size was too big');
137
138
        $v->setAllowedMaxFileSize(array('txt' => 200000));
139
        $u1->setValidator($v);
140
        $result = $u1->loadIntoFile($tmpFile);
141
        $this->assertTrue($result, 'Load failed with setting max file size');
142
143
        // check max file size set by app category
144
        $tmpFileName = 'UploadTest-testUpload.jpg';
145
        $this->tmpFilePath = TEMP_FOLDER . '/' . $tmpFileName;
146
        file_put_contents($this->tmpFilePath, $tmpFileContent . $tmpFileContent);
147
148
        $tmpFile = array(
149
            'name' => $tmpFileName,
150
            'type' => 'image/jpeg',
151
            'size' => filesize($this->tmpFilePath),
152
            'tmp_name' => $this->tmpFilePath,
153
            'extension' => 'jpg',
154
            'error' => UPLOAD_ERR_OK,
155
        );
156
157
        $v->setAllowedMaxFileSize(array('[image]' => '40k'));
158
        $u1->setValidator($v);
159
        $result = $u1->loadIntoFile($tmpFile);
160
        $this->assertTrue($result, 'Load failed with setting max file size');
161
162
        $v->setAllowedMaxFileSize(array('[image]' => '1k'));
163
        $u1->setValidator($v);
164
        $result = $u1->loadIntoFile($tmpFile);
165
        $this->assertFalse($result, 'Load failed because size was too big');
166
167
        $v->setAllowedMaxFileSize(array('[image]' => 1000));
168
        $u1->setValidator($v);
169
        $result = $u1->loadIntoFile($tmpFile);
170
        $this->assertFalse($result, 'Load failed because size was too big');
171
    }
172
173
    public function testPHPUploadErrors()
174
    {
175
        $configMaxFileSizes = ['*' => '1k'];
176
        Config::inst()->update(
177
            'SilverStripe\\Assets\\Upload_Validator',
178
            'default_max_file_size',
179
            $configMaxFileSizes
180
        );
181
        // create tmp file
182
        $tmpFileName = 'myfile.jpg';
183
        $this->tmpFilePath = TEMP_FOLDER . '/' . $tmpFileName;
184
        $tmpFileContent = $this->getTemporaryFileContent(100);
185
        file_put_contents($this->tmpFilePath, $tmpFileContent);
186
187
        // Build file
188
        $upload = new Upload();
189
        $tmpFile = array(
190
            'name' => $tmpFileName,
191
            'type' => '',
192
            'tmp_name' => $this->tmpFilePath,
193
            'size' => filesize($this->tmpFilePath),
194
            'error' => UPLOAD_ERR_OK,
195
        );
196
197
        // Test ok
198
        $this->assertTrue($upload->validate($tmpFile));
199
200
        // Test zero size file
201
        $upload->clearErrors();
202
        $tmpFile['size'] = 0;
203
        $this->assertFalse($upload->validate($tmpFile));
204
        $this->assertContains(
205
            _t('File.NOFILESIZE', 'Filesize is zero bytes.'),
206
            $upload->getErrors()
207
        );
208
209
        // Test file too large
210
        $upload->clearErrors();
211
        $tmpFile['error'] = UPLOAD_ERR_INI_SIZE;
212
        $this->assertFalse($upload->validate($tmpFile));
213
        $this->assertContains(
214
            _t(
215
                'File.TOOLARGE',
216
                'Filesize is too large, maximum {size} allowed',
217
                'Argument 1: Filesize (e.g. 1MB)',
218
                array('size' => '1 KB')
219
            ),
220
            $upload->getErrors()
221
        );
222
223
        // Test form size
224
        $upload->clearErrors();
225
        $tmpFile['error'] = UPLOAD_ERR_FORM_SIZE;
226
        $this->assertFalse($upload->validate($tmpFile));
227
        $this->assertContains(
228
            _t(
229
                'File.TOOLARGE',
230
                'Filesize is too large, maximum {size} allowed',
231
                'Argument 1: Filesize (e.g. 1MB)',
232
                array('size' => '1 KB')
233
            ),
234
            $upload->getErrors()
235
        );
236
237
        // Test no file
238
        $upload->clearErrors();
239
        $tmpFile['error'] = UPLOAD_ERR_NO_FILE;
240
        $this->assertFalse($upload->validate($tmpFile));
241
        $this->assertContains(
242
            _t('File.NOVALIDUPLOAD', 'File is not a valid upload'),
243
            $upload->getErrors()
244
        );
245
    }
246
247
    public function testGetAllowedMaxFileSize()
248
    {
249
        Config::nest();
250
251
        // Check the max file size uses the config values
252
        $configMaxFileSizes = array(
253
            '[image]' => '1k',
254
            'txt' => 1000
255
        );
256
        Config::inst()->update('SilverStripe\\Assets\\Upload_Validator', 'default_max_file_size', $configMaxFileSizes);
257
        $v = new UploadTest\Validator();
258
259
        $retrievedSize = $v->getAllowedMaxFileSize('[image]');
260
        $this->assertEquals(
261
            1024,
262
            $retrievedSize,
263
            'Max file size check on default values failed (config category set check)'
264
        );
265
266
        $retrievedSize = $v->getAllowedMaxFileSize('txt');
267
        $this->assertEquals(
268
            1000,
269
            $retrievedSize,
270
            'Max file size check on default values failed (config extension set check)'
271
        );
272
273
        // Check instance values for max file size
274
        $maxFileSizes = array(
275
            '[document]' => 2000,
276
            'txt' => '4k'
277
        );
278
        $v = new UploadTest\Validator();
279
        $v->setAllowedMaxFileSize($maxFileSizes);
280
281
        $retrievedSize = $v->getAllowedMaxFileSize('[document]');
282
        $this->assertEquals(
283
            2000,
284
            $retrievedSize,
285
            'Max file size check on instance values failed (instance category set check)'
286
        );
287
288
        // Check that the instance values overwrote the default values
289
        // ie. The max file size will not exist for [image]
290
        $retrievedSize = $v->getAllowedMaxFileSize('[image]');
291
        $this->assertFalse($retrievedSize, 'Max file size check on instance values failed (config overridden check)');
292
293
        // Check a category that has not been set before
294
        $retrievedSize = $v->getAllowedMaxFileSize('[archive]');
295
        $this->assertFalse($retrievedSize, 'Max file size check on instance values failed (category not set check)');
296
297
        // Check a file extension that has not been set before
298
        $retrievedSize = $v->getAllowedMaxFileSize('mp3');
299
        $this->assertFalse($retrievedSize, 'Max file size check on instance values failed (extension not set check)');
300
301
        $retrievedSize = $v->getAllowedMaxFileSize('txt');
302
        $this->assertEquals(
303
            4096,
304
            $retrievedSize,
305
            'Max file size check on instance values failed (instance extension set check)'
306
        );
307
308
        // Check a wildcard max file size against a file with an extension
309
        $v = new UploadTest\Validator();
310
        $v->setAllowedMaxFileSize(2000);
311
312
        $retrievedSize = $v->getAllowedMaxFileSize('.jpg');
313
        $this->assertEquals(
314
            2000,
315
            $retrievedSize,
316
            'Max file size check on instance values failed (wildcard max file size)'
317
        );
318
319
        Config::unnest();
320
    }
321
322
    public function testAllowedSizeOnFileWithNoExtension()
323
    {
324
        // create tmp file
325
        $tmpFileName = 'UploadTest-testUpload';
326
        $this->tmpFilePath = TEMP_FOLDER . '/' . $tmpFileName;
327
        $tmpFileContent = $this->getTemporaryFileContent();
328
        file_put_contents($this->tmpFilePath, $tmpFileContent);
329
330
        // emulates the $_FILES array
331
        $tmpFile = array(
332
            'name' => $tmpFileName,
333
            'type' => 'text/plaintext',
334
            'size' => filesize($this->tmpFilePath),
335
            'tmp_name' => $this->tmpFilePath,
336
            'extension' => '',
337
            'error' => UPLOAD_ERR_OK,
338
        );
339
340
        $v = new UploadTest\Validator();
341
        $v->setAllowedMaxFileSize(array('' => 10));
342
343
        // test upload into default folder
344
        $u1 = new Upload();
345
        $u1->setValidator($v);
346
        $result = $u1->loadIntoFile($tmpFile);
347
348
        $this->assertFalse($result, 'Load failed because size was too big');
349
    }
350
351
    public function testUploadDoesNotAllowUnknownExtension()
352
    {
353
        // create tmp file
354
        $tmpFileName = 'UploadTest-testUpload.php';
355
        $this->tmpFilePath = TEMP_FOLDER . '/' . $tmpFileName;
356
        $tmpFileContent = $this->getTemporaryFileContent();
357
        file_put_contents($this->tmpFilePath, $tmpFileContent);
358
359
        // emulates the $_FILES array
360
        $tmpFile = array(
361
            'name' => $tmpFileName,
362
            'type' => 'text/plaintext',
363
            'size' => filesize($this->tmpFilePath),
364
            'tmp_name' => $this->tmpFilePath,
365
            'extension' => 'php',
366
            'error' => UPLOAD_ERR_OK,
367
        );
368
369
        $v = new UploadTest\Validator();
370
        $v->setAllowedExtensions(array('txt'));
371
372
        // test upload into default folder
373
        $u = new Upload();
374
        $u->setValidator($v);
375
        $result = $u->loadIntoFile($tmpFile);
376
377
        $this->assertFalse($result, 'Load failed because extension was not accepted');
378
    }
379
380
    public function testUploadAcceptsAllowedExtension()
381
    {
382
        // create tmp file
383
        $tmpFileName = 'UploadTest-testUpload.txt';
384
        $this->tmpFilePath = TEMP_FOLDER . '/' . $tmpFileName;
385
        $tmpFileContent = $this->getTemporaryFileContent();
386
        file_put_contents($this->tmpFilePath, $tmpFileContent);
387
388
        // emulates the $_FILES array
389
        $tmpFile = array(
390
            'name' => $tmpFileName,
391
            'type' => 'text/plaintext',
392
            'size' => filesize($this->tmpFilePath),
393
            'tmp_name' => $this->tmpFilePath,
394
            'extension' => 'txt',
395
            'error' => UPLOAD_ERR_OK,
396
        );
397
398
        $v = new UploadTest\Validator();
399
        $v->setAllowedExtensions(array('txt'));
400
401
        // test upload into default folder
402
        $u = new Upload();
403
        $u->setValidator($v);
404
        $u->loadIntoFile($tmpFile);
405
        $file = $u->getFile();
406
        $this->assertFileExists(
407
            TestAssetStore::getLocalPath($file),
408
            'File upload to custom directory in /assets'
409
        );
410
    }
411
412
    public function testUploadDeniesNoExtensionFilesIfNoEmptyStringSetForValidatorExtensions()
413
    {
414
        // create tmp file
415
        $tmpFileName = 'UploadTest-testUpload';
416
        $this->tmpFilePath = TEMP_FOLDER . '/' . $tmpFileName;
417
        $tmpFileContent = $this->getTemporaryFileContent();
418
        file_put_contents($this->tmpFilePath, $tmpFileContent);
419
420
        // emulates the $_FILES array
421
        $tmpFile = array(
422
            'name' => $tmpFileName,
423
            'type' => 'text/plaintext',
424
            'size' => filesize($this->tmpFilePath),
425
            'tmp_name' => $this->tmpFilePath,
426
            'extension' => '',
427
            'error' => UPLOAD_ERR_OK,
428
        );
429
430
        $v = new UploadTest\Validator();
431
        $v->setAllowedExtensions(array('txt'));
432
433
        // test upload into default folder
434
        $u = new Upload();
435
        $result = $u->loadIntoFile($tmpFile);
436
437
        $this->assertFalse($result, 'Load failed because extension was not accepted');
438
        $this->assertEquals(1, count($u->getErrors()), 'There is a single error of the file extension');
439
    }
440
441
    public function testUploadTarGzFileTwiceAppendsNumber()
442
    {
443
        // create tmp file
444
        $tmpFileName = 'UploadTest-testUpload.tar.gz';
445
        $this->tmpFilePath = TEMP_FOLDER . '/' . $tmpFileName;
446
        $tmpFileContent = $this->getTemporaryFileContent();
447
        file_put_contents($this->tmpFilePath, $tmpFileContent);
448
449
        // emulates the $_FILES array
450
        $tmpFile = array(
451
            'name' => $tmpFileName,
452
            'type' => 'text/plaintext',
453
            'size' => filesize($this->tmpFilePath),
454
            'tmp_name' => $this->tmpFilePath,
455
            'extension' => 'tar.gz',
456
            'error' => UPLOAD_ERR_OK,
457
        );
458
459
        // test upload into default folder
460
        $u = new Upload();
461
        $u->loadIntoFile($tmpFile);
462
        $file = $u->getFile();
463
        $this->assertEquals(
464
            'UploadTest-testUpload.tar.gz',
465
            $file->Name,
0 ignored issues
show
Bug introduced by
Accessing Name on the interface SilverStripe\Assets\Storage\AssetContainer suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
466
            'File has a name without a number because it\'s not a duplicate'
467
        );
468
        $this->assertFileExists(
469
            TestAssetStore::getLocalPath($file),
470
            'File exists'
471
        );
472
473
        $u = new Upload();
474
        $u->loadIntoFile($tmpFile);
475
        $file2 = $u->getFile();
476
        $this->assertEquals(
477
            'UploadTest-testUpload-v2.tar.gz',
478
            $file2->Name,
0 ignored issues
show
Bug introduced by
Accessing Name on the interface SilverStripe\Assets\Storage\AssetContainer suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
479
            'File receives a number attached to the end before the extension'
480
        );
481
        $this->assertFileExists(
482
            TestAssetStore::getLocalPath($file2),
483
            'File exists'
484
        );
485
        $this->assertGreaterThan(
486
            $file->ID,
0 ignored issues
show
Bug introduced by
Accessing ID on the interface SilverStripe\Assets\Storage\AssetContainer suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
487
            $file2->ID,
0 ignored issues
show
Bug introduced by
Accessing ID on the interface SilverStripe\Assets\Storage\AssetContainer suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
488
            'File database record is not the same'
489
        );
490
491
        $u = new Upload();
492
        $u->loadIntoFile($tmpFile);
493
        $file3 = $u->getFile();
494
        $this->assertEquals(
495
            'UploadTest-testUpload-v3.tar.gz',
496
            $file3->Name,
0 ignored issues
show
Bug introduced by
Accessing Name on the interface SilverStripe\Assets\Storage\AssetContainer suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
497
            'File receives a number attached to the end before the extension'
498
        );
499
        $this->assertFileExists(
500
            TestAssetStore::getLocalPath($file3),
501
            'File exists'
502
        );
503
        $this->assertGreaterThan(
504
            $file2->ID,
0 ignored issues
show
Bug introduced by
Accessing ID on the interface SilverStripe\Assets\Storage\AssetContainer suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
505
            $file3->ID,
0 ignored issues
show
Bug introduced by
Accessing ID on the interface SilverStripe\Assets\Storage\AssetContainer suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
506
            'File database record is not the same'
507
        );
508
    }
509
510
    public function testUploadFileWithNoExtensionTwiceAppendsNumber()
511
    {
512
        // create tmp file
513
        $tmpFileName = 'UploadTest-testUpload';
514
        $this->tmpFilePath = TEMP_FOLDER . '/' . $tmpFileName;
515
        $tmpFileContent = $this->getTemporaryFileContent();
516
        file_put_contents($this->tmpFilePath, $tmpFileContent);
517
518
        // emulates the $_FILES array
519
        $tmpFile = array(
520
            'name' => $tmpFileName,
521
            'type' => 'text/plaintext',
522
            'size' => filesize($this->tmpFilePath),
523
            'tmp_name' => $this->tmpFilePath,
524
            'extension' => 'txt',
525
            'error' => UPLOAD_ERR_OK,
526
        );
527
528
        $v = new UploadTest\Validator();
529
        $v->setAllowedExtensions(array(''));
530
531
        // test upload into default folder
532
        $u = new Upload();
533
        $u->setValidator($v);
534
        $u->loadIntoFile($tmpFile);
535
        $file = $u->getFile();
536
537
        $this->assertEquals(
538
            'UploadTest-testUpload',
539
            $file->Name,
0 ignored issues
show
Bug introduced by
Accessing Name on the interface SilverStripe\Assets\Storage\AssetContainer suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
540
            'File is uploaded without extension'
541
        );
542
        $this->assertFileExists(
543
            TestAssetStore::getLocalPath($file),
544
            'File exists'
545
        );
546
547
        $u = new Upload();
548
        $u->setValidator($v);
549
        $u->loadIntoFile($tmpFile);
550
        $file2 = $u->getFile();
551
        $this->assertEquals(
552
            'UploadTest-testUpload-v2',
553
            $file2->Name,
0 ignored issues
show
Bug introduced by
Accessing Name on the interface SilverStripe\Assets\Storage\AssetContainer suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
554
            'File receives a number attached to the end'
555
        );
556
        $this->assertFileExists(
557
            TestAssetStore::getLocalPath($file2),
558
            'File exists'
559
        );
560
        $this->assertGreaterThan(
561
            $file->ID,
0 ignored issues
show
Bug introduced by
Accessing ID on the interface SilverStripe\Assets\Storage\AssetContainer suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
562
            $file2->ID,
0 ignored issues
show
Bug introduced by
Accessing ID on the interface SilverStripe\Assets\Storage\AssetContainer suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
563
            'File database record is not the same'
564
        );
565
    }
566
567
    public function testReplaceFile()
568
    {
569
        // create tmp file
570
        $tmpFileName = 'UploadTest-testUpload';
571
        $this->tmpFilePath = TEMP_FOLDER . '/' . $tmpFileName;
572
        $tmpFileContent = $this->getTemporaryFileContent();
573
        file_put_contents($this->tmpFilePath, $tmpFileContent);
574
575
        // emulates the $_FILES array
576
        $tmpFile = array(
577
            'name' => $tmpFileName,
578
            'type' => 'text/plaintext',
579
            'size' => filesize($this->tmpFilePath),
580
            'tmp_name' => $this->tmpFilePath,
581
            'extension' => 'txt',
582
            'error' => UPLOAD_ERR_OK,
583
        );
584
585
        $v = new UploadTest\Validator();
586
        $v->setAllowedExtensions(array(''));
587
588
        // test upload into default folder
589
        $u = new Upload();
590
        $u->setValidator($v);
591
        $u->loadIntoFile($tmpFile);
592
        $file = $u->getFile();
593
594
        $this->assertEquals(
595
            'UploadTest-testUpload',
596
            $file->Name,
0 ignored issues
show
Bug introduced by
Accessing Name on the interface SilverStripe\Assets\Storage\AssetContainer suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
597
            'File is uploaded without extension'
598
        );
599
        $this->assertFileExists(
600
            TestAssetStore::getLocalPath($file),
601
            'File exists'
602
        );
603
604
        $u = new Upload();
605
        $u->setValidator($v);
606
        $u->setReplaceFile(true);
607
        $u->loadIntoFile($tmpFile);
608
        $file2 = $u->getFile();
609
        $this->assertEquals(
610
            'UploadTest-testUpload',
611
            $file2->Name,
0 ignored issues
show
Bug introduced by
Accessing Name on the interface SilverStripe\Assets\Storage\AssetContainer suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
612
            'File does not receive new name'
613
        );
614
        $this->assertFileExists(
615
            TestAssetStore::getLocalPath($file2),
616
            'File exists'
617
        );
618
        $this->assertEquals(
619
            $file->ID,
0 ignored issues
show
Bug introduced by
Accessing ID on the interface SilverStripe\Assets\Storage\AssetContainer suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
620
            $file2->ID,
0 ignored issues
show
Bug introduced by
Accessing ID on the interface SilverStripe\Assets\Storage\AssetContainer suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
621
            'File database record is the same'
622
        );
623
    }
624
625
    public function testReplaceFileWithLoadIntoFile()
626
    {
627
        // create tmp file
628
        $tmpFileName = 'UploadTest-testUpload.txt';
629
        $this->tmpFilePath = TEMP_FOLDER . '/' . $tmpFileName;
630
        $tmpFileContent = $this->getTemporaryFileContent();
631
        file_put_contents($this->tmpFilePath, $tmpFileContent);
632
633
        // emulates the $_FILES array
634
        $tmpFile = array(
635
            'name' => $tmpFileName,
636
            'type' => 'text/plaintext',
637
            'size' => filesize($this->tmpFilePath),
638
            'tmp_name' => $this->tmpFilePath,
639
            'extension' => 'txt',
640
            'error' => UPLOAD_ERR_OK,
641
        );
642
643
        $v = new UploadTest\Validator();
644
645
        // test upload into default folder
646
        $u = new Upload();
647
        $u->setValidator($v);
648
        $u->loadIntoFile($tmpFile);
649
        $file = $u->getFile();
650
651
        $this->assertEquals(
652
            'UploadTest-testUpload.txt',
653
            $file->Name,
0 ignored issues
show
Bug introduced by
Accessing Name on the interface SilverStripe\Assets\Storage\AssetContainer suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
654
            'File is uploaded without extension'
655
        );
656
        $this->assertFileExists(
657
            TestAssetStore::getLocalPath($file),
658
            'File exists'
659
        );
660
661
        // replace=true
662
        $u = new Upload();
663
        $u->setValidator($v);
664
        $u->setReplaceFile(true);
665
        $u->loadIntoFile($tmpFile, new File());
666
        $file2 = $u->getFile();
667
        $this->assertEquals(
668
            'UploadTest-testUpload.txt',
669
            $file2->Name,
0 ignored issues
show
Bug introduced by
Accessing Name on the interface SilverStripe\Assets\Storage\AssetContainer suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
670
            'File does not receive new name'
671
        );
672
        $this->assertFileExists(
673
            TestAssetStore::getLocalPath($file2),
674
            'File exists'
675
        );
676
        $this->assertEquals(
677
            $file->ID,
0 ignored issues
show
Bug introduced by
Accessing ID on the interface SilverStripe\Assets\Storage\AssetContainer suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
678
            $file2->ID,
0 ignored issues
show
Bug introduced by
Accessing ID on the interface SilverStripe\Assets\Storage\AssetContainer suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
679
            'File database record is the same'
680
        );
681
682
        // replace=false
683
        $u = new Upload();
684
        $u->setValidator($v);
685
        $u->setReplaceFile(false);
686
        $u->loadIntoFile($tmpFile, new File());
687
        $file3 = $u->getFile();
688
        $this->assertEquals(
689
            'UploadTest-testUpload-v2.txt',
690
            $file3->Name,
0 ignored issues
show
Bug introduced by
Accessing Name on the interface SilverStripe\Assets\Storage\AssetContainer suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
691
            'File does receive new name'
692
        );
693
        $this->assertFileExists(
694
            TestAssetStore::getLocalPath($file3),
695
            'File exists'
696
        );
697
        $this->assertGreaterThan(
698
            $file2->ID,
0 ignored issues
show
Bug introduced by
Accessing ID on the interface SilverStripe\Assets\Storage\AssetContainer suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
699
            $file3->ID,
0 ignored issues
show
Bug introduced by
Accessing ID on the interface SilverStripe\Assets\Storage\AssetContainer suggest that you code against a concrete implementation. How about adding an instanceof check?

If you access a property on an interface, you most likely code against a concrete implementation of the interface.

Available Fixes

  1. Adding an additional type check:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeInterface $object) {
        if ($object instanceof SomeClass) {
            $a = $object->a;
        }
    }
    
  2. Changing the type hint:

    interface SomeInterface { }
    class SomeClass implements SomeInterface {
        public $a;
    }
    
    function someFunction(SomeClass $object) {
        $a = $object->a;
    }
    
Loading history...
700
            'File database record is not the same'
701
        );
702
    }
703
704
    public function testDeleteResampledImagesOnUpload()
705
    {
706
        $tmpFileName = 'UploadTest-testUpload.jpg';
707
        $this->tmpFilePath = TEMP_FOLDER . '/' . $tmpFileName;
708
709
        $uploadImage = function () use ($tmpFileName) {
710
            copy(__DIR__ . '/GDTest/images/test_jpg.jpg', $this->tmpFilePath);
711
712
            // emulates the $_FILES array
713
            $tmpFile = array(
714
                'name' => $tmpFileName,
715
                'type' => 'text/plaintext',
716
                'size' => filesize($this->tmpFilePath),
717
                'tmp_name' => $this->tmpFilePath,
718
                'extension' => 'jpg',
719
                'error' => UPLOAD_ERR_OK,
720
            );
721
722
            $v = new UploadTest\Validator();
723
724
            // test upload into default folder
725
            $u = new Upload();
726
            $u->setReplaceFile(true);
727
            $u->setValidator($v);
728
            $u->loadIntoFile($tmpFile);
729
            return $u->getFile();
730
        };
731
732
        // Image upload and generate a resampled image
733
        $image = $uploadImage();
734
        $resampled = $image->ResizedImage(123, 456);
735
        $resampledPath = TestAssetStore::getLocalPath($resampled);
736
        $this->assertFileExists($resampledPath);
737
738
        // Re-upload the image, overwriting the original
739
        // Resampled images should removed when their parent file is overwritten
740
        $image = $uploadImage();
741
        $this->assertFileExists($resampledPath);
742
    }
743
744
    public function testFileVersioningWithAnExistingFile()
745
    {
746
        $upload = function ($tmpFileName) {
747
            // create tmp file
748
            $this->tmpFilePath = TEMP_FOLDER . '/' . $tmpFileName;
749
            $tmpFileContent = $this->getTemporaryFileContent();
750
            file_put_contents($this->tmpFilePath, $tmpFileContent);
751
752
            // emulates the $_FILES array
753
            $tmpFile = array(
754
                'name' => $tmpFileName,
755
                'type' => 'text/plaintext',
756
                'size' => filesize($this->tmpFilePath),
757
                'tmp_name' => $this->tmpFilePath,
758
                'extension' => 'jpg',
759
                'error' => UPLOAD_ERR_OK,
760
            );
761
762
            $v = new UploadTest\Validator();
763
764
            // test upload into default folder
765
            $u = new Upload();
766
            $u->setReplaceFile(false);
767
            $u->setValidator($v);
768
            $u->loadIntoFile($tmpFile);
769
            return $u->getFile();
770
        };
771
772
        // test empty file version prefix
773
        Config::inst()->update('SilverStripe\\Assets\\Storage\\DefaultAssetNameGenerator', 'version_prefix', '');
774
775
        $file1 = $upload('UploadTest-IMG001.jpg');
776
        $this->assertEquals(
777
            'UploadTest-IMG001.jpg',
778
            $file1->Name,
779
            'File does not receive new name'
780
        );
781
782
        $file2 = $upload('UploadTest-IMG001.jpg');
783
        $this->assertEquals(
784
            'UploadTest-IMG002.jpg',
785
            $file2->Name,
786
            'File does receive new name'
787
        );
788
789
        $file3 = $upload('UploadTest-IMG002.jpg');
790
        $this->assertEquals(
791
            'UploadTest-IMG003.jpg',
792
            $file3->Name,
793
            'File does receive new name'
794
        );
795
796
        $file4 = $upload('UploadTest-IMG3.jpg');
797
        $this->assertEquals(
798
            'UploadTest-IMG3.jpg',
799
            $file4->Name,
800
            'File does not receive new name'
801
        );
802
803
        $file1->delete();
804
        $file2->delete();
805
        $file3->delete();
806
        $file4->delete();
807
808
        // test '-v' file version prefix
809
        Config::inst()->update('SilverStripe\\Assets\\Storage\\DefaultAssetNameGenerator', 'version_prefix', '-v');
810
811
        $file1 = $upload('UploadTest2-IMG001.jpg');
812
        $this->assertEquals(
813
            'UploadTest2-IMG001.jpg',
814
            $file1->Name,
815
            'File does not receive new name'
816
        );
817
818
        $file2 = $upload('UploadTest2-IMG001.jpg');
819
        $this->assertEquals(
820
            'UploadTest2-IMG001-v2.jpg',
821
            $file2->Name,
822
            'File does receive new name'
823
        );
824
825
        $file3 = $upload('UploadTest2-IMG001.jpg');
826
        $this->assertEquals(
827
            'UploadTest2-IMG001-v3.jpg',
828
            $file3->Name,
829
            'File does receive new name'
830
        );
831
832
        $file4 = $upload('UploadTest2-IMG001-v3.jpg');
833
        $this->assertEquals(
834
            'UploadTest2-IMG001-v4.jpg',
835
            $file4->Name,
836
            'File does receive new name'
837
        );
838
    }
839
840
    /**
841
     * Generate some dummy file content
842
     *
843
     * @param  int $reps How many zeros to return
844
     * @return string
845
     */
846
    protected function getTemporaryFileContent($reps = 10000)
847
    {
848
        return str_repeat('0', $reps);
849
    }
850
}
851