Completed
Push — namespace-model ( c67c40...018a87 )
by Sam
07:37
created

FileTest::testSizeAndAbsoluteSizeParameters()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %
Metric Value
dl 0
loc 8
rs 9.4285
cc 1
eloc 4
nc 1
nop 0
1
<?php
2
3
use Filesystem as SS_Filesystem;
4
use SilverStripe\Filesystem\Storage\AssetStore;
5
use SilverStripe\Model\DataObject;
6
7
8
/**
9
 * Tests for the File class
10
 */
11
class FileTest extends SapphireTest {
12
13
	protected static $fixture_file = 'FileTest.yml';
14
15
	protected $extraDataObjects = array('FileTest_MyCustomFile');
16
17
	public function setUp() {
18
		parent::setUp();
19
		$this->logInWithPermission('ADMIN');
20
		Versioned::set_stage(Versioned::DRAFT);
21
22
		// Set backend root to /ImageTest
23
		AssetStoreTest_SpyStore::activate('FileTest');
24
25
		// Create a test folders for each of the fixture references
26
		$folderIDs = $this->allFixtureIDs('Folder');
27
		foreach($folderIDs as $folderID) {
0 ignored issues
show
Bug introduced by
The expression $folderIDs of type object<A> is not traversable.
Loading history...
28
			$folder = DataObject::get_by_id('Folder', $folderID);
29
			$filePath = ASSETS_PATH . '/FileTest/' . $folder->getFilename();
30
			SS_Filesystem::makeFolder($filePath);
31
		}
32
33
		// Create a test files for each of the fixture references
34
		$fileIDs = $this->allFixtureIDs('File');
35
		foreach($fileIDs as $fileID) {
0 ignored issues
show
Bug introduced by
The expression $fileIDs of type object<A> is not traversable.
Loading history...
36
			$file = DataObject::get_by_id('File', $fileID);
37
			$root = ASSETS_PATH . '/FileTest/';
38
			if($folder = $file->Parent()) {
0 ignored issues
show
Bug introduced by
The method Parent() does not exist on SilverStripe\Model\DataObject. Did you maybe mean parentClass()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
39
				$root .= $folder->getFilename();
40
			}
41
			$path = $root . substr($file->getHash(), 0, 10) . '/' . basename($file->getFilename());
42
			SS_Filesystem::makeFolder(dirname($path));
43
			$fh = fopen($path, "w+");
44
			fwrite($fh, str_repeat('x', 1000000));
45
			fclose($fh);
46
		}
47
48
		// Conditional fixture creation in case the 'cms' module is installed
49
		if(class_exists('ErrorPage')) {
50
			$page = new ErrorPage(array(
51
				'Title' => 'Page not Found',
52
				'ErrorCode' => 404
53
			));
54
			$page->write();
55
			$page->copyVersionToStage('Stage', 'Live');
56
		}
57
	}
58
59
	public function tearDown() {
60
		AssetStoreTest_SpyStore::reset();
61
		parent::tearDown();
62
	}
63
64
	public function testLinkShortcodeHandler() {
65
		$testFile = $this->objFromFixture('File', 'asdf');
66
67
		$parser = new ShortcodeParser();
68
		$parser->register('file_link', array('File', 'handle_shortcode'));
69
70
		$fileShortcode = sprintf('[file_link,id=%d]', $testFile->ID);
71
		$fileEnclosed  = sprintf('[file_link,id=%d]Example Content[/file_link]', $testFile->ID);
72
73
		$fileShortcodeExpected = $testFile->Link();
74
		$fileEnclosedExpected  = sprintf(
75
			'<a href="%s" class="file" data-type="txt" data-size="977 KB">Example Content</a>', $testFile->Link());
76
77
		$this->assertEquals($fileShortcodeExpected, $parser->parse($fileShortcode), 'Test that simple linking works.');
78
		$this->assertEquals($fileEnclosedExpected, $parser->parse($fileEnclosed), 'Test enclosed content is linked.');
79
80
		$testFile->delete();
81
82
		$fileShortcode = '[file_link,id="-1"]';
83
		$fileEnclosed  = '[file_link,id="-1"]Example Content[/file_link]';
84
85
		$this->assertEquals('', $parser->parse('[file_link]'), 'Test that invalid ID attributes are not parsed.');
86
		$this->assertEquals('', $parser->parse('[file_link,id="text"]'));
87
		$this->assertEquals('', $parser->parse('[file_link]Example Content[/file_link]'));
88
89
		if(class_exists('ErrorPage')) {
90
			$errorPage = ErrorPage::get()->filter('ErrorCode', 404)->First();
91
			$this->assertEquals(
92
				$errorPage->Link(),
93
				$parser->parse($fileShortcode),
94
				'Test link to 404 page if no suitable matches.'
95
			);
96
			$this->assertEquals(
97
				sprintf('<a href="%s">Example Content</a>', $errorPage->Link()),
98
				$parser->parse($fileEnclosed)
99
			);
100
		} else {
101
			$this->assertEquals('', $parser->parse($fileShortcode),
102
				'Short code is removed if file record is not present.');
103
			$this->assertEquals('', $parser->parse($fileEnclosed));
104
		}
105
	}
106
107
	public function testCreateWithFilenameWithSubfolder() {
108
		// Note: We can't use fixtures/setUp() for this, as we want to create the db record manually.
109
		// Creating the folder is necessary to avoid having "Filename" overwritten by setName()/setRelativePath(),
110
		// because the parent folders don't exist in the database
111
		$folder = Folder::find_or_make('/FileTest/');
112
		$testfilePath = BASE_PATH . '/assets/FileTest/CreateWithFilenameHasCorrectPath.txt'; // Important: No leading slash
113
		$fh = fopen($testfilePath, "w");
114
		fwrite($fh, str_repeat('x',1000000));
115
		fclose($fh);
116
117
		$file = new File();
118
		$file->setFromLocalFile($testfilePath);
119
		$file->ParentID = $folder->ID;
120
		$file->write();
121
122
		$this->assertEquals(
123
			'CreateWithFilenameHasCorrectPath.txt',
124
			$file->Name,
125
			'"Name" property is automatically set from "Filename"'
126
		);
127
		$this->assertEquals(
128
			'FileTest/CreateWithFilenameHasCorrectPath.txt',
129
			$file->Filename,
130
			'"Filename" property remains unchanged'
131
		);
132
133
		// TODO This should be auto-detected, see File->updateFilesystem()
134
		// $this->assertInstanceOf('Folder', $file->Parent(), 'Parent folder is created in database');
135
		// $this->assertFileExists($file->Parent()->getURL(), 'Parent folder is created on filesystem');
136
		// $this->assertEquals('FileTest', $file->Parent()->Name);
137
		// $this->assertInstanceOf('Folder', $file->Parent()->Parent(), 'Grandparent folder is created in database');
138
		// $this->assertFileExists($file->Parent()->Parent()->getURL(),
139
		// 'Grandparent folder is created on filesystem');
140
		// $this->assertEquals('assets', $file->Parent()->Parent()->Name);
141
	}
142
143
	public function testGetExtension() {
144
		$this->assertEquals('', File::get_file_extension('myfile'),
145
			'No extension');
146
		$this->assertEquals('txt', File::get_file_extension('myfile.txt'),
147
			'Simple extension');
148
		$this->assertEquals('gz', File::get_file_extension('myfile.tar.gz'),
149
			'Double-barrelled extension only returns last bit');
150
	}
151
152
	public function testValidateExtension() {
153
		Session::set('loggedInAs', null);
154
155
		$orig = Config::inst()->get('File', 'allowed_extensions');
156
		Config::inst()->remove('File', 'allowed_extensions');
157
		Config::inst()->update('File', 'allowed_extensions', array('txt'));
158
159
		$file = $this->objFromFixture('File', 'asdf');
160
161
		// Invalid ext
162
		$file->Name = 'asdf.php';
0 ignored issues
show
Documentation introduced by
The property Name does not exist on object<SilverStripe\Model\DataObject>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
163
		$v = $file->validate();
164
		$this->assertFalse($v->valid());
165
		$this->assertContains('Extension is not allowed', $v->message());
166
167
		// Valid ext
168
		$file->Name = 'asdf.txt';
0 ignored issues
show
Documentation introduced by
The property Name does not exist on object<SilverStripe\Model\DataObject>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
169
		$v = $file->validate();
170
		$this->assertTrue($v->valid());
171
172
		// Capital extension is valid as well
173
		$file->Name = 'asdf.TXT';
0 ignored issues
show
Documentation introduced by
The property Name does not exist on object<SilverStripe\Model\DataObject>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
174
		$v = $file->validate();
175
		$this->assertTrue($v->valid());
176
177
		Config::inst()->remove('File', 'allowed_extensions');
178
		Config::inst()->update('File', 'allowed_extensions', $orig);
179
	}
180
181
	public function testAppCategory() {
182
		// Test various categories
183
		$this->assertEquals('image', File::get_app_category('jpg'));
184
		$this->assertEquals('image', File::get_app_category('JPG'));
185
		$this->assertEquals('image', File::get_app_category('JPEG'));
186
		$this->assertEquals('image', File::get_app_category('png'));
187
		$this->assertEquals('image', File::get_app_category('tif'));
188
		$this->assertEquals('document', File::get_app_category('pdf'));
189
		$this->assertEquals('video', File::get_app_category('mov'));
190
		$this->assertEquals('audio', File::get_app_category('OGG'));
191
	}
192
193
	public function testGetCategoryExtensions() {
194
		// Test specific categories
195
		$images = array(
196
			'alpha', 'als', 'bmp', 'cel', 'gif', 'ico', 'icon', 'jpeg', 'jpg', 'pcx', 'png', 'ps', 'tif', 'tiff'
197
		);
198
		$this->assertEquals($images, File::get_category_extensions('image'));
199
		$this->assertEquals(array('gif', 'jpeg', 'jpg', 'png'), File::get_category_extensions('image/supported'));
200
		$this->assertEquals($images, File::get_category_extensions(array('image', 'image/supported')));
201
		$this->assertEquals(
202
			array('fla', 'gif', 'jpeg', 'jpg', 'png', 'swf'),
203
			File::get_category_extensions(array('flash', 'image/supported'))
204
		);
205
206
		// Test other categories have at least one item
207
		$this->assertNotEmpty(File::get_category_extensions('archive'));
208
		$this->assertNotEmpty(File::get_category_extensions('audio'));
209
		$this->assertNotEmpty(File::get_category_extensions('document'));
210
		$this->assertNotEmpty(File::get_category_extensions('flash'));
211
		$this->assertNotEmpty(File::get_category_extensions('video'));
212
	}
213
214
	/**
215
	 * @dataProvider allowedExtensions
216
	 * @param string $extension
217
	 */
218
	public function testAllFilesHaveCategory($extension) {
219
		$this->assertNotEmpty(
220
			File::get_app_category($extension),
221
			"Assert that extension {$extension} has a valid category"
222
		);
223
	}
224
225
	/**
226
	 * Gets the list of all extensions for testing
227
	 *
228
	 * @return array
229
	 */
230
	public function allowedExtensions() {
231
		$args = array();
232
		foreach(array_filter(File::config()->allowed_extensions) as $ext) {
233
			$args[] = array($ext);
234
		}
235
		return $args;
236
	}
237
238
	public function testSetNameChangesFilesystemOnWrite() {
239
		/** @var File $file */
240
		$file = $this->objFromFixture('File', 'asdf');
241
		$this->logInWithPermission('ADMIN');
242
		$file->publishRecursive();
243
		$oldTuple = $file->File->getValue();
244
245
		// Rename
246
		$file->Name = 'renamed.txt';
247
		$newTuple = $oldTuple;
248
		$newTuple['Filename'] = $file->generateFilename();
249
250
		// Before write()
251
		$this->assertTrue(
252
			$this->getAssetStore()->exists($oldTuple['Filename'], $oldTuple['Hash']),
253
			'Old path is still present'
254
		);
255
		$this->assertFalse(
256
			$this->getAssetStore()->exists($newTuple['Filename'], $newTuple['Hash']),
257
			'New path is updated in memory, not written before write() is called'
258
		);
259
260
		// After write()
261
		$file->write();
262
		$this->assertTrue(
263
			$this->getAssetStore()->exists($oldTuple['Filename'], $oldTuple['Hash']),
264
			'Old path exists after draft change'
265
		);
266
		$this->assertTrue(
267
			$this->getAssetStore()->exists($newTuple['Filename'], $newTuple['Hash']),
268
			'New path is created after write()'
269
		);
270
271
		// After publish
272
		$file->publishRecursive();
273
		$this->assertFalse(
274
			$this->getAssetStore()->exists($oldTuple['Filename'], $oldTuple['Hash']),
275
			'Old file is finally removed after publishing new file'
276
		);
277
		$this->assertTrue(
278
			$this->getAssetStore()->exists($newTuple['Filename'], $newTuple['Hash']),
279
			'New path is created after write()'
280
		);
281
	}
282
283
	public function testSetParentIDChangesFilesystemOnWrite() {
284
		$file = $this->objFromFixture('File', 'asdf');
285
		$this->logInWithPermission('ADMIN');
286
		$file->publishRecursive();
287
		$subfolder = $this->objFromFixture('Folder', 'subfolder');
288
		$oldTuple = $file->File->getValue();
289
290
		// set ParentID
291
		$file->ParentID = $subfolder->ID;
0 ignored issues
show
Documentation introduced by
The property ParentID does not exist on object<SilverStripe\Model\DataObject>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
292
		$newTuple = $oldTuple;
293
		$newTuple['Filename'] = $file->generateFilename();
294
295
		// Before write()
296
		$this->assertTrue(
297
			$this->getAssetStore()->exists($oldTuple['Filename'], $oldTuple['Hash']),
298
			'Old path is still present'
299
		);
300
		$this->assertFalse(
301
			$this->getAssetStore()->exists($newTuple['Filename'], $newTuple['Hash']),
302
			'New path is updated in memory, not written before write() is called'
303
		);
304
		$file->write();
305
306
		// After write()
307
		$file->write();
308
		$this->assertTrue(
309
			$this->getAssetStore()->exists($oldTuple['Filename'], $oldTuple['Hash']),
310
			'Old path exists after draft change'
311
		);
312
		$this->assertTrue(
313
			$this->getAssetStore()->exists($newTuple['Filename'], $newTuple['Hash']),
314
			'New path is created after write()'
315
		);
316
317
		// After publish
318
		$file->publishSingle();
319
		$this->assertFalse(
320
			$this->getAssetStore()->exists($oldTuple['Filename'], $oldTuple['Hash']),
321
			'Old file is finally removed after publishing new file'
322
		);
323
		$this->assertTrue(
324
			$this->getAssetStore()->exists($newTuple['Filename'], $newTuple['Hash']),
325
			'New path is created after write()'
326
		);
327
	}
328
329
	/**
330
	 * @see http://open.silverstripe.org/ticket/5693
331
	 *
332
	 * @expectedException ValidationException
333
	 */
334
	public function testSetNameWithInvalidExtensionDoesntChangeFilesystem() {
335
		$orig = Config::inst()->get('File', 'allowed_extensions');
336
		Config::inst()->remove('File', 'allowed_extensions');
337
		Config::inst()->update('File', 'allowed_extensions', array('txt'));
338
339
		$file = $this->objFromFixture('File', 'asdf');
340
		$oldPath = $file->getURL();
0 ignored issues
show
Unused Code introduced by
$oldPath is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
341
342
		$file->Name = 'renamed.php'; // evil extension
0 ignored issues
show
Documentation introduced by
The property Name does not exist on object<SilverStripe\Model\DataObject>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
343
		try {
344
			$file->write();
345
		} catch(ValidationException $e) {
346
			Config::inst()->remove('File', 'allowed_extensions');
347
			Config::inst()->update('File', 'allowed_extensions', $orig);
348
			throw $e;
349
		}
350
	}
351
352
	public function testGetURL() {
353
		$rootfile = $this->objFromFixture('File', 'asdf');
354
		$this->assertEquals('/assets/FileTest/55b443b601/FileTest.txt', $rootfile->getURL());
355
	}
356
357
	public function testGetAbsoluteURL() {
358
		$rootfile = $this->objFromFixture('File', 'asdf');
359
		$this->assertEquals(
360
			Director::absoluteBaseURL() . 'assets/FileTest/55b443b601/FileTest.txt',
361
			$rootfile->getAbsoluteURL()
362
		);
363
	}
364
365
	public function testNameAndTitleGeneration() {
366
		// When name is assigned, title is automatically assigned
367
		$file = $this->objFromFixture('Image', 'setfromname');
368
		$this->assertEquals('FileTest', $file->Title);
369
	}
370
371
	public function testSizeAndAbsoluteSizeParameters() {
372
		$file = $this->objFromFixture('File', 'asdf');
373
374
		/* AbsoluteSize will give the integer number */
375
		$this->assertEquals(1000000, $file->AbsoluteSize);
376
		/* Size will give a humanised number */
377
		$this->assertEquals('977 KB', $file->Size);
378
	}
379
380
	public function testFileType() {
381
		$file = $this->objFromFixture('Image', 'gif');
382
		$this->assertEquals("GIF image - good for diagrams", $file->FileType);
383
384
		$file = $this->objFromFixture('File', 'pdf');
385
		$this->assertEquals("Adobe Acrobat PDF file", $file->FileType);
386
387
		$file = $this->objFromFixture('Image', 'gifupper');
388
		$this->assertEquals("GIF image - good for diagrams", $file->FileType);
389
390
		/* Only a few file types are given special descriptions; the rest are unknown */
391
		$file = $this->objFromFixture('File', 'asdf');
392
		$this->assertEquals("unknown", $file->FileType);
393
	}
394
395
	/**
396
	 * Test the File::format_size() method
397
	 */
398
	public function testFormatSize() {
399
		$this->assertEquals("1000 bytes", File::format_size(1000));
400
		$this->assertEquals("1023 bytes", File::format_size(1023));
401
		$this->assertEquals("1 KB", File::format_size(1025));
402
		$this->assertEquals("9.8 KB", File::format_size(10000));
403
		$this->assertEquals("49 KB", File::format_size(50000));
404
		$this->assertEquals("977 KB", File::format_size(1000000));
405
		$this->assertEquals("1 MB", File::format_size(1024*1024));
406
		$this->assertEquals("954 MB", File::format_size(1000000000));
407
		$this->assertEquals("1 GB", File::format_size(1024*1024*1024));
408
		$this->assertEquals("9.3 GB", File::format_size(10000000000));
409
		// It use any denomination higher than GB.  It also doesn't overflow with >32 bit integers
410
		$this->assertEquals("93132.3 GB", File::format_size(100000000000000));
411
	}
412
413
	public function testDeleteFile() {
414
		/** @var File $file */
415
		$file = $this->objFromFixture('File', 'asdf');
416
		$this->logInWithPermission('ADMIN');
417
		$file->publishSingle();
418
		$tuple = $file->File->getValue();
419
420
		// Before delete
421
		$this->assertTrue(
422
			$this->getAssetStore()->exists($tuple['Filename'], $tuple['Hash']),
423
			'File is still present'
424
		);
425
426
		// after unpublish
427
		$file->doUnpublish();
428
		$this->assertTrue(
429
			$this->getAssetStore()->exists($tuple['Filename'], $tuple['Hash']),
430
			'File is still present after unpublish'
431
		);
432
433
		// after delete
434
		$file->delete();
435
		$this->assertFalse(
436
			$this->getAssetStore()->exists($tuple['Filename'], $tuple['Hash']),
437
			'File is deleted after unpublish and delete'
438
		);
439
	}
440
441
	public function testRenameFolder() {
442
		$newTitle = "FileTest-folder-renamed";
443
444
		//rename a folder's title
445
		$folderID = $this->objFromFixture("Folder","folder2")->ID;
446
		$folder = DataObject::get_by_id('Folder',$folderID);
447
		$folder->Title = $newTitle;
0 ignored issues
show
Documentation introduced by
The property Title does not exist on object<SilverStripe\Model\DataObject>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
448
		$folder->write();
449
450
		//get folder again and see if the filename has changed
451
		$folder = DataObject::get_by_id('Folder',$folderID);
452
		$this->assertEquals(
453
			$newTitle . "/",
454
			$folder->Filename,
455
			"Folder Filename updated after rename of Title"
456
		);
457
458
		//rename a folder's name
459
		$newTitle2 = "FileTest-folder-renamed2";
460
		$folder->Name = $newTitle2;
0 ignored issues
show
Documentation introduced by
The property Name does not exist on object<SilverStripe\Model\DataObject>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
461
		$folder->write();
462
463
		//get folder again and see if the Title has changed
464
		$folder = DataObject::get_by_id('Folder',$folderID);
465
		$this->assertEquals($folder->Title, $newTitle2,
466
			"Folder Title updated after rename of Name");
467
468
469
		//rename a folder's Filename
470
		$newTitle3 = "FileTest-folder-renamed3";
471
		$folder->Filename = $newTitle3;
0 ignored issues
show
Documentation introduced by
The property Filename does not exist on object<SilverStripe\Model\DataObject>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
472
		$folder->write();
473
474
		//get folder again and see if the Title has changed
475
		$folder = DataObject::get_by_id('Folder',$folderID);
476
		$this->assertEquals($folder->Title, $newTitle3,
477
			"Folder Title updated after rename of Filename");
478
	}
479
480
	public function testSetsOwnerOnFirstWrite() {
481
		Session::set('loggedInAs', null);
482
		$member1 = new Member();
483
		$member1->write();
484
		$member2 = new Member();
485
		$member2->write();
486
487
		$file1 = new File();
488
		$file1->write();
489
		$this->assertEquals(0, $file1->OwnerID, 'Owner not written when no user is logged in');
490
491
		$member1->logIn();
492
		$file2 = new File();
493
		$file2->write();
494
		$this->assertEquals($member1->ID, $file2->OwnerID, 'Owner written when user is logged in');
495
496
		$member2->logIn();
497
		$file2->forceChange();
498
		$file2->write();
499
		$this->assertEquals($member1->ID, $file2->OwnerID, 'Owner not overwritten on existing files');
500
	}
501
502
	public function testCanEdit() {
503
		$file = $this->objFromFixture('Image', 'gif');
504
505
		// Test anonymous permissions
506
		Session::set('loggedInAs', null);
507
		$this->assertFalse($file->canEdit(), "Anonymous users can't edit files");
508
509
		// Test permissionless user
510
		$this->objFromFixture('Member', 'frontend')->logIn();
511
		$this->assertFalse($file->canEdit(), "Permissionless users can't edit files");
512
513
		// Test global CMS section users
514
		$this->objFromFixture('Member', 'cms')->logIn();
515
		$this->assertTrue($file->canEdit(), "Users with all CMS section access can edit files");
516
517
		// Test cms access users without file access
518
		$this->objFromFixture('Member', 'security')->logIn();
519
		$this->assertFalse($file->canEdit(), "Security CMS users can't edit files");
520
521
		// Test asset-admin user
522
		$this->objFromFixture('Member', 'assetadmin')->logIn();
523
		$this->assertTrue($file->canEdit(), "Asset admin users can edit files");
524
525
		// Test admin
526
		$this->objFromFixture('Member', 'admin')->logIn();
527
		$this->assertTrue($file->canEdit(), "Admins can edit files");
528
	}
529
530
531
	public function testJoinPaths() {
532
		$this->assertEquals('name/file.jpg', File::join_paths('/name', 'file.jpg'));
533
		$this->assertEquals('name/file.jpg', File::join_paths('name', 'file.jpg'));
534
		$this->assertEquals('name/file.jpg', File::join_paths('/name', '/file.jpg'));
535
		$this->assertEquals('name/file.jpg', File::join_paths('name/', '/', 'file.jpg'));
536
		$this->assertEquals('file.jpg', File::join_paths('/', '/', 'file.jpg'));
537
		$this->assertEquals('', File::join_paths('/', '/'));
538
	}
539
540
	/**
541
	 * @return AssetStore
542
	 */
543
	protected function getAssetStore() {
544
		return Injector::inst()->get('AssetStore');
545
	}
546
547
}
548
549
class FileTest_MyCustomFile extends File implements TestOnly {
550
551
}
552