1<?php
2
3namespace Elgg\Filesystem;
4
5/**
6 * @group UnitTests
7 */
8abstract class DirectoryUnitTest extends \Elgg\UnitTestCase {
9
10	/**
11	 * Returns an array of one-element arrays. Those elements should
12	 * be fresh (empty) directory instances that use the relevant implementation.
13	 *
14	 * @return array
15	 */
16	abstract public function emptyDirectoryProvider();
17
18	public function up() {
19
20	}
21
22	public function down() {
23
24	}
25
26	/**
27	 * @dataProvider emptyDirectoryProvider
28	 */
29	public function testListFilesAndDirsInTheDirectory(Directory $directory) {
30		$directory->putContents('/foo/bar/bar.php', 'bar');
31		$directory->putContents('/foo/baz/baz.php', 'baz');
32		$directory->putContents('/foo/foo.php', 'foo');
33		$directory->putContents('/qux.php', 'qux');
34
35		$this->assertEquals(4, count($directory->getFiles()));
36		$this->assertEquals(1, count($directory->getFiles('', false)));
37
38		$this->assertEquals(3, count($directory->getDirectories()));
39		$this->assertEquals(1, count($directory->getDirectories('', false)));
40	}
41
42	/**
43	 * @dataProvider emptyDirectoryProvider
44	 */
45	public function testListFilesAndDirsInASubdirectory(Directory $directory) {
46		$directory->putContents('/foo/bar/bar.php', 'bar');
47		$directory->putContents('/foo/baz/baz.php', 'baz');
48		$directory->putContents('/foo/baz/bing/foo.php', 'foo');
49		$directory->putContents('/foo/foo.php', 'foo');
50		$directory->putContents('/qux.php', 'qux');
51
52		foreach (['foo', '/foo', 'foo/', '/foo/'] as $path) {
53			$this->assertEquals(4, count($directory->getFiles($path)));
54			$this->assertEquals(1, count($directory->getFiles($path, false)));
55
56			$this->assertEquals(3, count($directory->getDirectories($path)));
57			$this->assertEquals(2, count($directory->getDirectories($path, false)));
58		}
59	}
60
61	/**
62	 * @dataProvider emptyDirectoryProvider
63	 */
64	public function testChrootReturnsANewDirectoryThatOnlyHasAccessToTheGivenSubdir(Directory $directory) {
65		$directory->putContents('/foo/bar/bar.php', 'bar');
66		$directory->putContents('/foo/baz/baz.php', 'baz');
67		$directory->putContents('/foo/foo.php', 'foo');
68		$directory->putContents('/qux.php', 'qux');
69
70		$this->assertEquals(3, count($directory->chroot('/foo/')->getFiles()));
71		$this->assertEquals(3, count($directory->chroot('foo/')->getFiles()));
72		$this->assertEquals(3, count($directory->chroot('/foo')->getFiles()));
73		$this->assertEquals(3, count($directory->chroot('foo')->getFiles()));
74
75		$this->assertEquals(1, count($directory->chroot('/foo/bar/')->getFiles()));
76		$this->assertEquals(1, count($directory->chroot('foo/bar/')->getFiles()));
77		$this->assertEquals(1, count($directory->chroot('/foo/bar')->getFiles()));
78		$this->assertEquals(1, count($directory->chroot('foo/bar')->getFiles()));
79	}
80
81	/**
82	 * @dataProvider emptyDirectoryProvider
83	 */
84	public function testCanGetAnyFileInThisDirectoryEvenIfTheFileDoesNotExistYet(Directory $directory) {
85		$this->assertFalse($directory->getFile('foo.php')->exists());
86	}
87
88	/**
89	 * @dataProvider emptyDirectoryProvider
90	 */
91	public function testPathsCannotContainDots(Directory $directory) {
92		$funcs = [
93			function () use ($directory) {
94				$directory->chroot('.');
95			},
96			function () use ($directory) {
97				$directory->chroot('..');
98			},
99			function () use ($directory) {
100				$directory->getFile('.');
101			},
102			function () use ($directory) {
103				$directory->getFile('..');
104			},
105		];
106
107		foreach ($funcs as $i => $f) {
108			try {
109				$f();
110				$this->fail("A path was allowed to contain . or .. in function #$i");
111			} catch (\InvalidArgumentException $e) {
112
113			}
114		}
115	}
116
117	/**
118	 * @dataProvider emptyDirectoryProvider
119	 */
120	public function testCanGetFileInsideItself(Directory $directory) {
121		$directory->putContents('/foo/bar.php', 'bar');
122
123		$file = $directory->chroot('foo')->getFile('bar.php');
124
125		$this->assertInstanceOf(File::class, $file);
126
127		$this->assertEquals('bar', $file->getContents());
128	}
129
130	/**
131	 * @dataProvider emptyDirectoryProvider
132	 */
133	public function testCanGetDirectoryInsideItself(Directory $directory) {
134		$directory->putContents('/foo/bar/bang.php', 'bang');
135		$directory->putContents('/foo/boom/bang.php', 'bang');
136
137		$dirs = $directory->getDirectories('foo');
138		$this->assertCount(2, $dirs);
139		foreach ($dirs as $dir) {
140			$this->assertInstanceOf(Directory::class, $dir);
141			$this->assertEquals('bang', $dir->getFile('bang.php')->getContents());
142		}
143	}
144
145}
146