Completed
Pull Request — master (#5247)
by Damian
11:17
created

FolderTest::testFindOrMakeFolderThenMove()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 47
Code Lines 25

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 1
Metric Value
c 2
b 0
f 1
dl 0
loc 47
rs 9.0303
cc 1
eloc 25
nc 1
nop 0
1
<?php
2
3
use Filesystem as SS_Filesystem;
4
5
/**
6
 * @author Ingo Schommer (ingo at silverstripe dot com)
7
 *
8
 * @package framework
9
 * @subpackage tests
10
 */
11
class FolderTest extends SapphireTest {
12
13
	protected static $fixture_file = 'FileTest.yml';
14
15
	public function setUp() {
16
		parent::setUp();
17
18
		$this->logInWithPermission('ADMIN');
19
		Versioned::set_stage(Versioned::DRAFT);
20
21
		// Set backend root to /FolderTest
22
		AssetStoreTest_SpyStore::activate('FolderTest');
23
24
		// Create a test folders for each of the fixture references
25
		foreach(Folder::get() as $folder) {
26
			$path = AssetStoreTest_SpyStore::getLocalPath($folder);
27
			SS_Filesystem::makeFolder($path);
28
		}
29
30
		// Create a test files for each of the fixture references
31
		$files = File::get()->exclude('ClassName', 'Folder');
32
		foreach($files as $file) {
33
			$path = AssetStoreTest_SpyStore::getLocalPath($file);
34
			SS_Filesystem::makeFolder(dirname($path));
35
			$fh = fopen($path, "w+");
36
			fwrite($fh, str_repeat('x', 1000000));
37
			fclose($fh);
38
		}
39
	}
40
41
	public function tearDown() {
42
		AssetStoreTest_SpyStore::reset();
43
		parent::tearDown();
44
	}
45
46
	public function testCreateFromNameAndParentIDSetsFilename() {
47
		$folder1 = $this->objFromFixture('Folder', 'folder1');
48
		$newFolder = new Folder();
49
		$newFolder->Name = 'CreateFromNameAndParentID';
50
		$newFolder->ParentID = $folder1->ID;
51
		$newFolder->write();
52
53
		$this->assertEquals($folder1->Filename . 'CreateFromNameAndParentID/', $newFolder->Filename);
54
	}
55
56
	public function testAllChildrenIncludesFolders() {
57
		$folder1 = $this->objFromFixture('Folder', 'folder1');
58
		$subfolder1 = $this->objFromFixture('Folder', 'folder1-subfolder1');
59
		$file1 = $this->objFromFixture('File', 'file1-folder1');
60
61
		$children = $folder1->allChildren();
62
		$this->assertEquals(2, $children->Count());
63
		$this->assertContains($subfolder1->ID, $children->column('ID'));
64
		$this->assertContains($file1->ID, $children->column('ID'));
65
	}
66
67
	public function testFindOrMake() {
68
		$path = 'parent/testFindOrMake/';
69
		$folder = Folder::find_or_make($path);
70
		$this->assertEquals(
71
			ASSETS_PATH . '/FolderTest/' . $path,
72
			AssetStoreTest_SpyStore::getLocalPath($folder),
73
			'Nested path information is correctly saved to database (with trailing slash)'
74
		);
75
76
		// Folder does not exist until it contains files
77
		$this->assertFileNotExists(
78
			AssetStoreTest_SpyStore::getLocalPath($folder),
79
			'Empty folder does not have a filesystem record automatically'
80
		);
81
82
		$parentFolder = DataObject::get_one('Folder', array(
83
			'"File"."Name"' => 'parent'
84
		));
85
		$this->assertNotNull($parentFolder);
86
		$this->assertEquals($parentFolder->ID, $folder->ParentID);
87
88
		$path = 'parent/testFindOrMake'; // no trailing slash
89
		$folder = Folder::find_or_make($path);
90
		$this->assertEquals(
91
			ASSETS_PATH . '/FolderTest/' . $path . '/', // Slash is automatically added here
92
			AssetStoreTest_SpyStore::getLocalPath($folder),
93
			'Path information is correctly saved to database (without trailing slash)'
94
		);
95
96
		$path = 'assets/'; // relative to "assets/" folder, should produce "assets/assets/"
97
		$folder = Folder::find_or_make($path);
98
		$this->assertEquals(
99
			ASSETS_PATH . '/FolderTest/' . $path,
100
			AssetStoreTest_SpyStore::getLocalPath($folder),
101
			'A folder named "assets/" within "assets/" is allowed'
102
		);
103
	}
104
105
	/**
106
	 * Tests for the bug #5994 - Moving folder after executing Folder::findOrMake will not set the Filenames properly
107
	 */
108
	public function testFindOrMakeFolderThenMove() {
109
		$folder1 = $this->objFromFixture('Folder', 'folder1');
110
		Folder::find_or_make($folder1->Filename);
111
		$folder2 = $this->objFromFixture('Folder', 'folder2');
112
113
		// Publish file1
114
		/** @var File $file1 */
115
		$file1 = DataObject::get_by_id('File', $this->idFromFixture('File', 'file1-folder1'), false);
116
		$file1->publishRecursive();
117
118
		// set ParentID. This should cause updateFilesystem to be called on all children
119
		$folder1->ParentID = $folder2->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...
120
		$folder1->write();
121
122
		// Check if the file in the folder moved along
123
		/** @var File $file1Draft */
124
		$file1Draft = Versioned::get_by_stage('File', Versioned::DRAFT)->byID($file1->ID);
125
		$this->assertFileExists(AssetStoreTest_SpyStore::getLocalPath($file1Draft));
126
127
		$this->assertEquals(
128
			'FileTest-folder2/FileTest-folder1/File1.txt',
129
			$file1Draft->Filename,
130
			'The file DataObject has updated path'
131
		);
132
133
		// File should be located in new folder
134
		$this->assertEquals(
135
			ASSETS_PATH . '/FolderTest/.protected/FileTest-folder2/FileTest-folder1/55b443b601/File1.txt',
136
			AssetStoreTest_SpyStore::getLocalPath($file1Draft)
137
		);
138
139
		// Published (live) version remains in the old location
140
		/** @var File $file1Live */
141
		$file1Live = Versioned::get_by_stage('File', Versioned::LIVE)->byID($file1->ID);
142
		$this->assertEquals(
143
			ASSETS_PATH . '/FolderTest/FileTest-folder1/55b443b601/File1.txt',
144
			AssetStoreTest_SpyStore::getLocalPath($file1Live)
145
		);
146
147
		// Publishing the draft to live should move the new file to the public store
148
		$file1Draft->publishRecursive();
149
		$this->assertEquals(
150
			ASSETS_PATH . '/FolderTest/FileTest-folder2/FileTest-folder1/55b443b601/File1.txt',
151
			AssetStoreTest_SpyStore::getLocalPath($file1Draft)
152
		);
153
154
	}
155
156
	/**
157
	 * Tests for the bug #5994 - if you don't execute get_by_id prior to the rename or move, it will fail.
158
	 */
159
	public function testRenameFolderAndCheckTheFile() {
160
		// ID is prefixed in case Folder is subclassed by project/other module.
161
		$folder1 = DataObject::get_one('Folder', array(
162
			'"File"."ID"' => $this->idFromFixture('Folder', 'folder1')
163
		));
164
165
		$folder1->Name = 'FileTest-folder1-changed';
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...
166
		$folder1->write();
167
168
		// Check if the file in the folder moved along
169
		$file1 = DataObject::get_by_id('File', $this->idFromFixture('File', 'file1-folder1'), false);
170
		$this->assertFileExists(
171
			AssetStoreTest_SpyStore::getLocalPath($file1)
172
		);
173
		$this->assertEquals(
174
			$file1->Filename,
175
			'FileTest-folder1-changed/File1.txt',
176
			'The file DataObject path uses renamed folder'
177
		);
178
179
		// File should be located in new folder
180
		$this->assertEquals(
181
			ASSETS_PATH . '/FolderTest/.protected/FileTest-folder1-changed/55b443b601/File1.txt',
182
			AssetStoreTest_SpyStore::getLocalPath($file1)
183
		);
184
	}
185
186
	/**
187
	 * URL and Link are undefined for folder dataobjects
188
	 */
189
	public function testLinkAndRelativeLink() {
190
		$folder = $this->objFromFixture('Folder', 'folder1');
191
		$this->assertEmpty($folder->getURL());
192
		$this->assertEmpty($folder->Link());
193
	}
194
195
	public function testIllegalFilenames() {
196
197
		// Test that generating a filename with invalid characters generates a correctly named folder.
198
		$folder = Folder::find_or_make('/FolderTest/EN_US Lang');
199
		$this->assertEquals('FolderTest/EN-US-Lang/', $folder->getFilename());
200
201
		// Test repeatitions of folder
202
		$folder2 = Folder::find_or_make('/FolderTest/EN_US Lang');
203
		$this->assertEquals($folder->ID, $folder2->ID);
204
205
		$folder3 = Folder::find_or_make('/FolderTest/EN--US_L!ang');
206
		$this->assertEquals($folder->ID, $folder3->ID);
207
208
		$folder4 = Folder::find_or_make('/FolderTest/EN-US-Lang');
209
		$this->assertEquals($folder->ID, $folder4->ID);
210
	}
211
212
	public function testTitleTiedToName() {
213
		$newFolder = new Folder();
214
215
		$newFolder->Name = 'TestNameCopiedToTitle';
216
		$this->assertEquals($newFolder->Name, $newFolder->Title);
217
218
		$newFolder->Title = 'TestTitleCopiedToName';
219
		$this->assertEquals($newFolder->Name, $newFolder->Title);
220
221
		$newFolder->Name = 'TestNameWithIllegalCharactersCopiedToTitle <!BANG!>';
222
		$this->assertEquals($newFolder->Name, $newFolder->Title);
223
224
		$newFolder->Title = 'TestTitleWithIllegalCharactersCopiedToName <!BANG!>';
225
		$this->assertEquals($newFolder->Name, $newFolder->Title);
226
	}
227
}
228