From 27dd871878bfdf9afa6e4c101336eba3d86058d0 Mon Sep 17 00:00:00 2001 From: Anyon Date: Mon, 31 Aug 2020 20:26:30 +0800 Subject: [PATCH] ComposerUpdate --- app/admin/controller/api/Update.php | 3 +- vendor/composer/autoload_classmap.php | 1 - vendor/composer/autoload_static.php | 1 - vendor/composer/installed.json | 16 +- vendor/services.php | 2 +- .../zoujingli/think-library/src/Library.php | 5 + .../think-library/src/command/Install.php | 6 +- .../src/service/AdminService.php | 1 + .../src/service/InstallService.php | 196 ------------------ .../src/service/ModuleService.php | 188 +++++++++++++++-- 10 files changed, 184 insertions(+), 235 deletions(-) delete mode 100644 vendor/zoujingli/think-library/src/service/InstallService.php diff --git a/app/admin/controller/api/Update.php b/app/admin/controller/api/Update.php index 3405fdb00..a9fc24460 100644 --- a/app/admin/controller/api/Update.php +++ b/app/admin/controller/api/Update.php @@ -16,7 +16,6 @@ namespace app\admin\controller\api; use think\admin\Controller; -use think\admin\service\InstallService; use think\admin\service\ModuleService; /** @@ -50,7 +49,7 @@ class Update extends Controller */ public function node() { - $this->success('获取文件列表成功!', InstallService::instance()->getList( + $this->success('获取文件列表成功!', ModuleService::instance()->getChanges( json_decode($this->request->post('rules', '[]', ''), true), json_decode($this->request->post('ignore', '[]', ''), true) )); diff --git a/vendor/composer/autoload_classmap.php b/vendor/composer/autoload_classmap.php index 4926e7c6e..77a7a328d 100644 --- a/vendor/composer/autoload_classmap.php +++ b/vendor/composer/autoload_classmap.php @@ -299,7 +299,6 @@ return array( 'think\\admin\\service\\AdminService' => $vendorDir . '/zoujingli/think-library/src/service/AdminService.php', 'think\\admin\\service\\CaptchaService' => $vendorDir . '/zoujingli/think-library/src/service/CaptchaService.php', 'think\\admin\\service\\ExpressService' => $vendorDir . '/zoujingli/think-library/src/service/ExpressService.php', - 'think\\admin\\service\\InstallService' => $vendorDir . '/zoujingli/think-library/src/service/InstallService.php', 'think\\admin\\service\\InterfaceService' => $vendorDir . '/zoujingli/think-library/src/service/InterfaceService.php', 'think\\admin\\service\\MenuService' => $vendorDir . '/zoujingli/think-library/src/service/MenuService.php', 'think\\admin\\service\\MessageService' => $vendorDir . '/zoujingli/think-library/src/service/MessageService.php', diff --git a/vendor/composer/autoload_static.php b/vendor/composer/autoload_static.php index 096e98773..2764cc804 100644 --- a/vendor/composer/autoload_static.php +++ b/vendor/composer/autoload_static.php @@ -436,7 +436,6 @@ class ComposerStaticInitb55556af42203bcef68382c66bc39c70 'think\\admin\\service\\AdminService' => __DIR__ . '/..' . '/zoujingli/think-library/src/service/AdminService.php', 'think\\admin\\service\\CaptchaService' => __DIR__ . '/..' . '/zoujingli/think-library/src/service/CaptchaService.php', 'think\\admin\\service\\ExpressService' => __DIR__ . '/..' . '/zoujingli/think-library/src/service/ExpressService.php', - 'think\\admin\\service\\InstallService' => __DIR__ . '/..' . '/zoujingli/think-library/src/service/InstallService.php', 'think\\admin\\service\\InterfaceService' => __DIR__ . '/..' . '/zoujingli/think-library/src/service/InterfaceService.php', 'think\\admin\\service\\MenuService' => __DIR__ . '/..' . '/zoujingli/think-library/src/service/MenuService.php', 'think\\admin\\service\\MessageService' => __DIR__ . '/..' . '/zoujingli/think-library/src/service/MessageService.php', diff --git a/vendor/composer/installed.json b/vendor/composer/installed.json index 4a7fb2a89..5f6cf8d0c 100644 --- a/vendor/composer/installed.json +++ b/vendor/composer/installed.json @@ -573,8 +573,8 @@ }, { "name": "symfony/options-resolver", - "version": "v3.4.43", - "version_normalized": "3.4.43.0", + "version": "v3.4.44", + "version_normalized": "3.4.44.0", "source": { "type": "git", "url": "https://github.com/symfony/options-resolver.git", @@ -958,17 +958,17 @@ }, { "name": "zoujingli/think-library", - "version": "v6.0.1", - "version_normalized": "6.0.1.0", + "version": "v6.0.2", + "version_normalized": "6.0.2.0", "source": { "type": "git", "url": "https://github.com/zoujingli/ThinkLibrary.git", - "reference": "a5c1e18d0e57dd0a83174793f09cca5ba592b773" + "reference": "a498595d637568481601091985ae22d5cd05a057" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/zoujingli/ThinkLibrary/zipball/a5c1e18d0e57dd0a83174793f09cca5ba592b773", - "reference": "a5c1e18d0e57dd0a83174793f09cca5ba592b773", + "url": "https://api.github.com/repos/zoujingli/ThinkLibrary/zipball/a498595d637568481601091985ae22d5cd05a057", + "reference": "a498595d637568481601091985ae22d5cd05a057", "shasum": "", "mirrors": [ { @@ -985,7 +985,7 @@ "ext-mbstring": "*", "topthink/framework": "^6.0" }, - "time": "2020-08-28T11:32:28+00:00", + "time": "2020-08-31T11:59:58+00:00", "type": "library", "extra": { "think": { diff --git a/vendor/services.php b/vendor/services.php index 84cc7093c..da4051860 100644 --- a/vendor/services.php +++ b/vendor/services.php @@ -1,5 +1,5 @@ 'think\\admin\\Library', diff --git a/vendor/zoujingli/think-library/src/Library.php b/vendor/zoujingli/think-library/src/Library.php index 058445c21..f2b09fcfa 100644 --- a/vendor/zoujingli/think-library/src/Library.php +++ b/vendor/zoujingli/think-library/src/Library.php @@ -38,6 +38,11 @@ use function Composer\Autoload\includeFile; */ class Library extends Service { + /** + * 扩展库版本号 + */ + const VERSION = '6.0.2'; + /** * 启动服务 */ diff --git a/vendor/zoujingli/think-library/src/command/Install.php b/vendor/zoujingli/think-library/src/command/Install.php index 978d1da6b..abf8776e0 100644 --- a/vendor/zoujingli/think-library/src/command/Install.php +++ b/vendor/zoujingli/think-library/src/command/Install.php @@ -16,7 +16,7 @@ namespace think\admin\command; use think\admin\Command; -use think\admin\service\InstallService; +use think\admin\service\ModuleService; use think\console\Input; use think\console\input\Argument; use think\console\Output; @@ -114,10 +114,10 @@ class Install extends Command protected function installFile() { - $data = InstallService::instance()->grenerateDifference($this->rules, $this->ignore); + $data = ModuleService::instance()->grenerateDifference($this->rules, $this->ignore); if (empty($data)) $this->output->writeln('No need to update the file if the file comparison is consistent'); else foreach ($data as $file) { - [$state, $mode, $name] = InstallService::instance()->updateFileByDownload($file); + [$state, $mode, $name] = ModuleService::instance()->updateFileByDownload($file); if ($state) { if ($mode === 'add') $this->output->writeln("--- {$name} add successfully"); if ($mode === 'mod') $this->output->writeln("--- {$name} update successfully"); diff --git a/vendor/zoujingli/think-library/src/service/AdminService.php b/vendor/zoujingli/think-library/src/service/AdminService.php index 51b46b7fe..3740fb7e5 100644 --- a/vendor/zoujingli/think-library/src/service/AdminService.php +++ b/vendor/zoujingli/think-library/src/service/AdminService.php @@ -74,6 +74,7 @@ class AdminService extends Service if ($this->isSuper()) return true; $service = NodeService::instance(); [$real, $nodes] = [$service->fullnode($node), $service->getMethods()]; + // 以下代码为兼容 win 控制器不区分大小写的验证问题 foreach ($nodes as $key => $rule) { if (strpos($key, '_') !== false && strpos($key, '/') !== false) { $attr = explode('/', $key); diff --git a/vendor/zoujingli/think-library/src/service/InstallService.php b/vendor/zoujingli/think-library/src/service/InstallService.php deleted file mode 100644 index ca2e199a4..000000000 --- a/vendor/zoujingli/think-library/src/service/InstallService.php +++ /dev/null @@ -1,196 +0,0 @@ -root = strtr($this->app->getRootPath(), '\\', '/'); - $this->server = ModuleService::instance()->getServer(); - } - - /** - * 获取文件信息列表 - * @param array $rules 文件规则 - * @param array $ignore 忽略规则 - * @param array $data 扫描结果列表 - * @return array - */ - public function getList(array $rules, array $ignore = [], array $data = []): array - { - // 扫描规则文件 - foreach ($rules as $key => $rule) { - $name = strtr(trim($rule, '\\/'), '\\', '/'); - $data = array_merge($data, $this->_scanList($this->root . $name)); - } - // 清除忽略文件 - foreach ($data as $key => $item) foreach ($ignore as $ign) { - if (stripos($item['name'], $ign) === 0) unset($data[$key]); - } - // 返回文件数据 - return ['rules' => $rules, 'ignore' => $ignore, 'list' => $data]; - } - - /** - * 获取文件差异数据 - * @param array $rules 文件规则 - * @param array $ignore 忽略规则 - * @return array - */ - public function grenerateDifference(array $rules = [], array $ignore = []): array - { - [$rules1, $ignore1, $data] = [$rules, $ignore, []]; - $result = json_decode(HttpExtend::post($this->server . '/admin/api.update/node', [ - 'rules' => json_encode($rules1), 'ignore' => json_encode($ignore1), - ]), true); - if (!empty($result['code'])) { - $new = $this->getList($result['data']['rules'], $result['data']['ignore']); - foreach ($this->_grenerateDifferenceContrast($result['data']['list'], $new['list']) as $file) { - if (in_array($file['type'], ['add', 'del', 'mod'])) foreach ($rules1 as $rule) { - if (stripos($file['name'], $rule) === 0) $data[] = $file; - } - } - } - return $data; - } - - /** - * 下载并更新文件 - * @param array $file 文件信息 - * @return array - */ - public function updateFileByDownload(array $file): array - { - if (in_array($file['type'], ['add', 'mod'])) { - if ($this->_downloadFile(encode($file['name']))) { - return [true, $file['type'], $file['name']]; - } else { - return [false, $file['type'], $file['name']]; - } - } elseif (in_array($file['type'], ['del'])) { - $real = $this->root . $file['name']; - if (is_file($real) && unlink($real)) { - $this->_removeEmptyDirectory(dirname($real)); - return [true, $file['type'], $file['name']]; - } else { - return [false, $file['type'], $file['name']]; - } - } - } - - /** - * 下载更新文件内容 - * @param string $encode - * @return boolean|integer - */ - private function _downloadFile($encode) - { - $source = $this->server . '/admin/api.update/get?encode=' . $encode; - $result = json_decode(HttpExtend::get($source), true); - if (empty($result['code'])) return false; - $filename = $this->root . decode($encode); - file_exists(dirname($filename)) || mkdir(dirname($filename), 0755, true); - return file_put_contents($filename, base64_decode($result['data']['content'])); - } - - /** - * 清理空目录 - * @param string $path - */ - private function _removeEmptyDirectory($path) - { - if (is_dir($path) && count(scandir($path)) === 2 && rmdir($path)) { - $this->_removeEmptyDirectory(dirname($path)); - } - } - - /** - * 两二维数组对比 - * @param array $serve 线上文件列表信息 - * @param array $local 本地文件列表信息 - * @return array - */ - private function _grenerateDifferenceContrast(array $serve = [], array $local = []): array - { - // 数据扁平化 - [$_serve, $_local, $_diffy] = [[], [], []]; - foreach ($serve as $t) $_serve[$t['name']] = $t; - foreach ($local as $t) $_local[$t['name']] = $t; - unset($serve, $local); - // 线上数据差异计算 - foreach ($_serve as $t) isset($_local[$t['name']]) ? array_push($_diffy, [ - 'type' => $t['hash'] === $_local[$t['name']]['hash'] ? null : 'mod', 'name' => $t['name'], - ]) : array_push($_diffy, ['type' => 'add', 'name' => $t['name']]); - // 本地数据增量计算 - foreach ($_local as $t) if (!isset($_serve[$t['name']])) array_push($_diffy, ['type' => 'del', 'name' => $t['name']]); - unset($_serve, $_local); - usort($_diffy, function ($a, $b) { - return $a['name'] !== $b['name'] ? ($a['name'] > $b['name'] ? 1 : -1) : 0; - }); - return $_diffy; - } - - /** - * 获取指定文件信息 - * @param string $path 文件路径 - * @return array - */ - private function _getInfo($path): array - { - return [ - 'name' => str_replace($this->root, '', $path), - 'hash' => md5(preg_replace('/\s+/', '', file_get_contents($path))), - ]; - } - - /** - * 获取目录文件列表 - * @param string $path 待扫描目录 - * @param array $data 扫描结果 - * @return array - */ - private function _scanList($path, $data = []): array - { - foreach (NodeService::instance()->scanDirectory($path, [], null) as $file) { - $data[] = $this->_getInfo(strtr($file, '\\', '/')); - } - return $data; - } -} \ No newline at end of file diff --git a/vendor/zoujingli/think-library/src/service/ModuleService.php b/vendor/zoujingli/think-library/src/service/ModuleService.php index deaa9710b..024edd2e3 100644 --- a/vendor/zoujingli/think-library/src/service/ModuleService.php +++ b/vendor/zoujingli/think-library/src/service/ModuleService.php @@ -17,6 +17,7 @@ namespace think\admin\service; use think\admin\extend\HttpExtend; use think\admin\extend\Parsedown; +use think\admin\Library; use think\admin\Service; /** @@ -26,6 +27,12 @@ use think\admin\Service; */ class ModuleService extends Service { + /** + * 代码根目录 + * @var string + */ + protected $root; + /** * 官方应用地址 * @var string @@ -39,14 +46,14 @@ class ModuleService extends Service protected $version; /** - * 服务初始化 + * 模块服务初始化 */ public function initialize() { - $full = $this->app->config->get('app.thinkadmin_ver', 'v4.0.0'); - $this->version = trim($full, 'v'); - $version = strstr($full . '.', '.', true); - $this->server = "https://{$version}.thinkadmin.top"; + $this->root = $this->app->getRootPath(); + $this->version = trim(Library::VERSION, 'v'); + $maxver = strstr($this->version, '.', true); + $this->server = "https://v{$maxver}.thinkadmin.top"; } /** @@ -115,13 +122,12 @@ class ModuleService extends Service */ public function install($name): array { - $install = InstallService::instance(); $this->app->cache->set('moduleOnlineData', []); - $data = $install->grenerateDifference(['app' . '/' . $name]); + $data = $this->grenerateDifference(['app' . '/' . $name]); if (empty($data)) return [0, '没有需要安装的文件', []]; $lines = []; foreach ($data as $file) { - [$state, $mode, $name] = $install->updateFileByDownload($file); + [$state, $mode, $name] = $this->updateFileByDownload($file); if ($state) { if ($mode === 'add') $lines[] = "add {$name} successed"; if ($mode === 'mod') $lines[] = "modify {$name} successed"; @@ -147,7 +153,7 @@ class ModuleService extends Service $vars = $this->_getModuleVersion($name); if (is_array($vars) && isset($vars['version']) && preg_match('|^\d{4}\.\d{2}\.\d{2}\.\d{2}$|', $vars['version'])) { $data[$name] = array_merge($vars, ['change' => []]); - foreach ($service->scanDirectory($this->_getModulePath($name) . 'change', [], 'md') as $file) { + foreach ($service->scanDirectory($this->_getModuleInfoPath($name) . 'change', [], 'md') as $file) { $data[$name]['change'][pathinfo($file, PATHINFO_FILENAME)] = Parsedown::instance()->parse(file_get_contents($file)); } } @@ -156,17 +162,25 @@ class ModuleService extends Service } /** - * 获取允许下载的规则 + * 获取文件信息列表 + * @param array $rules 文件规则 + * @param array $ignore 忽略规则 + * @param array $data 扫描结果列表 * @return array */ - public function getAllowDownloadRule(): array + public function getChanges(array $rules, array $ignore = [], array $data = []): array { - $data = $this->app->cache->get('moduleAllowRule', []); - if (is_array($data) && count($data) > 0) return $data; - $data = ['config', 'public/static', 'public/router.php', 'public/index.php']; - foreach (array_keys($this->getModules()) as $name) $data[] = "app/{$name}"; - $this->app->cache->set('moduleAllowRule', $data, 30); - return $data; + // 扫描规则文件 + foreach ($rules as $key => $rule) { + $name = strtr(trim($rule, '\\/'), '\\', '/'); + $data = array_merge($data, $this->_scanLocalFileHashList($this->root . $name)); + } + // 清除忽略文件 + foreach ($data as $key => $item) foreach ($ignore as $ign) { + if (stripos($item['name'], $ign) === 0) unset($data[$key]); + } + // 返回文件数据 + return ['rules' => $rules, 'ignore' => $ignore, 'list' => $data]; } /** @@ -174,28 +188,89 @@ class ModuleService extends Service * @param string $name 文件名称 * @return boolean */ - public function checkAllowDownload($name): bool + public function checkAllowDownload(string $name): bool { // 禁止下载数据库配置文件 if (stripos($name, 'database.php') !== false) { return false; } // 检查允许下载的文件规则 - foreach ($this->getAllowDownloadRule() as $rule) { + foreach ($this->_getAllowDownloadRule() as $rule) { if (stripos($name, $rule) !== false) return true; } // 不在允许下载的文件规则 return false; } + /** + * 获取文件差异数据 + * @param array $rules 文件规则 + * @param array $ignore 忽略规则 + * @return array + */ + public function grenerateDifference(array $rules = [], array $ignore = []): array + { + [$rules1, $ignore1, $data] = [$rules, $ignore, []]; + $result = json_decode(HttpExtend::post($this->server . '/admin/api.update/node', [ + 'rules' => json_encode($rules1), 'ignore' => json_encode($ignore1), + ]), true); + if (!empty($result['code'])) { + $new = $this->getChanges($result['data']['rules'], $result['data']['ignore']); + foreach ($this->_grenerateDifferenceContrast($result['data']['list'], $new['list']) as $file) { + if (in_array($file['type'], ['add', 'del', 'mod'])) foreach ($rules1 as $rule) { + if (stripos($file['name'], $rule) === 0) $data[] = $file; + } + } + } + return $data; + } + + /** + * 尝试下载并更新文件 + * @param array $file 文件信息 + * @return array + */ + public function updateFileByDownload(array $file): array + { + if (in_array($file['type'], ['add', 'mod'])) { + if ($this->_downloadUpdateFile(encode($file['name']))) { + return [true, $file['type'], $file['name']]; + } else { + return [false, $file['type'], $file['name']]; + } + } elseif (in_array($file['type'], ['del'])) { + $real = $this->root . $file['name']; + if (is_file($real) && unlink($real)) { + $this->_removeEmptyDirectory(dirname($real)); + return [true, $file['type'], $file['name']]; + } else { + return [false, $file['type'], $file['name']]; + } + } + } + + /** + * 获取允许下载的规则 + * @return array + */ + private function _getAllowDownloadRule(): array + { + $data = $this->app->cache->get('moduleAllowRule', []); + if (is_array($data) && count($data) > 0) return $data; + $data = ['think', 'config', 'public/static', 'public/router.php', 'public/index.php']; + foreach (array_keys($this->getModules()) as $name) $data[] = 'app/' . $name; + $this->app->cache->set('moduleAllowRule', $data, 30); + return $data; + } + /** * 获取模块版本信息 * @param string $name 模块名称 * @return bool|array|null */ - private function _getModuleVersion($name) + private function _getModuleVersion(string $name) { - $filename = $this->_getModulePath($name) . 'module.json'; + $filename = $this->_getModuleInfoPath($name) . 'module.json'; if (file_exists($filename) && is_file($filename) && is_readable($filename)) { $vars = json_decode(file_get_contents($filename), true); return isset($vars['name']) && isset($vars['version']) ? $vars : null; @@ -204,14 +279,81 @@ class ModuleService extends Service } } + /** + * 下载更新文件内容 + * @param string $encode + * @return boolean|integer + */ + private function _downloadUpdateFile(string $encode) + { + $source = $this->server . '/admin/api.update/get?encode=' . $encode; + $result = json_decode(HttpExtend::get($source), true); + if (empty($result['code'])) return false; + $filename = $this->root . decode($encode); + file_exists(dirname($filename)) || mkdir(dirname($filename), 0755, true); + return file_put_contents($filename, base64_decode($result['data']['content'])); + } + + /** + * 清理空目录 + * @param string $path + */ + private function _removeEmptyDirectory(string $path) + { + if (is_dir($path) && count(scandir($path)) === 2 && rmdir($path)) { + $this->_removeEmptyDirectory(dirname($path)); + } + } + /** * 获取模块信息路径 - * @param string $name + * @param string $name 模块名称 * @return string */ - private function _getModulePath($name) + private function _getModuleInfoPath(string $name): string { $appdir = $this->app->getBasePath() . $name; return $appdir . DIRECTORY_SEPARATOR . 'module' . DIRECTORY_SEPARATOR; } + + /** + * 根据线上线下生成操作数组 + * @param array $serve 线上文件列表信息 + * @param array $local 本地文件列表信息 + * @return array + */ + private function _grenerateDifferenceContrast(array $serve = [], array $local = []): array + { + // 数据扁平化 + [$_serve, $_local, $_diffy] = [[], [], []]; + foreach ($serve as $t) $_serve[$t['name']] = $t; + foreach ($local as $t) $_local[$t['name']] = $t; + unset($serve, $local); + // 线上数据差异计算 + foreach ($_serve as $t) isset($_local[$t['name']]) ? array_push($_diffy, [ + 'type' => $t['hash'] === $_local[$t['name']]['hash'] ? null : 'mod', 'name' => $t['name'], + ]) : array_push($_diffy, ['type' => 'add', 'name' => $t['name']]); + // 本地数据增量计算 + foreach ($_local as $t) if (!isset($_serve[$t['name']])) array_push($_diffy, ['type' => 'del', 'name' => $t['name']]); + unset($_serve, $_local); + usort($_diffy, function ($a, $b) { + return $a['name'] !== $b['name'] ? ($a['name'] > $b['name'] ? 1 : -1) : 0; + }); + return $_diffy; + } + + /** + * 获取目录文件列表 + * @param mixed $path 扫描目录 + * @param array $data 扫描结果 + * @return array + */ + private function _scanLocalFileHashList(string $path, array $data = []): array + { + foreach (NodeService::instance()->scanDirectory($path, [], null) as $file) $data[] = [ + 'name' => str_replace(strtr($this->root, '\\', '/'), '', $file), + 'hash' => md5(preg_replace('/\s+/', '', file_get_contents($file))), + ]; + return $data; + } } \ No newline at end of file