<?php
// +----------------------------------------------------------------------
// |HkCms 列表数据模型管理
// +----------------------------------------------------------------------
// | Copyright (c) 2020-2021 http://www.hkcms.cn, All rights reserved.
// +----------------------------------------------------------------------
// | Author: 广州恒企教育科技有限公司 <admin@hkcms.cn>
// +----------------------------------------------------------------------

namespace app\admin\controller\cms;

use app\admin\controller\BaseController;
use app\admin\model\cms\Category;
use app\admin\model\cms\ModelField;
use app\admin\model\cms\ModelFieldBind;
use libs\Tree;
use think\exception\ValidateException;
use think\facade\Db;

class Archives extends BaseController
{
    /**
     * 控制器中间件
     * @var array
     */
    protected $middleware = [
        'login',
    ];

    /**
     * 文章模型
     * @var \app\admin\model\cms\Archives
     */
    protected $model;

    protected $category_id = 0;

    /**
     * 初始化操作
     */
    public function initialize()
    {
        parent::initialize();

        $this->model = new \app\admin\model\cms\Archives;

        if (!$this->user->checkLogin()) {
            return json(['code'=>-1000, 'msg'=>__('Please log in and operate'), 'data'=>[]]);
        }

        $categoryArr = $this->user->getUserCategory(false);
        $this->category_id = $this->request->param('category_id','', 'intval');

        if (!in_array($this->category_id, $categoryArr)) {
            $this->error(__('No permission to operate this column'));
        }
    }

    public function index()
    {
        if ($this->request->isAjax()) {
            // 获取表名
            $model_id = $this->request->param('model_id');
            $tablename = Db::name('model')->where(['id'=>$model_id])->cache(3600)->value('tablename');
            // 是否显示下级
            $issub = $this->request->param('issub','');
            $cateMap = [['category_id','=',$this->category_id]];
            if ($issub==1) {
                $cids = Db::name('category')->where(['parent_id'=>$this->category_id,'model_id'=>$model_id])->cache(3600)->column('id');
                if (!empty($cids)) { // 上级显示下级的菜单
                    $cids[] = $this->category_id;
                    $cateMap = [['category_id','in',$cids]];
                }
            }

            list($map, $limit, $offset, $order, $sort) = $this->buildparams(null, 'a');

            $data = $this->model
                ->name($tablename)
                ->alias('a')
                ->leftJoin('admin','a.admin_id=admin.id')
                ->leftJoin('category category','a.category_id=category.id')
                ->where($map)
                ->where($cateMap)
                ->order($sort, $order)
                ->limit($offset, $limit)
                ->field('a.*,admin.username,category.title as category_title')
                ->select();

            $total = $this->model
                ->name($tablename)
                ->alias('a')
                ->leftJoin('admin','a.admin_id=admin.id')
                ->leftJoin('category category','a.category_id=category.id')
                ->where($map)
                ->where($cateMap)
                ->order($sort, $order)
                ->count();
            $data->append(['publish_time_text'])->toArray();
            return json(['total'=>$total,'rows'=>$data]);
        }

        // 文档属性
        $flags = Db::name('flags')->where(['lang'=>$this->contentLang])->select()->toArray();
        $flagsJson = [];
        foreach ($flags as $key=>$value) {
            $flagsJson[$value['name']] = $value['title'];
        }
        // 封面图
        $thumb = Db::name('model_field')->where(['field_name'=>'thumb','status'=>'normal','iscore'=>1,'model_id'=>$this->request->param('model_id')])->find();

        $this->view->assign('flags', $flags);
        $this->view->assign('flagsJson', json_encode($flagsJson));
        $this->view->assign('thumb', $thumb);
        $this->view->assign($this->request->param());
        return $this->view->fetch();
    }

    /**
     * 数据添加
     * @return mixed|string|void
     */
    public function add()
    {
        $category_id = $this->request->param('category_id','', 'intval');
        if (empty($category_id)) {
            $this->error(__('Parameter %s can not be empty', ['category_id']));
        }
        $categoryInfo = \app\admin\model\cms\Category::where(['id'=>$category_id,'status'=>'normal'])->find();
        if (empty($categoryInfo)) {
            $this->error(__('Column information does not exist'));
        }

        if ($this->request->isPost()) { // 数据添加
            $data = $this->request->post('row/a', '', 'stripslashes');
            $tempData = $data;
            $modelField = (new \app\admin\model\cms\ModelFieldBind)->getAllowField($categoryInfo['id'], $categoryInfo['model_id'], $data);

            // 验证
            list($valData,$msgData) = build_tp_rules($modelField);
            try {
                $this->validate($tempData, $valData, $msgData);
            } catch (ValidateException $e) {
                $this->error($e->getError());
            }

            $tablename = Db::name('model')->where(['id'=>$categoryInfo['model_id']])->value('tablename');

            Db::startTrans();
            try {
                if (isset($data['main'])) {
                    $this->model->setTable($tablename)->save(array_merge([
                        'model_id'=>$categoryInfo['model_id'],
                        'admin_id'=>$this->user->id,
                        'category_id'=>$category_id,
                        'lang'=>$categoryInfo['lang']
                    ],$data['main']));
                    Db::name($tablename.'_data')->insert(array_merge(['id'=>$this->model->id],$data['vice']));
                } else {
                    $this->model->setTable($tablename)->save(array_merge([
                        'model_id'=>$categoryInfo['model_id'],
                        'admin_id'=>$this->user->id,
                        'category_id'=>$category_id,
                        'lang'=>$categoryInfo['lang']
                    ],$data));
                }
                Db::commit();
            } catch (\Exception $e) {
                Db::rollback();
                $this->error($e->getMessage());
            }
            $this->success();
        }

        $this->buildPage($categoryInfo);
        return $this->view->fetch();
    }

    /**
     * 修改
     * @param null $id
     * @return mixed|string|void
     */
    public function edit($id = null)
    {
        // 获取栏目数据
        $category_id = $this->request->param('category_id', '', 'intval');
        $modelInfo = $this->model->getTableInfo($category_id,$categoryInfo);
        $row = $this->model->setTable($modelInfo['tablename'])->find($id);
        if (!$row) {
            $this->error(__('No results were found'));
        }
        $content = [];
        if ($modelInfo['type']=='more' && $modelInfo['allow_single']==0) {
            $content = Db::name($modelInfo['tablename'].'_data')->find($row->id);
            $content = empty($content) ? [] : $content;
        }

        if ($this->request->isPost()) {
            $params = $this->request->post("row/a",'','stripslashes');
            $modelField = (new \app\admin\model\cms\ModelFieldBind)->getAllowField($categoryInfo['id'], $categoryInfo['model_id'], $params);

            Db::startTrans();
            try {
                if (isset($params['main'])) {
                    $row->save(array_merge([
                        'model_id'=>$categoryInfo['model_id'],
                        'admin_id'=>$this->user->id,
                        'category_id'=>$category_id,
                    ],$params['main']));
                    if (Db::name($modelInfo['tablename'].'_data')->where(['id'=>$row->id])->find()) {
                        Db::name($modelInfo['tablename'].'_data')->where(['id'=>$row->id])->save($params['vice']);
                    } else {
                        $params['id'] = $row->id;
                        Db::name($modelInfo['tablename'].'_data')->insert($params['vice']);
                    }

                } else {
                    $row->save(array_merge([
                        'model_id'=>$categoryInfo['model_id'],
                        'admin_id'=>$this->user->id,
                        'category_id'=>$category_id,
                    ],$params));
                }
                Db::commit();
            } catch (\Exception $e) {
                Db::rollback();
                $this->error($e->getMessage());
            }
            $this->success();
        }
        $row = array_merge($content, $row->toArray());
        if ($newid = $this->request->param('newid','','intval')) {
            $categoryInfo = Category::where(['id'=>$newid,'status'=>'normal'])->find();
        }
        $this->buildPage($categoryInfo, $row);
        return $this->view->fetch();
    }

    /**
     * 软删除
     * @param string $ids
     */
    public function del($ids = '')
    {
        if ($ids) {
            $category_id = $this->request->param('category_id', '', 'intval');
            $modelInfo = $this->model->getTableInfo($category_id);
            $this->model->setTable($modelInfo['tablename']);
            parent::del($ids);
        }
        $this->error(__('Parameter %s can not be empty', ['ids']));
    }

    /**
     * 批量修改
     */
    public function batches()
    {
        if ($this->request->isAjax()) {
            $category_id = $this->request->param('category_id', '', 'intval');
            $ids = $this->request->param('ids', '');
            $params = $this->request->param('params', '');
            $modelInfo = $this->model->getTableInfo($category_id);

            $this->model->setTable($modelInfo['tablename']);
            $this->postData = compact('ids','params');
            parent::batches();
        }
    }

    /**
     * 推送
     * @param string $ids
     * @return string|void
     * @throws \Exception
     */
    public function push($ids = '')
    {
        $model_id = $this->request->param('model_id','');
        $category_id = $this->request->param('category_id','');

        if ($this->request->isPost()) {
            $to = $this->request->param('to','');
            if (empty($to)) {
                $this->error(__('Please select'));
            }

            // 获取源数据
            list($data, $obj, $model) = controller($model_id, function ($obj, $model, $category) use($ids) {
                return [$obj->whereIn('id',$ids)->select()->toArray(), $obj, $model];
            });
            $model = $model->toArray();
            $toArr = explode(',', $to);
            foreach ($data as $key=>$value) {
                $id = $value['id'];
                unset($value['id']);
                unset($value['url']);
                foreach ($toArr as $k=>$v) {
                    $value['category_id'] = $v;
                    $value['admin_id'] = $this->user->id;
                    $value['create_time'] = time();
                    $value['update_time'] = time();

                    $archives = (new \app\admin\model\cms\Archives)->setTable($obj->getName());
                    $archives->save($value);

                    // 有副表的情况下
                    if ($model['type']=='more' && $model['allow_single']!=1) {
                        $info = Db::table($obj->getTable().'_data')->where(['id'=>$id])->find();
                        $info['id'] = $archives->id;
                        Db::table($obj->getTable().'_data')->insert($info);
                    }
                }
            }
            $this->success();
        }

        $model = \app\admin\model\cms\Category::alias('c')->leftJoin('model m','m.id=c.model_id')->field('c.*,m.name as model_name')->where(['lang'=>$this->contentLang]);
        if (!$this->user->hasSuperAdmin()) { // 判断是否是超级管理员
            $group = $this->user->getUserGroupId();
            $categoryIdArr = Db::name('category_priv')->whereIn('auth_group_id', $group)->column('category_id');
            $data = [];
            if (!empty($categoryIdArr)) {
                $data = $model->whereIn('c.id', $categoryIdArr)->order(['c.weigh'=>'desc','c.id'=>'asc'])->select()->append(['type_text'])->toArray();
            }
        } else {
            $data = $model->order(['c.weigh'=>'desc','c.id'=>'asc'])->select()->append(['type_text'])->toArray();
        }

        // 剔除不是本模型的栏目
        foreach ($data as $key=>$value) {
            if ($value['model_id']!=$model_id && $value['parent_id']==0) {
                $bl = true;
                foreach ($data as $k=>$v) {
                    if ($v['parent_id']==$value['id'] && $v['model_id']!=$model_id) {
                        unset($data[$k]);
                    } else if ($v['parent_id']==$value['id'] && $v['model_id']==$model_id) {
                        $bl = false;
                    }
                }
                if ($bl) {
                    unset($data[$key]);
                }
            }
        }

        $arr = Tree::instance()->getTreeList(Tree::instance()->init($data)->getTreeArray(0));

        $this->view->assign('categoryList', $arr);
        $this->view->assign('category_id', $category_id);
        $this->view->assign('model_id', $model_id);
        $this->view->assign('ids', $ids);
        return $this->view->fetch();
    }

    /**
     * 移动
     * @param string $ids
     * @return string|void
     * @throws \Exception
     */
    public function move($ids = '')
    {
        $model_id = $this->request->param('model_id','');
        $category_id = $this->request->param('category_id','');

        if ($this->request->isPost()) {
            $to = $this->request->param('to','');
            if (empty($to)) {
                $this->error(__('Please select'));
            }

            // 获取源数据
            $data = controller($model_id, function ($obj, $model, $category) use($ids) {
                return $obj->whereIn('id',$ids)->select();
            });

            foreach ($data as $key=>$value) {
                $value->save(['category_id'=>$to]);
            }
            $this->success();
        }

        $model = \app\admin\model\cms\Category::alias('c')->leftJoin('model m','m.id=c.model_id')->field('c.*,m.name as model_name')->where(['lang'=>$this->contentLang]);
        if (!$this->user->hasSuperAdmin()) { // 判断是否是超级管理员
            $group = $this->user->getUserGroupId();
            $categoryIdArr = Db::name('category_priv')->whereIn('auth_group_id', $group)->column('category_id');
            $data = [];
            if (!empty($categoryIdArr)) {
                $data = $model->whereIn('c.id', $categoryIdArr)->order(['c.weigh'=>'desc','c.id'=>'asc'])->select()->append(['type_text'])->toArray();
            }
        } else {
            $data = $model->order(['c.weigh'=>'desc','c.id'=>'asc'])->select()->append(['type_text'])->toArray();
        }

        // 剔除不是本模型的栏目
        foreach ($data as $key=>$value) {
            if ($value['model_id']!=$model_id && $value['parent_id']==0) {
                $bl = true;
                foreach ($data as $k=>$v) {
                    if ($v['parent_id']==$value['id'] && $v['model_id']!=$model_id) {
                        unset($data[$k]);
                    } else if ($v['parent_id']==$value['id'] && $v['model_id']==$model_id) {
                        $bl = false;
                    }
                }
                if ($bl) {
                    unset($data[$key]);
                }
            }
        }

        $arr = Tree::instance()->getTreeList(Tree::instance()->init($data)->getTreeArray(0));
        $this->view->assign('categoryList', $arr);
        $this->view->assign('category_id', $category_id);
        $this->view->assign('model_id', $model_id);
        $this->view->assign('ids', $ids);
        return $this->view->fetch();
    }

    /**
     * 回收站
     * @return string|\think\response\Json|void
     */
    public function recycle()
    {
        $category_id = $this->request->param('category_id', '', 'intval');
        $modelInfo = $this->model->getTableInfo($category_id);
        if ($this->request->isAjax()) {

            list($map, $limit, $offset, $order, $sort) = $this->buildparams(null, 'a');

            $data = $this->model
                ->onlyTrashed()
                ->name($modelInfo['tablename'])
                ->alias('a')
                ->leftJoin('admin admin','a.admin_id=admin.id')
                ->leftJoin('category category','a.category_id=category.id')
                ->where($map)
                ->order($sort, $order)
                ->limit($offset, $limit)
                ->field('a.*,admin.username,category.title as category_title')
                ->select();

            $total = $this->model
                ->onlyTrashed()
                ->name($modelInfo['tablename'])
                ->alias('a')
                ->leftJoin('admin admin','a.admin_id=admin.id')
                ->leftJoin('category category','a.category_id=category.id')
                ->where($map)
                ->order($sort, $order)
                ->count();
            return json(['total'=>$total, 'rows'=>$data->append(['publish_time_text','delete_time_text'])->toArray()]);
        }
        $this->view->assign('category_id', $category_id);
        return $this->view->fetch();
    }

    /**
     * 还原
     * @param string $ids 为空的时候还原全部
     */
    public function restore($ids="")
    {
        $category_id = $this->request->param('category_id', '', 'intval');
        $modelInfo = $this->model->getTableInfo($category_id);

        $pk = $this->model->setTable($modelInfo['tablename'])->getPk();

        $bl = 0;
        Db::startTrans();
        try {
            $model = $this->model->onlyTrashed()->name($modelInfo['tablename']);
            if ($ids) {
                $model = $model->where($pk, 'in', $ids);
            }
            $list = $model->name($modelInfo['tablename'])->select();
            foreach ($list as $index => $item) {
                $bl += $item->restore();
            }
            Db::commit();
        } catch (\Exception $e) {
            Db::rollback();
            $this->error($e->getMessage());
        }

        if ($bl) {
            $this->success();
        } else {
            $this->error(__('Operation failed'));
        }
    }

    /**
     * 销毁
     * @param string $ids
     */
    public function destroy($ids="")
    {
        $category_id = $this->request->param('category_id', '', 'intval');
        $modelInfo = $this->model->getTableInfo($category_id);

        $pk = $this->model->setTable($modelInfo['tablename'])->getPk();

        $bl = 0;
        Db::startTrans();
        try {
            $model = $this->model->onlyTrashed()->name($modelInfo['tablename']);
            if ($ids) {
                $model = $model->where($pk, 'in', $ids);
            }
            $list = $model->name($modelInfo['tablename'])->select();
            foreach ($list as $index => $item) {
                if ($modelInfo['type']=='more' && $modelInfo['allow_single']==0) {
                    Db::name($modelInfo['tablename'].'_data')->where(['id'=>$item->getAttr('id')])->delete();
                }
                $bl += $item->force()->delete();
            }
            Db::commit();
        } catch (\Exception $e) {
            Db::rollback();
            $this->error($e->getMessage());
        }

        if ($bl) {
            $this->success();
        } else {
            $this->error(__('Operation failed'));
        }
    }

    /**
     * 生成文章临时预览
     * @return string|void
     */
    public function preview()
    {
        $id = $this->request->param('id', 0, 'intval');

        $info = Category::where(['id'=>$this->category_id])->find();
        if (empty($info)) {
            $this->error(__('Column information does not exist'));
        }
        $info = $info->toArray();
        $key = md5(app('session')->getId());
        $info['aid'] = $id;

        $site = site();
        if ($site['url_mode']==1 && !empty($site['url_rewrite'])) {
            $value = index_url('/index/show', $info,'','','',[],['key'=>$key]);
        } else {
            $param['key'] = $key;
            $param['id'] = $id;
            $param['catname'] = $info['name'];
            if ($site['content_lang_on']==1) {
                $param['lang'] = $this->request->param('lang');
            }
            $value = index_url('/index/show', $param);
        }

        return redirect($value);
    }

    /**
     * 属性
     */
    public function property()
    {
        $ids = $this->request->param('ids');
        $p = $this->request->param('p');
        $type = $this->request->param('type','','intval');
        $category_id = $this->request->param('category_id', '', 'intval');

        $ids = explode(',', $ids);
        if (empty($ids) || empty($p)) {
            $this->error(__('Parameter %s can not be empty'));
        }

        $modelInfo = $this->model->getTableInfo($category_id,$categoryInfo);
        $data = $this->model->setTable($modelInfo['tablename'])->whereIn('id', $ids)->select()->toArray();
        foreach ($data as $key=>$val) {
            if ($type==1) {
                // 新增属性
                if (!empty($val['flags'])) {
                    $flags = explode(',', $val['flags']);
                    $flags = array_unique(array_merge($flags, $p));
                } else {
                    $flags = $p;
                }
                $up = [];
                if (in_array('top', $flags)) {
                    $up['weigh'] = 9999;
                }
                $up['flags'] = implode(',', $flags);
                Db::name($modelInfo['tablename'])->where(['id'=>$val['id']])->update($up);
            } else if ($type==2 && !empty($val['flags'])) {
                // 删除属性
                $flags = explode(',', $val['flags']);
                $flags = array_diff($flags, $p);
                $up = [];
                if (!in_array('top', $flags) && $val['weigh']==9999) {
                    $up['weigh'] = 0;
                }
                $up['flags'] = empty($flags)?'':implode(',', $flags);
                Db::name($modelInfo['tablename'])->where(['id'=>$val['id']])->update($up);
            }
        }
        $this->success();
    }
}