Skip to content

Commit 9cf2028

Browse files
committed
Assert readable directory in NsDirUtil::iterate().
1 parent 489fc5c commit 9cf2028

File tree

4 files changed

+45
-3
lines changed

4 files changed

+45
-3
lines changed

src/NsDirUtil.php

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,28 @@ public static function terminateNamespace(string $namespace): string {
4343
public static function iterate(string $dir, string $terminatedNamespace): \Iterator {
4444
assert(!str_ends_with($dir, '/'));
4545
assert(str_ends_with($terminatedNamespace, '\\') || $terminatedNamespace === '');
46+
self::assertReadableDirectory($dir);
4647
return self::doIterateRecursively($dir, $terminatedNamespace);
4748
}
4849

50+
/**
51+
* Asserts that a path is a readable directory.
52+
*
53+
* @param string $dir
54+
* Directory path.
55+
*/
56+
public static function assertReadableDirectory(string $dir): void {
57+
if (!is_dir($dir)) {
58+
if (!file_exists($dir)) {
59+
throw new \RuntimeException("Directory '$dir' does not exist.");
60+
}
61+
throw new \RuntimeException("Path '$dir' is not a directory.");
62+
}
63+
if (!is_readable($dir)) {
64+
throw new \RuntimeException("Directory '$dir' is not readable.");
65+
}
66+
}
67+
4968
/**
5069
* Recursively iterates over class files.
5170
*

tests/src/ClassFilesIATest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ public function testGetIterator(): void {
109109
__DIR__ . '/Fixtures/Acme/Plant/Tree/Fig.php' => Fig::class,
110110
__DIR__ . '/Fixtures/Acme/Plant/VenusFlyTrap.php' => VenusFlyTrap::class,
111111
], $classFiles);
112-
$this->callAndAssertException(\RuntimeException::class, ClassFilesIA_NamespaceDirectoryPsr4::create(__DIR__ . '/non/existing/subdir', 'Acme\\Zoo')->getIterator()->valid(...));
112+
$this->callAndAssertException(\RuntimeException::class, ClassFilesIA_NamespaceDirectoryPsr4::create(__DIR__ . '/non/existing/subdir', 'Acme\\Zoo')->getIterator(...));
113113
}
114114

115115
public function testEmpty(): void {

tests/src/NamespaceDirectoryTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -445,7 +445,7 @@ public function testGetIterator(): void {
445445
iterator_to_array($nsdir->getIterator()),
446446
);
447447
$bad_nsdir = $this->nsdir(__DIR__ . '/non/existing/subdir', 'Acme\Missing');
448-
$this->callAndAssertException(\RuntimeException::class, $bad_nsdir->getIterator()->valid(...));
448+
$this->callAndAssertException(\RuntimeException::class, $bad_nsdir->getIterator(...));
449449
}
450450

451451
public function testGetElements(): void {

tests/src/NsDirUtilTest.php

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ public function testIterate(): void {
4040
iterator_to_array(NsDirUtil::iterate($nsdir->getDirectory(), $nsdir->getTerminatedNamespace())),
4141
);
4242

43-
$assert_exception = fn (string $path) => $this->callAndAssertException(\RuntimeException::class, NsDirUtil::iterate($path, '')->valid(...));
43+
$assert_exception = fn (string $path) => $this->callAndAssertException(\RuntimeException::class, fn () => NsDirUtil::iterate($path, ''));
4444

4545
$assert_exception(__DIR__ . '/NonExistingSubdir');
4646
$assert_exception(__FILE__);
@@ -62,6 +62,29 @@ public function testIterate(): void {
6262
$this->assertFalse(@include $file);
6363
}
6464

65+
public function testAssertReadableDirectory(): void {
66+
$f = NsDirUtil::assertReadableDirectory(...);
67+
$assert_exception = fn(string $path) => $this->callAndAssertException(\RuntimeException::class, fn () => $f($path));
68+
69+
$f(__DIR__);
70+
$assert_exception(__DIR__ . '/NonExistingSubdir');
71+
$assert_exception(__FILE__);
72+
73+
mkdir($dir = sys_get_temp_dir() . '/test-dir-' . uniqid());
74+
$perms = fileperms($dir) & 0777;
75+
touch($file = $dir . '/Test.php');
76+
$f($dir);
77+
78+
// Write and "execute" permissions.
79+
chmod($dir, $perms & 0333);
80+
$assert_exception($dir);
81+
82+
// Only read permissions, no execute bit.
83+
// The directory will appear as empty.
84+
chmod($dir, $perms & 0444);
85+
$f($dir);
86+
}
87+
6588
public function testScanKnownDir(): void {
6689
$f = NsDirUtil::scanKnownDir(...);
6790
$this->callAndAssertException(\RuntimeException::class, fn () => $f(__DIR__ . '/NonExistingDir'));

0 commit comments

Comments
 (0)