433 lines
13 KiB
PHP
Executable File
433 lines
13 KiB
PHP
Executable File
<?php// +----------------------------------------------------------------------
|
|
// | 宏驰云科技开发团队 版权所有 拥有最终解释权
|
|
// +----------------------------------------------------------------------
|
|
|
|
// | Author: HcyShop-松鼠
|
|
// +----------------------------------------------------------------------
|
|
|
|
|
|
namespace app\admin\logic;
|
|
|
|
|
|
use think\Db;
|
|
use Requests;
|
|
use think\Exception;
|
|
use think\facade\Cache;
|
|
use think\facade\Log;
|
|
|
|
class UpgradeLogic
|
|
{
|
|
|
|
protected static $base_url = 'https://shop.likemarket.net';
|
|
|
|
/**
|
|
* Notes: 版本列表
|
|
* @param $page_no
|
|
* @param $page_size
|
|
* @author 竹
|
|
* @return array
|
|
*/
|
|
public static function index($page_no, $page_size)
|
|
{
|
|
$lists = self::getRemoteVersion($page_no, $page_size) ?? [];
|
|
if (empty($lists)) {
|
|
return ['count' => 0, 'lists' => []];
|
|
}
|
|
|
|
$local_data = local_version();
|
|
$local_version = $local_data['version'];
|
|
|
|
foreach ($lists as $k => $item) {
|
|
|
|
$lists[$k]['version_str'] = '';
|
|
$lists[$k]['able_update'] = 0;
|
|
if ($local_version == $item['version_no']) {
|
|
$lists[$k]['version_str'] = '您的系统当前处于此版本';
|
|
}
|
|
|
|
if ($local_version < $item['version_no']) {
|
|
$lists[$k]['version_str'] = '系统可更新至此版本';
|
|
$lists[$k]['able_update'] = 1;
|
|
}
|
|
|
|
//最新的版本号标志
|
|
$lists[$k]['new_version'] = 0;
|
|
$lists[0]['new_version'] = 1;
|
|
|
|
//注意,是否需要重新发布描述
|
|
$lists[$k]['notice'] = '';
|
|
if ($item['is_republish'] == 1) {
|
|
$lists[$k]['notice'] = '更新至当前版本后需重新发布前端商城';
|
|
}
|
|
|
|
//处理更新内容信息
|
|
$contents = $item['update_content'];
|
|
$add = [];
|
|
$optimize = [];
|
|
$repair = [];
|
|
if (!empty($contents)) {
|
|
foreach ($contents as $content) {
|
|
if ($content['type'] == 1) {
|
|
$add[] = '新增:'.$content['update_function'];
|
|
}
|
|
if ($content['type'] == 2) {
|
|
$optimize[] = '优化:'.$content['update_function'];
|
|
}
|
|
if ($content['type'] == 3) {
|
|
$repair[] = '修复:'.$content['update_function'];
|
|
}
|
|
}
|
|
}
|
|
$lists[$k]['add'] = $add;
|
|
$lists[$k]['optimize'] = $optimize;
|
|
$lists[$k]['repair'] = $repair;
|
|
unset($lists[$k]['update_content']);
|
|
}
|
|
|
|
return ['count' => count($lists), 'lists' => $lists];
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
* Notes: 获取远程数据
|
|
* @param string $page_no
|
|
* @param string $page_size
|
|
* @author 竹
|
|
* @return mixed
|
|
*/
|
|
public static function getRemoteVersion($page_no = '', $page_size = '')
|
|
{
|
|
$cache_version = Cache::get('version_lists');
|
|
if (!empty($cache_version)) {
|
|
return $cache_version;
|
|
}
|
|
|
|
if (empty($page_no) || empty($page_size)) {
|
|
$remote_url = self::$base_url."/api/version/lists?type=2";
|
|
} else {
|
|
$remote_url = self::$base_url."/api/version/lists?type=2&page_no=$page_no&page_size=$page_size";
|
|
}
|
|
$result = Requests::get($remote_url);
|
|
$result = json_decode($result->body, true);
|
|
$result = $result['data'] ?? [];
|
|
Cache::set('version_lists', $result, 1800);
|
|
return $result;
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
* Notes: 更新主程序
|
|
* @param $version
|
|
* @return bool|string
|
|
* @author 竹
|
|
*/
|
|
public static function upgrade($post)
|
|
{
|
|
$post['update_type'] = 1;
|
|
Db::startTrans();
|
|
try {
|
|
//修改旧数据
|
|
self::handleOldData();
|
|
|
|
//要更新的版本
|
|
$version = $post['version_no'];
|
|
//远程下载链接
|
|
$remote_url = $post['package_link'];
|
|
// 本地更新路径
|
|
$local_upgrade_dir = ROOT_PATH . '/upgrade/';
|
|
// 本地更新包路径
|
|
$path = ROOT_PATH . '/upgrade/';
|
|
// 本地更新临时文件
|
|
$temp_dir = $path . 'temp/';
|
|
|
|
if (!is_dir($path)) {
|
|
mkdir(iconv("UTF-8", "GBK", $path), 0777, true);
|
|
}
|
|
|
|
//下载更新压缩包保存到本地
|
|
$remote_data = self::downFile($remote_url, $local_upgrade_dir);
|
|
if (false === $remote_data) {
|
|
throw new Exception('获取文件错误');
|
|
}
|
|
|
|
//解压缩
|
|
if (false === unzip($remote_data['save_path'], $temp_dir)) {
|
|
throw new Exception('解压文件错误');
|
|
}
|
|
|
|
//更新sql
|
|
if (false === self::upgradeSql($temp_dir . 'sql/')) {
|
|
throw new Exception('更新数据库失败');
|
|
}
|
|
|
|
//更新文件
|
|
if (false === self::upgradeDir($temp_dir . 'project/', self::getProjectPath())) {
|
|
throw new Exception('更新文件失败');
|
|
}
|
|
|
|
//更新本地版本号文件
|
|
$upgrade_data = ['version' => $version];
|
|
if (false === self::upgradeVersion($upgrade_data)) {
|
|
throw new Exception('本地更新日志写入失败');
|
|
}
|
|
|
|
//删除临时文件(压缩包不删除,删除解压的文件)
|
|
if (false === del_target_dir($temp_dir, true)) {
|
|
Log::write('删除临时文件失败');
|
|
}
|
|
|
|
Db::commit();
|
|
//增加日志
|
|
self::addlog($post);
|
|
return true;
|
|
|
|
} catch (Exception $e) {
|
|
|
|
Db::rollback();
|
|
//错误日志
|
|
$post['error'] = $e->getMessage();
|
|
self::addlog($post, false);
|
|
|
|
//删除临时文件(压缩包不删除,删除解压的文件)
|
|
if (false === del_target_dir($temp_dir, true)) {
|
|
Log::write('删除临时文件失败');
|
|
}
|
|
return $e->getMessage();
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* Notes: 添加日志
|
|
* @param $data
|
|
* @param bool $status
|
|
* @author 竹
|
|
* @return bool|\Requests_Response
|
|
*/
|
|
public static function addlog($data, $status = true)
|
|
{
|
|
$log_msg = json_encode($data, JSON_UNESCAPED_UNICODE);
|
|
Log::write('更新日志:'.$log_msg);
|
|
|
|
try{
|
|
$data = [
|
|
'version_id' => $data['id'],
|
|
'version_no' => $data['version_no'],
|
|
'ip_address' => get_client_ip(),
|
|
'domain' => request()->domain(),
|
|
'type' => 2,
|
|
'update_type' => $data['update_type'],
|
|
'status' => $status ? 1 : 0,
|
|
'error' => $data['error'] ?? '未知错误'
|
|
];
|
|
$request_url = self::$base_url.'/api/version/log';
|
|
return Requests::post($request_url, [], $data);
|
|
} catch(\Exception $e) {
|
|
Log::write('更新日志添加失败:'.$e->getMessage());
|
|
return false;
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* Notes: 下载压缩包
|
|
* @param $url
|
|
* @param string $savePath
|
|
* @return array|bool
|
|
* @author 竹
|
|
*/
|
|
public static function downFile($url, $savePath = './upgrade/')
|
|
{
|
|
$ch = curl_init();
|
|
curl_setopt($ch, CURLOPT_URL, $url);
|
|
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
|
|
curl_setopt($ch, CURLOPT_HEADER, TRUE); //需要response header
|
|
curl_setopt($ch, CURLOPT_NOBODY, FALSE); //需要response body
|
|
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
|
|
$response = curl_exec($ch);
|
|
$header = '';
|
|
$body = '';
|
|
if (curl_getinfo($ch, CURLINFO_HTTP_CODE) == '200') {
|
|
$headerSize = curl_getinfo($ch, CURLINFO_HEADER_SIZE); //头信息size
|
|
$header = substr($response, 0, $headerSize);
|
|
$body = substr($response, $headerSize);
|
|
}
|
|
curl_close($ch);
|
|
//文件名
|
|
$fullName = basename($url);
|
|
//文件保存完整路径
|
|
$savePath = $savePath . $fullName;
|
|
//创建目录并设置权限
|
|
$basePath = dirname($savePath);
|
|
if (!file_exists($basePath)) {
|
|
@mkdir($basePath, 0777, true);
|
|
@chmod($basePath, 0777);
|
|
}
|
|
if (file_put_contents($savePath, $body)) {
|
|
return [
|
|
'save_path' => $savePath,
|
|
'file_name' => $fullName,
|
|
];
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Notes: 获取项目路径
|
|
* @return string
|
|
* @author 竹
|
|
*/
|
|
public static function getProjectPath()
|
|
{
|
|
$path = dirname(ROOT_PATH);
|
|
$path = trim(str_replace('server', '', $path));
|
|
return $path;
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
* Notes: 执行指定文件夹内的sql文件
|
|
* @param $dir
|
|
* @return bool
|
|
* @author 竹
|
|
*/
|
|
public static function upgradeSql($dir)
|
|
{
|
|
//遍历指定目录下的指定后缀文件
|
|
$sql_files = get_scandir($dir, '', 'sql');
|
|
|
|
if (false === $sql_files) {
|
|
return false;
|
|
}
|
|
|
|
//当前数据库前缀
|
|
$sql_prefix = config('database.prefix');
|
|
|
|
//遍历更新sql
|
|
foreach ($sql_files as $k => $sql_file) {
|
|
if (get_extension($sql_file) != 'sql') {
|
|
continue;
|
|
}
|
|
$sql_content = file_get_contents($dir . $sql_file);
|
|
if (empty($sql_content)) {
|
|
continue;
|
|
}
|
|
$sqls = explode(';', $sql_content);
|
|
//执行sql
|
|
foreach ($sqls as $sql) {
|
|
if (!empty($sql)) {
|
|
$sql = str_replace('`ls_', '`' . $sql_prefix, $sql);
|
|
Db::execute($sql . ';');
|
|
}
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
|
|
/**
|
|
* Notes: 更新文件
|
|
* @param $temp_file //临时更新文件路径 (新的更新文件)
|
|
* @param $old_file //需要更新的文件路囧 (旧的文件)
|
|
* @author 竹
|
|
* @return array|bool
|
|
*/
|
|
public static function upgradeDir($temp_file, $old_file)
|
|
{
|
|
if (!file_exists($temp_file)) {
|
|
return [];
|
|
}
|
|
|
|
if (empty(trim($temp_file)) || empty(trim($old_file))) {
|
|
return false;
|
|
}
|
|
|
|
// 目录不存在就新建
|
|
if (!is_dir($old_file)) {
|
|
mkdir($old_file, 0777, true);
|
|
}
|
|
|
|
foreach (glob($temp_file . '*') as $file_name) {
|
|
// 要处理的是目录时,递归处理文件目录。
|
|
if (is_dir($file_name)) {
|
|
self::upgradeDir($file_name . '/', $old_file . basename($file_name) . '/');
|
|
}
|
|
// 要处理的是文件时,判断是否存在 或者 与原来文件不一致 则覆盖
|
|
if (is_file($file_name)) {
|
|
if (!file_exists($old_file . basename($file_name))
|
|
|| md5(file_get_contents($file_name)) != md5(file_get_contents($old_file . basename($file_name)))
|
|
) {
|
|
copy($file_name, $old_file . basename($file_name));
|
|
}
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
|
|
/**
|
|
* Notes: 更新本地版本号
|
|
* @param $data
|
|
* @return bool
|
|
* @author 竹
|
|
*/
|
|
public static function upgradeVersion($data)
|
|
{
|
|
$version = './upgrade/version.json';
|
|
$res = file_put_contents($version, json_encode($data, JSON_UNESCAPED_UNICODE));
|
|
if (empty($res)) {
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
|
|
/**
|
|
* Notes: 修改旧数据
|
|
* @author 竹
|
|
* @throws Exception
|
|
* @throws \think\db\exception\DataNotFoundException
|
|
* @throws \think\db\exception\ModelNotFoundException
|
|
* @throws \think\exception\DbException
|
|
* @throws \think\exception\PDOException
|
|
*/
|
|
public static function handleOldData()
|
|
{
|
|
try {
|
|
//修改旧活动专区错误
|
|
$temp = [];
|
|
$count = 0;
|
|
$lists = Db::name('activity_goods')->where(['del' => 0])->select();
|
|
|
|
foreach ($lists as $k => $v) {
|
|
$temp_key = $v['goods_id'].'_'.$v['activity_id'];
|
|
if (in_array($temp_key, $temp)) {
|
|
Db::name('activity_goods')
|
|
->where(['del' => 0, 'id' => $v['id']])
|
|
->update(['del' => 1]);
|
|
$count += 1;
|
|
} else {
|
|
$temp[] = $temp_key;
|
|
}
|
|
}
|
|
if ($count > 0) {
|
|
Log::write('处理活动专区错误,删除'.$count.'数据');
|
|
}
|
|
|
|
|
|
// 更新file_cate表中type=null值的旧记录
|
|
$handle_file = Db::name('file_cate')->whereNull('type')->update(['type' => 1]);
|
|
if ($handle_file) {
|
|
Log::write('更新file_cate表中type=null值的旧记录');
|
|
}
|
|
|
|
} catch (\Exception $e) {
|
|
Log::write('修改旧数据错误:'.$e->getMessage());
|
|
}
|
|
}
|
|
|
|
} |