PluginsAdminService.php 45.4 KB
Newer Older
D
devil_gong 已提交
1 2 3 4
<?php
// +----------------------------------------------------------------------
// | ShopXO 国内领先企业级B2C免费开源电商系统
// +----------------------------------------------------------------------
D
devil_gong 已提交
5
// | Copyright (c) 2011~2019 http://shopxo.net All rights reserved.
D
devil_gong 已提交
6 7 8 9 10 11 12 13
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: Devil
// +----------------------------------------------------------------------
namespace app\service;

use think\Db;
D
Devil 已提交
14
use app\service\PluginsService;
D
devil_gong 已提交
15
use app\service\ResourcesService;
D
devil_gong 已提交
16
use app\service\SqlconsoleService;
D
devil_gong 已提交
17 18 19 20 21 22 23 24 25 26

/**
 * 应用管理服务层
 * @author   Devil
 * @blog     http://gong.gg/
 * @version  0.0.1
 * @datetime 2016-12-01T21:51:08+0800
 */
class PluginsAdminService
{
G
gongfuxiang 已提交
27 28 29
    // 排除不能使用的名称
    public static $plugins_exclude_verification = ['view', 'shopxo', 'www'];

D
devil 已提交
30
    // 排除的文件后缀
31
    public static $exclude_ext = ['php'];
D
devil 已提交
32

33
    // 读取插件排序方式(自定义排序 -> 最早安装)
34
    public static $plugins_order_by = 'sort asc,id asc';
35

D
devil_gong 已提交
36 37 38 39 40 41 42 43 44 45 46
    /**
     * 列表
     * @author   Devil
     * @blog    http://gong.gg/
     * @version 1.0.0
     * @date    2018-09-29
     * @desc    description
     * @param   [array]          $params [输入参数]
     */
    public static function PluginsList($params = [])
    {
D
devil_gong 已提交
47
        $data = [];
48 49
        $db_data = [];
        $dir_data = [];
D
Devil 已提交
50
        $temp_data = [];
D
devil_gong 已提交
51 52 53 54 55
        $plugins_dir = APP_PATH.'plugins'.DS;
        if(is_dir($plugins_dir))
        {
            if($dh = opendir($plugins_dir))
            {
56
                // 获取数据库已安装插件
D
Devil 已提交
57
                $temp_data = Db::name('Plugins')->order(self::$plugins_order_by)->column('*', 'plugins');
58 59

                // 获取目录所有插件
D
devil_gong 已提交
60 61 62 63 64 65
                while(($temp_file = readdir($dh)) !== false)
                {
                    if(!in_array($temp_file, ['.', '..', '/', 'view', 'index.html']) && substr($temp_file, 0, 1) != '.')
                    {
                        // 获取插件配置信息
                        $config = self::GetPluginsConfig($temp_file);
66
                        if($config !== false && !empty($config['base']))
D
devil_gong 已提交
67 68
                        {
                            // 获取数据库配置信息
69
                            $base = $config['base'];
D
Devil 已提交
70
                            $db_config = array_key_exists($base['plugins'], $temp_data) ? $temp_data[$base['plugins']] : [];
D
devil_gong 已提交
71 72

                            // 数据组装
73 74 75
                            $dir_data[$base['plugins']] = [
                                'id'            => empty($db_config['id']) ? 0 : $db_config['id'],
                                'plugins'       => $base['plugins'],
D
devil_gong 已提交
76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
                                'is_enable'     => isset($db_config['is_enable']) ? $db_config['is_enable'] : 0,
                                'is_install'    => empty($db_config) ? 0 : 1,
                                'logo_old'      => $base['logo'],
                                'logo'          => ResourcesService::AttachmentPathViewHandle($base['logo']),
                                'is_home'       => isset($base['is_home']) ? $base['is_home'] : false,
                                'name'          => isset($base['name']) ? $base['name'] : '',
                                'author'        => isset($base['author']) ? $base['author'] : '',
                                'author_url'    => isset($base['author_url']) ? $base['author_url'] : '',
                                'version'       => isset($base['version']) ? $base['version'] : '',
                                'desc'          => isset($base['desc']) ? $base['desc'] : '',
                                'apply_version' => isset($base['apply_version']) ? $base['apply_version'] : [],
                                'apply_terminal'=> isset($base['apply_terminal']) ? $base['apply_terminal'] : [],
                                'add_time_time' => isset($db_config['add_time']) ? date('Y-m-d H:i:s', $db_config['add_time']) : '',
                                'add_time_date' => isset($db_config['add_time']) ? date('Y-m-d', $db_config['add_time']) : '',
                            ];
                        }
                    }
                }
                closedir($dh);
            }
        }
D
devil_gong 已提交
97

98
        // 存在插件和数据库插件数据则处理排序合并
D
Devil 已提交
99
        if(!empty($dir_data) && !empty($temp_data))
100
        {
D
Devil 已提交
101
            foreach($temp_data as $v)
102 103 104
            {
                if(array_key_exists($v['plugins'], $dir_data))
                {
D
Devil 已提交
105
                    $db_data[] = $dir_data[$v['plugins']];
106 107 108 109 110
                    unset($dir_data[$v['plugins']]);
                }
            }
        }

D
Devil 已提交
111 112 113 114
        $data = [
            'db_data'   => $db_data,
            'dir_data'  => array_values($dir_data),
        ];
D
devil_gong 已提交
115
        return DataReturn('处理成功', 0, $data);
D
devil_gong 已提交
116 117 118
    }

    /**
D
devil_gong 已提交
119 120
     * 应用安装
     * @author  Devil
D
devil_gong 已提交
121 122
     * @blog    http://gong.gg/
     * @version 1.0.0
D
devil_gong 已提交
123
     * @date    2018-09-17
D
devil_gong 已提交
124
     * @desc    description
D
devil_gong 已提交
125
     * @param   [array]          $params [输入参数]
D
devil_gong 已提交
126
     */
D
devil_gong 已提交
127
    public static function PluginsInstall($params = [])
D
devil_gong 已提交
128
    {
D
devil_gong 已提交
129 130 131 132 133 134 135 136
        // 参数
        if(empty($params['id']))
        {
            return DataReturn('参数错误', -1);
        }

        // 数据处理
        $config = self::GetPluginsConfig($params['id']);;
137
        if($config !== false && !empty($config['base']) && !empty($config['base']['name']))
D
devil_gong 已提交
138
        {
D
Devil 已提交
139
            $cache = PluginsService::PluginsCacheData($params['id']);
D
devil_gong 已提交
140
            $data = [
141
                'name'      => $config['base']['name'],
D
devil_gong 已提交
142
                'plugins'   => $params['id'],
D
Devil 已提交
143
                'data'      => empty($cache) ? '' : json_encode($cache),
D
devil_gong 已提交
144 145 146 147 148 149
                'is_enable' => 0,
                'add_time'  => time(),
            ];

            // 添加数据
            if(Db::name('Plugins')->insertGetId($data) > 0)
D
devil_gong 已提交
150
            {
D
devil_gong 已提交
151
               return DataReturn('安装成功');
D
devil_gong 已提交
152 153
            } else {
                return DataReturn('安装失败', -100);
D
devil_gong 已提交
154
            }
D
devil_gong 已提交
155 156
        } else {
            return DataReturn('插件配置有误', -10);
D
devil_gong 已提交
157 158 159 160
        }
    }

    /**
D
devil_gong 已提交
161 162
     * 卸载应用
     * @author  Devil
D
devil_gong 已提交
163 164
     * @blog    http://gong.gg/
     * @version 1.0.0
D
devil_gong 已提交
165
     * @date    2018-09-17
D
devil_gong 已提交
166
     * @desc    description
D
devil_gong 已提交
167
     * @param   [array]          $params [输入参数]
D
devil_gong 已提交
168
     */
D
devil_gong 已提交
169
    public static function PluginsUninstall($params = [])
D
devil_gong 已提交
170
    {
D
devil_gong 已提交
171 172 173 174 175 176 177 178 179 180
        // 参数
        if(empty($params['id']))
        {
            return DataReturn('参数错误', -1);
        }

        // 开启事务
        Db::startTrans();

        // 开始卸载
G
gongfuxiang 已提交
181
        if(DB::name('Plugins')->where(['plugins'=>$params['id']])->delete())
D
devil_gong 已提交
182 183 184 185 186 187 188 189 190
        {
            // 钩子部署
            $ret = self::PluginsHookDeployment();
            if($ret['code'] == 0)
            {
                // 提交事务
                Db::commit();
                return DataReturn('卸载成功');
            }
G
gongfuxiang 已提交
191 192
        } else {
            $ret = DataReturn('卸载失败', -100);
D
devil_gong 已提交
193 194 195 196
        }

        // 事务回退
        Db::rollback();
G
gongfuxiang 已提交
197
        return $ret;
D
devil_gong 已提交
198 199 200
    }

    /**
D
devil_gong 已提交
201
     * 获取插件配置信息
D
devil_gong 已提交
202 203 204
     * @author   Devil
     * @blog    http://gong.gg/
     * @version 1.0.0
D
devil_gong 已提交
205
     * @date    2018-09-17
D
devil_gong 已提交
206
     * @desc    description
D
devil_gong 已提交
207
     * @param   [string]          $plugins [插件名称]
D
devil_gong 已提交
208
     */
D
devil_gong 已提交
209
    private static function GetPluginsConfig($plugins)
D
devil_gong 已提交
210
    {
D
devil_gong 已提交
211 212 213 214 215 216 217
        $config = [];
        $file = APP_PATH.'plugins'.DS.$plugins.DS.'config.json';
        if(file_exists($file))
        {
            $config = json_decode(file_get_contents($file), true);
        }
        return empty($config) ? false : $config;
D
devil_gong 已提交
218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249
    }

    /**
     * 状态更新
     * @author   Devil
     * @blog     http://gong.gg/
     * @version  0.0.1
     * @datetime 2016-12-06T21:31:53+0800
     * @param    [array]          $params [输入参数]
     */
    public static function PluginsStatusUpdate($params = [])
    {
        // 请求参数
        $p = [
            [
                'checked_type'      => 'empty',
                'key_name'          => 'id',
                'error_msg'         => '操作id有误',
            ],
            [
                'checked_type'      => 'in',
                'key_name'          => 'state',
                'checked_data'      => [0,1],
                'error_msg'         => '状态有误',
            ],
        ];
        $ret = ParamsChecked($params, $p);
        if($ret !== true)
        {
            return DataReturn($ret, -1);
        }

G
gongfuxiang 已提交
250 251 252
        // 开启事务
        Db::startTrans();

D
devil_gong 已提交
253
        // 数据更新
D
devil_gong 已提交
254
        if(Db::name('Plugins')->where(['plugins'=>$params['id']])->update(['is_enable'=>intval($params['state']), 'upd_time'=>time()]))
D
devil_gong 已提交
255
        {
D
devil_gong 已提交
256 257
            // 钩子部署
            $ret = self::PluginsHookDeployment();
G
gongfuxiang 已提交
258
            if($ret['code'] == 0)
D
devil_gong 已提交
259
            {
G
gongfuxiang 已提交
260 261 262
                // 提交事务
                Db::commit();
                return DataReturn('操作成功');
D
devil_gong 已提交
263
            }
G
gongfuxiang 已提交
264 265
        } else {
            $ret = DataReturn('操作失败', -100);
D
devil_gong 已提交
266
        }
G
gongfuxiang 已提交
267 268 269 270

        // 事务回退
        Db::rollback();
        return $ret;
D
devil_gong 已提交
271 272
    }

D
devil_gong 已提交
273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322
    /**
     * 应用钩子部署
     * @author   Devil
     * @blog    http://gong.gg/
     * @version 1.0.0
     * @date    2019-02-13
     * @desc    description
     */
    private static function PluginsHookDeployment()
    {
        // 钩子配置文件
        $tags_file = APP_PATH.'tags.php';
        if(!is_writable($tags_file))
        {
            return DataReturn('钩子配置文件没有操作权限'.'['.$tags_file.']', -3);
        }

        // 钩子容器
        $result = [];

        // 系统自带钩子处理
        if(file_exists($tags_file))
        {
            $tags = require $tags_file;
            if(!empty($tags) && is_array($tags))
            {
                $system_hook_list = [
                    'app_init',
                    'app_dispatch',
                    'app_begin',
                    'module_init',
                    'action_begin',
                    'view_filter',
                    'app_end',
                    'log_write',
                    'log_level',
                    'response_send',
                    'response_end'
                ];
                foreach($system_hook_list as $system_hook)
                {
                    if(isset($tags[$system_hook]))
                    {
                        $result[$system_hook] = $tags[$system_hook];
                    }
                }
            }
        }

        // 处理应用钩子
323
        $data = Db::name('Plugins')->where(['is_enable'=>1])->order(self::$plugins_order_by)->column('plugins');
D
devil_gong 已提交
324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351
        if(!empty($data))
        {
            foreach($data as $plugins)
            {
                if(file_exists(APP_PATH.'plugins'.DS.$plugins.DS.'config.json'))
                {
                    $config = json_decode(file_get_contents(APP_PATH.'plugins'.DS.$plugins.DS.'config.json'), true);
                    if(!empty($config['hook']) && is_array($config['hook']))
                    {
                        foreach($config['hook'] as $hook_key=>$hook_value)
                        {
                            if(isset($result[$hook_key]))
                            {
                               $result[$hook_key] = array_merge($result[$hook_key], $hook_value); 
                            } else {
                                $result[$hook_key] = $hook_value;
                            }
                        }
                    }
                }
            }
        }

        // 部署钩子到文件
        $ret = @file_put_contents($tags_file, "<?php
// +----------------------------------------------------------------------
// | ShopXO 国内领先企业级B2C免费开源电商系统
// +----------------------------------------------------------------------
D
devil_gong 已提交
352
// | Copyright (c) 2011~2019 http://shopxo.net All rights reserved.
D
devil_gong 已提交
353 354 355 356 357 358 359 360 361 362 363 364 365 366 367
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: Devil
// +----------------------------------------------------------------------

// 应用行为扩展定义文件\nreturn ".var_export($result, true).";\n?>");
        if($ret === false)
        {
            return DataReturn('应用钩子部署失败', -10);
        }

        return DataReturn('处理成功', 0);
    }

D
devil_gong 已提交
368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391
    /**
     * 删除
     * @author   Devil
     * @blog    http://gong.gg/
     * @version 1.0.0
     * @date    2018-12-18
     * @desc    description
     * @param   [array]          $params [输入参数]
     */
    public static function PluginsDelete($params = [])
    {
        // 请求参数
        $p = [
            [
                'checked_type'      => 'empty',
                'key_name'          => 'id',
                'error_msg'         => '操作id有误',
            ],
        ];
        $ret = ParamsChecked($params, $p);
        if($ret !== true)
        {
            return DataReturn($ret, -1);
        }
D
devil_gong 已提交
392 393 394 395 396 397

        // 应用是否存在
        if(!file_exists(APP_PATH.'plugins'.DS.$params['id']))
        {
           return DataReturn('应用不存在', -10); 
        }
D
devil_gong 已提交
398 399
        
        // 获取应用标记
D
devil_gong 已提交
400 401
        $data = Db::name('Plugins')->where(['plugins'=>$params['id']])->find();
        if(!empty($data['is_enable']))
D
devil_gong 已提交
402
        {
D
devil_gong 已提交
403
           return DataReturn('请先卸载应用', -10);
D
devil_gong 已提交
404 405
        }

D
devil_gong 已提交
406 407 408
        // 钩子部署
        $ret = self::PluginsHookDeployment();
        if($ret['code'] == 0)
D
devil_gong 已提交
409
        {
D
devil_gong 已提交
410 411
            // 是否需要删除应用数据,sql运行
            $is_delete_static = (isset($params['value']) && $params['value'] == 1);
D
Devil 已提交
412

D
Devil 已提交
413
            // 删除数据
D
devil_gong 已提交
414
            if($is_delete_static === true)
D
devil_gong 已提交
415
            {
D
Devil 已提交
416
                // 删除缓存
D
Devil 已提交
417
                PluginsService::PluginsCacheDelete($params['id']);
D
Devil 已提交
418 419

                // 执行卸载sql
D
devil_gong 已提交
420 421
                $uninstall_sql = APP_PATH.'plugins'.DS.$params['id'].DS.'uninstall.sql';
                if(file_exists($uninstall_sql))
D
devil_gong 已提交
422
                {
D
devil_gong 已提交
423
                    SqlconsoleService::Implement(['sql'=>file_get_contents($uninstall_sql)]);
D
devil_gong 已提交
424
                }
D
devil_gong 已提交
425
            }
D
devil_gong 已提交
426 427 428 429 430 431

            // 删除数据库附件
            ResourcesService::AttachmentPathTypeDelete('plugins_'.$params['id']);

            // 删除应用文件
            self::PluginsResourcesDelete($params['id'], $is_delete_static);
D
Devil 已提交
432

D
devil_gong 已提交
433
            return DataReturn('删除成功');
D
devil_gong 已提交
434
        }
D
devil_gong 已提交
435
        return $ret;
D
devil_gong 已提交
436 437 438 439 440 441 442 443 444
    }

    /**
     * 应用资源删除
     * @author   Devil
     * @blog    http://gong.gg/
     * @version 1.0.0
     * @date    2019-02-13
     * @desc    description
G
gongfuxiang 已提交
445 446
     * @param   [string]          $plugins          [唯一标记]
     * @param   [boolean]         $is_delete_static [是否删除应用数据]
D
devil_gong 已提交
447
     */
G
gongfuxiang 已提交
448
    private static function PluginsResourcesDelete($plugins, $is_delete_static = false)
D
devil_gong 已提交
449 450 451 452 453 454
    {
        \base\FileUtil::UnlinkDir(APP_PATH.'plugins'.DS.$plugins);
        \base\FileUtil::UnlinkDir(APP_PATH.'plugins'.DS.'view'.DS.$plugins);
        \base\FileUtil::UnlinkDir(ROOT.'public'.DS.'static'.DS.'plugins'.DS.'css'.DS.$plugins);
        \base\FileUtil::UnlinkDir(ROOT.'public'.DS.'static'.DS.'plugins'.DS.'js'.DS.$plugins);
        \base\FileUtil::UnlinkDir(ROOT.'public'.DS.'static'.DS.'plugins'.DS.'images'.DS.$plugins);
G
gongfuxiang 已提交
455 456 457 458 459 460 461 462

        // 是否需要删除应用数据
        if($is_delete_static === true)
        {
            \base\FileUtil::UnlinkDir(ROOT.'public'.DS.'static'.DS.'upload'.DS.'images'.DS.'plugins_'.$plugins);
            \base\FileUtil::UnlinkDir(ROOT.'public'.DS.'static'.DS.'upload'.DS.'video'.DS.'plugins_'.$plugins);
            \base\FileUtil::UnlinkDir(ROOT.'public'.DS.'static'.DS.'upload'.DS.'file'.DS.'plugins_'.$plugins);
        }
D
devil_gong 已提交
463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530
    }

    /**
     * 保存
     * @author   Devil
     * @blog    http://gong.gg/
     * @version 1.0.0
     * @date    2018-12-18
     * @desc    description
     * @param   [array]          $params [输入参数]
     */
    public static function PluginsSave($params = [])
    {
        // 请求参数
        $p = [
            [
                'checked_type'      => 'empty',
                'key_name'          => 'plugins',
                'error_msg'         => '应用唯一标记不能为空',
            ],
            [
                'checked_type'      => 'empty',
                'key_name'          => 'logo',
                'error_msg'         => '请上传LOGO',
            ],
            [
                'checked_type'      => 'empty',
                'key_name'          => 'name',
                'error_msg'         => '应用名称不能为空',
            ],
            [
                'checked_type'      => 'empty',
                'key_name'          => 'author',
                'error_msg'         => '作者不能为空',
            ],
            [
                'checked_type'      => 'empty',
                'key_name'          => 'author_url',
                'error_msg'         => '作者主页不能为空',
            ],
            [
                'checked_type'      => 'empty',
                'key_name'          => 'version',
                'error_msg'         => '版本号不能为空',
            ],
            [
                'checked_type'      => 'empty',
                'key_name'          => 'desc',
                'error_msg'         => '描述不能为空',
            ],
            [
                'checked_type'      => 'empty',
                'key_name'          => 'apply_terminal',
                'error_msg'         => '请至少选择一个适用终端',
            ],
            [
                'checked_type'      => 'empty',
                'key_name'          => 'apply_version',
                'error_msg'         => '请至少选择一个适用系统版本',
            ],
        ];
        $ret = ParamsChecked($params, $p);
        if($ret !== true)
        {
            return DataReturn($ret, -1);
        }

        // 权限校验
D
devil_gong 已提交
531
        $ret = self::PowerCheck();
D
devil_gong 已提交
532 533 534 535 536
        if($ret['code'] != 0)
        {
            return $ret;
        }

D
devil_gong 已提交
537 538 539
        // 应用唯一标记
        $plugins = trim($params['plugins']);

D
devil_gong 已提交
540 541
        // 应用校验
        $ret = self::PluginsVerification($plugins);
D
devil_gong 已提交
542 543 544 545 546 547 548
        if($ret['code'] != 0)
        {
            return $ret;
        }

        // 应用目录不存在则创建
        $app_dir = APP_PATH.'plugins'.DS.$plugins;
549
        if(!is_dir($app_dir) && \base\FileUtil::CreateDir($app_dir) !== true)
D
devil_gong 已提交
550 551 552 553 554 555 556 557 558 559 560 561
        {
            return DataReturn('应用主目录创建失败', -10);
        }

        // 生成配置文件
        $ret = self::PluginsConfigCreated($params, $app_dir);
        if($ret['code'] != 0)
        {
            return $ret;
        }

        // 应用主文件生成
562 563
        $ret = self::PluginsApplicationCreated($params, $app_dir);
        if($ret['code'] != 0)
D
devil_gong 已提交
564
        {
565
            return $ret;
D
devil_gong 已提交
566 567
        }

568
        return DataReturn('操作成功', 0);
D
devil_gong 已提交
569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585
    }

    /**
     * 应用文件生成
     * @author   Devil
     * @blog    http://gong.gg/
     * @version 1.0.0
     * @date    2018-12-18
     * @desc    description
     * @param   [array]          $params    [输入参数]
     * @param   [string]         $app_dir   [主目录地址]
     */
    private static function PluginsApplicationCreated($params, $app_dir)
    {
        $plugins = trim($params['plugins']);
$admin=<<<php
<?php
G
gongfuxiang 已提交
586
namespace app\plugins\\$plugins\admin;
587

D
devil_gong 已提交
588
use think\Controller;
589

D
devil_gong 已提交
590 591 592 593 594 595 596
/**
 * {$params['name']} - 后台管理
 * @author   Devil
 * @blog     http://gong.gg/
 * @version  0.0.1
 * @datetime 2016-12-01T21:51:08+0800
 */
D
devil_gong 已提交
597
class Admin extends Controller
D
devil_gong 已提交
598
{
D
devil 已提交
599 600 601 602 603 604
    // 构造方法
    public function __construct(\$params = [])
    {
        parent::__construct();
    }

D
devil_gong 已提交
605 606 607 608
    // 后台管理入口
    public function index(\$params = [])
    {
        // 数组组装
D
devil_gong 已提交
609 610
        \$this->assign('data', ['hello', 'world!']);
        \$this->assign('msg', 'hello world! admin');
G
gongfuxiang 已提交
611
        return \$this->fetch('../../../plugins/view/$plugins/admin/admin/index');
D
devil_gong 已提交
612 613 614 615 616 617 618 619
    }
}
?>
php;

$hook=<<<php
<?php
namespace app\plugins\\$plugins;
620

D
devil_gong 已提交
621
use think\Controller;
622

D
devil_gong 已提交
623 624 625 626 627 628 629
/**
 * {$params['name']} - 钩子入口
 * @author   Devil
 * @blog     http://gong.gg/
 * @version  0.0.1
 * @datetime 2016-12-01T21:51:08+0800
 */
D
devil_gong 已提交
630
class Hook extends Controller
D
devil_gong 已提交
631 632 633 634 635
{
    // 应用响应入口
    public function run(\$params = [])
    {
        // 是否控制器钩子
636
        // is_backend 当前为后端业务处理
637
        // hook_name 钩子名称
638
        if(isset(\$params['is_backend']) && \$params['is_backend'] === true && !empty(\$params['hook_name']))
D
devil_gong 已提交
639
        {
640 641 642 643
            // 参数一   描述
            // 参数二   0 为处理成功, 负数为失败
            // 参数三   返回数据
            return DataReturn('返回描述', 0);
D
devil_gong 已提交
644 645 646 647 648 649 650 651 652 653 654 655

        // 默认返回视图
        } else {
            return 'hello world!';
        }
    }
}
?>
php;

$index=<<<php
<?php
G
gongfuxiang 已提交
656
namespace app\plugins\\$plugins\index;
657

D
devil_gong 已提交
658
use think\Controller;
659

D
devil_gong 已提交
660 661 662 663 664 665 666
/**
 * {$params['name']} - 前端独立页面入口
 * @author   Devil
 * @blog     http://gong.gg/
 * @version  0.0.1
 * @datetime 2016-12-01T21:51:08+0800
 */
D
devil_gong 已提交
667
class Index extends Controller
D
devil_gong 已提交
668
{
D
devil 已提交
669 670 671 672 673 674
    // 构造方法
    public function __construct(\$params = [])
    {
        parent::__construct();
    }

D
devil_gong 已提交
675 676 677 678
    // 前端页面入口
    public function index(\$params = [])
    {
        // 数组组装
D
devil_gong 已提交
679 680
        \$this->assign('data', ['hello', 'world!']);
        \$this->assign('msg', 'hello world! index');
G
gongfuxiang 已提交
681
        return \$this->fetch('../../../plugins/view/$plugins/index/index/index');
D
devil_gong 已提交
682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757
    }
}
?>
php;

$admin_view=<<<php
{{include file="public/header" /}}

<!-- right content start  -->
<div class="content-right">
    <div class="content">
        <h1>后台管理页面</h1>
        {{:print_r(\$data)}}
        <p class="msg">{{\$msg}}</p>
    </div>
</div>
<!-- right content end  -->
        
<!-- footer start -->
{{include file="public/footer" /}}
<!-- footer end -->
php;

$index_view=<<<php
{{include file="public/header" /}}

<!-- nav start -->
{{include file="public/nav" /}}
<!-- nav end -->

<!-- header top nav -->
{{include file="public/header_top_nav" /}}

<!-- search -->
{{include file="public/nav_search" /}}

<!-- header nav -->
{{include file="public/header_nav" /}}

<!-- goods category -->
{{include file="public/goods_category" /}}

<!-- content start -->
<div class="am-g my-content">
    <div class="am-u-md-6 am-u-sm-centered">
        <h1>前端页面</h1>
        {{:print_r(\$data)}}
        <p class="msg">{{\$msg}}</p>
    </div>
</div>
<!-- content end -->

<!-- footer start -->
{{include file="public/footer" /}}
<!-- footer end -->
php;

$admin_css=<<<php
h1 {
    font-size: 60px;
}
.msg {
    font-size: 38px;
    color: #F00;
}
php;

$index_css=<<<php
h1 {
    font-size: 60px;
}
.msg {
    font-size: 68px;
    color: #4CAF50;
}
php;
758
        // 静态文件目录
D
devil_gong 已提交
759
        $app_static_css_dir = ROOT.'public'.DS.'static'.DS.'plugins'.DS.'css'.DS.trim($params['plugins']);
760
        if(!is_dir($app_static_css_dir) && \base\FileUtil::CreateDir($app_static_css_dir) !== true)
D
devil_gong 已提交
761 762
        {
            return DataReturn('应用静态目录创建失败[css]', -10);
D
devil_gong 已提交
763 764
        } else {
            // 后端css目录创建
765
            if(!is_dir($app_static_css_dir.DS.'admin') && \base\FileUtil::CreateDir($app_static_css_dir.DS.'admin') !== true)
D
devil_gong 已提交
766 767 768
            {
                return DataReturn('应用静态目录创建失败[css/admin]', -10);
            }
D
devil_gong 已提交
769
        }
770

771 772
        // 后端admin目录创建
        if(!is_dir($app_dir.DS.'admin') && \base\FileUtil::CreateDir($app_dir.DS.'admin') !== true)
D
devil_gong 已提交
773
        {
774 775
            return DataReturn('应用后端目录创建失败[admin]', -10);
        }
776

777 778 779 780 781 782 783 784 785
        // 创建文件
        if(!file_exists($app_dir.DS.'admin'.DS.'Admin.php') && @file_put_contents($app_dir.DS.'admin'.DS.'Admin.php', $admin) === false)
        {
            return DataReturn('应用文件创建失败[Admin.php]', -11);
        }
        if(!file_exists($app_dir.DS.'Hook.php') && @file_put_contents($app_dir.DS.'Hook.php', $hook) === false)
        {
            return DataReturn('应用文件创建失败[Hook.php]', -11);
        }
786

787 788 789 790 791 792 793 794 795
        // 应用后台视图目录不存在则创建
        $app_view_admin_dir = APP_PATH.'plugins'.DS.'view'.DS.trim($params['plugins']).DS.'admin'.DS.'admin';
        if(!is_dir($app_view_admin_dir) && \base\FileUtil::CreateDir($app_view_admin_dir) !== true)
        {
            return DataReturn('应用视图目录创建失败[admin]', -10);
        }
        if(!file_exists($app_view_admin_dir.DS.'index.html') && @file_put_contents($app_view_admin_dir.DS.'index.html', $admin_view) === false)
        {
            return DataReturn('应用视图文件创建失败[admin-view]', -11);
D
devil_gong 已提交
796 797
        }

798 799 800 801 802
        // css创建
        if(!file_exists($app_static_css_dir.DS.'admin'.DS.'admin.css') && @file_put_contents($app_static_css_dir.DS.'admin'.DS.'admin.css', $admin_css) === false)
        {
            return DataReturn('应用静态文件创建失败[admin-css]', -11);
        }
D
devil_gong 已提交
803 804 805 806

        // 是否有前端页面
        if(isset($params['is_home']) && $params['is_home'] == 1)
        {
G
gongfuxiang 已提交
807
            // 前端index目录创建
808
            if(!is_dir($app_dir.DS.'index') && \base\FileUtil::CreateDir($app_dir.DS.'index') !== true)
G
gongfuxiang 已提交
809 810 811 812
            {
                return DataReturn('应用前端目录创建失败[index]', -10);
            }

D
devil_gong 已提交
813
            // 创建文件
G
gongfuxiang 已提交
814
            if(!file_exists($app_dir.DS.'index'.DS.'Index.php') && @file_put_contents($app_dir.DS.'index'.DS.'Index.php', $index) === false)
D
devil_gong 已提交
815 816 817 818 819
            {
                return DataReturn('应用文件创建失败[index]', -11);
            }

            // 应用前端视图目录不存在则创建
G
gongfuxiang 已提交
820
            $app_view_index_dir = APP_PATH.'plugins'.DS.'view'.DS.trim($params['plugins']).DS.'index'.DS.'index';
D
devil_gong 已提交
821
            if(!is_dir($app_view_index_dir) && \base\FileUtil::CreateDir($app_view_index_dir) !== true)
D
devil_gong 已提交
822 823 824
            {
                return DataReturn('应用视图目录创建失败[index]', -10);
            }
D
devil_gong 已提交
825
            if(!file_exists($app_view_index_dir.DS.'index.html') && @file_put_contents($app_view_index_dir.DS.'index.html', $index_view) === false)
D
devil_gong 已提交
826 827 828 829
            {
                return DataReturn('应用视图文件创建失败[index-view]', -11);
            }

D
devil_gong 已提交
830
            // 前端css目录创建
D
devil_gong 已提交
831
            if(!is_dir($app_static_css_dir.DS.'index') && \base\FileUtil::CreateDir($app_static_css_dir.DS.'index') !== true)
D
devil_gong 已提交
832 833 834 835
            {
                return DataReturn('应用静态目录创建失败[css/index]', -10);
            }

D
devil_gong 已提交
836
            // css创建
D
devil_gong 已提交
837
            if(!file_exists($app_static_css_dir.DS.'index'.DS.'index.css') && @file_put_contents($app_static_css_dir.DS.'index'.DS.'index.css', $index_css) === false)
D
devil_gong 已提交
838 839 840 841 842
            {
                return DataReturn('应用静态文件创建失败[index-css]', -11);
            }
        }

843
        return DataReturn('操作成功', 0);
D
devil_gong 已提交
844 845 846 847 848 849 850 851 852 853 854 855 856 857
    }

    /**
     * 应用配置文件生成
     * @author   Devil
     * @blog    http://gong.gg/
     * @version 1.0.0
     * @date    2018-12-18
     * @desc    description
     * @param   [array]          $params    [输入参数]
     * @param   [string]         $app_dir   [主目录地址]
     */
    private static function PluginsConfigCreated($params, $app_dir)
    {
D
devil_gong 已提交
858 859 860 861 862 863 864 865
        // 模块名称
        $plugins = trim($params['plugins']);

        // 配置信息
        $config = self::GetPluginsConfig($plugins);
        $hook = empty($config['hook']) ? [] : $config['hook'];

        // 配置信息组装
D
devil_gong 已提交
866 867 868
        $data = [
            // 基础信息
            'base'  => [
D
devil_gong 已提交
869
                'plugins'           => $plugins,
D
devil_gong 已提交
870
                'name'              => $params['name'],
D
devil_gong 已提交
871
                'logo'              => ResourcesService::AttachmentPathHandle($params['logo']),
D
devil_gong 已提交
872 873 874 875 876 877 878 879 880 881
                'author'            => $params['author'],
                'author_url'        => $params['author_url'],
                'version'           => $params['version'],
                'desc'              => $params['desc'],
                'apply_terminal'    => explode(',', $params['apply_terminal']),
                'apply_version'     => explode(',', $params['apply_version']),
                'is_home'           => (isset($params['is_home']) && $params['is_home'] == 1) ? true : false,
            ],

            // 钩子配置
D
devil_gong 已提交
882
            'hook'  => (object) $hook,
D
devil_gong 已提交
883 884
        ];

885
        // 文件是否存在、存在判断权限、则创建
D
devil_gong 已提交
886
        $config_file = $app_dir.DS.'config.json';
887
        if(file_exists($config_file))
D
devil_gong 已提交
888
        {
889 890 891 892 893
            // 文件存在是否有权限
            if(!is_writable($config_file))
            {
                return DataReturn('应用配置文件没有操作权限'.'['.$config_file.']', -3);
            }
D
Devil 已提交
894 895 896 897 898 899
        }

        // 创建配置文件
        if(@file_put_contents($config_file, JsonFormat($data)) === false)
        {
            return DataReturn('应用配置文件创建失败', -10);
D
devil_gong 已提交
900 901
        }

902
        return DataReturn('操作成功', 0);
D
devil_gong 已提交
903 904
    }

G
gongfuxiang 已提交
905 906 907 908 909 910
    /**
     * 名称校验
     * @author   Devil
     * @blog     http://gong.gg/
     * @version  1.0.0
     * @datetime 2019-05-13T00:00:45+0800
D
devil_gong 已提交
911
     * @param   [string]          $plugins   [应用唯一标记]
G
gongfuxiang 已提交
912
     */
D
devil_gong 已提交
913
    public static function PluginsVerification($plugins)
G
gongfuxiang 已提交
914 915 916 917 918 919 920 921 922 923
    {
        // 排除校验
        if(in_array($plugins, self::$plugins_exclude_verification))
        {
            return DataReturn('不能使用限制的名称['.$plugins.']', -1);
        }

        return DataReturn('校验成功', 0);
    }

D
devil_gong 已提交
924 925 926 927 928 929 930 931 932
    /**
     * 应用添加
     * @author   Devil
     * @blog    http://gong.gg/
     * @version 1.0.0
     * @date    2018-12-18
     * @desc    description
     * @param   [string]          $plugins   [应用唯一标记]
     */
D
devil_gong 已提交
933
    private static function PluginsExist($plugins)
D
devil_gong 已提交
934
    {
D
devil_gong 已提交
935 936
        // 应用是否存在
        if(is_dir(APP_PATH.'plugins'.DS.$plugins))
D
devil_gong 已提交
937
        {
D
devil_gong 已提交
938
            return DataReturn('应用名称已存在['.$plugins.']', -1);
D
devil_gong 已提交
939
        }
G
gongfuxiang 已提交
940

D
devil_gong 已提交
941 942 943 944 945 946 947 948 949 950
        return DataReturn('添加成功', 0);
    }

    /**
     * 权限校验
     * @author   Devil
     * @blog     http://gong.gg/
     * @version  1.0.0
     * @datetime 2018-09-29T00:01:49+0800
     */
D
devil_gong 已提交
951
    private static function PowerCheck()
D
devil_gong 已提交
952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986
    {
        // 应用目录
        $app_dir = APP_PATH.'plugins';
        if(!is_writable($app_dir))
        {
            return DataReturn('应用目录没有操作权限'.'['.$app_dir.']', -3);
        }

        // 应用视图目录
        $app_view_dir = APP_PATH.'plugins'.DS.'view';
        if(!is_writable($app_view_dir))
        {
            return DataReturn('应用视图目录没有操作权限'.'['.$app_view_dir.']', -3);
        }

        // 应用css目录
        $app_static_css_dir = ROOT.'public'.DS.'static'.DS.'plugins'.DS.'css';
        if(!is_writable($app_static_css_dir))
        {
            return DataReturn('应用css目录没有操作权限'.'['.$app_static_css_dir.']', -3);
        }

        // 应用js目录
        $app_static_js_dir = ROOT.'public'.DS.'static'.DS.'plugins'.DS.'js';
        if(!is_writable($app_static_js_dir))
        {
            return DataReturn('应用js目录没有操作权限'.'['.$app_static_js_dir.']', -3);
        }

        // 应用images目录
        $app_static_images_dir = ROOT.'public'.DS.'static'.DS.'plugins'.DS.'images';
        if(!is_writable($app_static_images_dir))
        {
            return DataReturn('应用images目录没有操作权限'.'['.$app_static_images_dir.']', -3);
        }
G
gongfuxiang 已提交
987 988 989 990 991 992 993 994

        // 应用upload目录
        $app_upload_dir = ROOT.'public'.DS.'static'.DS.'upload';
        if(!is_writable($app_upload_dir))
        {
            return DataReturn('应用upload目录没有操作权限'.'['.$app_upload_dir.']', -3);
        }

D
devil_gong 已提交
995 996
        return DataReturn('权限正常', 0);
    }
D
devil_gong 已提交
997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015

    /**
     * 应用上传
     * @author   Devil
     * @blog     http://gong.gg/
     * @version  1.0.0
     * @datetime 2018-12-19T00:53:45+0800
     * @param    [array]          $params [输入参数]
     */
    public static function PluginsUpload($params = [])
    {
        // 文件上传校验
        $error = FileUploadError('file');
        if($error !== true)
        {
            return DataReturn($error, -1);
        }

        // 文件格式化校验
D
Devil 已提交
1016
        $type = ResourcesService::ZipExtTypeList();
D
devil_gong 已提交
1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028
        if(!in_array($_FILES['file']['type'], $type))
        {
            return DataReturn('文件格式有误,请上传zip压缩包', -2);
        }

        // 权限校验
        $ret = self::PowerCheck();
        if($ret['code'] != 0)
        {
            return $ret;
        }

D
devil_gong 已提交
1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043
        // 资源目录
        $dir_list = [
            '_controller_'      => APP_PATH.'plugins'.DS,
            '_view_'            => APP_PATH.'plugins'.DS.'view'.DS,
            '_css_'             => ROOT.'public'.DS.'static'.DS.'plugins'.DS.'css'.DS,
            '_js_'              => ROOT.'public'.DS.'static'.DS.'plugins'.DS.'js'.DS,
            '_images_'          => ROOT.'public'.DS.'static'.DS.'plugins'.DS.'images'.DS,
            '_uploadfile_'      => ROOT.'public'.DS.'static'.DS.'upload'.DS.'file'.DS,
            '_uploadimages_'    => ROOT.'public'.DS.'static'.DS.'upload'.DS.'images'.DS,
            '_uploadvideo_'     => ROOT.'public'.DS.'static'.DS.'upload'.DS.'video'.DS,
        ];

        // 包名
        $plugins_name = '';

D
devil_gong 已提交
1044 1045
        // 开始解压文件
        $resource = zip_open($_FILES['file']['tmp_name']);
D
devil_gong 已提交
1046 1047 1048 1049 1050
        if(!is_resource($resource))
        {
            return DataReturn('压缩包打开失败['.$resource.']', -10);
        }

D
devil_gong 已提交
1051 1052 1053 1054 1055 1056 1057
        while(($temp_resource = zip_read($resource)) !== false)
        {
            if(zip_entry_open($resource, $temp_resource))
            {
                // 当前压缩包中项目名称
                $file = zip_entry_name($temp_resource);

D
devil_gong 已提交
1058 1059 1060
                // 获取包名
                if(empty($plugins_name))
                {
D
devil_gong 已提交
1061
                    // 应用名称
D
devil_gong 已提交
1062
                    $plugins_name = substr($file, 0, strpos($file, '/'));
D
devil_gong 已提交
1063 1064
                    if(empty($plugins_name))
                    {
1065 1066 1067 1068 1069 1070 1071 1072 1073
                        // 应用名称为空、则校验是否为支付插件
                        $file_size = zip_entry_filesize($temp_resource);
                        $file_content = zip_entry_read($temp_resource, $file_size);
                        if(stripos($file_content, 'namespace payment') !== false)
                        {
                            return DataReturn('支付插件请到[ 网站管理->支付方式 ]模块里面去上传安装', -1);
                        }

                        // 不是支付插件则提示插件包错误
D
devil_gong 已提交
1074 1075 1076 1077
                        return DataReturn('插件包有误', -30);
                    }

                    // 应用不存在则添加
D
devil_gong 已提交
1078 1079 1080 1081 1082 1083 1084 1085 1086
                    $ret = self::PluginsVerification($plugins_name);
                    if($ret['code'] != 0)
                    {
                        zip_entry_close($temp_resource);
                        return $ret;
                    }

                    // 应用是否存在
                    $ret = self::PluginsExist($plugins_name);
D
devil_gong 已提交
1087 1088 1089 1090 1091 1092 1093
                    if($ret['code'] != 0)
                    {
                        zip_entry_close($temp_resource);
                        return $ret;
                    }
                }

D
devil_gong 已提交
1094 1095 1096
                // 排除临时文件和临时目录
                if(strpos($file, '/.') === false && strpos($file, '__') === false)
                {
D
devil_gong 已提交
1097
                    // 文件包对应系统所在目录
D
devil_gong 已提交
1098
                    $is_has_find = false;
D
devil_gong 已提交
1099
                    foreach($dir_list as $dir_key=>$dir_value)
D
devil_gong 已提交
1100
                    {
D
devil_gong 已提交
1101 1102
                        if(strpos($file, $dir_key) !== false)
                        {
D
devil 已提交
1103 1104 1105 1106 1107 1108 1109
                            // 仅控制器模块支持php文件
                            if($dir_key != '_controller_')
                            {
                                // 排除后缀文件
                                $pos = strripos($file, '.');
                                if($pos !== false)
                                {
D
devil 已提交
1110 1111
                                    $info = pathinfo($file);
                                    if(isset($info['extension']) && in_array($info['extension'], self::$exclude_ext))
D
devil 已提交
1112 1113 1114 1115 1116 1117 1118
                                    {
                                        continue;
                                    }
                                }
                            }

                            // 匹配成功文件路径处理、跳出循环
D
devil_gong 已提交
1119
                            $file = str_replace($plugins_name.'/'.$dir_key.'/', '', $dir_value.$file);
D
devil_gong 已提交
1120
                            $is_has_find = true;
D
devil_gong 已提交
1121 1122
                            break;
                        }
D
devil_gong 已提交
1123 1124
                    }

D
devil_gong 已提交
1125 1126 1127 1128 1129 1130
                    // 没有匹配到则指定目录跳过
                    if($is_has_find == false)
                    {
                        continue;
                    }

D
devil_gong 已提交
1131 1132
                    // 截取文件路径
                    $file_path = substr($file, 0, strrpos($file, '/'));
D
devil_gong 已提交
1133

D
devil_gong 已提交
1134
                    // 路径不存在则创建
D
devil_gong 已提交
1135
                    \base\FileUtil::CreateDir($file_path);
D
devil_gong 已提交
1136 1137 1138 1139 1140 1141 1142

                    // 如果不是目录则写入文件
                    if(!is_dir($file))
                    {
                        // 读取这个文件
                        $file_size = zip_entry_filesize($temp_resource);
                        $file_content = zip_entry_read($temp_resource, $file_size);
D
devil_gong 已提交
1143
                        @file_put_contents($file, $file_content);
D
devil_gong 已提交
1144
                    }
D
devil_gong 已提交
1145

D
devil_gong 已提交
1146 1147 1148 1149 1150
                    // 关闭目录项  
                    zip_entry_close($temp_resource);
                }
            }
        }
D
devil_gong 已提交
1151

D
devil_gong 已提交
1152 1153 1154
        // 附件同步到数据库
        ResourcesService::AttachmentDiskFilesToDb('plugins_'.$plugins_name);

D
devil_gong 已提交
1155 1156 1157 1158
        // sql运行
        $install_sql = APP_PATH.'plugins'.DS.$plugins_name.DS.'install.sql';
        if(!empty($plugins_name) && file_exists($install_sql))
        {
D
Devil 已提交
1159
            SqlconsoleService::Implement(['sql'=>file_get_contents($install_sql)]);
D
devil_gong 已提交
1160 1161
        }

D
devil_gong 已提交
1162
        return DataReturn('安装成功');
D
devil_gong 已提交
1163
    }
D
devil_gong 已提交
1164 1165 1166 1167 1168 1169 1170 1171

    /**
     * 应用打包
     * @author   Devil
     * @blog    http://gong.gg/
     * @version 1.0.0
     * @date    2019-03-22
     * @desc    description
G
gongfuxiang 已提交
1172
     * @param   [array]          $params [输入参数]
D
devil_gong 已提交
1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188
     */
    public static function PluginsDownload($params = [])
    {
        // 请求参数
        $p = [
            [
                'checked_type'      => 'empty',
                'key_name'          => 'id',
                'error_msg'         => '操作id有误',
            ],
        ];
        $ret = ParamsChecked($params, $p);
        if($ret !== true)
        {
            return DataReturn($ret, -1);
        }
D
devil_gong 已提交
1189 1190 1191 1192 1193 1194

        // 是否开启开发者模式
        if(config('shopxo.is_develop') !== true)
        {
            return DataReturn('请先开启开发者模式', -1); 
        }
D
Devil 已提交
1195

D
devil_gong 已提交
1196
        // 获取应用标记
D
Devil 已提交
1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209
        // 防止路径回溯
        $plugins = htmlentities(str_replace(array('.', '/', '\\', ':'), '', strip_tags($params['id'])));
        if(empty($plugins))
        {
            return DataReturn('插件标识有误', -1);
        }

        // 配置信息
        $config = self::GetPluginsConfig($plugins);
        if($config === false)
        {
            return DataReturn('插件配置有误', -10);
        }
D
devil_gong 已提交
1210

D
devil_gong 已提交
1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294
        // 目录不存在则创建
        $new_dir = ROOT.'runtime'.DS.'data'.DS.'plugins_package'.DS.$plugins;
        \base\FileUtil::CreateDir($new_dir);

        // 复制包目录 - 控制器
        $old_dir = APP_PATH.'plugins'.DS.$plugins;
        if(is_dir($old_dir))
        {
            if(\base\FileUtil::CopyDir($old_dir, $new_dir.DS.'_controller_'.DS.$plugins) != true)
            {
                return DataReturn('项目包复制失败[控制器]', -2);
            }
        }

        // 复制包目录 - 视图
        $old_dir = APP_PATH.'plugins'.DS.'view'.DS.$plugins;
        if(is_dir($old_dir))
        {
            if(\base\FileUtil::CopyDir($old_dir, $new_dir.DS.'_view_'.DS.$plugins) != true)
            {
                return DataReturn('项目包复制失败[视图]', -2);
            }
        }

        // 复制包目录 - css
        $old_dir = ROOT.'public'.DS.'static'.DS.'plugins'.DS.'css'.DS.$plugins;
        if(is_dir($old_dir))
        {
            if(\base\FileUtil::CopyDir($old_dir, $new_dir.DS.'_css_'.DS.$plugins) != true)
            {
                return DataReturn('项目包复制失败[css]', -2);
            }
        }

        // 复制包目录 - js
        $old_dir = ROOT.'public'.DS.'static'.DS.'plugins'.DS.'js'.DS.$plugins;
        if(is_dir($old_dir))
        {
            if(\base\FileUtil::CopyDir($old_dir, $new_dir.DS.'_js_'.DS.$plugins) != true)
            {
                return DataReturn('项目包复制失败[js]', -2);
            }
        }

        // 复制包目录 - images
        $old_dir = ROOT.'public'.DS.'static'.DS.'plugins'.DS.'images'.DS.$plugins;
        if(is_dir($old_dir))
        {
            if(\base\FileUtil::CopyDir($old_dir, $new_dir.DS.'_images_'.DS.$plugins) != true)
            {
                return DataReturn('项目包复制失败[images]', -2);
            }
        }

        // 复制包目录 - uploadimages
        $old_dir = ROOT.'public'.DS.'static'.DS.'upload'.DS.'images'.DS.'plugins_'.$plugins;
        if(is_dir($old_dir))
        {
            if(\base\FileUtil::CopyDir($old_dir, $new_dir.DS.'_uploadimages_'.DS.'plugins_'.$plugins) != true)
            {
                return DataReturn('项目包复制失败[uploadimages]', -2);
            }
        }

        // 复制包目录 - uploadvideo
        $old_dir = ROOT.'public'.DS.'static'.DS.'upload'.DS.'video'.DS.'plugins_'.$plugins;
        if(is_dir($old_dir))
        {
            if(\base\FileUtil::CopyDir($old_dir, $new_dir.DS.'_uploadvideo_'.DS.'plugins_'.$plugins) != true)
            {
                return DataReturn('项目包复制失败[uploadvideo]', -2);
            }
        }

        // 复制包目录 - uploadfile
        $old_dir = ROOT.'public'.DS.'static'.DS.'upload'.DS.'file'.DS.'plugins_'.$plugins;
        if(is_dir($old_dir))
        {
            if(\base\FileUtil::CopyDir($old_dir, $new_dir.DS.'_uploadfile_'.DS.'plugins_'.$plugins) != true)
            {
                return DataReturn('项目包复制失败[uploadfile]', -2);
            }
        }

D
Devil 已提交
1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315
        // 配置文件历史信息更新
        $new_config_file = $new_dir.DS.'_controller_'.DS.$plugins.DS.'config.json';
        if(!file_exists($new_config_file))
        {
            return DataReturn('新配置文件有误', -10);
        }
        if(empty($config['history']))
        {
            $config['history'] = [];
        }
        $config['history'][] = [
            'host'  => __MY_HOST__,
            'url'   => __MY_URL__,
            'ip'    => __MY_ADDR__,
            'time'  => date('Y-m-d H:i:s'),
        ];
        if(@file_put_contents($new_config_file, JsonFormat($config)) === false)
        {
            return DataReturn('新应用配置文件更新失败', -11);
        }

D
devil_gong 已提交
1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326
        // 生成压缩包
        $zip = new \base\ZipFolder();
        if(!$zip->zip($new_dir.'.zip', $new_dir))
        {
            return DataReturn('压缩包生成失败', -100);
        }

        // 生成成功删除目录
        \base\FileUtil::UnlinkDir($new_dir);

        // 开始下载
D
Devil 已提交
1327
        if(\base\FileUtil::DownloadFile($new_dir.'.zip', $config['base']['name'].'.zip'))
D
devil_gong 已提交
1328 1329 1330 1331 1332
        {
            @unlink($new_dir.'.zip');
        } else {
            return DataReturn('下载失败', -100);
        }
D
devil_gong 已提交
1333
    }
1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397

    /**
     * 排序保存
     * @author  Devil
     * @blog    http://gong.gg/
     * @version 1.0.0
     * @date    2021-01-05
     * @desc    description
     * @param   [array]           $params [输入参数]
     */
    public static function SortSave($params = [])
    {
        // 请求类型
        $p = [
            [
                'checked_type'      => 'empty',
                'key_name'          => 'data',
                'error_msg'         => '没有可保存的插件数据',
            ]
        ];
        $ret = ParamsChecked($params, $p);
        if($ret !== true)
        {
            return DataReturn($ret, -1);
        }

        // 排序数据、非数组则当做json转换一次
        $data = is_array($params['data']) ? $params['data'] : json_decode($params['data'], true);
        if(!empty($data) && is_array($data))
        {
            // 启动事务
            Db::startTrans();

            // 捕获异常
            try {
                foreach($data as $k=>$v)
                {
                    $upd_data = [
                        'sort'      => intval($k),
                        'add_time'  => time(),
                    ];
                    if(Db::name('Plugins')->where(['id'=>intval($v)])->update($upd_data) === false)
                    {
                        throw new \Exception('操作失败');
                    }
                }

                // 钩子部署
                $ret = self::PluginsHookDeployment();
                if($ret['code'] != 0)
                {
                    throw new \Exception($ret['msg']);
                }

                // 完成
                Db::commit();
                return DataReturn('操作成功', 0);
            } catch(\Exception $e) {
                Db::rollback();
                return DataReturn($e->getMessage(), -1);
            }
        }
        return DataReturn('插件排序数据有误', -1);
    }
D
devil_gong 已提交
1398 1399
}
?>