v2.2.0: includes/Tools/FileManagerTools.php
This commit is contained in:
@@ -0,0 +1,104 @@
|
||||
<?php
|
||||
namespace AskTamMCP\Tools;
|
||||
defined('ABSPATH') || exit;
|
||||
|
||||
/**
|
||||
* FileManagerTools — sandboxed to /wp-content/uploads/
|
||||
*/
|
||||
class FileManagerTools {
|
||||
|
||||
private static function safePath(string $rel): string {
|
||||
$uploads = wp_upload_dir();
|
||||
$base_dir = rtrim($uploads['basedir'], '/');
|
||||
// Strip leading slashes and normalize
|
||||
$rel = ltrim(str_replace(['..', '\\'], '', $rel), '/');
|
||||
$full = $base_dir . '/' . $rel;
|
||||
// Double-check it's still inside uploads
|
||||
if (strpos(realpath($full) ?: $full, $base_dir) !== 0) {
|
||||
throw new \RuntimeException("Path outside uploads directory.");
|
||||
}
|
||||
return $full;
|
||||
}
|
||||
|
||||
public static function listDir(array $args): array {
|
||||
$rel = $args['path'] ?? '';
|
||||
$path = self::safePath($rel);
|
||||
if (!is_dir($path)) throw new \RuntimeException("Directory not found: $rel");
|
||||
|
||||
$items = [];
|
||||
foreach (scandir($path) as $entry) {
|
||||
if ($entry === '.' || $entry === '..') continue;
|
||||
$full = $path . '/' . $entry;
|
||||
$items[] = [
|
||||
'name' => $entry,
|
||||
'type' => is_dir($full) ? 'dir' : 'file',
|
||||
'size' => is_file($full) ? filesize($full) : null,
|
||||
'modified' => date('Y-m-d H:i:s', filemtime($full)),
|
||||
'url' => is_file($full) ? wp_upload_dir()['baseurl'] . '/' . ltrim($rel . '/' . $entry, '/') : null,
|
||||
];
|
||||
}
|
||||
usort($items, fn($a,$b) => ($a['type'] === $b['type']) ? strcmp($a['name'],$b['name']) : ($a['type']==='dir'?-1:1));
|
||||
return ['path'=>$rel?:'/','items'=>$items,'count'=>count($items)];
|
||||
}
|
||||
|
||||
public static function readFile(array $args): array {
|
||||
$rel = $args['path'] ?? '';
|
||||
$path = self::safePath($rel);
|
||||
if (!is_file($path)) throw new \RuntimeException("File not found: $rel");
|
||||
|
||||
$mime = mime_content_type($path) ?: 'application/octet-stream';
|
||||
$size = filesize($path);
|
||||
$text_mimes = ['text/','application/json','application/xml','application/javascript'];
|
||||
$is_text = array_filter($text_mimes, fn($m) => str_starts_with($mime, $m));
|
||||
|
||||
return [
|
||||
'path' => $rel,
|
||||
'size' => $size,
|
||||
'mime' => $mime,
|
||||
'modified' => date('Y-m-d H:i:s', filemtime($path)),
|
||||
'content' => $is_text ? file_get_contents($path) : base64_encode(file_get_contents($path)),
|
||||
'encoding' => $is_text ? 'text' : 'base64',
|
||||
];
|
||||
}
|
||||
|
||||
public static function deleteFile(array $args): array {
|
||||
$rel = $args['path'] ?? '';
|
||||
$path = self::safePath($rel);
|
||||
if (!file_exists($path)) throw new \RuntimeException("File not found: $rel");
|
||||
if (is_dir($path)) throw new \RuntimeException("Use delete_directory to remove directories.");
|
||||
if (!unlink($path)) throw new \RuntimeException("Failed to delete: $rel");
|
||||
return ['path'=>$rel,'deleted'=>true];
|
||||
}
|
||||
|
||||
public static function deleteDirectory(array $args): array {
|
||||
$rel = $args['path'] ?? '';
|
||||
if (empty($rel)) throw new \RuntimeException("Cannot delete uploads root.");
|
||||
$path = self::safePath($rel);
|
||||
if (!is_dir($path)) throw new \RuntimeException("Directory not found: $rel");
|
||||
|
||||
$files = new \RecursiveIteratorIterator(
|
||||
new \RecursiveDirectoryIterator($path, \RecursiveDirectoryIterator::SKIP_DOTS),
|
||||
\RecursiveIteratorIterator::CHILD_FIRST
|
||||
);
|
||||
foreach ($files as $f) {
|
||||
$f->isDir() ? rmdir($f->getRealPath()) : unlink($f->getRealPath());
|
||||
}
|
||||
rmdir($path);
|
||||
return ['path'=>$rel,'deleted'=>true];
|
||||
}
|
||||
|
||||
public static function getUploadsInfo(array $args): array {
|
||||
$uploads = wp_upload_dir();
|
||||
$base = $uploads['basedir'];
|
||||
$size = 0;
|
||||
foreach (new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($base)) as $f) {
|
||||
if ($f->isFile()) $size += $f->getSize();
|
||||
}
|
||||
return [
|
||||
'base_dir' => $base,
|
||||
'base_url' => $uploads['baseurl'],
|
||||
'total_size' => $size,
|
||||
'total_size_human' => size_format($size),
|
||||
];
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user