getInteger('memberUserId');
$apiToken = $input->getTrimString('apiToken');
return Cache::remember('ModuleStore_Modules:' . $memberUserId, 60, function () use ($apiToken) {
return CurlUtil::getJSONData(self::REMOTE_BASE . '/api/store/module', [
'api_token' => $apiToken,
]);
});
}
public static function all()
{
$storeConfig = [
'disable' => config('env.MS_MODULE_STORE_DISABLE', false),
];
$result = self::remoteModuleData();
$categories = [];
if (!empty($result['data']['categories'])) {
$categories = $result['data']['categories'];
}
$types = [];
if (!empty($result['data']['types'])) {
$types = $result['data']['types'];
}
$modules = [];
if (!empty($result['data']['modules'])) {
foreach ($result['data']['modules'] as $remote) {
$remote['_isLocal'] = false;
$remote['_isInstalled'] = false;
$remote['_isEnabled'] = false;
$remote['_localVersion'] = null;
$remote['_isSystem'] = false;
$remote['_hasConfig'] = false;
$modules[$remote['name']] = $remote;
}
}
foreach (ModuleManager::listModules() as $m => $config) {
$info = ModuleManager::getModuleBasic($m);
if (isset($modules[$m])) {
$modules[$m]['_isInstalled'] = $config['isInstalled'];
$modules[$m]['_isEnabled'] = $config['enable'];
$modules[$m]['_localVersion'] = $info['version'];
$modules[$m]['_isSystem'] = $config['isSystem'];
$modules[$m]['_hasConfig'] = !empty($info['config']);
} else {
$modules[$m] = [
'id' => 0,
'name' => $m,
'title' => $info['title'],
'cover' => null,
'categoryId' => null,
'latestVersion' => $info['version'],
'releases' => [],
'url' => null,
'isFee' => false,
'priceSuper' => null,
'priceSuperEnable' => false,
'priceYear' => null,
'priceYearEnable' => false,
'description' => $info['description'],
'_isLocal' => true,
'_isInstalled' => $config['isInstalled'],
'_isEnabled' => $config['enable'],
'_localVersion' => $info['version'],
'_isSystem' => $config['isSystem'],
'_hasConfig' => !empty($info['config']),
];
}
}
return [
'storeConfig' => $storeConfig,
'categories' => $categories,
'types' => $types,
'modules' => array_values($modules),
];
}
private static function baseRequest($api, $data, $token)
{
return CurlUtil::postJSONBody(self::REMOTE_BASE . $api, $data, [
'header' => [
'api-token' => $token,
'X-Requested-With' => 'XMLHttpRequest',
]
]);
}
public static function checkPackage($token, $module, $version)
{
$ret = self::baseRequest('/api/store/module_info', [
'module' => $module,
'version' => $version,
], $token);
BizException::throwsIfResponseError($ret);
$config = $ret['data']['config'];
$packageSize = $ret['data']['packageSize'];
$requires = [];
if (!empty($config['modstartVersion'])) {
$require = [
'name' => "ModStart:" . htmlspecialchars($config['modstartVersion']),
'success' => VersionUtil::match(ModStart::$version, $config['modstartVersion']),
'resolve' => null,
];
if (!$require['success']) {
$require['resolve'] = '请使用版本 ' . $config['modstartVersion'] . ' 的ModStart核心';
}
$requires[] = $require;
}
if (!empty($config['require'])) {
foreach ($config['require'] as $require) {
list($m, $v) = VersionUtil::parse($require);
$require = [
'name' => "$m:" . htmlspecialchars($v),
'success' => true,
'resolve' => null,
];
if (ModuleManager::isModuleInstalled($m)) {
$basic = ModuleManager::getModuleBasic($m);
BizException::throwsIfEmpty("获取模块 $m 信息失败", $basic);
$require['success'] = VersionUtil::match($basic['version'], $v);
if (!$require['success']) {
$require['resolve'] = "请使用版本 " . htmlspecialchars($v) . " 的模块 $m";
}
} else {
$require['success'] = false;
$require['resolve'] = "请先安装 $require[name] [点击查看]";
}
$requires[] = $require;
}
}
return Response::generateSuccessData([
'requires' => $requires,
'errorCount' => count(array_filter($requires, function ($o) {
return !$o['success'];
})),
'packageSize' => $packageSize,
]);
}
public static function downloadPackage($token, $module, $version)
{
$ret = self::baseRequest('/api/store/module_package', [
'module' => $module,
'version' => $version,
], $token);
BizException::throwsIfResponseError($ret);
$package = $ret['data']['package'];
$packageMd5 = $ret['data']['packageMd5'];
$licenseKey = $ret['data']['licenseKey'];
$data = CurlUtil::getRaw($package);
BizException::throwsIfEmpty('安装包获取失败', $data);
$zipTemp = FileUtil::generateLocalTempPath('zip');
file_put_contents($zipTemp, $data);
BizException::throwsIf('文件MD5校验失败', md5_file($zipTemp) != $packageMd5);
return Response::generateSuccessData([
'package' => $zipTemp,
'licenseKey' => $licenseKey,
'packageSize' => filesize($zipTemp),
]);
}
public static function cleanDownloadedPackage($package)
{
FileUtil::safeCleanLocalTemp($package);
}
public static function unpackModule($module, $package, $licenseKey)
{
$results = [];
BizException::throwsIf('文件不存在 ' . $package, empty($package) || !file_exists($package));
$moduleDir = base_path('module/' . $module);
if (file_exists($moduleDir)) {
$moduleBackup = '_delete_.' . date('Ymd_His') . '.' . $module;
BizException::throwsIf('模块目录 module/' . $module . ' 不正常,请手动删除', !is_dir($moduleDir));
$moduleBackupDir = base_path("module/$moduleBackup");
try {
rename($moduleDir, $moduleBackupDir);
} catch (\Exception $e) {
BizException::throws("备份模块 $module 到 $moduleBackup 失败,请确保模块 $module 中没有文件正在被使用");
}
BizException::throwsIf('备份模块旧文件失败', !file_exists($moduleBackupDir));
$results[] = "备份模块 $module 到 $moduleBackup";
}
BizException::throwsIf('模块目录 module/' . $module . ' 不正常,请手动删除', file_exists($moduleDir));
$zipper = new Zipper();
$zipper->make($package);
if ($zipper->contains($module . '/config.json')) {
$zipper->folder($module . '');
}
$zipper->extractTo($moduleDir);
$zipper->close();
BizException::throwsIf('解压失败', !file_exists($moduleDir . '/config.json'));
file_put_contents($moduleDir . '/license.json', json_encode([
'licenseKey' => $licenseKey,
]));
self::cleanDownloadedPackage($package);
return Response::generateSuccessData($results);
}
public static function removeModule($module, $version)
{
$moduleDir = base_path('module/' . $module);
BizException::throwsIf('模块目录不存在 ', !file_exists($moduleDir));
BizException::throwsIf('模块目录 module/' . $module . ' 不正常,请手动删除', !is_dir($moduleDir));
$moduleBackup = '_delete_.' . date('Ymd_His') . '.' . $module;
$moduleBackupDir = base_path("module/$moduleBackup");
try {
rename($moduleDir, $moduleBackupDir);
} catch (\Exception $e) {
BizException::throws("移除模块 $module 到 $moduleBackup 失败,请确保模块 $module 中没有文件正在被使用");
}
BizException::throwsIf('模块目录备份失败', !file_exists($moduleBackupDir));
return Response::generateSuccessData([]);
}
}