friendship ended with social-app. php is my new best friend
1<?php 2/** 3 * Class Directory 4 * 5 * @created 29.10.2024 6 * @author smiley <smiley@chillerlan.net> 7 * @copyright 2024 smiley 8 * @license MIT 9 */ 10declare(strict_types=1); 11 12namespace chillerlan\Utilities; 13 14use InvalidArgumentException; 15use RuntimeException; 16use function clearstatcache; 17use function dirname; 18use function file_exists; 19use function is_dir; 20use function is_file; 21use function is_readable; 22use function is_writable; 23use function mkdir; 24use function rmdir; 25use function sprintf; 26use function str_replace; 27use function trim; 28use const DIRECTORY_SEPARATOR; 29 30/** 31 * Basic directory utilities 32 */ 33final class Directory{ 34 35 /** 36 * Checks whether a directory exists 37 * 38 * @codeCoverageIgnore 39 */ 40 public static function exists(string $dir):bool{ 41 return file_exists($dir) && is_dir($dir); 42 } 43 44 /** 45 * Checks whether the given directory is readable 46 * 47 * @codeCoverageIgnore 48 */ 49 public static function isReadable(string $dir):bool{ 50 return self::exists($dir) && is_readable($dir); 51 } 52 53 /** 54 * Checks whether the given directory is writable 55 * 56 * @codeCoverageIgnore 57 */ 58 public static function isWritable(string $dir):bool{ 59 return self::exists($dir) && is_writable($dir); 60 } 61 62 /** 63 * Creates a directory 64 * 65 * @throws \InvalidArgumentException|\RuntimeException 66 */ 67 public static function create(string $dir, int $permissions = 0o777, bool $recursive = true):string{ 68 $dir = trim($dir); 69 70 if($dir === ''){ 71 throw new InvalidArgumentException('invalid directory'); 72 } 73 74 // $dir exists but is not a directory 75 if(file_exists($dir) && !is_dir($dir)){ 76 throw new InvalidArgumentException(sprintf('cannot create directory: %s already exists as a file or link', $dir)); 77 } 78 79 // $dir doesn't exist and the attempt to create failed 80 if(!file_exists($dir) && !mkdir($dir, $permissions, $recursive)){ 81 throw new RuntimeException(sprintf('could not create directory: %s', $dir)); // @codeCoverageIgnore 82 } 83 84 clearstatcache(); 85 86 return File::realpath($dir); 87 } 88 89 /** 90 * Removes a directory 91 */ 92 public static function remove(string $dir):bool{ 93 94 if($dir === '' || !self::isWritable($dir)){ 95 throw new InvalidArgumentException('invalid directory'); 96 } 97 98 if(!rmdir($dir)){ 99 throw new RuntimeException('could not delete the given directory'); // @codeCoverageIgnore 100 } 101 102 clearstatcache(); 103 104 return true; 105 } 106 107 /** 108 * Returns the relative path from the given directory (realpath) 109 */ 110 public static function relativePath(string $path, string $from, string $separator = DIRECTORY_SEPARATOR):string{ 111 $path = File::realpath($path); 112 $from = File::realpath($from); 113 114 if(is_file($path)){ 115 $path = dirname($path); 116 } 117 118 if(is_file($from)){ 119 $from = dirname($from); 120 } 121 122 return trim(str_replace([$from, '\\', '/'], ['', $separator, $separator], $path), '\\/'); 123 } 124 125}