<?php
/**
 * @link      http://www.u-bo.com
 * @copyright 南京友博网络科技有限公司 
 * @license   http://www.u-bo.com/license/
 */

namespace home\modules\task\models;

use Yii;
use yii\db\ActiveRecord;
use yii\db\Query;
use yii\helpers\Url;
use common\components\Tree;
use common\components\Tool;
use common\models\User;
use yii\helpers\StringHelper;
use yii\web\NotFoundHttpException;
use home\models\Announcement;
use common\models\PermissionScope;
use common\models\Common;
use qcbase\models\TaskStatus;
use home\modules\blog\models\Blog;
use yii\helpers\ArrayHelper;

/**
 * 任务表 ({{qc_task}})
 *
 * @property integer $task_id  (ID)
 * @property string $task_no  (任务编号)
 * @property string $name  (任务名称)
 * @property smallint $category_id  (任务类型ID（关联qc_task_category表）)
 * @property integer $parent_id  (父级ID)
 * @property string $parent_ids  (父级ID集)
 * @property string $child_ids  (子集ID集)
 * @property smallint $link_type  (关联类型)
 * @property integer $link_id  (关联信息ID)
 * @property integer $leader_id  (负责人ID （关联qc_user表）)
 * @property float $workload  (预估工作量（小时）)
 * @property string $join_ids  (参与人)
 * @property string $follow_ids  (关注人)
 * @property integer $begin_time  (开始日期)
 * @property integer $end_time  (结束日期)
 * @property text $description  (任务描述)
 * @property text $remark  (任务备注)
 * @property string $attach_ids  (附件)
 * @property integer $create_time  (创建时间)
 * @property smallint $status_id  (任务状态 关联qc_task_status)
 * @property string $status_name  (状态名称)
 * @property integer $update_time  (最后更新时间)
 * @property smallint $status  (99逻辑删除)
 * @property integer $user_id  (创建人ID)
 * @property string $ip  (创建人IP)
 *
 * @author legendjw http://blog.u-bo.com
 * @since 0.1
 */
class Task extends \yii\db\ActiveRecord
{
    public $parent_name;
    public $leader_name;
    public $link_name;
    public $join_names;
    public $follow_names;

    /**
     * @var array 公共分类
     */
    public static $publicCategorys;

    /**
     * @var array 共享的当前所有数据列表
     */
    public static $list;

    /**
     * @inheritdoc
     */
    public static function tableName()
    {
        return '{{%task}}';
    }

    /**
     * @inheritdoc
     */
    public function rules()
    {
        return [
            [['task_no', 'name', 'category_id'], 'required'],
            ['name', 'unique', 'targetAttribute' => ['name', 'link_id', 'link_type'], 'message' => '同一关联下名称已经存在'],
            [['category_id', 'leader_id', 'create_time', 'status_id', 'update_time', 'status', 'user_id'], 'integer'],
            ['parent_id', 'validateParent'],
            [['workload'], 'number'],
            [['description', 'remark'], 'string'],
            [['task_no', 'link_type', 'link_id'], 'string', 'max' => 64],
            [['task_no'], 'unique'],
            [['begin_time', 'end_time'], 'date', 'format' => 'php:Y-m-d'],
            [['name'], 'string', 'max' => 100],
            [['status_name'], 'string', 'max' => 50],
            [['parent_ids', 'child_ids', 'join_ids', 'follow_ids', 'attach_ids'], 'string', 'max' => 255],
            [['ip'], 'string', 'max' => 15]
        ];
    }

    /**
     * 验证父任务
     */
    public function validateParent($attribute, $params)
    {
        if ($this->$attribute == $this->task_no) {
            $this->addError($attribute, '父任务不能是当前任务');
        }
    }

    /**
     * @inheritdoc
     */
    public function attributeLabels()
    {
        return [
            'task_id' => 'ID',
            'task_no' => '任务编号',
            'name' => '任务名称',
            'category_id' => '任务类别',
            'parent_id' => '父任务',
            'parent_ids' => '父级ID集',
            'child_ids' => '子集ID集',
            'link_type' => '关联类型',
            'link_id' => '关联信息',
            'leader_id' => '负责人',
            'leader_name' => '负责人',
            'workload' => '预估工作量',
            'join_ids' => '参与人',
            'join_names' => '参与人',
            'follow_ids' => '关注人',
            'follow_names' => '关注人',
            'begin_time' => '开始日期',
            'end_time' => '结束日期',
            'description' => '任务描述',
            'remark' => '任务备注',
            'attach_ids' => '附件',
            'create_time' => '创建时间',
            'status_id' => '任务状态',
            'status_name' => '状态名称',
            'update_time' => '更新时间',
            'status' => '逻辑删除',
            'user_id' => '创建人ID',
            'ip' => '创建人IP',
        ];
    }

    /**
     * 前置操作
     */
    public function beforeSave($insert)
    {
        if (parent::beforeSave($insert)) {
            if ($insert) {
                $this->user_id = Yii::$app->user->identity->user_id;
                $this->ip = Yii::$app->getRequest()->getUserIP();
                $this->create_time = time();
            }
            //获取父级任务，由于统一返回编号所以要查询到id
            if (!empty($this->parent_id)) {
                $parentId = (new Query())->select('task_id')->where(['task_no' => $this->parent_id])->from(self::tableName())->scalar();
                $this->parent_id = (!empty($parentId)) ? $parentId : 0;
            } else {
                $this->parent_id = 0;
            }
            //判断自动加入添加人到关注人列表
            if (!empty($this->leader_id)) {
                $this->judgeTaskUser();
            }

            $this->workload = (empty($this->workload)) ? 0 : $this->workload;
            $this->begin_time = (!empty($this->begin_time)) ? strtotime($this->begin_time) : 0;
            $this->end_time = (!empty($this->end_time)) ? strtotime($this->end_time) : 0;
            $this->update_time = time();
            $this->status_name = \qcbase\models\TaskStatus::find()->select('name')->where(['status_id' => $this->status_id])->scalar();

            return true;
        } else {
            return false;
        }
    }

    /**
     * 更新后更新子父级关系
     */
    public function afterSave($insert, $changedAttributes)
    {
        parent::afterSave($insert, $changedAttributes);

        self::repairTree($this, $insert ? 'insert' : 'update', $changedAttributes);

        //新增任务时发送提醒，更新时若是更改了负责人则发送提醒
        if ($insert) {
            self::sendAnnounce($this);
        } elseif (array_key_exists('leader_id', $changedAttributes) && $changedAttributes['leader_id'] != $this->leader_id) {
            $this->join_ids = '';
            $this->follow_ids = '';
            self::sendAnnounce($this);
        }

        \qcbase\models\ActionLog::insertLog('home', '修改', json_encode($changedAttributes));
    }

    /**
     * 删除后更新子父级关系
     */
    public function afterDelete()
    {
        parent::afterDelete();

        self::repairTree($this, 'delete', []);
    }

    /**
     * 搜索
     */
    public function search()
    {
        return [
            'keywords' => [
                'name' => '任务名称',
                'task_no' => '任务编号',
                'realname' => '真实姓名',
                'username' => '用户名',
            ],
        ];
    }

    /**
     * 获取关联负责人信息
     */
    public function getLeader()
    {
        $fields = User::getSafeFields();
        return $this->hasOne(User::className(), ['user_id' => 'leader_id'])->asArray()->select($fields);
    }

    /**
     * 获取创建人信息
     */
    public function getUser()
    {
        $fields = User::getSafeFields();
        return $this->hasOne(User::className(), ['user_id' => 'user_id'])->asArray()->select($fields);
    }

    /**
     * 获取关联负责人信息
     */
    public function getCategory()
    {
        return $this->hasOne(Category::className(), ['cat_id' => 'category_id'])->asArray();
    }

    /**
     * 获取父级任务信息
     */
    public function getParentTask()
    {
        return $this->hasOne(Task::className(), ['task_id' => 'parent_id'])->asArray();
    }

    /**
     * 获取任务编号
     * 
     * @return type
     */
    public static function getNo()
    {
        $prefix = 'RW';
        return $prefix . date('Ymd') . mt_rand(1000, 9999);
    }

    /**
     * 新增任务时发送任务通知
     */
    public static function sendAnnounce($task)
    {
        $taskLink = '<a href="' . Url::to(['/task/task/detail', 'id' => $task['task_id']]) . '" target="_blank">' . $task['name'] . '</a>';
        $creater = Yii::$app->user->identity->realname;
        if ($task['leader_id'] && $task['user_id'] != $task['leader_id']) {
            $title = '负责任务通知';
            $content = $creater . ' 发布了由你负责的任务： ' . $taskLink;
            $toUsers = $task['leader_id'];
            Announcement::Send($title, $content, $toUsers, 1);
            @\common\models\Email::sendTaskEmail($task['task_no']);
        }
        if (!empty($task['join_ids'])) {
            $title = '参与任务通知';
            $content = $creater . ' 发布了由你参与的任务： ' . $taskLink;
            $joinIds = explode(',', $task['join_ids']);
            if (false !== ($k = array_search($task['user_id'], $joinIds))) {
                unset($joinIds[$k]);
            }
            if (!empty($joinIds)) {
                $toUsers = $joinIds;
                Announcement::Send($title, $content, $toUsers, 1);
                @\common\models\Email::sendTaskEmail($task['task_no']);
            }
        }
        if (!empty($task['follow_ids'])) {
            $title = '关注任务通知';
            $content = $creater . ' 发布了由你关注的任务： ' . $taskLink;
            $followIds = explode(',', $task['follow_ids']);
            if (false !== ($k = array_search($task['user_id'], $followIds))) {
                unset($followIds[$k]);
            }
            if (!empty($followIds)) {
                $toUsers = $followIds;
                Announcement::Send($title, $content, $toUsers, 1);
            }
        }
    }

    /**
     * 判断任务负责人、参与人、关注人中是否有添加人本身
     */
    public function judgeTaskUser()
    {
        if ($this->leader_id != $this->user_id && false === strpos(',' . $this->join_ids . ',', ',' . $this->user_id . ',') && false === strpos(',' . $this->follow_ids . ',',
                ',' . $this->user_id . ',')) {
            $followArr = (!empty($this->follow_ids)) ? explode(',', $this->follow_ids) : [];
            $followArr[] = $this->user_id;
            $this->follow_ids = implode(',', $followArr);
        }
    }

    /**
     * 获取任务比较特殊的权限认证项
     */
    public static function getPermissionItem()
    {
        $item = [
            'task/task/detail' => '查看任务详情',
            'task/task/view-blog' => '查看任务日志',
            'task/task/view-link' => '查看关联信息',
            'task/task/create-blog' => '写日志',
            'task/task/create-reimbursement' => '报销',
            'task/task/create-child' => '建立子任务',
            'task/task/status' => '修改任务状态',
            'task/task/update' => '修改任务信息',
            'task/task/delete' => '删除任务信息',
        ];
        return $item;
    }

    /**
     * 获取公共任务的权限,暂定为查看详情、查看日志、查看关联、创建日志、创建报销
     */
    public static function getPublicTaskPermissions()
    {
        return [
            'task/task/detail',
            'task/task/view-blog',
            'task/task/view-link',
            'task/task/create-blog',
            'task/task/create-reimbursement',
        ];
    }

    /**
     * 检测任务主权限
     *
     * @param object $task 任务对象
     * @param object $action 当前动作对象
     * @param bool $skipPermission 是否越过主权限判断，适用与没有权限节点的任务配置权限
     * @return bool 返回是否有权限
     */
    public static function checkTaskAccess($task, $action, $skipPermission = false)
    {
        $permission = (is_string($action)) ? $action : Common::getActionPermission($action);
        //如果是管理员
        if (Yii::$app->session->get('isSuperAdmin')) {
            return true;
        }

        //如果是公共任务(即任务所属类别为公共类别）
        if (in_array($permission, self::getPublicTaskPermissions()) && self::isPublicTask($task)) {
            return true;
        }

        //如果没有对应主权限
        if (!$skipPermission && !Yii::$app->user->can($permission)) {
            return false;
        }

        //有主权限,进行范围过滤,这里只判断负责人在范围内就直接通过
        $scopeUser = PermissionScope::getScopeUser($permission);
        if (false !== $scopeUser) {
            if ($scopeUser === [] || in_array($task['leader_id'], $scopeUser) || ($task['leader_id'] == 0 && in_array($task['user_id'], $scopeUser))) {
                return true;
            }
        }

        //判断参与、关注权限
        $extraPermissions = self::getTaskPermission($task);
        if (in_array($permission, $extraPermissions)) {
            return true;
        }


        return false;
    }

    /**
     * 获取某个任务的权限
     *
     * @param int|object $taskId 任务id或者任务对象
     */
    public static function getTaskPermission($task)
    {
        $userId = Yii::$app->user->id;
        //$task = (!is_object($task)) ? self::findOne($task) : $task;
        if ($task === null) {
            throw new NotFoundHttpException('任务不存在');
        }

        $permissions = [];
        $roleType = self::getTaskRoleType($task);
        $taskConfig = Yii::$app->cache->get('task_config');

        if (!empty($roleType)) {
            //如果是负责人,直接返回所有权限
            if (in_array('lead', $roleType)) {
                return array_keys(self::getPermissionItem());
            }
            foreach ($roleType as $type) {
                $taskPermissions = (isset($taskConfig['task_' . $type . '_permission'])) ? (array) $taskConfig['task_' . $type . '_permission'] : [];
                $permissions = array_merge($permissions, $taskPermissions);
            }
        }
        return $permissions;
    }

    /**
     * 获取一个任务对于当前用户来讲的角色类型(负责、参与、关注)
     *
     * @param array|object $task 任务
     * @return array ['lead', 'join', 'follow']
     */
    public static function getTaskRoleType($task, $userId = null)
    {
        $userId = ($userId === null) ? Yii::$app->user->id : $userId;
        $role = [];
        if ($task['leader_id'] == 0) {
            $task['user_id'] == $userId && $role[] = 'lead';
        } elseif ($userId == $task['leader_id']) {
            $role[] = 'lead';
        }
        if (false !== strpos(',' . $task['join_ids'] . ',', ',' . $userId . ',')) {
            $role[] = 'join';
        }
        if (false !== strpos(',' . $task['follow_ids'] . ',', ',' . $userId . ',')) {
            $role[] = 'follow';
        }
        return $role;
    }

    /**
     * 获取配置里有一个权限的角色类型
     *
     * @param string $permission 权限
     */
    public static function getPermissionRole($permission)
    {
        $data = ['lead'];
        $taskConfig = Yii::$app->cache->get('task_config');
        foreach (['join', 'follow'] as $type) {
            $taskPermissions = (isset($taskConfig['task_' . $type . '_permission'])) ? (array) $taskConfig['task_' . $type . '_permission'] : [];
            if (in_array($permission, $taskPermissions)) {
                $data[] = $type;
            }
        }
        return $data;
    }

    /**
     * 获取时间排序数据
     */
    public static function getTimeOrder()
    {
        $data = [
            'today' => '今日截止',
            'week' => '本周截止',
            'month' => '本月截止',
            'create' => '最近分配',
            'update' => '最近更新',
        ];
        return $data;
    }

    /**
     * 获取任务
     * 
     * @param int $userId 用户id
     * @param type $type 获取类型 lead => 负责 join => 参与 follow => 关注
     * @param int $limit 字数限制
     * @param array $order 排序 
     * @return array ['tasks' => [], 'count' => 10] 索引tasks所有的任务、索引count为任务总数
     */
    public static function getTask($userId, $type = 'lead', $limit = 5, $order = ['create_time' => SORT_DESC])
    {
        $userId = Yii::$app->user->id;
        $tasks = static::find()
            ->with(['category', 'leader'])
            ->orderBy($order)
            ->limit($limit)
            ->asArray()
            ->indexBy('task_id');

        //$scopeUser = PermissionScope::getScopeUser('task/task/list');
        $scopeUser = [$userId];
        if ($type == 'lead') {
            $tasks->where(['leader_id' => $scopeUser]);
            $tasks->orWhere(['leader_id' => 0, 'user_id' => $scopeUser]);
            $countTasks = clone $tasks;
        } elseif ($type == 'join') {
            $findArr = [];
            foreach ($scopeUser as $u) {
                $findArr[] = 'FIND_IN_SET(' . (int) $u . ', join_ids)';
            }
            $findStr = implode(' or ', $findArr);
            $tasks->where($findStr);
            $countTasks = clone $tasks;
            //过滤同时是负责任务
            $tasks->andWhere(['not in', 'leader_id', $scopeUser]);
        } elseif ($type == 'follow') {
            $findArr = [];
            $notFindArr = [];
            foreach ($scopeUser as $u) {
                $findArr[] = 'FIND_IN_SET(' . (int) $u . ', follow_ids)';
                $notFindArr[] = 'NOT FIND_IN_SET(' . (int) $u . ', join_ids)';
            }
            $findStr = implode(' or ', $findArr);
            $notFindStr = implode(' and ', $notFindArr);
            $tasks->where($findStr);
            $countTasks = clone $tasks;
            //过滤同时是负责、参与任务 
            $tasks->andWhere($notFindStr);
            $tasks->andWhere(['not in', 'leader_id', $scopeUser]);
        }

        //只取状态为显示的任务
        $showStatus = TaskStatus::getShowListStatus();
        $tasks->andWhere(['status_id' => $showStatus]);
        $countTasks->andWhere(['status_id' => $showStatus]);

        //取总数
        $countTasks->limit(null);
        $count = $countTasks->count();

        $tasks = $tasks->all();
        $tasks = self::toSecondTree($tasks);

        return ['tasks' => $tasks, 'count' => $count];
    }

    /**
     * 转换数据为二级树结构
     */
    public static function toSecondTree($data)
    {
        //\common\components\Tool::dump($data);
        if (empty($data)) {
            return '';
        }
        $newData = []; //组装的最新数据
        foreach ($data as $d) {
            if (isset($newData[$d['task_id']])) {
                continue;
            } elseif ($d['parent_id'] == 0) {
                $newData[$d['task_id']] = $d;
            } elseif (!empty($d['parent_ids'])) {
                $parentIds = explode(',', $d['parent_ids']);
                //取得最顶层任务id
                $topParentId = $parentIds[1];
                //如果顶层任务已经存在则直接把任务加在子变量里
                if (isset($newData[$topParentId])) {
                    $newData[$topParentId]['_childs'][] = $d;
                } else {
                    //新数组里若不存在顶层任务则去获取顶层任务
                    if (isset($data[$topParentId])) {
                        $newData[$topParentId] = $data[$topParentId];
                        $newData[$topParentId]['_childs'][] = $d;
                    } else {
                        $topParent = static::find()->where(['task_id' => $topParentId])->with('category', 'leader')->asArray()->one();
                        //如果父任务丢失，直接把任务放在顶级
                        if ($topParent !== null) {
                            $newData[$topParentId] = $topParent;
                            $newData[$topParentId]['_childs'][] = $d;
                        } else {
                            $newData[$d['task_id']] = $d;
                        }
                    }
                }
            }
            //\common\components\Tool::dump($newData);
        }
        $realData = []; //真实返回数据
        //这里从上面的子父级数组里循环按顺序重组数组，方便列表调用
        foreach ($newData as $n) {
            if (!empty($n)) {
                $realData[$n['task_id']] = $n;
                if (isset($n['_childs'])) {
                    foreach ($n['_childs'] as $child) {
                        $child['_is_child'] = 1;
                        $realData[$child['task_id']] = $child;
                    }
                    unset($realData[$n['task_id']]['_childs']);
                }
            }
        }
        return $realData;
    }

    /**
     * 获取ztree二级树数据
     */
    public static function getSecondTreeData($id)
    {
        $task = static::find()->where(['task_id' => $id])->asArray()->one();
        if ($task['parent_id'] != 0) {
            $parentIds = explode(',', $task['parent_ids']);
            $topParentId = $parentIds[1];
            $task = static::find()->where(['task_id' => $topParentId])->asArray()->one();
        }
        $parentTask = ['id' => (int) $task['task_id'], 'pid' => (int) $task['parent_id'], 'name' => StringHelper::truncate($task['name'], 10), 'title' => $task['name'], 'url' => Url::to(['/task/task/detail',
                'id' => $task['task_id']]), 'target' => '_self', 'open' => true];
        $data[] = $parentTask;

        $childs = explode(',', $task['child_ids']);
        $temp = static::find()->where(['task_id' => $childs])->asArray()->all();
        if (!empty($temp)) {
            unset($temp[0]);
        }

        foreach ($temp as $t) {
            $data[] = ['id' => (int) $t['task_id'], 'pId' => (int) $task['task_id'], 'name' => StringHelper::truncate($t['name'], 10), 'title' => $t['name'], 'url' => Url::to(['/task/task/detail', 'id' => $t['task_id']]),
                'target' => '_self'];
        }

        return $data;
    }

    /**
     * 根据任务id获取整个任务树形结构所需数据
     */
    public static function getTreeData($id)
    {
        $data = [];
        $topParentTask = self::getTopParent($id);
        $userId = Yii::$app->user->id;

        if (false != $topParentTask) {
            $childIds = $topParentTask->child_ids;
            //权限范围过滤
            $scopeUser = PermissionScope::getScopeUser('task/task/list');
            $scopeWhere = self::getRelatedTaskQueryStr($scopeUser);
            //获取公共任务类别
            $publicCategorys = Category::getPublicCategory();
            $dotCategorys = implode(',', $publicCategorys);

            $childList = static::find()->where(['task_id' => explode(',', $childIds)])->indexBy('task_id')->asArray();
            if (!empty($scopeWhere)) {
                $scopeWhere .= ' or concat(task_id) != child_ids'; //默认取出所有父级,防止树出错
                if (!empty($dotCategorys)) {
                    $scopeWhere .= ' or category_id in (' . $dotCategorys . ')'; //公共任务
                }
                $childList->andWhere($scopeWhere);
            }
            $childList = $childList->all();

            foreach ($childList as $c) {
                $data[] = ['id' => (int) $c['task_id'], 'pId' => (int) $c['parent_id'], 'name' => StringHelper::truncate($c['name'], 10), 'title' => $c['name'], 'url' => Url::to(['/task/task/detail', 'id' => $c['task_id']]),
                    'target' => '_self', 'open' => true];
            }
        } else {
            $data = false;
        }

        return $data;
    }

    /**
     * 获取与某个人相关的任务的查询拼接字符串
     *
     * @param array $userIds 要相关的人的id数组
     * @param string $prefix 前缀
     * @param array $relatedRole 相关所包含的角色含义，默认相关代表我负责、参与、关注的
     */
    public static function getRelatedTaskQueryStr($userIds, $prefix = '', $relatedRole = ['lead', 'join', 'follow'])
    {
        $str = '';
        if (!empty($userIds)) {
            $findArr = [];
            foreach ($userIds as $u) {
                if (in_array('lead', $relatedRole)) {
                    $findArr[] = '(' . $prefix . 'leader_id = 0 && ' . $prefix . 'user_id = ' . (int) $u . ')';
                    $findArr[] = $prefix . 'leader_id = ' . (int) $u;
                }
                if (in_array('join', $relatedRole)) {
                    $findArr[] = 'FIND_IN_SET(' . (int) $u . ', ' . $prefix . 'join_ids)';
                }
                if (in_array('follow', $relatedRole)) {
                    $findArr[] = 'FIND_IN_SET(' . (int) $u . ', ' . $prefix . 'follow_ids)';
                }
            }
            $str = implode(' or ', $findArr);
        }
        return $str;
    }

    /**
     * 获取关联项目的最新一条顶级任务
     *
     * @param string $projectNo 项目编号
     */
    public static function getProjectRelatedTask($projectNo)
    {
        $task = self::find()
            ->where(['link_id' => $projectNo, 'link_type' => 'project'])
            ->one();
        if ($task !== null) {
            $task = self::getTopParent($task);
        }

        return $task;
    }

    /**
     * 判断任务是否是公共任务
     *
     * @param array|object $task 任务对象
     */
    public static function isPublicTask($task)
    {
        if (self::$publicCategorys === null) {
            self::$publicCategorys = Category::getPublicCategory();
        }
        return in_array($task['category_id'], self::$publicCategorys);
    }

    /**
     * 生成树形结构下拉框
     * 
     * @param  integer $curCat      默认选择节点
     * @param  integer $disabledId  忽略节点
     * @return array   $list        上级类别下拉框内容
     */
    public static function getDropDownTreeList($curCat = 0, $disabledId = 0)
    {
        $data = static::find()
            ->select('task_id, parent_id as pid, name')
            ->asArray()
            ->orderBy(['task_id' => SORT_DESC])
            ->indexBy('task_id')
            ->all();
        $str = "<option value='\$task_id' \$selected \$disabled>\$spacer  \$name</option>";
        $Tree = new Tree($data);
        $Tree->icon = array('&nbsp;&nbsp;&nbsp;│', '&nbsp;&nbsp;&nbsp;├─ ', '&nbsp;&nbsp;&nbsp;└─ ');
        $list = $Tree->get_tree(0, $str, intval($curCat), intval($disabledId));
        return $list;
    }

    /**
     * 获取顶级父类 
     *
     * @param int|object $data 任务id或者任务对象
     */
    public static function getTopParent($data)
    {
        if (is_int($data)) {
            $data = static::findOne($data);
        }

        if (empty($data)) {
            return false;
        }
        if ($data['parent_id'] == 0) {
            return $data;
        } else {
            $parentIds = explode(',', $data['parent_ids']);
            $topParentId = $parentIds[1];
            $topParentTask = static::findOne($topParentId);
        }

        return $topParentTask;
    }

    /**
     * 获取一个任务的所有父级任务
     *
     * @param integer $taskId 任务ID
     * @return array 不存在则返回空数组
     */
    public static function getAllParents($taskId)
    {
        $parents = [];
        $task = static::findOne($taskId);
        if ($task === null || empty($task['parent_ids'])) {
            return $parents;
        }
        $parentIds = explode(',', $task['parent_ids']);
        foreach ($parentIds as $parentId) {
            if ($parentId != 0 && ($parentTask = static::findOne($parentId)) !== null) {
                $parents[$parentTask['task_id']] = $parentTask;
            }
        }
        return $parents;
    }

    /**
     * 修复节点取得顶级父类
     *
     * @param object $data 任务对象
     */
    public static function getRepairTopParent($data)
    {
        if (empty($data) || $data->parent_id == 0) {
            return $data;
        }
        $parentTask = static::findOne($data->parent_id);

        if ($parentTask['parent_id']) {
            $parentIds = explode(',', $parentTask['parent_ids']);
            $topParentId = $parentIds[1];
            $topParentTask = static::findOne($topParentId);
        } else {
            $topParentTask = $parentTask;
        }
        return $topParentTask;
    }

    /**
     * 更新表里的父级ID集，子ID集
     *
     * @param char $tableName 要更新的表名
     */
    public static function repairTree($data, $action, $changedAttributes)
    {
        $query = static::find();

        //根据操作的不同取得所有波及到的任务来更新树结构
        if ($action == 'insert' || $action == 'delete') {
            if ($data->parent_id) {
                $topParentTask = self::getRepairTopParent($data);
                $inIds = explode(',', $topParentTask['child_ids']);
                $inIds[] = $data->task_id;
                $query->where(['task_id' => $inIds]);
            } else {
                $query->where(['task_id' => $data->task_id]);
            }
        } elseif ($action == 'update') {
            //判断父任务有没有改变,若未变则返回
            if (!array_key_exists('parent_id', $changedAttributes) || $data->parent_id == $changedAttributes['parent_id']) {
                $topParentTask = self::getRepairTopParent($data);
                $inIds = explode(',', $topParentTask['child_ids']);
                $query->where(['task_id' => $inIds]);
            } else {
                //取得原来父任务的顶级任务
                $oldData = clone $data; //注意！这里的data是对象，必须复制一份而不能赋值
                $oldData['parent_id'] = $changedAttributes['parent_id'];
                $oldTopParentTask = self::getRepairTopParent($oldData);
                //取得最新父任务的顶级任务
                $newTopParentTask = self::getRepairTopParent($data);

                //如果顶级任务相同则取其一
                if ($oldTopParentTask['task_id'] == $newTopParentTask['task_id']) {
                    $inIds = explode(',', $oldTopParentTask['child_ids']);
                    $inIds[] = $data->task_id;
                    $query->where(['task_id' => $inIds]);
                } else {
                    $oldInIds = explode(',', $oldTopParentTask['child_ids']);
                    $newInIds = explode(',', $newTopParentTask['child_ids']);
                    $inIds = array_merge($oldInIds, $newInIds);
                    $query->where(['task_id' => $inIds]);
                }
            }
        }

        self::$list = $query
            ->asArray()
            ->indexBy('task_id')
            ->orderBy(['task_id' => SORT_ASC])
            ->all();

        if (is_array(self::$list)) {
            $command = Yii::$app->db->createCommand();

            //这里要先更新父级ID集,然后在更新子集，因为子集的选择需要依赖父级字段，且会有顺序问题，
            //而顺序在许多情况下是不可控的，所以只能等待所有父级全部获取成功后才去更新子级
            foreach (self::$list as $id => $value) {
                self::$list[$id]['parent_ids'] = $parent_ids = self::getParentids($id);
            }
            foreach (self::$list as $id => $value) {
                $parent_ids = self::$list[$id]['parent_ids'];
                self::$list[$id]['child_ids'] = $child_ids = self::getChildids($id);

                $command->update(self::tableName(), ['parent_ids' => $parent_ids, 'child_ids' => $child_ids], 'task_id = :id', [':id' => $id])->execute();
            }
        }
    }

    /**
     * 修复所有数据的树关系,用于导入数据修复使用
     */
    public static function repairAllTree()
    {
        set_time_limit(0);
        self::$list = static::find()
            ->asArray()
            ->indexBy('task_id')
            ->orderBy(['task_id' => SORT_ASC])
            ->all();

        if (is_array(self::$list)) {
            $command = Yii::$app->db->createCommand();

            //这里要先更新父级ID集,然后在更新子集，因为子集的选择需要依赖父级字段，且会有顺序问题，
            //而顺序在许多情况下是不可控的，所以只能等待所有父级全部获取成功后才去更新子级
            foreach (self::$list as $id => $value) {
                self::$list[$id]['parent_ids'] = $parent_ids = self::getParentids($id);
            }
            foreach (self::$list as $id => $value) {
                $parent_ids = self::$list[$id]['parent_ids'];
                self::$list[$id]['child_ids'] = $child_ids = self::getChildids($id);

                $command->update(self::tableName(), ['parent_ids' => $parent_ids, 'child_ids' => $child_ids], 'task_id = :id', [':id' => $id])->execute();
            }
            return true;
        }
    }

    /**
     * 获取父级ID集
     * 
     * @param  integer $id          表ID
     * @param  string  $arrparentid 父级ID集
     * @return string  $arrparentid 父级ID集
     */
    public static function getParentids($id, $arrparentid = '')
    {
        $category = self::$list;
        if (!is_array($category) || !isset($category[$id])) return false;
        $parentid = $category[$id]['parent_id'];
        $arrparentid = $arrparentid ? $parentid . ',' . $arrparentid : $parentid;
        if ($parentid) {
            $arrparentid = self::getParentids($parentid, $arrparentid);
        } else {
            $category[$id]['parent_ids'] = $arrparentid;
        }
        return $arrparentid;
    }

    /**
     * 获取子ID集
     * 
     * @param  integer $id         表ID
     * @return string  $arrchildid 子ID集
     */
    public static function getChildids($id)
    {
        $category = self::$list;
        $arrchildid = $id;
        if (is_array($category)) {
            foreach ($category as $catid => $value) {
                if ($value['parent_id'] && $id != $catid) {
                    $arrparentids = explode(',', $value['parent_ids']);
                    if (in_array($id, $arrparentids)) {
                        $arrchildid .= ',' . $catid;
                    }
                }
            }
        }
        return $arrchildid;
    }

    /**
     * 根据条件获取相关任务
     *
     * @param array $where  关联条件
     * @param array $order 排序
     * @return array ['tasks' => [], 'count' => 10] 索引tasks所有的任务、索引count为任务总数
     *
     * @author HuLimin <http://blog.u-bo.com>
     */
    public static function getLinkTask($where = [], $order = ['create_time' => SORT_DESC])
    {
        $userId = Yii::$app->user->id;
        $tasks = static::find()
            ->with('category', 'leader')
            ->where($where)
            ->orderBy($order)
            ->asArray()
            ->indexBy('task_id');
        //取总数
        $countTasks = clone $tasks;
        $countTasks->limit(null);
        $count = $countTasks->count();
        $tasks = $tasks->all();
        $tasks = self::toSecondTree($tasks);
        return ['tasks' => $tasks, 'count' => $count];
    }

    /**
     * 获取部门以及任务当前所有用户可见负责人
     *
     * @author HuLimin <http://blog.u-bo.com>
     * @since 0.1
     */
    public static function obtainLeaderTree()
    {
        $session = Yii::$app->session;
        $scopeUser = PermissionScope::getScopeUser('task/task/list');
        //没有权限
        if ($scopeUser === FALSE) {
            return;
        }
        if (empty($scopeUser)) {//超级管理员
            $where = [];
        } else {
            $where = ['or', ['in', 'leader_id', $scopeUser], ['in', 'user_id', $scopeUser]];
        }
        $leaderUsers = static::find()->select('leader_id')->where($where)->distinct()->column();
        $map = empty($leaderUsers) ? [] : ['user_id' => $leaderUsers];
        $listDeptsTree = \qcbase\models\UserDepartment::getDepartmentByUser($map, $leaderUsers);
        foreach ($listDeptsTree as &$dept) {
            if (isset($dept['parent_ids'])) {
                $dept['isParent'] = true;
                $dept['open'] = false;
                $dept['nocheck'] = true;
            }
        }
        $otherArr[]=['dept_id' => '','parent_id' => '0','name' => '未分配','child_ids' => 0,'user_ids' => '0'];
        return ArrayHelper::merge($listDeptsTree,$otherArr);
    }
}