236 lines
7.0 KiB
PHP
236 lines
7.0 KiB
PHP
<?php ! defined('__TYPECHO_ROOT_DIR__') and exit();
|
||
|
||
class AppStore_Action extends Typecho_Widget
|
||
{
|
||
|
||
/**
|
||
* 是否支持自动下载安装
|
||
*
|
||
* 如果在云平台上,则处理为手动下载模式。
|
||
*
|
||
* @var boolean
|
||
*/
|
||
private $installale = true;
|
||
|
||
/**
|
||
* 应用商店服务器
|
||
*
|
||
* @var string
|
||
*/
|
||
private $server = '';
|
||
|
||
/**
|
||
* Http Request 方式
|
||
*
|
||
* @var string
|
||
*/
|
||
private $http = '';
|
||
|
||
/**
|
||
* 构造函数
|
||
*
|
||
* @param mixed $request
|
||
* @param mixed $response
|
||
* @param null $params
|
||
*/
|
||
public function __construct($request, $response, $params = NULL)
|
||
{
|
||
parent::__construct($request, $response, $params);
|
||
|
||
//检测是否可以自动下载安装
|
||
$tempDir = __TYPECHO_ROOT_DIR__.__TYPECHO_PLUGIN_DIR__.'/.app_store/';
|
||
if (! @touch($tempDir.'.installable'.time())) {
|
||
$this->installale = false;
|
||
} else {
|
||
unlink($tempDir.'.installable'.time());
|
||
}
|
||
|
||
//如果没有json库,加载兼容包
|
||
! extension_loaded('json') and include('libs/compat_json.php');
|
||
|
||
//加载unzip包
|
||
include('libs/unzip.php');
|
||
|
||
//加载助手
|
||
include('helpers/helpers.php');
|
||
|
||
//加载异常类
|
||
include('libs/exceptions.php');
|
||
|
||
//从插件设置中读取应用商店服务器地址
|
||
$pluginOptions = Typecho_Widget::widget('Widget_Options')->plugin('AppStore');
|
||
$this->server = $pluginOptions->server;
|
||
$this->http = 'http_'.$pluginOptions->http;
|
||
|
||
define('TYPEHO_ADMIN_PATH', __TYPECHO_ROOT_DIR__.__TYPECHO_ADMIN_DIR__.'/');
|
||
|
||
}
|
||
|
||
/**
|
||
* 应用商店主页
|
||
*
|
||
*/
|
||
public function market()
|
||
{
|
||
$http = $this->http;
|
||
//获取插件列表
|
||
$result = json_decode($http($this->server.'packages.json'));
|
||
|
||
if ($result) {
|
||
|
||
//导出已激活插件
|
||
$activatedPlugins = Typecho_Plugin::export();
|
||
|
||
foreach ($result->packages as &$_package) {
|
||
|
||
$pluginPath = __TYPECHO_ROOT_DIR__.__TYPECHO_PLUGIN_DIR__.'/'.$_package->name.'/';
|
||
|
||
$pluginEntry = $pluginPath.'Plugin.php';
|
||
|
||
$_package->existed = 0;
|
||
|
||
if (file_exists($pluginEntry)) {
|
||
|
||
$_package->existed = 1;
|
||
|
||
$pluginMeta = Typecho_Plugin::parseInfo($pluginEntry);
|
||
|
||
foreach ($_package->versions as &$_version) {
|
||
|
||
$_version->activated = 0;
|
||
|
||
$_version->description = strip_tags($_version->description);
|
||
$_version->author = strip_tags($_version->author);
|
||
|
||
if ($_version->version == $pluginMeta['version'] and
|
||
isset($activatedPlugins['activated'][$_package->name])
|
||
) {
|
||
$_version->activated = 1;
|
||
}
|
||
|
||
}
|
||
|
||
} else {
|
||
|
||
foreach ($_package->versions as &$_version) {
|
||
|
||
$_version->description = strip_tags($_version->description);
|
||
$_version->author = strip_tags($_version->author);
|
||
$_version->activated = 0;
|
||
|
||
}
|
||
|
||
}
|
||
|
||
}
|
||
|
||
}
|
||
|
||
include 'views/market.php';
|
||
|
||
}
|
||
|
||
public function install()
|
||
{
|
||
$version = $this->request->get('version');
|
||
$plugin = $this->request->get('plugin');
|
||
$require = $this->request->get('require');
|
||
|
||
$require === '*' and $require = '';
|
||
|
||
$pluginPath = __TYPECHO_ROOT_DIR__.__TYPECHO_PLUGIN_DIR__.'/'.$plugin.'/';
|
||
$pluginBackupPath = __TYPECHO_ROOT_DIR__.__TYPECHO_PLUGIN_DIR__.'/_'.$plugin.'/';
|
||
$activatedPlugins = Typecho_Plugin::export();
|
||
$existed = false;
|
||
$activated = false;
|
||
$tempFile = __TYPECHO_ROOT_DIR__.__TYPECHO_PLUGIN_DIR__.'/.app_store/'.$plugin.'-'.$version.'.zip';
|
||
|
||
try {
|
||
|
||
//检查版本
|
||
list(, $buildVersion) = explode('/', Typecho_Common::VERSION);
|
||
if (! Typecho_Plugin::checkDependence($buildVersion, $require)) {
|
||
throw new VersionNotMatchException('版本不匹配,无法安装.');
|
||
}
|
||
|
||
//查看插件是否已经存在
|
||
//查看插件是否已经激活
|
||
if (file_exists($pluginPath)) {
|
||
$existed = true;
|
||
if (file_exists($pluginPath.'Plugin.php') and isset($activatedPlugins['activated'][$plugin])) {
|
||
$activated = true;
|
||
}
|
||
}
|
||
|
||
//插件如果存在,则需要备份下,后面出错可以进行回滚
|
||
if ($existed or $activated) {
|
||
|
||
file_exists($pluginBackupPath) and delete_files($pluginBackupPath) and @rmdir($pluginBackupPath);
|
||
@rename($pluginPath, $pluginBackupPath);
|
||
|
||
}
|
||
|
||
//下载新插件zip包
|
||
$zipUrl = $this->server.'plugins/'.$plugin.'/download/'.str_replace(' ', '%20', $version).'.zip';
|
||
$http = $this->http;
|
||
$archive = $http($zipUrl);
|
||
|
||
if (! $archive) {
|
||
throw new DownloadErrorException('下载插件包出错!'.$zipUrl);
|
||
}
|
||
|
||
//保存文件
|
||
$fp = fopen($tempFile, 'w');
|
||
fwrite($fp, $archive);
|
||
fclose($fp);
|
||
|
||
//解压缩文件
|
||
$unzip = new Unzip();
|
||
|
||
//创建文件夹
|
||
@mkdir($pluginPath);
|
||
|
||
$extractedFiles = $unzip->extract($tempFile, $pluginPath);
|
||
|
||
if ($extractedFiles === false) {
|
||
throw new UnzipErrorException('解压缩出错!');
|
||
}
|
||
|
||
//OK,解压缩成功了
|
||
|
||
//删除备份文件
|
||
file_exists($pluginBackupPath) and delete_files($pluginBackupPath) and @rmdir($pluginBackupPath);
|
||
|
||
//删除临时文件
|
||
@unlink($tempFile);
|
||
|
||
//报告首长, 安装顺利完成
|
||
|
||
echo json_encode(array(
|
||
'status' => true,
|
||
'activated' => $activated
|
||
));
|
||
|
||
|
||
} catch (VersionNotMatchException $e) {
|
||
$e->responseJson();
|
||
} catch (DownloadErrorException $e) {
|
||
//如果存在备份包,则进行回滚
|
||
file_exists($pluginBackupPath) and @rename($pluginBackupPath, $pluginPath);
|
||
$e->responseJson();
|
||
} catch (UnzipErrorException $e) {
|
||
//清理解锁压缩的废弃文件
|
||
file_exists($pluginPath) and delete_files($pluginPath) and @rmdir($pluginPath);
|
||
//如果存在备份包,则进行回滚
|
||
file_exists($pluginBackupPath) and @rename($pluginBackupPath, $pluginPath);
|
||
//删除临时文件
|
||
@unlink($tempFile);
|
||
$e->responseJson();
|
||
} catch(Exception $e) {
|
||
$error = new JsonableException($e->getMessage());
|
||
$error->responseJson();
|
||
}
|
||
}
|
||
|
||
}
|