<?php

/**
 * Goweb Sitemanager 5 Framework
 *
 * @version    5.0.0
 * @category   Goweb
 * @package    Goweb_Controller
 * @subpackage Goweb_Controller_Action_Helper_Acl
 * @author     I&D <dev@goweb.pt>, Pedro Pinto <ppinto@goweb.pt>
 * @copyright  2009 (c) Goweb (http://www.goweb.pt)
 */

goweb::loadClass('Zend_Controller_Action_Helper_Abstract');
goweb::loadClass('Zend_Auth');
goweb::loadClass('Zend_Acl');
goweb::loadClass('Zend_Acl_Resource');
goweb::loadClass('Zend_Acl_Role');

/**
 * Classe helper para o Acl
 *
 * @version    5.0.0
 * @category   Goweb
 * @package    Goweb_Controller
 * @subpackage Goweb_Controller_Action_Helper_Acl
 * @author     I&D <dev@goweb.pt>, Pedro Pinto <ppinto@goweb.pt>
 * @copyright  2009 (c) Goweb (http://www.goweb.pt)
 */
class Goweb_Controller_Action_Helper_Acl extends Zend_Controller_Action_Helper_Abstract{
    /**
     * Goweb_Controller_Action
     *
     * @var Goweb_Controller_Action
     */
    protected $_action;
    
    /**
     * Zend_Auth
     *
     * @var Zend_Auth
     */
    protected $_auth;
    
    /**
     * Goweb_Acl
     *
     * @var Goweb_Acl
     */
    protected $_acl;
    
    /**
     * Nome do Controller
     *
     * @var String
     */
    protected $_controllerName;
    
    /**
     * Contructor
     *
     * @param Zend_View_Interface $view
     * @param array $options
     */
    public function __construct(Zend_View_Interface $view = null, array $options = array()){
        $this->_auth = Zend_Auth::getInstance();
        $this->_acl = isset($options['acl']) ? $options['acl'] : new Zend_Acl();
    }
     
    /**
     * Hook into action controller initialization
     * @return void
     */
    public function init(){
        $this->_action = $this->getActionController();
        // add resource for this controller
        $controller = $this->_action->getRequest()->getControllerName();
        if(!$this->_acl->has($controller)) {
            $this->_acl->add(new Zend_Acl_Resource($controller));
        }
        if (!$this->_acl->hasRole('guest'))
            $this->_acl->addRole(new Zend_Acl_Role('guest'));
        if (!$this->_acl->hasRole('Super Utilizador'))
            $this->_acl->addRole(new Zend_Acl_Role('Super Utilizador'));
    }
     
    public function allow($roles = null, $resource= null, $actions = null){
        if (is_null($resource)) $resource = $this->_controllerName;
        $this->addResource($resource);
        $this->_acl->allow($roles, $resource, $actions);
        return $this;
    }
    public function deny($roles = null, $resource= null, $actions = null){
        if (is_null($resource)) $resource = $this->_controllerName;
        $this->addResource($resource);
        $this->_acl->deny($roles, $resource, $actions);
        return $this;
    }
    public function addRole($role){
        if (!$this->_acl->hasRole($role))
            $this->_acl->addRole(new Zend_Acl_Role($role));
    }
    public function addResource($controller){
        if (!$this->_acl->has($controller))
            $this->_acl->add(new Zend_Acl_Resource($controller));
    }

    public function preDispatch(){
        $role = 'guest';
        if ($this->_auth->hasIdentity()) {
            $user = $this->_auth->getIdentity();
            if(is_object($user)) {
                $role = $this->_auth->getIdentity()->role;
            }elseif (is_array($user)){
                $auth = $this->_auth->getIdentity();
                $role = $auth['role'];
            }
            $this->addRole($role);
        }
        $request = $this->_action->getRequest();
        $controller = $request->getControllerName();
        if (strcmp($controller, 'index') == 0) $controller = $request->getParam('controller');
        $action = $request->getActionName();
        $module = $request->getModuleName();
        $this->_controllerName = $controller;
        $resource = $controller;
        $resourceFormatted = strtolower($resource);
        $privilege = $action;
        /**
         * Assegurar que a variável $resource é válida
         */
        if (!$this->_acl->has($resource)) {
            $resource = null;
        }
        $dispatcher = Zend_Controller_Front::getInstance()->getDispatcher();
        $privilegeFormatted = str_replace('Action', '', $dispatcher->formatActionName($privilege));
        /**
         * Verificar permissões
         */
        if (!$this->isAllowed($role, $resource, $privilege) && !$this->isAllowed($role, $resource, $privilegeFormatted) &&
        !$this->isAllowed($role, $resourceFormatted, $privilege) && !$this->isAllowed($role, $resourceFormatted, $privilegeFormatted)) {
            $request->setModuleName('default');
            if ($this->_action->isAdmin()){
                $controllerName = 'auth';
                if ($this->_auth->hasIdentity()){
                    $actionName = 'noAccess';
                } else {
                    $actionName = 'login';
                }
            }else{
                $controllerName = 'utilizador';
                $actionName = 'login';
            }
            $request->setControllerName($controllerName);
            $request->setActionName($actionName);
            $request->setDispatched(false);
        }
    }
    
    public function isAllowed($role = null, $resource = null, $privilege = null){
        if (!$this->_acl->hasRole($role)) return false;
        if (!$this->_acl->has($resource)) return false;
        if (is_null($privilege)){
            return $this->_acl->isAllowed($role, $resource, 'index') || $this->_acl->isAllowed($role, $resource, 'list');    
        }
        return $this->_acl->isAllowed($role, $resource, $privilege);
    }
}