<?php

class RBACHook
{
    private $allowedAliases = [];

    public function __construct()
    {
        $this->CI = &get_instance();
        $this->CI->load->model('rbac_model');
    }

    public function checkPermission()
    {
        if (CLI === true) {
            return false;
        }

        $class = $this->CI->router->fetch_class();
        $method = $this->CI->router->fetch_method();

        //only authorized users will be checked
        if (
            !class_exists($class) ||
            !(is_subclass_of($class, Cf_Controller::class) || is_subclass_of($class, Cf_REST_Controller::class))
        ) {
            return false;
        }

        $reflectionClass = new ReflectionClass($class);

        // Cf_REST_Controller methods have suffix _%http_method%
        if ($reflectionClass->getParentClass()->name == Cf_REST_Controller::class) {
            $method = $method . '_' . strtolower($_SERVER['REQUEST_METHOD']);
        }

        if (!in_array($method, get_class_methods($class))) {
            return false;
        }

        $reflectionMethod = new ReflectionMethod($class, $method);

        $methodComment = $reflectionMethod->getDocComment();
        $matches = [];
        preg_match('/@rbacAlias(.*?)\*/s', $methodComment, $matches);

        $alias = isset($matches[1]) ? trim($matches[1]) : false;
        $this->loadPermissions();
        if (!empty($alias) && !in_array($alias, $this->allowedAliases)) {
            redirect('auth/permission_deny', 'refresh');
            exit();
        }
    }

    private function loadPermissions()
    {
        $permissions = $this->CI->rbac_model->getUserPermissions();
        foreach ($permissions as $permission) {
            $this->allowedAliases[] = $permission['alias'];
        }
    }
}
