diff --git a/src/Cleaner/Caches.php b/src/Cleaner/Caches.php index 032b56f..084a404 100644 --- a/src/Cleaner/Caches.php +++ b/src/Cleaner/Caches.php @@ -19,7 +19,8 @@ use Dotclear\Plugin\Uninstaller\{ CleanerDescriptor, CleanerParent, TraitCleanerDir, - ValueDescriptor + ValueDescriptor, + Helper\DirTrait }; /** @@ -30,7 +31,7 @@ use Dotclear\Plugin\Uninstaller\{ */ class Caches extends CleanerParent { - use TraitCleanerDir; + use DirTrait; public function __construct() { @@ -72,10 +73,10 @@ class Caches extends CleanerParent public function values(): array { $res = []; - foreach (self::getDirs(DC_TPL_CACHE) as $dir) { + foreach (self::getDirs(DC_TPL_CACHE) as $path => $count) { $res[] = new ValueDescriptor( - ns: $dir['key'], - count: (int) $dir['value'] + ns: $path, + count: $count ); } diff --git a/src/Cleaner/Plugins.php b/src/Cleaner/Plugins.php index 3e09425..e1ac308 100644 --- a/src/Cleaner/Plugins.php +++ b/src/Cleaner/Plugins.php @@ -19,7 +19,7 @@ use Dotclear\Plugin\Uninstaller\{ CleanerDescriptor, CleanerParent, ValueDescriptor, - TraitCleanerDir + Helper\DirTrait }; /** @@ -29,7 +29,7 @@ use Dotclear\Plugin\Uninstaller\{ */ class Plugins extends CleanerParent { - use TraitCleanerDir; + use DirTrait; public function __construct() { @@ -57,14 +57,14 @@ class Plugins extends CleanerParent public function values(): array { - $dirs = self::getDirs(explode(PATH_SEPARATOR, DC_PLUGINS_ROOT)); + $dirs = self::getDirs(DC_PLUGINS_ROOT); sort($dirs); $res = []; - foreach ($dirs as $dir) { + foreach ($dirs as $path => $count) { $res[] = new ValueDescriptor( - ns: $dir['key'], - count: (int) $dir['value'] + ns: $path, + count: $count ); } @@ -74,8 +74,7 @@ class Plugins extends CleanerParent public function execute(string $action, string $ns): bool { if ($action == 'delete') { - $res = explode(PATH_SEPARATOR, DC_PLUGINS_ROOT); - self::delDir($res, $ns, true); + self::delDir(DC_PLUGINS_ROOT, $ns, true); return true; } diff --git a/src/Cleaner/Themes.php b/src/Cleaner/Themes.php index 64f9a4c..a9f65c5 100644 --- a/src/Cleaner/Themes.php +++ b/src/Cleaner/Themes.php @@ -20,7 +20,7 @@ use Dotclear\Plugin\Uninstaller\{ CleanerDescriptor, CleanerParent, ValueDescriptor, - TraitCleanerDir + Helper\DirTrait }; /** @@ -30,7 +30,7 @@ use Dotclear\Plugin\Uninstaller\{ */ class Themes extends CleanerParent { - use TraitCleanerDir; + use DirTrait; public function __construct() { @@ -66,10 +66,10 @@ class Themes extends CleanerParent sort($dirs); $res = []; - foreach ($dirs as $dir) { + foreach ($dirs as $path => $count) { $res[] = new ValueDescriptor( - ns: $dir['key'], - count: (int) $dir['value'] + ns: $path, + count: $count ); } diff --git a/src/Cleaner/Vars.php b/src/Cleaner/Vars.php index 9f92366..40af05e 100644 --- a/src/Cleaner/Vars.php +++ b/src/Cleaner/Vars.php @@ -19,7 +19,7 @@ use Dotclear\Plugin\Uninstaller\{ CleanerDescriptor, CleanerParent, ValueDescriptor, - TraitCleanerDir + Helper\DirTrait }; /** @@ -30,7 +30,7 @@ use Dotclear\Plugin\Uninstaller\{ */ class Vars extends CleanerParent { - use TraitCleanerDir; + use DirTrait; public function __construct() { @@ -59,10 +59,10 @@ class Vars extends CleanerParent public function values(): array { $res = []; - foreach (self::getDirs(DC_VAR) as $dir) { + foreach (self::getDirs(DC_VAR) as $path => $count) { $res[] = new ValueDescriptor( - ns: $dir['key'], - count: (int) $dir['value'] + ns: $path, + count: $count ); } diff --git a/src/Helper/DirTrait.php b/src/Helper/DirTrait.php index 1229189..29d6e6e 100644 --- a/src/Helper/DirTrait.php +++ b/src/Helper/DirTrait.php @@ -12,7 +12,7 @@ */ declare(strict_types=1); -namespace Dotclear\Plugin\Uninstaller; +namespace Dotclear\Plugin\Uninstaller\Helper; use Dotclear\Helper\File\Files; use Dotclear\Helper\File\Path; @@ -20,7 +20,7 @@ use Dotclear\Helper\File\Path; /** * Cleaner helper for files structure. */ -trait TraitCleanerDir +trait DirTrait { /** @var array The excluded files */ public const EXCLUDED = [ @@ -37,46 +37,67 @@ trait TraitCleanerDir '_disabled', ]; - protected static function getDirs(string|array $roots): array + /** + * Get path structure. + * + * @param string $paths The directories paths to scan + * + * @return array The path structure + */ + protected static function getDirs(string $paths): array { - if (!is_array($roots)) { - $roots = [$roots]; - } - $rs = []; - $i = 0; - foreach ($roots as $root) { - $dirs = Files::scanDir($root); + $paths = explode(PATH_SEPARATOR, $paths); + + $stack = []; + foreach ($paths as $path) { + $dirs = Files::scanDir($path); foreach ($dirs as $k) { - if (in_array($k, self::EXCLUDED) || !is_dir($root . DIRECTORY_SEPARATOR . $k)) { + if (!is_string($k) || in_array($k, self::EXCLUDED) || !is_dir($path . DIRECTORY_SEPARATOR . $k)) { continue; } - $rs[$i]['key'] = $k; - $rs[$i]['value'] = count(self::scanDir($root . DIRECTORY_SEPARATOR . $k)); - $i++; + $stack[$k] = count(self::scanDir($path . DIRECTORY_SEPARATOR . $k)); } } - return $rs; + return $stack; } - protected static function delDir(string|array $roots, string $folder, bool $delfolder = true): bool + /** + * Delete path structure. + * + * @param string $paths The directories paths to scan + * @param string $folder The folder in path + * @param bool $delete Also delete folder itself + * + * @return bool True on success + */ + protected static function delDir(string $paths, string $folder, bool $delete = true): bool { + $paths = explode(PATH_SEPARATOR, $paths); + if (strpos($folder, DIRECTORY_SEPARATOR)) { return false; } - if (!is_array($roots)) { - $roots = [$roots]; - } - foreach ($roots as $root) { - if (file_exists($root . DIRECTORY_SEPARATOR . $folder)) { - return self::delTree($root . DIRECTORY_SEPARATOR . $folder, $delfolder); + + foreach ($paths as $path) { + if (file_exists($path . DIRECTORY_SEPARATOR . $folder)) { + return self::delTree($path . DIRECTORY_SEPARATOR . $folder, $delete); } } return false; } - protected static function scanDir(string $path, string $dir = '', array $res = []): array + /** + * Scan recursively a directory. + * + * @param string $path The directory path to scan + * @param string $dir The current directory + * @param array $stack The paths stack + * + * @return array The paths stack + */ + private static function scanDir(string $path, string $dir = '', array $stack = []): array { $path = Path::real($path); if ($path === false || !is_dir($path) || !is_readable($path)) { @@ -89,35 +110,43 @@ trait TraitCleanerDir continue; } if (is_dir($path . DIRECTORY_SEPARATOR . $file)) { - $res[] = $file; - $res = self::scanDir($path . DIRECTORY_SEPARATOR . $file, $dir . DIRECTORY_SEPARATOR . $file, $res); + $stack[] = $file; + $stack = self::scanDir($path . DIRECTORY_SEPARATOR . $file, $dir . DIRECTORY_SEPARATOR . $file, $stack); } else { - $res[] = empty($dir) ? $file : $dir . DIRECTORY_SEPARATOR . $file; + $stack[] = empty($dir) ? $file : $dir . DIRECTORY_SEPARATOR . $file; } } - return $res; + return $stack; } - protected static function delTree(string $dir, bool $delroot = true): bool + /** + * Delete path tree. + * + * @param string $path The directory path + * @param bool $delete Also delete the directory path + * + * @return bool True on success + */ + private static function delTree(string $path, bool $delete = true): bool { - if (!is_dir($dir) || !is_readable($dir)) { + if (!is_dir($path) || !is_readable($path)) { return false; } - if (substr($dir, -1) != DIRECTORY_SEPARATOR) { - $dir .= DIRECTORY_SEPARATOR; + if (substr($path, -1) != DIRECTORY_SEPARATOR) { + $path .= DIRECTORY_SEPARATOR; } - if (($d = @dir($dir)) === false) { + if (($d = @dir($path)) === false) { return false; } while (($entryname = $d->read()) !== false) { if ($entryname != '.' && $entryname != '..') { - if (is_dir($dir . DIRECTORY_SEPARATOR . $entryname)) { - if (!self::delTree($dir . DIRECTORY_SEPARATOR . $entryname)) { + if (is_dir($path . DIRECTORY_SEPARATOR . $entryname)) { + if (!self::delTree($path . DIRECTORY_SEPARATOR . $entryname)) { return false; } } else { - if (!@unlink($dir . DIRECTORY_SEPARATOR . $entryname)) { + if (!@unlink($path . DIRECTORY_SEPARATOR . $entryname)) { return false; } } @@ -125,8 +154,8 @@ trait TraitCleanerDir } $d->close(); - if ($delroot) { - return @rmdir($dir); + if ($delete) { + return @rmdir($path); } return true;