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

namespace home\behaviors;

use Yii;
use yii\base\Action;
use yii\base\ActionFilter;
use yii\web\ForbiddenHttpException;
use home\modules\task\models\Task;
use yii\base\InvalidConfigException;
use yii\web\NotFoundHttpException;

/**
 * 任务权限控制
 *
 *
 * @author legendjw http://blog.u-bo.com
 * @since 0.1
 */
class TaskAccessControlFilter extends ActionFilter
{
    /**
     * @var array 要控制的权限节点,和only属性中的动作id一一对应
     */
    public $permissions;

    /**
     * @var string 任务字段，根据此字段类型查找任务对象
     */
    public $taskField = 'task_no';

    /**
     * @var int|string 任务字段值，字段名称由属性$taskField确定
     */
    public $id;

    /**
     * @var bool|Closure 是否要执行过滤,如果由于一些特殊情况导致需要判断
     * 来决定是否要执行权限过滤，可以传递布尔值或匿名函数来动态控制
     */
    public $enableFilter = true;

    /**
     * @var bool|Closure 是否要验证主权限
     */
    public $skipPermission = false;

    /**
     * 要进行权限判断的任务对象
     */
    private $_task;

    /**
     * 权限配置
     */
    private $_permissionCofing;

    /**
     * 初始化参数
     *
     * 父类的init函数会在实例化当前过滤器的时候执行,
     * 这样就会忽略是否是only属性所配置的动作
     */
    private function initProperty($action)
    {
        if (empty($this->taskField) || empty($this->id)) {
            throw new InvalidConfigException('任务控制过滤器参数缺失！');
        }

        //获取任务
        $this->_task = Task::find()
            ->where([$this->taskField => $this->id])
            ->one();
        if ($this->_task === null) {
            throw new NotFoundHttpException('任务不存在！');
        }

        // $this->_permissionItem = Task::getPermissionItem();

        $this->skipPermission = ($this->skipPermission instanceof \Closure) ? call_user_func($this->skipPermission, $action) : $this->skipPermission;
        
        //按照顺序合并权限验证项对应的动作id
        $this->permissions = array_combine($this->only, $this->permissions);

        //获取权限控制配置
        $this->_permissionCofing = Yii::$app->cache->get('task_config');
    }

    /**
     * 动作前置操作
     *
     * @param Action $action 要执行的动作
     */
    public function beforeAction($action)
    {
        //判断是否要执行过滤
        if ($this->enableFilter instanceof \Closure) {
            $this->enableFilter = call_user_func($this->enableFilter, Yii::$app->request);
        }
        if (!$this->enableFilter) {
            return true;
        }

        $this->initProperty($action);

        $action = (isset($this->permissions[$action->id]) && !empty($this->permissions[$action->id])) ? $this->permissions[$action->id] : $action;

        //检测主权限
        if (Task::checkTaskAccess($this->_task, $action, $this->skipPermission)) {
            return true;
        }

        throw new ForbiddenHttpException('权限不足！');
        
    }

}
