Completed
Pull Request — 3.6 (#7850)
by Jono
07:19
created

FileTest::ini2BytesProvider()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 12
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 10
nc 1
nop 0
dl 0
loc 12
rs 9.4285
c 0
b 0
f 0
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');
0 ignored issues
show
Unused Code Comprehensibility introduced by
73% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
78
		// $this->assertFileExists($file->Parent()->getFullPath(), 'Parent folder is created on filesystem');
0 ignored issues
show
Unused Code Comprehensibility introduced by
74% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
79
		// $this->assertEquals('FileTest', $file->Parent()->Name);
0 ignored issues
show
Unused Code Comprehensibility introduced by
71% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
80
		// $this->assertInstanceOf('Folder', $file->Parent()->Parent(), 'Grandparent folder is created in database');
0 ignored issues
show
Unused Code Comprehensibility introduced by
73% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
81
		// $this->assertFileExists($file->Parent()->Parent()->getFullPath(),
0 ignored issues
show
Unused Code Comprehensibility introduced by
74% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
82
		// 'Grandparent folder is created on filesystem');
83
		// $this->assertEquals('assets', $file->Parent()->Parent()->Name);
0 ignored issues
show
Unused Code Comprehensibility introduced by
72% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
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
	public function testSetNameChangesFilesystemOnWrite() {
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
	public function testSetParentIDChangesFilesystemOnWrite() {
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();
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
	/**
191
	 * Uses fixtures Folder.folder1 and File.setfromname
192
	 * @dataProvider setNameFileProvider
193
	 */
194
	public function testSetNameAddsUniqueSuffixWhenFilenameAlreadyExists($name, $expected)
195
	{
196
		$duplicate = new Folder;
197
		$duplicate->setName($name);
198
		$duplicate->write();
199
200
		$this->assertSame($expected, $duplicate->Name);
201
	}
202
203
	/**
204
	 * @return array[]
205
	 */
206
	public function setNameFileProvider()
207
	{
208
		return array(
209
			array('FileTest-folder1', 'FileTest-folder1-2'),
210
			array('FileTest.png', 'FileTest-2.png'),
211
		);
212
	}
213
214
	public function testLinkAndRelativeLink() {
215
		$file = $this->objFromFixture('File', 'asdf');
216
		$this->assertEquals(ASSETS_DIR . '/FileTest.txt', $file->RelativeLink());
217
		$this->assertEquals(Director::baseURL() . ASSETS_DIR . '/FileTest.txt', $file->Link());
218
	}
219
220
	public function testGetRelativePath() {
221
		$rootfile = $this->objFromFixture('File', 'asdf');
222
		$this->assertEquals('assets/FileTest.txt', $rootfile->getRelativePath(), 'File in assets/ folder');
223
224
		$subfolderfile = $this->objFromFixture('File', 'subfolderfile');
225
		$this->assertEquals('assets/FileTest-subfolder/FileTestSubfolder.txt', $subfolderfile->getRelativePath(),
226
			'File in subfolder within assets/ folder, with existing Filename');
227
228
		$subfolderfilesetfromname = $this->objFromFixture('File', 'subfolderfile-setfromname');
229
		$this->assertEquals('assets/FileTest-subfolder/FileTestSubfolder2.txt',
230
			$subfolderfilesetfromname->getRelativePath(),
231
			'File in subfolder within assets/ folder, with Filename generated through setName()');
232
	}
233
234
	public function testGetFullPath() {
235
		$rootfile = $this->objFromFixture('File', 'asdf');
236
		$this->assertEquals(ASSETS_PATH . '/FileTest.txt', $rootfile->getFullPath(), 'File in assets/ folder');
237
	}
238
239
	public function testGetURL() {
240
		$rootfile = $this->objFromFixture('File', 'asdf');
241
		$this->assertEquals(Director::baseURL() . $rootfile->getFilename(), $rootfile->getURL());
242
	}
243
244
	public function testGetAbsoluteURL() {
245
		$rootfile = $this->objFromFixture('File', 'asdf');
246
		$this->assertEquals(Director::absoluteBaseURL() . $rootfile->getFilename(), $rootfile->getAbsoluteURL());
247
	}
248
249
	public function testNameAndTitleGeneration() {
250
		/* If objects are loaded into the system with just a Filename, then Name is generated but Title isn't */
251
		$file = $this->objFromFixture('File', 'asdf');
252
		$this->assertEquals('FileTest.txt', $file->Name);
253
		$this->assertNull($file->Title);
254
255
		/* However, if Name is set instead of Filename, then Title is set */
256
		$file = $this->objFromFixture('File', 'setfromname');
257
		$this->assertEquals(ASSETS_DIR . '/FileTest.png', $file->Filename);
258
		$this->assertEquals('FileTest', $file->Title);
259
	}
260
261
	public function testSizeAndAbsoluteSizeParameters() {
262
		$file = $this->objFromFixture('File', 'asdf');
263
264
		/* AbsoluteSize will give the integer number */
265
		$this->assertEquals(1000000, $file->AbsoluteSize);
266
		/* Size will give a humanised number */
267
		$this->assertEquals('977 KB', $file->Size);
268
	}
269
270
	public function testFileType() {
271
		$file = $this->objFromFixture('File', 'gif');
272
		$this->assertEquals("GIF image - good for diagrams", $file->FileType);
273
274
		$file = $this->objFromFixture('File', 'pdf');
275
		$this->assertEquals("Adobe Acrobat PDF file", $file->FileType);
276
277
		$file = $this->objFromFixture('File', 'gifupper');
278
		$this->assertEquals("GIF image - good for diagrams", $file->FileType);
279
280
		/* Only a few file types are given special descriptions; the rest are unknown */
281
		$file = $this->objFromFixture('File', 'asdf');
282
		$this->assertEquals("unknown", $file->FileType);
283
	}
284
285
	/**
286
	 * Test the File::format_size() method
287
	 */
288
	public function testFormatSize() {
289
		$this->assertEquals("1000 bytes", File::format_size(1000));
290
		$this->assertEquals("1023 bytes", File::format_size(1023));
291
		$this->assertEquals("1 KB", File::format_size(1025));
292
		$this->assertEquals("9.8 KB", File::format_size(10000));
293
		$this->assertEquals("49 KB", File::format_size(50000));
294
		$this->assertEquals("977 KB", File::format_size(1000000));
295
		$this->assertEquals("1 MB", File::format_size(1024*1024));
296
		$this->assertEquals("954 MB", File::format_size(1000000000));
297
		$this->assertEquals("1 GB", File::format_size(1024*1024*1024));
298
		$this->assertEquals("9.3 GB", File::format_size(10000000000));
299
		// It use any denomination higher than GB.  It also doesn't overflow with >32 bit integers
300
		$this->assertEquals("93132.3 GB", File::format_size(100000000000000));
301
	}
302
303
	public function testDeleteDatabaseOnly() {
304
		$file = $this->objFromFixture('File', 'asdf');
305
		$fileID = $file->ID;
306
		$filePath = $file->getFullPath();
307
308
		$file->deleteDatabaseOnly();
309
310
		DataObject::flush_and_destroy_cache();
311
312
		$this->assertFileExists($filePath);
313
		$this->assertFalse(DataObject::get_by_id('File', $fileID));
314
	}
315
316
	public function testRenameFolder() {
317
		$newTitle = "FileTest-folder-renamed";
318
319
		//rename a folder's title
320
		$folderID = $this->objFromFixture("Folder","folder2")->ID;
321
		$folder = DataObject::get_by_id('Folder',$folderID);
322
		$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...
323
		$folder->write();
324
325
		//get folder again and see if the filename has changed
326
		$folder = DataObject::get_by_id('Folder',$folderID);
327
		$this->assertEquals($folder->Filename, ASSETS_DIR ."/". $newTitle ."/",
328
			"Folder Filename updated after rename of Title");
329
330
331
		//rename a folder's name
332
		$newTitle2 = "FileTest-folder-renamed2";
333
		$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...
334
		$folder->write();
335
336
		//get folder again and see if the Title has changed
337
		$folder = DataObject::get_by_id('Folder',$folderID);
338
		$this->assertEquals($folder->Title, $newTitle2,
339
			"Folder Title updated after rename of Name");
340
341
342
		//rename a folder's Filename
343
		$newTitle3 = "FileTest-folder-renamed3";
344
		$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...
345
		$folder->write();
346
347
		//get folder again and see if the Title has changed
348
		$folder = DataObject::get_by_id('Folder',$folderID);
349
		$this->assertEquals($folder->Title, $newTitle3,
350
			"Folder Title updated after rename of Filename");
351
	}
352
353
354
	public function testGetClassForFileExtension() {
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('*' => '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...
357
		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...
358
359
		$this->assertEquals(
360
			'MyFooFileClass',
361
			File::get_class_for_file_extension('foo'),
362
			'Finds directly mapped file classes'
363
		);
364
		$this->assertEquals(
365
			'MyFooFileClass',
366
			File::get_class_for_file_extension('FOO'),
367
			'Works without case sensitivity'
368
		);
369
		$this->assertEquals(
370
			'MyGenericFileClass',
371
			File::get_class_for_file_extension('unknown'),
372
			'Falls back to generic class for unknown extensions'
373
		);
374
375
		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...
376
	}
377
378
	public function testFolderConstructChild() {
379
		$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...
380
		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...
381
382
		$folder1 = $this->objFromFixture('Folder', 'folder1');
383
		$fileID = $folder1->constructChild('myfile.gif');
384
		$file = DataObject::get_by_id('File', $fileID);
385
		$this->assertEquals('FileTest_MyCustomFile', get_class($file));
386
387
		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...
388
	}
389
390
	public function testSetsOwnerOnFirstWrite() {
391
		Session::set('loggedInAs', null);
392
		$member1 = new Member();
393
		$member1->write();
394
		$member2 = new Member();
395
		$member2->write();
396
397
		$file1 = new File();
398
		$file1->write();
399
		$this->assertEquals(0, $file1->OwnerID, 'Owner not written when no user is logged in');
400
401
		$member1->logIn();
402
		$file2 = new File();
403
		$file2->write();
404
		$this->assertEquals($member1->ID, $file2->OwnerID, 'Owner written when user is logged in');
405
406
		$member2->logIn();
407
		$file2->forceChange();
408
		$file2->write();
409
		$this->assertEquals($member1->ID, $file2->OwnerID, 'Owner not overwritten on existing files');
410
	}
411
412
	public function testCanEdit() {
413
		$file = $this->objFromFixture('File', 'gif');
414
415
		// Test anonymous permissions
416
		Session::set('loggedInAs', null);
417
		$this->assertFalse($file->canEdit(), "Anonymous users can't edit files");
418
419
		// Test permissionless user
420
		$this->objFromFixture('Member', 'frontend')->logIn();
421
		$this->assertFalse($file->canEdit(), "Permissionless users can't edit files");
422
423
		// Test global CMS section users
424
		$this->objFromFixture('Member', 'cms')->logIn();
425
		$this->assertTrue($file->canEdit(), "Users with all CMS section access can edit files");
426
427
		// Test cms access users without file access
428
		$this->objFromFixture('Member', 'security')->logIn();
429
		$this->assertFalse($file->canEdit(), "Security CMS users can't edit files");
430
431
		// Test asset-admin user
432
		$this->objFromFixture('Member', 'assetadmin')->logIn();
433
		$this->assertTrue($file->canEdit(), "Asset admin users can edit files");
434
435
		// Test admin
436
		$this->objFromFixture('Member', 'admin')->logIn();
437
		$this->assertTrue($file->canEdit(), "Admins can edit files");
438
	}
439
440
	/////////////////////////////////////////////////////////////////////////////////////////////////////////////
441
442
	public function setUp() {
443
		parent::setUp();
444
445
		if(!file_exists(ASSETS_PATH)) mkdir(ASSETS_PATH);
446
447
		/* Create a test folders for each of the fixture references */
448
		$folderIDs = $this->allFixtureIDs('Folder');
449
		foreach($folderIDs as $folderID) {
0 ignored issues
show
Bug introduced by
The expression $folderIDs of type object<A> is not traversable.
Loading history...
450
			$folder = DataObject::get_by_id('Folder', $folderID);
451
			if(!file_exists(BASE_PATH."/$folder->Filename")) mkdir(BASE_PATH."/$folder->Filename");
452
		}
453
454
		/* Create a test files for each of the fixture references */
455
		$fileIDs = $this->allFixtureIDs('File');
456
		foreach($fileIDs as $fileID) {
0 ignored issues
show
Bug introduced by
The expression $fileIDs of type object<A> is not traversable.
Loading history...
457
			$file = DataObject::get_by_id('File', $fileID);
458
			$fh = fopen(BASE_PATH."/$file->Filename", "w");
459
			fwrite($fh, str_repeat('x',1000000));
460
			fclose($fh);
461
		}
462
463
		// Conditional fixture creation in case the 'cms' module is installed
464
		if(class_exists('ErrorPage')) {
465
			$page = new ErrorPage(array(
466
				'Title' => 'Page not Found',
467
				'ErrorCode' => 404
468
			));
469
			$page->write();
470
			$page->publish('Stage', 'Live');
471
		}
472
	}
473
474
	public function tearDown() {
475
		parent::tearDown();
476
477
		/* Remove the test files that we've created */
478
		$fileIDs = $this->allFixtureIDs('File');
479
		foreach($fileIDs as $fileID) {
0 ignored issues
show
Bug introduced by
The expression $fileIDs of type object<A> is not traversable.
Loading history...
480
			$file = DataObject::get_by_id('File', $fileID);
481
			if($file && file_exists(BASE_PATH."/$file->Filename")) unlink(BASE_PATH."/$file->Filename");
482
		}
483
484
		/* Remove the test folders that we've crated */
485
		$folderIDs = $this->allFixtureIDs('Folder');
486
		foreach($folderIDs as $folderID) {
0 ignored issues
show
Bug introduced by
The expression $folderIDs of type object<A> is not traversable.
Loading history...
487
			$folder = DataObject::get_by_id('Folder', $folderID);
488
			if($folder && file_exists(BASE_PATH."/$folder->Filename")) {
489
				Filesystem::removeFolder(BASE_PATH."/$folder->Filename");
490
			}
491
		}
492
493
		// Remove left over folders and any files that may exist
494
		if(file_exists('../assets/FileTest')) Filesystem::removeFolder('../assets/FileTest');
495
		if(file_exists('../assets/FileTest-subfolder')) Filesystem::removeFolder('../assets/FileTest-subfolder');
496
		if(file_exists('../assets/FileTest.txt')) unlink('../assets/FileTest.txt');
497
498
		if (file_exists("../assets/FileTest-folder-renamed1")) {
499
			Filesystem::removeFolder("../assets/FileTest-folder-renamed1");
500
		}
501
		if (file_exists("../assets/FileTest-folder-renamed2")) {
502
			Filesystem::removeFolder("../assets/FileTest-folder-renamed2");
503
		}
504
		if (file_exists("../assets/FileTest-folder-renamed3")) {
505
			Filesystem::removeFolder("../assets/FileTest-folder-renamed3");
506
		}
507
	}
508
509
}
510
511
class FileTest_MyCustomFile extends File implements TestOnly {
512
513
}
514