Skip to content

Commit

Permalink
fix: 重构 ToolsExtend 文件系统操作工具
Browse files Browse the repository at this point in the history
  • Loading branch information
zoujingli committed Oct 17, 2024
1 parent 9c1d02f commit a440863
Show file tree
Hide file tree
Showing 6 changed files with 79 additions and 54 deletions.
2 changes: 1 addition & 1 deletion src/Library.php
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ public function register()
{
// 动态加载全局配置
[$dir, $ext] = [$this->app->getBasePath(), $this->app->getConfigExt()];
ToolsExtend::findFilesArray($dir, 2, function (SplFileInfo $info) use ($ext) {
ToolsExtend::find($dir, 2, function (SplFileInfo $info) use ($ext) {
$info->isFile() && $info->getBasename() === "sys{$ext}" && include_once $info->getPathname();
});
if (is_file($file = "{$dir}common{$ext}")) include_once $file;
Expand Down
4 changes: 2 additions & 2 deletions src/extend/PhinxExtend.php
Original file line number Diff line number Diff line change
Expand Up @@ -338,13 +338,13 @@ private function _create_{$table}()
private static function nextFile(string $class): string
{
[$snake, $items] = [Str::snake($class), [20010000000000]];
ToolsExtend::findFilesArray(syspath('database/migrations'), 1, function (SplFileInfo $info) use ($snake, &$items) {
ToolsExtend::find(syspath('database/migrations'), 1, function (SplFileInfo $info) use ($snake, &$items) {
if ($info->isFile()) {
$bname = pathinfo($info->getBasename(), PATHINFO_FILENAME);
$items[] = $version = intval(substr($bname, 0, 14));
if ($snake === substr($bname, 15) && unlink($info->getRealPath())) {
if (is_dir($dataPath = $info->getPath() . DIRECTORY_SEPARATOR . $version)) {
ToolsExtend::removeEmptyDirectory($dataPath);
ToolsExtend::remove($dataPath);
}
}
}
Expand Down
113 changes: 69 additions & 44 deletions src/extend/ToolsExtend.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
use FilesystemIterator;
use Generator;
use SplFileInfo;
use think\admin\Exception;

/**
* 通用工具扩展
Expand All @@ -30,6 +31,44 @@
*/
class ToolsExtend
{

/**
* 扫描目录下的文件列表
* @param string $path 扫描目录
* @param ?integer $depth 扫描深度
* @param string $ext 筛选后缀
* @param boolean $short 相对路径
* @return array
*/
public static function scan(string $path, ?int $depth = null, string $ext = '', bool $short = true): array
{
return static::find($path, $depth, function (SplFileInfo $info) use ($ext) {
return $info->isDir() || $ext === '' || strtolower($info->getExtension()) === strtolower($ext);
}, $short);
}

/**
* 扫描目录并返回文件路径数组
* @param string $path 扫描目录
* @param ?integer $depth 扫描深度
* @param ?Closure $filter 文件过滤,返回 false 表示放弃
* @param boolean $short 是否返回相对于给定路径的短路径
* @return array 包含文件路径的数组
*/
public static function find(string $path, ?int $depth = null, ?Closure $filter = null, bool $short = true): array
{
[$info, $files] = [new SplFileInfo($path), []];
if ($info->isDir() || $info->isFile()) {
if ($info->isFile() && ($filter === null || $filter($info) !== false)) {
$files[] = $short ? $info->getBasename() : $info->getPathname();
}
if ($info->isDir()) foreach (static::findFilesYield($info->getPathname(), $depth, $filter) as $file) {
$files[] = $short ? substr($file->getPathname(), strlen($info->getPathname()) + 1) : $file->getPathname();
}
}
return $files;
}

/**
* 深度拷贝到指定目录
* @param string $frdir 来源目录
Expand All @@ -39,13 +78,13 @@ class ToolsExtend
* @param boolean $remove 删除文件
* @return boolean
*/
public static function copyfile(string $frdir, string $todir, array $files = [], bool $force = true, bool $remove = true): bool
public static function copy(string $frdir, string $todir, array $files = [], bool $force = true, bool $remove = true): bool
{
$frdir = rtrim($frdir, '\\/') . DIRECTORY_SEPARATOR;
$todir = rtrim($todir, '\\/') . DIRECTORY_SEPARATOR;
// 扫描目录文件
if (empty($files) && is_dir($frdir)) {
$files = static::findFilesArray($frdir, null, function (SplFileInfo $info) {
$files = static::find($frdir, null, function (SplFileInfo $info) {
return $info->getBasename()[0] !== '.';
});
}
Expand All @@ -60,7 +99,7 @@ public static function copyfile(string $frdir, string $todir, array $files = [],
$remove && unlink($fromPath);
}
// 删除来源目录
$remove && static::removeEmptyDirectory($frdir);
$remove && static::remove($frdir);
return true;
}

Expand All @@ -69,54 +108,41 @@ public static function copyfile(string $frdir, string $todir, array $files = [],
* @param string $path
* @return boolean
*/
public static function removeEmptyDirectory(string $path): bool
public static function remove(string $path): bool
{
if (!file_exists($path)) return true;
if (is_file($path)) return unlink($path);
$dirs = [$path];
iterator_to_array(self::findFilesYield($path, null, function (SplFileInfo $file) use (&$dirs) {
$file->isDir() ? $dirs[] = $file->getPathname() : unlink($file->getPathname());
}));
usort($dirs, function ($a, $b) {
return strlen($b) <=> strlen($a);
});
foreach ($dirs as $dir) rmdir($dir);
foreach ($dirs as $dir) file_exists($dir) && is_dir($dir) && rmdir($dir);
return !file_exists($path);
}

/**
* 扫描目录列表
* @param string $path 扫描目录
* @param ?integer $depth 扫描深度
* @param string $filterExt 筛选后缀
* @param boolean $shortPath 相对路径
* @return array
* 兼容旧方式调用
* @param string $method
* @param array $arguments
* @return array|bool
* @throws \think\admin\Exception
*/
public static function scanDirectory(string $path, ?int $depth = null, string $filterExt = '', bool $shortPath = true): array
public static function __callStatic(string $method, array $arguments)
{
return static::findFilesArray($path, $depth, function (SplFileInfo $info) use ($filterExt, &$files) {
return $info->isDir() || $filterExt === '' || strtolower($info->getExtension()) === strtolower($filterExt);
}, $shortPath);
}

/**
* 扫描指定目录并返回文件路径数组
* @param string $path 扫描目录
* @param ?integer $depth 扫描深度
* @param ?Closure $filter 文件过滤,返回 false 表示放弃
* @param boolean $short 是否返回相对于给定路径的短路径
* @return array 包含文件路径的数组
*/
public static function findFilesArray(string $path, ?int $depth = null, ?Closure $filter = null, bool $short = true): array
{
[$info, $files] = [new SplFileInfo($path), []];
if ($info->isDir() || $info->isFile()) {
if ($info->isFile() && ($filter === null || $filter($info) !== false)) {
$files[] = $short ? $info->getBasename() : $info->getPathname();
}
if ($info->isDir()) foreach (static::findFilesYield($info->getPathname(), $depth, $filter) as $file) {
$files[] = $short ? substr($file->getPathname(), strlen($info->getPathname()) + 1) : $file->getPathname();
}
$methods = [
'copyfile' => 'copy',
'scandirectory' => 'scan',
'findfilesarray' => 'find',
'removeemptydirectory' => 'remove',
];
if ($real = $methods[strtolower($method)] ?? null) {
return self::{$real}(...$arguments);
} else {
throw new Exception("method not exists: ToolsExtend::{$method}()");
}
return $files;
}

/**
Expand All @@ -130,15 +156,14 @@ public static function findFilesArray(string $path, ?int $depth = null, ?Closure
*/
private static function findFilesYield(string $path, ?int $depth = null, ?Closure $filter = null, bool $appendPath = false, int $currDepth = 1): Generator
{
if (file_exists($path) && is_dir($path) && (!is_numeric($depth) || $currDepth <= $depth)) {
if (file_exists($path) && is_dir($path) && (is_null($depth) || $currDepth <= $depth)) {
foreach (new FilesystemIterator($path, FilesystemIterator::SKIP_DOTS) as $item) {
if ($filter === null || $filter($item) !== false) {
if ($item->isDir() && !$item->isLink()) {
$appendPath && yield $item;
yield from static::findFilesYield($item->getPathname(), $depth, $filter, $appendPath, $currDepth + 1);
} else {
yield $item;
}
if ($filter !== null && $filter($item) === false) continue;
if ($item->isDir() && !$item->isLink()) {
$appendPath && yield $item;
yield from static::findFilesYield($item->getPathname(), $depth, $filter, $appendPath, $currDepth + 1);
} else {
yield $item;
}
}
}
Expand Down
6 changes: 3 additions & 3 deletions src/service/NodeService.php
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ public static function getMethods(bool $force = false): array
$ignoreMethods = get_class_methods('\think\admin\Controller');
$ignoreAppNames = Library::$sapp->config->get('app.rbac_ignore', []);
// 扫描所有代码控制器节点,更新节点缓存
foreach (ToolsExtend::scanDirectory(Library::$sapp->getBasePath(), null, 'php') as $name) {
foreach (ToolsExtend::scan(Library::$sapp->getBasePath(), null, 'php') as $name) {
if (preg_match("|^(\w+)/controller/(.+)\.php$|i", strtr($name, '\\', '/'), $matches)) {
[, $appName, $className] = $matches;
if (in_array($appName, $ignoreAppNames)) continue;
Expand All @@ -130,7 +130,7 @@ public static function getMethods(bool $force = false): array
foreach (Plugin::get() as $appName => $plugin) {
if (in_array($appName, $ignoreAppNames)) continue;
[$appPath, $appSpace] = [$plugin['path'], $plugin['space']];
foreach (ToolsExtend::scanDirectory($appPath, null, 'php') as $name) {
foreach (ToolsExtend::scan($appPath, null, 'php') as $name) {
if (preg_match("|^.*?controller/(.+)\.php$|i", strtr($name, '\\', '/'), $matches)) {
static::_parseClass($appName, $appSpace, $matches[1], $ignoreMethods, $data);
}
Expand Down Expand Up @@ -208,7 +208,7 @@ public function __call(string $name, array $arguments)
public static function __callStatic(string $name, array $arguments)
{
if ($name === 'scanDirectory') {
return ToolsExtend::scanDirectory(...$arguments);
return ToolsExtend::scan(...$arguments);
} elseif ($name === 'getModules') {
return ModuleService::getModules(...$arguments);
} else {
Expand Down
6 changes: 3 additions & 3 deletions src/support/command/Publish.php
Original file line number Diff line number Diff line change
Expand Up @@ -87,15 +87,15 @@ private function copy(string $copy, bool $force = false)
{
// 复制系统配置文件
$frdir = rtrim($copy, '\\/') . DIRECTORY_SEPARATOR . 'config';
ToolsExtend::copyfile($frdir, syspath('config'), [], $force, false);
ToolsExtend::copy($frdir, syspath('config'), [], $force, false);

// 复制静态资料文件
$frdir = rtrim($copy, '\\/') . DIRECTORY_SEPARATOR . 'public';
ToolsExtend::copyfile($frdir, syspath('public'), [], true, false);
ToolsExtend::copy($frdir, syspath('public'), [], true, false);

// 复制数据库脚本
$frdir = rtrim($copy, '\\/') . DIRECTORY_SEPARATOR . 'database';
ToolsExtend::copyfile($frdir, syspath('database/migrations'), [], $force, false);
ToolsExtend::copy($frdir, syspath('database/migrations'), [], $force, false);
}

/**
Expand Down
2 changes: 1 addition & 1 deletion src/support/middleware/MultAccess.php
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ private function loadMultiApp(string $appPath): bool
// 加载应用函数文件
if (is_file($file = "{$appPath}common{$ext}")) include_once $file;
// 加载应用配置文件
ToolsExtend::findFilesArray($appPath . 'config', 1, function (SplFileInfo $info) use ($ext) {
ToolsExtend::find($appPath . 'config', 1, function (SplFileInfo $info) use ($ext) {
if ($info->isFile() && strtolower(".{$info->getExtension()}") === $ext) {
$this->app->config->load($info->getPathname(), $info->getBasename($ext));
}
Expand Down

0 comments on commit a440863

Please sign in to comment.