baseDir = rtrim(str_replace('\\', '/', $baseDataPath), '/') . '/pages/'; } /** * Преобразует Wiki ID (например, "отдел:инструкция") в абсолютный путь к .txt файлу */ public function resolvePath(string $id): string { // Безопасность: заменяем любые попытки выйти из папки (файлы вида ../) $id = str_replace(['..', '\\'], '', $id); // В DokuWiki двоеточие — это разделитель папок. Меняем ":" на "/" $relativePath = str_replace(':', '/', $id); return $this->baseDir . $relativePath . '.txt'; } /** * Проверяет, существует ли физический файл страницы */ public function exists(string $id): bool { return file_exists($this->resolvePath($id)); } /** * Безопасно читает содержимое вики-страницы */ public function read(string $id): string { $filePath = $this->resolvePath($id); if (file_exists($filePath)) { return file_get_contents($filePath) ?: ''; } return ''; } /** * Сохраняет текст страницы, автоматически создавая вложенную структуру папок */ public function save(string $id, string $content): bool { $filePath = $this->resolvePath($id); $dirPath = dirname($filePath); // Если папки для пространства имен не существуют, рекурсивно создаем их if (!is_dir($dirPath)) { if (!mkdir($dirPath, 0755, true) && !is_dir($dirPath)) { return false; // Не удалось создать папку (проблема прав доступа) } } // Записываем данные в файл атомарно return file_put_contents($filePath, $content) !== false; } }