pathProvider->resolvePath($path); } public function isDirectoryWritable(string $path): bool { $resolvedPath = $this->resolvePath($path); if (! is_dir($resolvedPath)) { return false; } return is_writable($resolvedPath); } public function canCreateDirectory(string $path): bool { $resolvedPath = $this->resolvePath($path); // Prüfe, ob Parent-Directory existiert und schreibbar ist $parentDir = dirname($resolvedPath); if (! is_dir($parentDir)) { return $this->canCreateDirectory(dirname($path)); } return is_writable($parentDir); } public function canWriteFile(string $path): bool { $resolvedPath = $this->resolvePath($path); // Wenn Datei existiert, prüfe ob sie schreibbar ist if (file_exists($resolvedPath)) { return is_writable($resolvedPath); } // Wenn Datei nicht existiert, prüfe ob Directory schreibbar ist $dir = dirname($path); return $this->isDirectoryWritable($dir) || $this->canCreateDirectory($dir); } public function canReadFile(string $path): bool { $resolvedPath = $this->resolvePath($path); return file_exists($resolvedPath) && is_readable($resolvedPath); } public function canDeleteFile(string $path): bool { $resolvedPath = $this->resolvePath($path); if (! file_exists($resolvedPath)) { return false; } // Datei muss schreibbar sein UND Directory muss schreibbar sein $dir = dirname($resolvedPath); return is_writable($resolvedPath) && is_writable($dir); } public function getPermissionString(string $path): string { $resolvedPath = $this->resolvePath($path); if (! file_exists($resolvedPath)) { return 'not found'; } $perms = fileperms($resolvedPath); $info = ''; // Type if (($perms & 0xC000) == 0xC000) { $info = 's'; // Socket } elseif (($perms & 0xA000) == 0xA000) { $info = 'l'; // Symbolic Link } elseif (($perms & 0x8000) == 0x8000) { $info = 'f'; // Regular file } elseif (($perms & 0x6000) == 0x6000) { $info = 'b'; // Block special } elseif (($perms & 0x4000) == 0x4000) { $info = 'd'; // Directory } elseif (($perms & 0x2000) == 0x2000) { $info = 'c'; // Character special } elseif (($perms & 0x1000) == 0x1000) { $info = 'p'; // FIFO pipe } else { $info = 'u'; // Unknown } // Owner $info .= (($perms & 0x0100) ? 'r' : '-'); $info .= (($perms & 0x0080) ? 'w' : '-'); $info .= (($perms & 0x0040) ? (($perms & 0x0800) ? 's' : 'x') : (($perms & 0x0800) ? 'S' : '-')); // Group $info .= (($perms & 0x0020) ? 'r' : '-'); $info .= (($perms & 0x0010) ? 'w' : '-'); $info .= (($perms & 0x0008) ? (($perms & 0x0400) ? 's' : 'x') : (($perms & 0x0400) ? 'S' : '-')); // World $info .= (($perms & 0x0004) ? 'r' : '-'); $info .= (($perms & 0x0002) ? 'w' : '-'); $info .= (($perms & 0x0001) ? (($perms & 0x0200) ? 't' : 'x') : (($perms & 0x0200) ? 'T' : '-')); return $info; } public function getDiagnosticInfo(string $path): array { $resolvedPath = $this->resolvePath($path); $realPath = realpath($resolvedPath) ?: $resolvedPath; return [ 'path' => $path, 'resolved_path' => $resolvedPath, 'real_path' => $realPath, 'exists' => file_exists($resolvedPath), 'is_file' => is_file($resolvedPath), 'is_dir' => is_dir($resolvedPath), 'is_readable' => is_readable($resolvedPath), 'is_writable' => is_writable($resolvedPath), 'permissions' => $this->getPermissionString($path), 'owner' => file_exists($resolvedPath) ? posix_getpwuid(fileowner($resolvedPath))['name'] ?? 'unknown' : null, 'group' => file_exists($resolvedPath) ? posix_getgrgid(filegroup($resolvedPath))['name'] ?? 'unknown' : null, 'parent_dir' => dirname($resolvedPath), 'parent_writable' => is_dir(dirname($resolvedPath)) && is_writable(dirname($resolvedPath)), ]; } /** * Get current file permissions as FilePermissions value object */ public function getPermissions(string $path): ?FilePermissions { $resolvedPath = $this->resolvePath($path); if (! file_exists($resolvedPath)) { return null; } $perms = fileperms($resolvedPath); // Extract only permission bits (last 9 bits) $mode = $perms & 0777; return new FilePermissions($mode); } /** * Set file permissions using FilePermissions value object */ public function setPermissions(string $path, FilePermissions $permissions): bool { $resolvedPath = $this->resolvePath($path); if (! file_exists($resolvedPath)) { return false; } return @chmod($resolvedPath, $permissions->mode); } /** * Ensure file has specific permissions, set them if different */ public function ensurePermissions(string $path, FilePermissions $permissions): bool { $current = $this->getPermissions($path); if ($current === null) { return false; // File doesn't exist } if ($current->equals($permissions)) { return true; // Already has correct permissions } return $this->setPermissions($path, $permissions); } }