Completed
Push — master ( 4bd9a0...b11bbf )
by Daniel
14:49
created

UploadTest::testGetAllowedMaxFileSize()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 53
Code Lines 31

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 31
c 1
b 0
f 0
nc 1
nop 0
dl 0
loc 53
rs 9.5797

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
/**
4
 * @package framework
5
 * @subpackage tests
6
 */
7
class UploadTest extends SapphireTest {
8
9
	protected $usesDatabase = true;
10
11
	public function setUp() {
12
		parent::setUp();
13
		Versioned::set_stage(Versioned::DRAFT);
14
		AssetStoreTest_SpyStore::activate('UploadTest');
15
	}
16
17
	public function tearDown() {
18
		AssetStoreTest_SpyStore::reset();
19
		parent::tearDown();
20
	}
21
22
	public function testUpload() {
23
		// create tmp file
24
		$tmpFileName = 'UploadTest-testUpload.txt';
25
		$tmpFilePath = TEMP_FOLDER . '/' . $tmpFileName;
26
		$tmpFileContent = '';
27
		for($i=0; $i<10000; $i++) $tmpFileContent .= '0';
28
		file_put_contents($tmpFilePath, $tmpFileContent);
29
30
		// emulates the $_FILES array
31
		$tmpFile = array(
32
			'name' => $tmpFileName,
33
			'type' => 'text/plaintext',
34
			'size' => filesize($tmpFilePath),
35
			'tmp_name' => $tmpFilePath,
36
			'extension' => 'txt',
37
			'error' => UPLOAD_ERR_OK,
38
		);
39
40
		$v = new UploadTest_Validator();
41
42
		// test upload into default folder
43
		$u1 = new Upload();
44
		$u1->setValidator($v);
45
		$u1->loadIntoFile($tmpFile);
46
		$file1 = $u1->getFile();
47
		$this->assertEquals(
48
			'Uploads/UploadTest-testUpload.txt',
49
			$file1->getFilename()
50
		);
51
		$this->assertEquals(
52
			BASE_PATH . '/assets/UploadTest/.protected/Uploads/315ae4c3d4/UploadTest-testUpload.txt',
53
			AssetStoreTest_SpyStore::getLocalPath($file1)
54
		);
55
		$this->assertFileExists(
56
			AssetStoreTest_SpyStore::getLocalPath($file1),
57
			'File upload to standard directory in /assets'
58
		);
59
60
		// test upload into custom folder
61
		$customFolder = 'UploadTest-testUpload';
62
		$u2 = new Upload();
63
		$u2->loadIntoFile($tmpFile, null, $customFolder);
64
		$file2 = $u2->getFile();
65
		$this->assertEquals(
66
			'UploadTest-testUpload/UploadTest-testUpload.txt',
67
			$file2->getFilename()
68
		);
69
		$this->assertEquals(
70
			BASE_PATH . '/assets/UploadTest/.protected/UploadTest-testUpload/315ae4c3d4/UploadTest-testUpload.txt',
71
			AssetStoreTest_SpyStore::getLocalPath($file2)
72
		);
73
		$this->assertFileExists(
74
			AssetStoreTest_SpyStore::getLocalPath($file2),
75
			'File upload to custom directory in /assets'
76
		);
77
	}
78
79
	public function testAllowedFilesize() {
80
		// create tmp file
81
		$tmpFileName = 'UploadTest-testUpload.txt';
82
		$tmpFilePath = TEMP_FOLDER . '/' . $tmpFileName;
83
		$tmpFileContent = '';
84
		for($i=0; $i<10000; $i++) $tmpFileContent .= '0';
85
		file_put_contents($tmpFilePath, $tmpFileContent);
86
87
		// emulates the $_FILES array
88
		$tmpFile = array(
89
			'name' => $tmpFileName,
90
			'type' => 'text/plaintext',
91
			'size' => filesize($tmpFilePath),
92
			'tmp_name' => $tmpFilePath,
93
			'extension' => 'txt',
94
			'error' => UPLOAD_ERR_OK,
95
		);
96
97
		// test upload into default folder
98
		$u1 = new Upload();
99
		$v = new UploadTest_Validator();
100
101
		$v->setAllowedMaxFileSize(array('txt' => 10));
102
		$u1->setValidator($v);
103
		$result = $u1->loadIntoFile($tmpFile);
104
		$this->assertFalse($result, 'Load failed because size was too big');
105
106
		$v->setAllowedMaxFileSize(array('[document]' => 10));
107
		$u1->setValidator($v);
108
		$result = $u1->loadIntoFile($tmpFile);
109
		$this->assertFalse($result, 'Load failed because size was too big');
110
111
		$v->setAllowedMaxFileSize(array('txt' => 200000));
112
		$u1->setValidator($v);
113
		$result = $u1->loadIntoFile($tmpFile);
114
		$this->assertTrue($result, 'Load failed with setting max file size');
115
116
		// check max file size set by app category
117
		$tmpFileName = 'UploadTest-testUpload.jpg';
118
		$tmpFilePath = TEMP_FOLDER . '/' . $tmpFileName;
119
		file_put_contents($tmpFilePath, $tmpFileContent . $tmpFileContent);
120
121
		$tmpFile = array(
122
			'name' => $tmpFileName,
123
			'type' => 'image/jpeg',
124
			'size' => filesize($tmpFilePath),
125
			'tmp_name' => $tmpFilePath,
126
			'extension' => 'jpg',
127
			'error' => UPLOAD_ERR_OK,
128
		);
129
130
		$v->setAllowedMaxFileSize(array('[image]' => '40k'));
131
		$u1->setValidator($v);
132
		$result = $u1->loadIntoFile($tmpFile);
133
		$this->assertTrue($result, 'Load failed with setting max file size');
134
135
		$v->setAllowedMaxFileSize(array('[image]' => '1k'));
136
		$u1->setValidator($v);
137
		$result = $u1->loadIntoFile($tmpFile);
138
		$this->assertFalse($result, 'Load failed because size was too big');
139
140
		$v->setAllowedMaxFileSize(array('[image]' => 1000));
141
		$u1->setValidator($v);
142
		$result = $u1->loadIntoFile($tmpFile);
143
		$this->assertFalse($result, 'Load failed because size was too big');
144
	}
145
146
	public function testGetAllowedMaxFileSize() {
147
		Config::nest();
148
149
		// Check the max file size uses the config values
150
		$configMaxFileSizes = array(
151
			'[image]' => '1k',
152
			'txt' => 1000
153
		);
154
		Config::inst()->update('Upload_Validator', 'default_max_file_size', $configMaxFileSizes);
155
		$v = new UploadTest_Validator();
156
157
		$retrievedSize = $v->getAllowedMaxFileSize('[image]');
158
		$this->assertEquals(1024, $retrievedSize, 'Max file size check on default values failed (config category set check)');
159
160
		$retrievedSize = $v->getAllowedMaxFileSize('txt');
161
		$this->assertEquals(1000, $retrievedSize, 'Max file size check on default values failed (config extension set check)');
162
163
		// Check instance values for max file size
164
		$maxFileSizes = array(
165
			'[document]' => 2000,
166
			'txt' => '4k'
167
		);
168
		$v = new UploadTest_Validator();
169
		$v->setAllowedMaxFileSize($maxFileSizes);
170
171
		$retrievedSize = $v->getAllowedMaxFileSize('[document]');
172
		$this->assertEquals(2000, $retrievedSize, 'Max file size check on instance values failed (instance category set check)');
173
174
		// Check that the instance values overwrote the default values
175
		// ie. The max file size will not exist for [image]
176
		$retrievedSize = $v->getAllowedMaxFileSize('[image]');
177
		$this->assertFalse($retrievedSize, 'Max file size check on instance values failed (config overridden check)');
178
179
		// Check a category that has not been set before
180
		$retrievedSize = $v->getAllowedMaxFileSize('[archive]');
181
		$this->assertFalse($retrievedSize, 'Max file size check on instance values failed (category not set check)');
182
183
		// Check a file extension that has not been set before
184
		$retrievedSize = $v->getAllowedMaxFileSize('mp3');
185
		$this->assertFalse($retrievedSize, 'Max file size check on instance values failed (extension not set check)');
186
187
		$retrievedSize = $v->getAllowedMaxFileSize('txt');
188
		$this->assertEquals(4096, $retrievedSize, 'Max file size check on instance values failed (instance extension set check)');
189
190
		// Check a wildcard max file size against a file with an extension
191
		$v = new UploadTest_Validator();
192
		$v->setAllowedMaxFileSize(2000);
193
194
		$retrievedSize = $v->getAllowedMaxFileSize('.jpg');
195
		$this->assertEquals(2000, $retrievedSize, 'Max file size check on instance values failed (wildcard max file size)');
196
197
		Config::unnest();
198
	}
199
200
	public function testAllowedSizeOnFileWithNoExtension() {
201
		// create tmp file
202
		$tmpFileName = 'UploadTest-testUpload';
203
		$tmpFilePath = TEMP_FOLDER . '/' . $tmpFileName;
204
		$tmpFileContent = '';
205
		for($i=0; $i<10000; $i++) $tmpFileContent .= '0';
206
		file_put_contents($tmpFilePath, $tmpFileContent);
207
208
		// emulates the $_FILES array
209
		$tmpFile = array(
210
			'name' => $tmpFileName,
211
			'type' => 'text/plaintext',
212
			'size' => filesize($tmpFilePath),
213
			'tmp_name' => $tmpFilePath,
214
			'extension' => '',
215
			'error' => UPLOAD_ERR_OK,
216
		);
217
218
		$v = new UploadTest_Validator();
219
		$v->setAllowedMaxFileSize(array('' => 10));
220
221
		// test upload into default folder
222
		$u1 = new Upload();
223
		$u1->setValidator($v);
224
		$result = $u1->loadIntoFile($tmpFile);
225
226
		$this->assertFalse($result, 'Load failed because size was too big');
227
	}
228
229
	public function testUploadDoesNotAllowUnknownExtension() {
230
		// create tmp file
231
		$tmpFileName = 'UploadTest-testUpload.php';
232
		$tmpFilePath = TEMP_FOLDER . '/' . $tmpFileName;
233
		$tmpFileContent = '';
234
		for($i=0; $i<10000; $i++) $tmpFileContent .= '0';
235
		file_put_contents($tmpFilePath, $tmpFileContent);
236
237
		// emulates the $_FILES array
238
		$tmpFile = array(
239
			'name' => $tmpFileName,
240
			'type' => 'text/plaintext',
241
			'size' => filesize($tmpFilePath),
242
			'tmp_name' => $tmpFilePath,
243
			'extension' => 'php',
244
			'error' => UPLOAD_ERR_OK,
245
		);
246
247
		$v = new UploadTest_Validator();
248
		$v->setAllowedExtensions(array('txt'));
249
250
		// test upload into default folder
251
		$u = new Upload();
252
		$u->setValidator($v);
253
		$result = $u->loadIntoFile($tmpFile);
254
255
		$this->assertFalse($result, 'Load failed because extension was not accepted');
256
	}
257
258
	public function testUploadAcceptsAllowedExtension() {
259
		// create tmp file
260
		$tmpFileName = 'UploadTest-testUpload.txt';
261
		$tmpFilePath = TEMP_FOLDER . '/' . $tmpFileName;
262
		$tmpFileContent = '';
263
		for($i=0; $i<10000; $i++) $tmpFileContent .= '0';
264
		file_put_contents($tmpFilePath, $tmpFileContent);
265
266
		// emulates the $_FILES array
267
		$tmpFile = array(
268
			'name' => $tmpFileName,
269
			'type' => 'text/plaintext',
270
			'size' => filesize($tmpFilePath),
271
			'tmp_name' => $tmpFilePath,
272
			'extension' => 'txt',
273
			'error' => UPLOAD_ERR_OK,
274
		);
275
276
		$v = new UploadTest_Validator();
277
		$v->setAllowedExtensions(array('txt'));
278
279
		// test upload into default folder
280
		$u = new Upload();
281
		$u->setValidator($v);
282
		$u->loadIntoFile($tmpFile);
283
		$file = $u->getFile();
284
		$this->assertFileExists(
285
			AssetStoreTest_SpyStore::getLocalPath($file),
286
			'File upload to custom directory in /assets'
287
		);
288
	}
289
290
	public function testUploadDeniesNoExtensionFilesIfNoEmptyStringSetForValidatorExtensions() {
291
		// create tmp file
292
		$tmpFileName = 'UploadTest-testUpload';
293
		$tmpFilePath = TEMP_FOLDER . '/' . $tmpFileName;
294
		$tmpFileContent = '';
295
		for($i=0; $i<10000; $i++) $tmpFileContent .= '0';
296
		file_put_contents($tmpFilePath, $tmpFileContent);
297
298
		// emulates the $_FILES array
299
		$tmpFile = array(
300
			'name' => $tmpFileName,
301
			'type' => 'text/plaintext',
302
			'size' => filesize($tmpFilePath),
303
			'tmp_name' => $tmpFilePath,
304
			'extension' => '',
305
			'error' => UPLOAD_ERR_OK,
306
		);
307
308
		$v = new UploadTest_Validator();
309
		$v->setAllowedExtensions(array('txt'));
310
311
		// test upload into default folder
312
		$u = new Upload();
313
		$result = $u->loadIntoFile($tmpFile);
314
315
		$this->assertFalse($result, 'Load failed because extension was not accepted');
316
		$this->assertEquals(1, count($u->getErrors()), 'There is a single error of the file extension');
317
	}
318
319
	public function testUploadTarGzFileTwiceAppendsNumber() {
320
		// create tmp file
321
		$tmpFileName = 'UploadTest-testUpload.tar.gz';
322
		$tmpFilePath = TEMP_FOLDER . '/' . $tmpFileName;
323
		$tmpFileContent = '';
324
		for($i=0; $i<10000; $i++) $tmpFileContent .= '0';
325
		file_put_contents($tmpFilePath, $tmpFileContent);
326
327
		// emulates the $_FILES array
328
		$tmpFile = array(
329
			'name' => $tmpFileName,
330
			'type' => 'text/plaintext',
331
			'size' => filesize($tmpFilePath),
332
			'tmp_name' => $tmpFilePath,
333
			'extension' => 'tar.gz',
334
			'error' => UPLOAD_ERR_OK,
335
		);
336
337
		// test upload into default folder
338
		$u = new Upload();
339
		$u->loadIntoFile($tmpFile);
340
		$file = $u->getFile();
341
		$this->assertEquals(
342
			'UploadTest-testUpload.tar.gz',
343
			$file->Name,
0 ignored issues
show
Bug introduced by
Accessing Name on the interface SilverStripe\Filesystem\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...
344
			'File has a name without a number because it\'s not a duplicate'
345
		);
346
		$this->assertFileExists(
347
			AssetStoreTest_SpyStore::getLocalPath($file),
348
			'File exists'
349
		);
350
351
		$u = new Upload();
352
		$u->loadIntoFile($tmpFile);
353
		$file2 = $u->getFile();
354
		$this->assertEquals(
355
			'UploadTest-testUpload-v2.tar.gz',
356
			$file2->Name,
0 ignored issues
show
Bug introduced by
Accessing Name on the interface SilverStripe\Filesystem\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...
357
			'File receives a number attached to the end before the extension'
358
		);
359
		$this->assertFileExists(
360
			AssetStoreTest_SpyStore::getLocalPath($file2),
361
			'File exists'
362
		);
363
		$this->assertGreaterThan(
364
			$file->ID,
0 ignored issues
show
Bug introduced by
Accessing ID on the interface SilverStripe\Filesystem\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...
365
			$file2->ID,
0 ignored issues
show
Bug introduced by
Accessing ID on the interface SilverStripe\Filesystem\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...
366
			'File database record is not the same'
367
		);
368
369
		$u = new Upload();
370
		$u->loadIntoFile($tmpFile);
371
		$file3 = $u->getFile();
372
		$this->assertEquals(
373
			'UploadTest-testUpload-v3.tar.gz',
374
			$file3->Name,
0 ignored issues
show
Bug introduced by
Accessing Name on the interface SilverStripe\Filesystem\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...
375
			'File receives a number attached to the end before the extension'
376
		);
377
		$this->assertFileExists(
378
			AssetStoreTest_SpyStore::getLocalPath($file3),
379
			'File exists'
380
		);
381
		$this->assertGreaterThan(
382
			$file2->ID,
0 ignored issues
show
Bug introduced by
Accessing ID on the interface SilverStripe\Filesystem\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...
383
			$file3->ID,
0 ignored issues
show
Bug introduced by
Accessing ID on the interface SilverStripe\Filesystem\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...
384
			'File database record is not the same'
385
		);
386
	}
387
388
	public function testUploadFileWithNoExtensionTwiceAppendsNumber() {
389
		// create tmp file
390
		$tmpFileName = 'UploadTest-testUpload';
391
		$tmpFilePath = TEMP_FOLDER . '/' . $tmpFileName;
392
		$tmpFileContent = '';
393
		for($i=0; $i<10000; $i++) $tmpFileContent .= '0';
394
		file_put_contents($tmpFilePath, $tmpFileContent);
395
396
		// emulates the $_FILES array
397
		$tmpFile = array(
398
			'name' => $tmpFileName,
399
			'type' => 'text/plaintext',
400
			'size' => filesize($tmpFilePath),
401
			'tmp_name' => $tmpFilePath,
402
			'extension' => 'txt',
403
			'error' => UPLOAD_ERR_OK,
404
		);
405
406
		$v = new UploadTest_Validator();
407
		$v->setAllowedExtensions(array(''));
408
409
		// test upload into default folder
410
		$u = new Upload();
411
		$u->setValidator($v);
412
		$u->loadIntoFile($tmpFile);
413
		$file = $u->getFile();
414
415
		$this->assertEquals(
416
			'UploadTest-testUpload',
417
			$file->Name,
0 ignored issues
show
Bug introduced by
Accessing Name on the interface SilverStripe\Filesystem\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...
418
			'File is uploaded without extension'
419
		);
420
		$this->assertFileExists(
421
			AssetStoreTest_SpyStore::getLocalPath($file),
422
			'File exists'
423
		);
424
425
		$u = new Upload();
426
		$u->setValidator($v);
427
		$u->loadIntoFile($tmpFile);
428
		$file2 = $u->getFile();
429
		$this->assertEquals(
430
			'UploadTest-testUpload-v2',
431
			$file2->Name,
0 ignored issues
show
Bug introduced by
Accessing Name on the interface SilverStripe\Filesystem\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...
432
			'File receives a number attached to the end'
433
		);
434
		$this->assertFileExists(
435
			AssetStoreTest_SpyStore::getLocalPath($file2),
436
			'File exists'
437
		);
438
		$this->assertGreaterThan(
439
			$file->ID,
0 ignored issues
show
Bug introduced by
Accessing ID on the interface SilverStripe\Filesystem\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...
440
			$file2->ID,
0 ignored issues
show
Bug introduced by
Accessing ID on the interface SilverStripe\Filesystem\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...
441
			'File database record is not the same'
442
		);
443
	}
444
445
	public function testReplaceFile() {
446
		// create tmp file
447
		$tmpFileName = 'UploadTest-testUpload';
448
		$tmpFilePath = TEMP_FOLDER . '/' . $tmpFileName;
449
		$tmpFileContent = '';
450
		for($i=0; $i<10000; $i++) $tmpFileContent .= '0';
451
		file_put_contents($tmpFilePath, $tmpFileContent);
452
453
		// emulates the $_FILES array
454
		$tmpFile = array(
455
			'name' => $tmpFileName,
456
			'type' => 'text/plaintext',
457
			'size' => filesize($tmpFilePath),
458
			'tmp_name' => $tmpFilePath,
459
			'extension' => 'txt',
460
			'error' => UPLOAD_ERR_OK,
461
		);
462
463
		$v = new UploadTest_Validator();
464
		$v->setAllowedExtensions(array(''));
465
466
		// test upload into default folder
467
		$u = new Upload();
468
		$u->setValidator($v);
469
		$u->loadIntoFile($tmpFile);
470
		$file = $u->getFile();
471
472
		$this->assertEquals(
473
			'UploadTest-testUpload',
474
			$file->Name,
0 ignored issues
show
Bug introduced by
Accessing Name on the interface SilverStripe\Filesystem\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...
475
			'File is uploaded without extension'
476
		);
477
		$this->assertFileExists(
478
			AssetStoreTest_SpyStore::getLocalPath($file),
479
			'File exists'
480
		);
481
482
		$u = new Upload();
483
		$u->setValidator($v);
484
		$u->setReplaceFile(true);
485
		$u->loadIntoFile($tmpFile);
486
		$file2 = $u->getFile();
487
		$this->assertEquals(
488
			'UploadTest-testUpload',
489
			$file2->Name,
0 ignored issues
show
Bug introduced by
Accessing Name on the interface SilverStripe\Filesystem\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...
490
			'File does not receive new name'
491
		);
492
		$this->assertFileExists(
493
			AssetStoreTest_SpyStore::getLocalPath($file2),
494
			'File exists'
495
		);
496
		$this->assertEquals(
497
			$file->ID,
0 ignored issues
show
Bug introduced by
Accessing ID on the interface SilverStripe\Filesystem\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...
498
			$file2->ID,
0 ignored issues
show
Bug introduced by
Accessing ID on the interface SilverStripe\Filesystem\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...
499
			'File database record is the same'
500
		);
501
	}
502
503
	public function testReplaceFileWithLoadIntoFile() {
504
		// create tmp file
505
		$tmpFileName = 'UploadTest-testUpload.txt';
506
		$tmpFilePath = TEMP_FOLDER . '/' . $tmpFileName;
507
		$tmpFileContent = '';
508
		for ($i = 0; $i < 10000; $i++)
509
			$tmpFileContent .= '0';
510
		file_put_contents($tmpFilePath, $tmpFileContent);
511
512
		// emulates the $_FILES array
513
		$tmpFile = array(
514
			'name' => $tmpFileName,
515
			'type' => 'text/plaintext',
516
			'size' => filesize($tmpFilePath),
517
			'tmp_name' => $tmpFilePath,
518
			'extension' => 'txt',
519
			'error' => UPLOAD_ERR_OK,
520
		);
521
522
		$v = new UploadTest_Validator();
523
524
		// test upload into default folder
525
		$u = new Upload();
526
		$u->setValidator($v);
527
		$u->loadIntoFile($tmpFile);
528
		$file = $u->getFile();
529
530
		$this->assertEquals(
531
			'UploadTest-testUpload.txt',
532
			$file->Name,
0 ignored issues
show
Bug introduced by
Accessing Name on the interface SilverStripe\Filesystem\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...
533
			'File is uploaded without extension'
534
		);
535
		$this->assertFileExists(
536
			AssetStoreTest_SpyStore::getLocalPath($file),
537
			'File exists'
538
		);
539
540
		// replace=true
541
		$u = new Upload();
542
		$u->setValidator($v);
543
		$u->setReplaceFile(true);
544
		$u->loadIntoFile($tmpFile, new File());
545
		$file2 = $u->getFile();
546
		$this->assertEquals(
547
			'UploadTest-testUpload.txt',
548
			$file2->Name,
0 ignored issues
show
Bug introduced by
Accessing Name on the interface SilverStripe\Filesystem\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...
549
			'File does not receive new name'
550
		);
551
		$this->assertFileExists(
552
			AssetStoreTest_SpyStore::getLocalPath($file2),
553
			'File exists'
554
		);
555
		$this->assertEquals(
556
			$file->ID,
0 ignored issues
show
Bug introduced by
Accessing ID on the interface SilverStripe\Filesystem\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...
557
			$file2->ID,
0 ignored issues
show
Bug introduced by
Accessing ID on the interface SilverStripe\Filesystem\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...
558
			'File database record is the same'
559
		);
560
561
		// replace=false
562
		$u = new Upload();
563
		$u->setValidator($v);
564
		$u->setReplaceFile(false);
565
		$u->loadIntoFile($tmpFile, new File());
566
		$file3 = $u->getFile();
567
		$this->assertEquals(
568
			'UploadTest-testUpload-v2.txt',
569
			$file3->Name,
0 ignored issues
show
Bug introduced by
Accessing Name on the interface SilverStripe\Filesystem\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...
570
			'File does receive new name'
571
		);
572
		$this->assertFileExists(
573
			AssetStoreTest_SpyStore::getLocalPath($file3),
574
			'File exists'
575
		);
576
		$this->assertGreaterThan(
577
			$file2->ID,
0 ignored issues
show
Bug introduced by
Accessing ID on the interface SilverStripe\Filesystem\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...
578
			$file3->ID,
0 ignored issues
show
Bug introduced by
Accessing ID on the interface SilverStripe\Filesystem\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...
579
			'File database record is not the same'
580
		);
581
	}
582
583
	public function testDeleteResampledImagesOnUpload() {
584
		$tmpFileName = 'UploadTest-testUpload.jpg';
585
		$tmpFilePath = TEMP_FOLDER . '/' . $tmpFileName;
586
587
		$uploadImage = function() use ($tmpFileName, $tmpFilePath) {
588
			copy(__DIR__ . '/gdtest/test_jpg.jpg', $tmpFilePath);
589
590
			// emulates the $_FILES array
591
			$tmpFile = array(
592
				'name' => $tmpFileName,
593
				'type' => 'text/plaintext',
594
				'size' => filesize($tmpFilePath),
595
				'tmp_name' => $tmpFilePath,
596
				'extension' => 'jpg',
597
				'error' => UPLOAD_ERR_OK,
598
			);
599
600
			$v = new UploadTest_Validator();
601
602
			// test upload into default folder
603
			$u = new Upload();
604
			$u->setReplaceFile(true);
605
			$u->setValidator($v);
606
			$u->loadIntoFile($tmpFile);
607
			return $u->getFile();
608
		};
609
610
		// Image upload and generate a resampled image
611
		$image = $uploadImage();
612
		$resampled = $image->ResizedImage(123, 456);
613
		$resampledPath = AssetStoreTest_SpyStore::getLocalPath($resampled);
614
		$this->assertFileExists($resampledPath);
615
616
		// Re-upload the image, overwriting the original
617
		// Resampled images should removed when their parent file is overwritten
618
		$image = $uploadImage();
619
		$this->assertFileExists($resampledPath);
620
	}
621
622
	public function testFileVersioningWithAnExistingFile() {
623
		$upload = function($tmpFileName) {
624
			// create tmp file
625
			$tmpFilePath = TEMP_FOLDER . '/' . $tmpFileName;
626
			$tmpFileContent = '';
627
			for ($i = 0; $i < 10000; $i++) {
628
				$tmpFileContent .= '0';
629
			}
630
			file_put_contents($tmpFilePath, $tmpFileContent);
631
632
			// emulates the $_FILES array
633
			$tmpFile = array(
634
				'name' => $tmpFileName,
635
				'type' => 'text/plaintext',
636
				'size' => filesize($tmpFilePath),
637
				'tmp_name' => $tmpFilePath,
638
				'extension' => 'jpg',
639
				'error' => UPLOAD_ERR_OK,
640
			);
641
642
			$v = new UploadTest_Validator();
643
644
			// test upload into default folder
645
			$u = new Upload();
646
			$u->setReplaceFile(false);
647
			$u->setValidator($v);
648
			$u->loadIntoFile($tmpFile);
649
			return $u->getFile();
650
		};
651
652
		// test empty file version prefix
653
		Config::inst()->update('SilverStripe\Filesystem\Storage\DefaultAssetNameGenerator', 'version_prefix', '');
654
655
		$file1 = $upload('UploadTest-IMG001.jpg');
656
		$this->assertEquals(
657
			'UploadTest-IMG001.jpg',
658
			$file1->Name,
659
			'File does not receive new name'
660
		);
661
662
		$file2 = $upload('UploadTest-IMG001.jpg');
663
		$this->assertEquals(
664
			'UploadTest-IMG002.jpg',
665
			$file2->Name,
666
			'File does receive new name'
667
		);
668
669
		$file3 = $upload('UploadTest-IMG002.jpg');
670
		$this->assertEquals(
671
			'UploadTest-IMG003.jpg',
672
			$file3->Name,
673
			'File does receive new name'
674
		);
675
676
		$file4 = $upload('UploadTest-IMG3.jpg');
677
		$this->assertEquals(
678
			'UploadTest-IMG3.jpg',
679
			$file4->Name,
680
			'File does not receive new name'
681
		);
682
683
		$file1->delete();
684
		$file2->delete();
685
		$file3->delete();
686
		$file4->delete();
687
688
		// test '-v' file version prefix
689
		Config::inst()->update('SilverStripe\Filesystem\Storage\DefaultAssetNameGenerator', 'version_prefix', '-v');
690
691
		$file1 = $upload('UploadTest2-IMG001.jpg');
692
		$this->assertEquals(
693
			'UploadTest2-IMG001.jpg',
694
			$file1->Name,
695
			'File does not receive new name'
696
		);
697
698
		$file2 = $upload('UploadTest2-IMG001.jpg');
699
		$this->assertEquals(
700
			'UploadTest2-IMG001-v2.jpg',
701
			$file2->Name,
702
			'File does receive new name'
703
		);
704
705
		$file3 = $upload('UploadTest2-IMG001.jpg');
706
		$this->assertEquals(
707
			'UploadTest2-IMG001-v3.jpg',
708
			$file3->Name,
709
			'File does receive new name'
710
		);
711
712
		$file4 = $upload('UploadTest2-IMG001-v3.jpg');
713
		$this->assertEquals(
714
			'UploadTest2-IMG001-v4.jpg',
715
			$file4->Name,
716
			'File does receive new name'
717
		);
718
	}
719
}
720
721
class UploadTest_Validator extends Upload_Validator implements TestOnly {
722
723
	/**
724
	 * Looser check validation that doesn't do is_upload_file()
725
	 * checks as we're faking a POST request that PHP didn't generate
726
	 * itself.
727
	 *
728
	 * @return boolean
729
	 */
730
	public function validate() {
731
		$pathInfo = pathinfo($this->tmpFile['name']);
732
		// filesize validation
733
734
		if(!$this->isValidSize()) {
735
			$ext = (isset($pathInfo['extension'])) ? $pathInfo['extension'] : '';
736
			$arg = File::format_size($this->getAllowedMaxFileSize($ext));
737
			$this->errors[] = _t(
738
				'File.TOOLARGE',
739
				'File size is too large, maximum {size} allowed',
740
				'Argument 1: File size (e.g. 1MB)',
741
				array('size' => $arg)
742
			);
743
			return false;
744
		}
745
746
		// extension validation
747
		if(!$this->isValidExtension()) {
748
			$this->errors[] = _t(
749
				'File.INVALIDEXTENSION',
750
				'Extension is not allowed (valid: {extensions})',
751
				'Argument 1: Comma-separated list of valid extensions',
752
				array('extensions' => implode(',', $this->allowedExtensions))
753
			);
754
			return false;
755
		}
756
757
		return true;
758
	}
759
760
}
761