1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012 |
- <?php
- namespace think\addons;
- use fast\Http;
- use GuzzleHttp\Client;
- use GuzzleHttp\Exception\TransferException;
- use PhpZip\Exception\ZipException;
- use PhpZip\ZipFile;
- use RecursiveDirectoryIterator;
- use RecursiveIteratorIterator;
- use Symfony\Component\VarExporter\VarExporter;
- use think\Cache;
- use think\Db;
- use think\Exception;
- /**
- * 插件服务
- * @package think\addons
- */
- class Service
- {
- /**
- * 远程下载插件
- *
- * @param string $name 插件名称
- * @param array $extend 扩展参数
- * @return string
- */
- public static function download($name, $extend = [])
- {
- $addonsTempDir = self::getAddonsBackupDir();
- $tmpFile = $addonsTempDir . $name . ".zip";
- try {
- $client = self::getClient();
- $response = $client->get('/addon/download', ['query' => array_merge(['name' => $name], $extend)]);
- $body = $response->getBody();
- $content = $body->getContents();
- if (substr($content, 0, 1) === '{') {
- $json = (array)json_decode($content, true);
- //如果传回的是一个下载链接,则再次下载
- if ($json['data'] && isset($json['data']['url'])) {
- $response = $client->get($json['data']['url']);
- $body = $response->getBody();
- $content = $body->getContents();
- } else {
- //下载返回错误,抛出异常
- throw new AddonException($json['msg'], $json['code'], $json['data']);
- }
- }
- } catch (TransferException $e) {
- throw new Exception("Addon package download failed");
- }
- if ($write = fopen($tmpFile, 'w')) {
- fwrite($write, $content);
- fclose($write);
- return $tmpFile;
- }
- throw new Exception("No permission to write temporary files");
- }
- /**
- * 解压插件
- *
- * @param string $name 插件名称
- * @return string
- * @throws Exception
- */
- public static function unzip($name)
- {
- if (!$name) {
- throw new Exception('Invalid parameters');
- }
- $addonsBackupDir = self::getAddonsBackupDir();
- $file = $addonsBackupDir . $name . '.zip';
- // 打开插件压缩包
- $zip = new ZipFile();
- try {
- $zip->openFile($file);
- } catch (ZipException $e) {
- $zip->close();
- throw new Exception('Unable to open the zip file');
- }
- $dir = self::getAddonDir($name);
- if (!is_dir($dir)) {
- @mkdir($dir, 0755);
- }
- // 解压插件压缩包
- try {
- $zip->extractTo($dir);
- } catch (ZipException $e) {
- throw new Exception('Unable to extract the file');
- } finally {
- $zip->close();
- }
- return $dir;
- }
- /**
- * 离线安装
- * @param string $file 插件压缩包
- * @param array $extend
- */
- public static function local($file, $extend = [])
- {
- $addonsTempDir = self::getAddonsBackupDir();
- if (!$file || !$file instanceof \think\File) {
- throw new Exception('No file upload or server upload limit exceeded');
- }
- $uploadFile = $file->rule('uniqid')->validate(['size' => 102400000, 'ext' => 'zip,fastaddon'])->move($addonsTempDir);
- if (!$uploadFile) {
- // 上传失败获取错误信息
- throw new Exception(__($file->getError()));
- }
- $tmpFile = $addonsTempDir . $uploadFile->getSaveName();
- $info = [];
- $zip = new ZipFile();
- try {
- // 打开插件压缩包
- try {
- $zip->openFile($tmpFile);
- } catch (ZipException $e) {
- @unlink($tmpFile);
- throw new Exception('Unable to open the zip file');
- }
- $config = self::getInfoIni($zip);
- // 判断插件标识
- $name = isset($config['name']) ? $config['name'] : '';
- if (!$name) {
- throw new Exception('Addon info file data incorrect');
- }
- // 判断插件是否存在
- if (!preg_match("/^[a-zA-Z0-9]+$/", $name)) {
- throw new Exception('Addon name incorrect');
- }
- // 判断新插件是否存在
- $newAddonDir = self::getAddonDir($name);
- if (is_dir($newAddonDir)) {
- throw new Exception('Addon already exists');
- }
- // 追加MD5和Data数据
- $extend['md5'] = md5_file($tmpFile);
- $extend['data'] = $zip->getArchiveComment();
- $extend['unknownsources'] = config('app_debug') && config('fastadmin.unknownsources');
- $extend['faversion'] = config('fastadmin.version');
- $params = array_merge($config, $extend);
- // 压缩包验证、版本依赖判断
- Service::valid($params);
- //创建插件目录
- @mkdir($newAddonDir, 0755, true);
- // 解压到插件目录
- try {
- $zip->extractTo($newAddonDir);
- } catch (ZipException $e) {
- @unlink($newAddonDir);
- throw new Exception('Unable to extract the file');
- }
- Db::startTrans();
- try {
- //默认禁用该插件
- $info = get_addon_info($name);
- if ($info['state']) {
- $info['state'] = 0;
- set_addon_info($name, $info);
- }
- //执行插件的安装方法
- $class = get_addon_class($name);
- if (class_exists($class)) {
- $addon = new $class();
- $addon->install();
- }
- Db::commit();
- } catch (\Exception $e) {
- Db::rollback();
- @rmdirs($newAddonDir);
- throw new Exception(__($e->getMessage()));
- }
- //导入SQL
- Service::importsql($name);
- } catch (AddonException $e) {
- throw new AddonException($e->getMessage(), $e->getCode(), $e->getData());
- } catch (Exception $e) {
- throw new Exception(__($e->getMessage()));
- } finally {
- $zip->close();
- unset($uploadFile);
- @unlink($tmpFile);
- }
- $info['config'] = get_addon_config($name) ? 1 : 0;
- $info['bootstrap'] = is_file(Service::getBootstrapFile($name));
- return $info;
- }
- /**
- * 验证压缩包、依赖验证
- * @param array $params
- * @return bool
- * @throws Exception
- */
- public static function valid($params = [])
- {
- $client = self::getClient();
- $multipart = [];
- foreach ($params as $name => $value) {
- $multipart[] = ['name' => $name, 'contents' => $value];
- }
- try {
- $response = $client->post('/addon/valid', ['multipart' => $multipart]);
- $content = $response->getBody()->getContents();
- } catch (TransferException $e) {
- throw new Exception("Network error");
- }
- $json = (array)json_decode($content, true);
- if ($json && isset($json['code'])) {
- if ($json['code']) {
- return true;
- } else {
- throw new Exception($json['msg'] ?? "Invalid addon package");
- }
- } else {
- throw new Exception("Unknown data format");
- }
- }
- /**
- * 备份插件
- * @param string $name 插件名称
- * @return bool
- * @throws Exception
- */
- public static function backup($name)
- {
- $addonsBackupDir = self::getAddonsBackupDir();
- $file = $addonsBackupDir . $name . '-backup-' . date("YmdHis") . '.zip';
- $zipFile = new ZipFile();
- try {
- $zipFile
- ->addDirRecursive(self::getAddonDir($name))
- ->saveAsFile($file)
- ->close();
- } catch (ZipException $e) {
- } finally {
- $zipFile->close();
- }
- return true;
- }
- /**
- * 检测插件是否完整
- *
- * @param string $name 插件名称
- * @return boolean
- * @throws Exception
- */
- public static function check($name)
- {
- if (!$name || !is_dir(ADDON_PATH . $name)) {
- throw new Exception('Addon not exists');
- }
- $addonClass = get_addon_class($name);
- if (!$addonClass) {
- throw new Exception("The addon file does not exist");
- }
- $addon = new $addonClass();
- if (!$addon->checkInfo()) {
- throw new Exception("The configuration file content is incorrect");
- }
- return true;
- }
- /**
- * 是否有冲突
- *
- * @param string $name 插件名称
- * @return boolean
- * @throws AddonException
- */
- public static function noconflict($name)
- {
- // 检测冲突文件
- $list = self::getGlobalFiles($name, true);
- if ($list) {
- //发现冲突文件,抛出异常
- throw new AddonException(__("Conflicting file found"), -3, ['conflictlist' => $list]);
- }
- return true;
- }
- /**
- * 导入SQL
- *
- * @param string $name 插件名称
- * @return boolean
- */
- public static function importsql($name)
- {
- $sqlFile = self::getAddonDir($name) . 'install.sql';
- if (is_file($sqlFile)) {
- $lines = file($sqlFile);
- $templine = '';
- foreach ($lines as $line) {
- if (substr($line, 0, 2) == '--' || $line == '' || substr($line, 0, 2) == '/*') {
- continue;
- }
- $templine .= $line;
- if (substr(trim($line), -1, 1) == ';') {
- $templine = str_ireplace('__PREFIX__', config('database.prefix'), $templine);
- $templine = str_ireplace('INSERT INTO ', 'INSERT IGNORE INTO ', $templine);
- try {
- Db::getPdo()->exec($templine);
- } catch (\PDOException $e) {
- //$e->getMessage();
- }
- $templine = '';
- }
- }
- }
- return true;
- }
- /**
- * 刷新插件缓存文件
- *
- * @return boolean
- * @throws Exception
- */
- public static function refresh()
- {
- //刷新addons.js
- $addons = get_addon_list();
- $bootstrapArr = [];
- foreach ($addons as $name => $addon) {
- $bootstrapFile = self::getBootstrapFile($name);
- if ($addon['state'] && is_file($bootstrapFile)) {
- $bootstrapArr[] = file_get_contents($bootstrapFile);
- }
- }
- $addonsFile = ROOT_PATH . str_replace("/", DS, "public/assets/js/addons.js");
- if ($handle = fopen($addonsFile, 'w')) {
- $tpl = <<<EOD
- define([], function () {
- {__JS__}
- });
- EOD;
- fwrite($handle, str_replace("{__JS__}", implode("\n", $bootstrapArr), $tpl));
- fclose($handle);
- } else {
- throw new Exception(__("Unable to open file '%s' for writing", "addons.js"));
- }
- Cache::rm("addons");
- Cache::rm("hooks");
- $file = self::getExtraAddonsFile();
- $config = get_addon_autoload_config(true);
- if ($config['autoload']) {
- return;
- }
- if (!is_really_writable($file)) {
- throw new Exception(__("Unable to open file '%s' for writing", "addons.php"));
- }
- if ($handle = fopen($file, 'w')) {
- fwrite($handle, "<?php\n\n" . "return " . VarExporter::export($config) . ";\n");
- fclose($handle);
- } else {
- throw new Exception(__("Unable to open file '%s' for writing", "addons.php"));
- }
- return true;
- }
- /**
- * 安装插件
- *
- * @param string $name 插件名称
- * @param boolean $force 是否覆盖
- * @param array $extend 扩展参数
- * @return boolean
- * @throws Exception
- * @throws AddonException
- */
- public static function install($name, $force = false, $extend = [])
- {
- if (!$name || (is_dir(ADDON_PATH . $name) && !$force)) {
- throw new Exception('Addon already exists');
- }
- // 远程下载插件
- $tmpFile = Service::download($name, $extend);
- $addonDir = self::getAddonDir($name);
- try {
- // 解压插件压缩包到插件目录
- Service::unzip($name);
- // 检查插件是否完整
- Service::check($name);
- if (!$force) {
- Service::noconflict($name);
- }
- } catch (AddonException $e) {
- @rmdirs($addonDir);
- throw new AddonException($e->getMessage(), $e->getCode(), $e->getData());
- } catch (Exception $e) {
- @rmdirs($addonDir);
- throw new Exception($e->getMessage());
- } finally {
- // 移除临时文件
- @unlink($tmpFile);
- }
- // 默认启用该插件
- $info = get_addon_info($name);
- Db::startTrans();
- try {
- if (!$info['state']) {
- $info['state'] = 1;
- set_addon_info($name, $info);
- }
- // 执行安装脚本
- $class = get_addon_class($name);
- if (class_exists($class)) {
- $addon = new $class();
- $addon->install();
- }
- Db::commit();
- } catch (Exception $e) {
- @rmdirs($addonDir);
- Db::rollback();
- throw new Exception($e->getMessage());
- }
- // 导入
- Service::importsql($name);
- // 启用插件
- Service::enable($name, true);
- $info['config'] = get_addon_config($name) ? 1 : 0;
- $info['bootstrap'] = is_file(Service::getBootstrapFile($name));
- return $info;
- }
- /**
- * 卸载插件
- *
- * @param string $name
- * @param boolean $force 是否强制卸载
- * @return boolean
- * @throws Exception
- */
- public static function uninstall($name, $force = false)
- {
- if (!$name || !is_dir(ADDON_PATH . $name)) {
- throw new Exception('Addon not exists');
- }
- if (!$force) {
- Service::noconflict($name);
- }
- // 移除插件全局资源文件
- if ($force) {
- $list = Service::getGlobalFiles($name);
- foreach ($list as $k => $v) {
- @unlink(ROOT_PATH . $v);
- }
- }
- // 执行卸载脚本
- try {
- $class = get_addon_class($name);
- if (class_exists($class)) {
- $addon = new $class();
- $addon->uninstall();
- }
- } catch (Exception $e) {
- throw new Exception($e->getMessage());
- }
- // 移除插件目录
- rmdirs(ADDON_PATH . $name);
- // 刷新
- Service::refresh();
- return true;
- }
- /**
- * 启用
- * @param string $name 插件名称
- * @param boolean $force 是否强制覆盖
- * @return boolean
- */
- public static function enable($name, $force = false)
- {
- if (!$name || !is_dir(ADDON_PATH . $name)) {
- throw new Exception('Addon not exists');
- }
- if (!$force) {
- Service::noconflict($name);
- }
- //备份冲突文件
- if (config('fastadmin.backup_global_files')) {
- $conflictFiles = self::getGlobalFiles($name, true);
- if ($conflictFiles) {
- $zip = new ZipFile();
- try {
- foreach ($conflictFiles as $k => $v) {
- $zip->addFile(ROOT_PATH . $v, $v);
- }
- $addonsBackupDir = self::getAddonsBackupDir();
- $zip->saveAsFile($addonsBackupDir . $name . "-conflict-enable-" . date("YmdHis") . ".zip");
- } catch (Exception $e) {
- } finally {
- $zip->close();
- }
- }
- }
- $addonDir = self::getAddonDir($name);
- $sourceAssetsDir = self::getSourceAssetsDir($name);
- $destAssetsDir = self::getDestAssetsDir($name);
- $files = self::getGlobalFiles($name);
- if ($files) {
- //刷新插件配置缓存
- Service::config($name, ['files' => $files]);
- }
- // 复制文件
- if (is_dir($sourceAssetsDir)) {
- copydirs($sourceAssetsDir, $destAssetsDir);
- }
- // 复制application和public到全局
- foreach (self::getCheckDirs() as $k => $dir) {
- if (is_dir($addonDir . $dir)) {
- copydirs($addonDir . $dir, ROOT_PATH . $dir);
- }
- }
- //插件纯净模式时将插件目录下的application、public和assets删除
- if (config('fastadmin.addon_pure_mode')) {
- // 删除插件目录已复制到全局的文件
- @rmdirs($sourceAssetsDir);
- foreach (self::getCheckDirs() as $k => $dir) {
- @rmdirs($addonDir . $dir);
- }
- }
- //执行启用脚本
- try {
- $class = get_addon_class($name);
- if (class_exists($class)) {
- $addon = new $class();
- if (method_exists($class, "enable")) {
- $addon->enable();
- }
- }
- } catch (Exception $e) {
- throw new Exception($e->getMessage());
- }
- $info = get_addon_info($name);
- $info['state'] = 1;
- unset($info['url']);
- set_addon_info($name, $info);
- // 刷新
- Service::refresh();
- return true;
- }
- /**
- * 禁用
- *
- * @param string $name 插件名称
- * @param boolean $force 是否强制禁用
- * @return boolean
- * @throws Exception
- */
- public static function disable($name, $force = false)
- {
- if (!$name || !is_dir(ADDON_PATH . $name)) {
- throw new Exception('Addon not exists');
- }
- $file = self::getExtraAddonsFile();
- if (!is_really_writable($file)) {
- throw new Exception(__("Unable to open file '%s' for writing", "addons.php"));
- }
- if (!$force) {
- Service::noconflict($name);
- }
- if (config('fastadmin.backup_global_files')) {
- //仅备份修改过的文件
- $conflictFiles = Service::getGlobalFiles($name, true);
- if ($conflictFiles) {
- $zip = new ZipFile();
- try {
- foreach ($conflictFiles as $k => $v) {
- $zip->addFile(ROOT_PATH . $v, $v);
- }
- $addonsBackupDir = self::getAddonsBackupDir();
- $zip->saveAsFile($addonsBackupDir . $name . "-conflict-disable-" . date("YmdHis") . ".zip");
- } catch (Exception $e) {
- } finally {
- $zip->close();
- }
- }
- }
- $config = Service::config($name);
- $addonDir = self::getAddonDir($name);
- //插件资源目录
- $destAssetsDir = self::getDestAssetsDir($name);
- // 移除插件全局文件
- $list = Service::getGlobalFiles($name);
- //插件纯净模式时将原有的文件复制回插件目录
- //当无法获取全局文件列表时也将列表复制回插件目录
- if (config('fastadmin.addon_pure_mode') || !$list) {
- if ($config && isset($config['files']) && is_array($config['files'])) {
- foreach ($config['files'] as $index => $item) {
- //避免切换不同服务器后导致路径不一致
- $item = str_replace(['/', '\\'], DS, $item);
- //插件资源目录,无需重复复制
- if (stripos($item, str_replace(ROOT_PATH, '', $destAssetsDir)) === 0) {
- continue;
- }
- //检查目录是否存在,不存在则创建
- $itemBaseDir = dirname($addonDir . $item);
- if (!is_dir($itemBaseDir)) {
- @mkdir($itemBaseDir, 0755, true);
- }
- if (is_file(ROOT_PATH . $item)) {
- @copy(ROOT_PATH . $item, $addonDir . $item);
- }
- }
- $list = $config['files'];
- }
- //复制插件目录资源
- if (is_dir($destAssetsDir)) {
- @copydirs($destAssetsDir, $addonDir . 'assets' . DS);
- }
- }
- $dirs = [];
- foreach ($list as $k => $v) {
- $file = ROOT_PATH . $v;
- $dirs[] = dirname($file);
- @unlink($file);
- }
- // 移除插件空目录
- $dirs = array_filter(array_unique($dirs));
- foreach ($dirs as $k => $v) {
- remove_empty_folder($v);
- }
- $info = get_addon_info($name);
- $info['state'] = 0;
- unset($info['url']);
- set_addon_info($name, $info);
- // 执行禁用脚本
- try {
- $class = get_addon_class($name);
- if (class_exists($class)) {
- $addon = new $class();
- if (method_exists($class, "disable")) {
- $addon->disable();
- }
- }
- } catch (Exception $e) {
- throw new Exception($e->getMessage());
- }
- // 刷新
- Service::refresh();
- return true;
- }
- /**
- * 升级插件
- *
- * @param string $name 插件名称
- * @param array $extend 扩展参数
- */
- public static function upgrade($name, $extend = [])
- {
- $info = get_addon_info($name);
- if ($info['state']) {
- throw new Exception(__('Please disable addon first'));
- }
- $config = get_addon_config($name);
- if ($config) {
- //备份配置
- }
- // 远程下载插件
- $tmpFile = Service::download($name, $extend);
- // 备份插件文件
- Service::backup($name);
- $addonDir = self::getAddonDir($name);
- // 删除插件目录下的application和public
- $files = self::getCheckDirs();
- foreach ($files as $index => $file) {
- @rmdirs($addonDir . $file);
- }
- try {
- // 解压插件
- Service::unzip($name);
- } catch (Exception $e) {
- throw new Exception($e->getMessage());
- } finally {
- // 移除临时文件
- @unlink($tmpFile);
- }
- if ($config) {
- // 还原配置
- set_addon_config($name, $config);
- }
- // 导入
- Service::importsql($name);
- // 执行升级脚本
- try {
- $addonName = ucfirst($name);
- //创建临时类用于调用升级的方法
- $sourceFile = $addonDir . $addonName . ".php";
- $destFile = $addonDir . $addonName . "Upgrade.php";
- $classContent = str_replace("class {$addonName} extends", "class {$addonName}Upgrade extends", file_get_contents($sourceFile));
- //创建临时的类文件
- file_put_contents($destFile, $classContent);
- $className = "\\addons\\" . $name . "\\" . $addonName . "Upgrade";
- $addon = new $className($name);
- //调用升级的方法
- if (method_exists($addon, "upgrade")) {
- $addon->upgrade();
- }
- //移除临时文件
- @unlink($destFile);
- } catch (Exception $e) {
- throw new Exception($e->getMessage());
- }
- // 刷新
- Service::refresh();
- //必须变更版本号
- $info['version'] = isset($extend['version']) ? $extend['version'] : $info['version'];
- $info['config'] = get_addon_config($name) ? 1 : 0;
- $info['bootstrap'] = is_file(Service::getBootstrapFile($name));
- return $info;
- }
- /**
- * 读取或修改插件配置
- * @param string $name
- * @param array $changed
- * @return array
- */
- public static function config($name, $changed = [])
- {
- $addonDir = self::getAddonDir($name);
- $addonConfigFile = $addonDir . '.addonrc';
- $config = [];
- if (is_file($addonConfigFile)) {
- $config = (array)json_decode(file_get_contents($addonConfigFile), true);
- }
- $config = array_merge($config, $changed);
- if ($changed) {
- file_put_contents($addonConfigFile, json_encode($config, JSON_UNESCAPED_UNICODE));
- }
- return $config;
- }
- /**
- * 获取插件在全局的文件
- *
- * @param string $name 插件名称
- * @param boolean $onlyconflict 是否只返回冲突文件
- * @return array
- */
- public static function getGlobalFiles($name, $onlyconflict = false)
- {
- $list = [];
- $addonDir = self::getAddonDir($name);
- $checkDirList = self::getCheckDirs();
- $checkDirList = array_merge($checkDirList, ['assets']);
- $assetDir = self::getDestAssetsDir($name);
- // 扫描插件目录是否有覆盖的文件
- foreach ($checkDirList as $k => $dirName) {
- //检测目录是否存在
- if (!is_dir($addonDir . $dirName)) {
- continue;
- }
- //匹配出所有的文件
- $files = new RecursiveIteratorIterator(
- new RecursiveDirectoryIterator($addonDir . $dirName, RecursiveDirectoryIterator::SKIP_DOTS), RecursiveIteratorIterator::CHILD_FIRST
- );
- foreach ($files as $fileinfo) {
- if ($fileinfo->isFile()) {
- $filePath = $fileinfo->getPathName();
- //如果名称为assets需要做特殊处理
- if ($dirName === 'assets') {
- $path = str_replace(ROOT_PATH, '', $assetDir) . str_replace($addonDir . $dirName . DS, '', $filePath);
- } else {
- $path = str_replace($addonDir, '', $filePath);
- }
- if ($onlyconflict) {
- $destPath = ROOT_PATH . $path;
- if (is_file($destPath)) {
- if (filesize($filePath) != filesize($destPath) || md5_file($filePath) != md5_file($destPath)) {
- $list[] = $path;
- }
- }
- } else {
- $list[] = $path;
- }
- }
- }
- }
- $list = array_filter(array_unique($list));
- return $list;
- }
- /**
- * 获取插件行为、路由配置文件
- * @return string
- */
- public static function getExtraAddonsFile()
- {
- return CONF_PATH . 'extra' . DS . 'addons.php';
- }
- /**
- * 获取bootstrap.js路径
- * @return string
- */
- public static function getBootstrapFile($name)
- {
- return ADDON_PATH . $name . DS . 'bootstrap.js';
- }
- /**
- * 获取指定插件的目录
- */
- public static function getAddonDir($name)
- {
- $dir = ADDON_PATH . $name . DS;
- return $dir;
- }
- /**
- * 获取插件备份目录
- */
- public static function getAddonsBackupDir()
- {
- $dir = RUNTIME_PATH . 'addons' . DS;
- if (!is_dir($dir)) {
- @mkdir($dir, 0755, true);
- }
- return $dir;
- }
- /**
- * 获取插件源资源文件夹
- * @param string $name 插件名称
- * @return string
- */
- protected static function getSourceAssetsDir($name)
- {
- return ADDON_PATH . $name . DS . 'assets' . DS;
- }
- /**
- * 获取插件目标资源文件夹
- * @param string $name 插件名称
- * @return string
- */
- protected static function getDestAssetsDir($name)
- {
- $assetsDir = ROOT_PATH . str_replace("/", DS, "public/assets/addons/{$name}/");
- return $assetsDir;
- }
- /**
- * 获取远程服务器
- * @return string
- */
- protected static function getServerUrl()
- {
- return config('fastadmin.api_url');
- }
- /**
- * 获取检测的全局文件夹目录
- * @return array
- */
- protected static function getCheckDirs()
- {
- return [
- 'application',
- 'public'
- ];
- }
- /**
- * 获取请求对象
- * @return Client
- */
- protected static function getClient()
- {
- $options = [
- 'base_uri' => self::getServerUrl(),
- 'timeout' => 30,
- 'connect_timeout' => 30,
- 'verify' => false,
- 'http_errors' => false,
- 'headers' => [
- 'X-REQUESTED-WITH' => 'XMLHttpRequest',
- 'Referer' => dirname(request()->root(true)),
- 'User-Agent' => 'FastAddon',
- ]
- ];
- static $client;
- if (empty($client)) {
- $client = new Client($options);
- }
- return $client;
- }
- /**
- * 匹配配置文件中info信息
- * @param ZipFile $zip
- * @return array|false
- * @throws Exception
- */
- protected static function getInfoIni($zip)
- {
- $config = [];
- // 读取插件信息
- try {
- $info = $zip->getEntryContents('info.ini');
- $config = parse_ini_string($info);
- } catch (ZipException $e) {
- throw new Exception('Unable to extract the file');
- }
- return $config;
- }
- }
|