Completed
Push — new-committers ( 29cb6f...bcba16 )
by Sam
12:18 queued 33s
created

FileTest::tearDown()   F

Complexity

Conditions 13
Paths 576

Size

Total Lines 34
Code Lines 20

Duplication

Lines 10
Ratio 29.41 %
Metric Value
dl 10
loc 34
rs 2.9431
cc 13
eloc 20
nc 576
nop 0

How to fix   Complexity   

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
 * Tests for the File class
5
 */
6
class FileTest extends SapphireTest {
7
8
	protected static $fixture_file = 'FileTest.yml';
9
10
	protected $extraDataObjects = array('FileTest_MyCustomFile');
11
12
	public function testLinkShortcodeHandler() {
13
		$testFile = $this->objFromFixture('File', 'asdf');
14
15
		$parser = new ShortcodeParser();
16
		$parser->register('file_link', array('File', 'link_shortcode_handler'));
17
18
		$fileShortcode = sprintf('[file_link,id=%d]', $testFile->ID);
19
		$fileEnclosed  = sprintf('[file_link,id=%d]Example Content[/file_link]', $testFile->ID);
20
21
		$fileShortcodeExpected = $testFile->Link();
22
		$fileEnclosedExpected  = sprintf(
23
			'<a href="%s" class="file" data-type="txt" data-size="977 KB">Example Content</a>', $testFile->Link());
24
25
		$this->assertEquals($fileShortcodeExpected, $parser->parse($fileShortcode), 'Test that simple linking works.');
26
		$this->assertEquals($fileEnclosedExpected, $parser->parse($fileEnclosed), 'Test enclosed content is linked.');
27
28
		$testFile->delete();
29
30
		$fileShortcode = '[file_link,id="-1"]';
31
		$fileEnclosed  = '[file_link,id="-1"]Example Content[/file_link]';
32
33
		$this->assertEquals('', $parser->parse('[file_link]'), 'Test that invalid ID attributes are not parsed.');
34
		$this->assertEquals('', $parser->parse('[file_link,id="text"]'));
35
		$this->assertEquals('', $parser->parse('[file_link]Example Content[/file_link]'));
36
37
		if(class_exists('ErrorPage')) {
38
			$errorPage = ErrorPage::get()->filter('ErrorCode', 404)->First();
39
			$this->assertEquals(
40
				$errorPage->Link(),
41
				$parser->parse($fileShortcode),
42
				'Test link to 404 page if no suitable matches.'
43
			);
44
			$this->assertEquals(
45
				sprintf('<a href="%s">Example Content</a>', $errorPage->Link()),
46
				$parser->parse($fileEnclosed)
47
			);
48
		} else {
49
			$this->assertEquals('', $parser->parse($fileShortcode),
50
				'Short code is removed if file record is not present.');
51
			$this->assertEquals('', $parser->parse($fileEnclosed));
52
		}
53
	}
54
55
	public function testCreateWithFilenameWithSubfolder() {
56
		// Note: We can't use fixtures/setUp() for this, as we want to create the db record manually.
57
		// Creating the folder is necessary to avoid having "Filename" overwritten by setName()/setRelativePath(),
58
		// because the parent folders don't exist in the database
59
		$folder = Folder::find_or_make('/FileTest/');
60
		$testfilePath = 'assets/FileTest/CreateWithFilenameHasCorrectPath.txt'; // Important: No leading slash
61
		$fh = fopen(BASE_PATH . '/' . $testfilePath, "w");
62
		fwrite($fh, str_repeat('x',1000000));
63
		fclose($fh);
64
65
		$file = new File();
66
		$file->Filename = $testfilePath;
67
		// TODO This should be auto-detected
68
		$file->ParentID = $folder->ID;
69
		$file->write();
70
71
		$this->assertEquals('CreateWithFilenameHasCorrectPath.txt', $file->Name,
72
			'"Name" property is automatically set from "Filename"');
73
		$this->assertEquals($testfilePath, $file->Filename,
74
			'"Filename" property remains unchanged');
75
76
		// TODO This should be auto-detected, see File->updateFilesystem()
77
		// $this->assertInstanceOf('Folder', $file->Parent(), 'Parent folder is created in database');
78
		// $this->assertFileExists($file->Parent()->getFullPath(), 'Parent folder is created on filesystem');
79
		// $this->assertEquals('FileTest', $file->Parent()->Name);
80
		// $this->assertInstanceOf('Folder', $file->Parent()->Parent(), 'Grandparent folder is created in database');
81
		// $this->assertFileExists($file->Parent()->Parent()->getFullPath(),
82
		// 'Grandparent folder is created on filesystem');
83
		// $this->assertEquals('assets', $file->Parent()->Parent()->Name);
84
	}
85
86
	public function testGetExtension() {
87
		$this->assertEquals('', File::get_file_extension('myfile'),
88
			'No extension');
89
		$this->assertEquals('txt', File::get_file_extension('myfile.txt'),
90
			'Simple extension');
91
		$this->assertEquals('gz', File::get_file_extension('myfile.tar.gz'),
92
			'Double-barrelled extension only returns last bit');
93
	}
94
95
	public function testValidateExtension() {
96
		Session::set('loggedInAs', null);
97
98
		$orig = Config::inst()->get('File', 'allowed_extensions');
99
		Config::inst()->remove('File', 'allowed_extensions');
100
		Config::inst()->update('File', 'allowed_extensions', array('txt'));
101
102
		$file = $this->objFromFixture('File', 'asdf');
103
104
		// Invalid ext
105
		$file->Name = 'asdf.php';
0 ignored issues
show
Documentation introduced by
The property Name does not exist on object<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...
106
		$v = $file->doValidate();
107
		$this->assertFalse($v->valid());
108
		$this->assertContains('Extension is not allowed', $v->message());
109
110
		// Valid ext
111
		$file->Name = 'asdf.txt';
0 ignored issues
show
Documentation introduced by
The property Name does not exist on object<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...
112
		$v = $file->doValidate();
113
		$this->assertTrue($v->valid());
114
115
		// Capital extension is valid as well
116
		$file->Name = 'asdf.TXT';
0 ignored issues
show
Documentation introduced by
The property Name does not exist on object<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...
117
		$v = $file->doValidate();
118
		$this->assertTrue($v->valid());
119
120
		Config::inst()->remove('File', 'allowed_extensions');
121
		Config::inst()->update('File', 'allowed_extensions', $orig);
122
	}
123
124 View Code Duplication
	public function testSetNameChangesFilesystemOnWrite() {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
125
		$file = $this->objFromFixture('File', 'asdf');
126
		$oldPath = $file->getFullPath();
127
128
		// Before write()
129
		$file->Name = 'renamed.txt';
0 ignored issues
show
Documentation introduced by
The property Name does not exist on object<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...
130
		$this->assertFileExists($oldPath,
131
			'Old path is still present');
132
		$this->assertFileNotExists($file->getFullPath(),
133
			'New path is updated in memory, not written before write() is called');
134
135
		$file->write();
136
137
		// After write()
138
		clearstatcache();
139
		$this->assertFileNotExists($oldPath, 'Old path is removed after write()');
140
		$this->assertFileExists($file->getFullPath(), 'New path is created after write()');
141
	}
142
143 View Code Duplication
	public function testSetParentIDChangesFilesystemOnWrite() {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
144
		$file = $this->objFromFixture('File', 'asdf');
145
		$subfolder = $this->objFromFixture('Folder', 'subfolder');
146
		$oldPath = $file->getFullPath();
147
148
		// set ParentID
149
		$file->ParentID = $subfolder->ID;
0 ignored issues
show
Documentation introduced by
The property ParentID does not exist on object<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...
150
151
		// Before write()
152
		$this->assertFileExists($oldPath,
153
			'Old path is still present');
154
		$this->assertFileNotExists($file->getFullPath(),
155
			'New path is updated in memory, not written before write() is called');
156
157
		$file->write();
158
159
		// After write()
160
		clearstatcache();
161
		$this->assertFileNotExists($oldPath,
162
			'Old path is removed after write()');
163
		$this->assertFileExists($file->getFullPath(),
164
			'New path is created after write()');
165
	}
166
167
	/**
168
	 * @see http://open.silverstripe.org/ticket/5693
169
	 *
170
	 * @expectedException ValidationException
171
	 */
172
	public function testSetNameWithInvalidExtensionDoesntChangeFilesystem() {
173
		$orig = Config::inst()->get('File', 'allowed_extensions');
174
		Config::inst()->remove('File', 'allowed_extensions');
175
		Config::inst()->update('File', 'allowed_extensions', array('txt'));
176
177
		$file = $this->objFromFixture('File', 'asdf');
178
		$oldPath = $file->getFullPath();
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...
179
180
		$file->Name = 'renamed.php'; // evil extension
0 ignored issues
show
Documentation introduced by
The property Name does not exist on object<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...
181
		try {
182
			$file->write();
183
		} catch(ValidationException $e) {
184
			Config::inst()->remove('File', 'allowed_extensions');
185
			Config::inst()->update('File', 'allowed_extensions', $orig);
186
			throw $e;
187
		}
188
	}
189
190
	public function testLinkAndRelativeLink() {
191
		$file = $this->objFromFixture('File', 'asdf');
192
		$this->assertEquals(ASSETS_DIR . '/FileTest.txt', $file->RelativeLink());
193
		$this->assertEquals(Director::baseURL() . ASSETS_DIR . '/FileTest.txt', $file->Link());
194
	}
195
196
	public function testGetRelativePath() {
197
		$rootfile = $this->objFromFixture('File', 'asdf');
198
		$this->assertEquals('assets/FileTest.txt', $rootfile->getRelativePath(), 'File in assets/ folder');
199
200
		$subfolderfile = $this->objFromFixture('File', 'subfolderfile');
201
		$this->assertEquals('assets/FileTest-subfolder/FileTestSubfolder.txt', $subfolderfile->getRelativePath(),
202
			'File in subfolder within assets/ folder, with existing Filename');
203
204
		$subfolderfilesetfromname = $this->objFromFixture('File', 'subfolderfile-setfromname');
205
		$this->assertEquals('assets/FileTest-subfolder/FileTestSubfolder2.txt',
206
			$subfolderfilesetfromname->getRelativePath(),
207
			'File in subfolder within assets/ folder, with Filename generated through setName()');
208
	}
209
210
	public function testGetFullPath() {
211
		$rootfile = $this->objFromFixture('File', 'asdf');
212
		$this->assertEquals(ASSETS_PATH . '/FileTest.txt', $rootfile->getFullPath(), 'File in assets/ folder');
213
	}
214
215
	public function testGetURL() {
216
		$rootfile = $this->objFromFixture('File', 'asdf');
217
		$this->assertEquals(Director::baseURL() . $rootfile->getFilename(), $rootfile->getURL());
218
	}
219
220
	public function testGetAbsoluteURL() {
221
		$rootfile = $this->objFromFixture('File', 'asdf');
222
		$this->assertEquals(Director::absoluteBaseURL() . $rootfile->getFilename(), $rootfile->getAbsoluteURL());
223
	}
224
225
	public function testNameAndTitleGeneration() {
226
		/* If objects are loaded into the system with just a Filename, then Name is generated but Title isn't */
227
		$file = $this->objFromFixture('File', 'asdf');
228
		$this->assertEquals('FileTest.txt', $file->Name);
229
		$this->assertNull($file->Title);
230
231
		/* However, if Name is set instead of Filename, then Title is set */
232
		$file = $this->objFromFixture('File', 'setfromname');
233
		$this->assertEquals(ASSETS_DIR . '/FileTest.png', $file->Filename);
234
		$this->assertEquals('FileTest', $file->Title);
235
	}
236
237
	public function testSizeAndAbsoluteSizeParameters() {
238
		$file = $this->objFromFixture('File', 'asdf');
239
240
		/* AbsoluteSize will give the integer number */
241
		$this->assertEquals(1000000, $file->AbsoluteSize);
242
		/* Size will give a humanised number */
243
		$this->assertEquals('977 KB', $file->Size);
244
	}
245
246
	public function testFileType() {
247
		$file = $this->objFromFixture('File', 'gif');
248
		$this->assertEquals("GIF image - good for diagrams", $file->FileType);
249
250
		$file = $this->objFromFixture('File', 'pdf');
251
		$this->assertEquals("Adobe Acrobat PDF file", $file->FileType);
252
253
		$file = $this->objFromFixture('File', 'gifupper');
254
		$this->assertEquals("GIF image - good for diagrams", $file->FileType);
255
256
		/* Only a few file types are given special descriptions; the rest are unknown */
257
		$file = $this->objFromFixture('File', 'asdf');
258
		$this->assertEquals("unknown", $file->FileType);
259
	}
260
261
	/**
262
	 * Test the File::format_size() method
263
	 */
264
	public function testFormatSize() {
265
		$this->assertEquals("1000 bytes", File::format_size(1000));
266
		$this->assertEquals("1023 bytes", File::format_size(1023));
267
		$this->assertEquals("1 KB", File::format_size(1025));
268
		$this->assertEquals("9.8 KB", File::format_size(10000));
269
		$this->assertEquals("49 KB", File::format_size(50000));
270
		$this->assertEquals("977 KB", File::format_size(1000000));
271
		$this->assertEquals("1 MB", File::format_size(1024*1024));
272
		$this->assertEquals("954 MB", File::format_size(1000000000));
273
		$this->assertEquals("1 GB", File::format_size(1024*1024*1024));
274
		$this->assertEquals("9.3 GB", File::format_size(10000000000));
275
		// It use any denomination higher than GB.  It also doesn't overflow with >32 bit integers
276
		$this->assertEquals("93132.3 GB", File::format_size(100000000000000));
277
	}
278
279
	public function testDeleteDatabaseOnly() {
280
		$file = $this->objFromFixture('File', 'asdf');
281
		$fileID = $file->ID;
282
		$filePath = $file->getFullPath();
283
284
		$file->deleteDatabaseOnly();
285
286
		DataObject::flush_and_destroy_cache();
287
288
		$this->assertFileExists($filePath);
289
		$this->assertFalse(DataObject::get_by_id('File', $fileID));
290
	}
291
292
	public function testRenameFolder() {
293
		$newTitle = "FileTest-folder-renamed";
294
295
		//rename a folder's title
296
		$folderID = $this->objFromFixture("Folder","folder2")->ID;
297
		$folder = DataObject::get_by_id('Folder',$folderID);
298
		$folder->Title = $newTitle;
0 ignored issues
show
Documentation introduced by
The property Title does not exist on object<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...
299
		$folder->write();
300
301
		//get folder again and see if the filename has changed
302
		$folder = DataObject::get_by_id('Folder',$folderID);
303
		$this->assertEquals($folder->Filename, ASSETS_DIR ."/". $newTitle ."/",
304
			"Folder Filename updated after rename of Title");
305
306
307
		//rename a folder's name
308
		$newTitle2 = "FileTest-folder-renamed2";
309
		$folder->Name = $newTitle2;
0 ignored issues
show
Documentation introduced by
The property Name does not exist on object<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...
310
		$folder->write();
311
312
		//get folder again and see if the Title has changed
313
		$folder = DataObject::get_by_id('Folder',$folderID);
314
		$this->assertEquals($folder->Title, $newTitle2,
315
			"Folder Title updated after rename of Name");
316
317
318
		//rename a folder's Filename
319
		$newTitle3 = "FileTest-folder-renamed3";
320
		$folder->Filename = $newTitle3;
0 ignored issues
show
Documentation introduced by
The property Filename does not exist on object<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...
321
		$folder->write();
322
323
		//get folder again and see if the Title has changed
324
		$folder = DataObject::get_by_id('Folder',$folderID);
325
		$this->assertEquals($folder->Title, $newTitle3,
326
			"Folder Title updated after rename of Filename");
327
	}
328
329
330
	public function testGetClassForFileExtension() {
331
		$orig = File::config()->class_for_file_extension;
0 ignored issues
show
Documentation introduced by
The property class_for_file_extension does not exist on object<Config_ForClass>. 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...
332
		File::config()->class_for_file_extension = array('*' => 'MyGenericFileClass');
0 ignored issues
show
Documentation introduced by
The property class_for_file_extension does not exist on object<Config_ForClass>. 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...
333
		File::config()->class_for_file_extension = array('foo' => 'MyFooFileClass');
0 ignored issues
show
Documentation introduced by
The property class_for_file_extension does not exist on object<Config_ForClass>. 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...
334
335
		$this->assertEquals(
336
			'MyFooFileClass',
337
			File::get_class_for_file_extension('foo'),
338
			'Finds directly mapped file classes'
339
		);
340
		$this->assertEquals(
341
			'MyFooFileClass',
342
			File::get_class_for_file_extension('FOO'),
343
			'Works without case sensitivity'
344
		);
345
		$this->assertEquals(
346
			'MyGenericFileClass',
347
			File::get_class_for_file_extension('unknown'),
348
			'Falls back to generic class for unknown extensions'
349
		);
350
351
		File::config()->class_for_file_extension = $orig;
0 ignored issues
show
Documentation introduced by
The property class_for_file_extension does not exist on object<Config_ForClass>. 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...
352
	}
353
354
	public function testFolderConstructChild() {
355
		$orig = File::config()->class_for_file_extension;
0 ignored issues
show
Documentation introduced by
The property class_for_file_extension does not exist on object<Config_ForClass>. 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...
356
		File::config()->class_for_file_extension = array('gif' => 'FileTest_MyCustomFile');
0 ignored issues
show
Documentation introduced by
The property class_for_file_extension does not exist on object<Config_ForClass>. 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...
357
358
		$folder1 = $this->objFromFixture('Folder', 'folder1');
359
		$fileID = $folder1->constructChild('myfile.gif');
360
		$file = DataObject::get_by_id('File', $fileID);
361
		$this->assertEquals('FileTest_MyCustomFile', get_class($file));
362
363
		File::config()->class_for_file_extension = $orig;
0 ignored issues
show
Documentation introduced by
The property class_for_file_extension does not exist on object<Config_ForClass>. 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...
364
	}
365
366
	public function testSetsOwnerOnFirstWrite() {
367
		Session::set('loggedInAs', null);
368
		$member1 = new Member();
369
		$member1->write();
370
		$member2 = new Member();
371
		$member2->write();
372
373
		$file1 = new File();
374
		$file1->write();
375
		$this->assertEquals(0, $file1->OwnerID, 'Owner not written when no user is logged in');
376
377
		$member1->logIn();
378
		$file2 = new File();
379
		$file2->write();
380
		$this->assertEquals($member1->ID, $file2->OwnerID, 'Owner written when user is logged in');
381
382
		$member2->logIn();
383
		$file2->forceChange();
384
		$file2->write();
385
		$this->assertEquals($member1->ID, $file2->OwnerID, 'Owner not overwritten on existing files');
386
	}
387
388
	public function testCanEdit() {
389
		$file = $this->objFromFixture('File', 'gif');
390
391
		// Test anonymous permissions
392
		Session::set('loggedInAs', null);
393
		$this->assertFalse($file->canEdit(), "Anonymous users can't edit files");
394
395
		// Test permissionless user
396
		$this->objFromFixture('Member', 'frontend')->logIn();
397
		$this->assertFalse($file->canEdit(), "Permissionless users can't edit files");
398
399
		// Test global CMS section users
400
		$this->objFromFixture('Member', 'cms')->logIn();
401
		$this->assertTrue($file->canEdit(), "Users with all CMS section access can edit files");
402
403
		// Test cms access users without file access
404
		$this->objFromFixture('Member', 'security')->logIn();
405
		$this->assertFalse($file->canEdit(), "Security CMS users can't edit files");
406
407
		// Test asset-admin user
408
		$this->objFromFixture('Member', 'assetadmin')->logIn();
409
		$this->assertTrue($file->canEdit(), "Asset admin users can edit files");
410
411
		// Test admin
412
		$this->objFromFixture('Member', 'admin')->logIn();
413
		$this->assertTrue($file->canEdit(), "Admins can edit files");
414
	}
415
416
	/////////////////////////////////////////////////////////////////////////////////////////////////////////////
417
418
	public function setUp() {
419
		parent::setUp();
420
421
		if(!file_exists(ASSETS_PATH)) mkdir(ASSETS_PATH);
422
423
		/* Create a test folders for each of the fixture references */
424
		$folderIDs = $this->allFixtureIDs('Folder');
425 View Code Duplication
		foreach($folderIDs as $folderID) {
0 ignored issues
show
Bug introduced by
The expression $folderIDs of type object<A> is not traversable.
Loading history...
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
426
			$folder = DataObject::get_by_id('Folder', $folderID);
427
			if(!file_exists(BASE_PATH."/$folder->Filename")) mkdir(BASE_PATH."/$folder->Filename");
428
		}
429
430
		/* Create a test files for each of the fixture references */
431
		$fileIDs = $this->allFixtureIDs('File');
432 View Code Duplication
		foreach($fileIDs as $fileID) {
0 ignored issues
show
Bug introduced by
The expression $fileIDs of type object<A> is not traversable.
Loading history...
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
433
			$file = DataObject::get_by_id('File', $fileID);
434
			$fh = fopen(BASE_PATH."/$file->Filename", "w");
435
			fwrite($fh, str_repeat('x',1000000));
436
			fclose($fh);
437
		}
438
439
		// Conditional fixture creation in case the 'cms' module is installed
440
		if(class_exists('ErrorPage')) {
441
			$page = new ErrorPage(array(
442
				'Title' => 'Page not Found',
443
				'ErrorCode' => 404
444
			));
445
			$page->write();
446
			$page->publish('Stage', 'Live');
447
		}
448
	}
449
450
	public function tearDown() {
451
		parent::tearDown();
452
453
		/* Remove the test files that we've created */
454
		$fileIDs = $this->allFixtureIDs('File');
455 View Code Duplication
		foreach($fileIDs as $fileID) {
0 ignored issues
show
Bug introduced by
The expression $fileIDs of type object<A> is not traversable.
Loading history...
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
456
			$file = DataObject::get_by_id('File', $fileID);
457
			if($file && file_exists(BASE_PATH."/$file->Filename")) unlink(BASE_PATH."/$file->Filename");
458
		}
459
460
		/* Remove the test folders that we've crated */
461
		$folderIDs = $this->allFixtureIDs('Folder');
462 View Code Duplication
		foreach($folderIDs as $folderID) {
0 ignored issues
show
Bug introduced by
The expression $folderIDs of type object<A> is not traversable.
Loading history...
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
463
			$folder = DataObject::get_by_id('Folder', $folderID);
464
			if($folder && file_exists(BASE_PATH."/$folder->Filename")) {
465
				Filesystem::removeFolder(BASE_PATH."/$folder->Filename");
466
			}
467
		}
468
469
		// Remove left over folders and any files that may exist
470
		if(file_exists('../assets/FileTest')) Filesystem::removeFolder('../assets/FileTest');
471
		if(file_exists('../assets/FileTest-subfolder')) Filesystem::removeFolder('../assets/FileTest-subfolder');
472
		if(file_exists('../assets/FileTest.txt')) unlink('../assets/FileTest.txt');
473
474
		if (file_exists("../assets/FileTest-folder-renamed1")) {
475
			Filesystem::removeFolder("../assets/FileTest-folder-renamed1");
476
		}
477
		if (file_exists("../assets/FileTest-folder-renamed2")) {
478
			Filesystem::removeFolder("../assets/FileTest-folder-renamed2");
479
		}
480
		if (file_exists("../assets/FileTest-folder-renamed3")) {
481
			Filesystem::removeFolder("../assets/FileTest-folder-renamed3");
482
		}
483
	}
484
485
}
486
487
class FileTest_MyCustomFile extends File implements TestOnly {
488
489
}
490