<?php
/**
 * core.framework
 *
 * @category  Core
 * @package   Core_Application
 * @copyright Copyright (c) 2011. Burza d.o.o. (http://web.burza.hr/en/)
 * @license   proprietary
 */

/**
 * @category  Core
 * @package   Core_Application
 * @copyright Copyright (c) 2011. Burza d.o.o. (http://web.burza.hr/en/)
 * @license   proprietary
 */
class Core_Application_Plugin_EventHandler_SecurityValidator extends Core_Application_Plugin_EventHandler_Abstract
{
    /**
     * @var array
     */
    protected $_subscriptions = array(
        array(
            'event'    => Core_Dispatcher::EVENT_PREDISPATCH,
            'method'   => 'securityHandler',
            'priority' => -100,
        ),
    );

    /**
     * @var Core_User
     */
    protected $_user;

    /**
     * @var Core_Security
     */
    protected $_security;

    /**
     * @param Core_User $user
     *
     * @return Core_Application_Plugin_EventHandler_SecurityValidator
     */
    public function setUser(Core_User $user)
    {
        $this->_user = $user;
        return $this;
    }

    /**
     * @return Core_User
     */
    public function getUser()
    {
        if (null === $this->_user) {
            $this->setUser(Core_Application::get('User'));
        }
        return $this->_user;
    }

    /**
     * @param Core_Security $security
     *
     * @return Core_Application_Plugin_EventHandler_SecurityValidator
     */
    public function setSecurity(Core_Security $security)
    {
        $this->_security = $security;
        return $this;
    }

    /**
     * @return Core_Security
     */
    public function getSecurity()
    {
        if (null === $this->_security) {
            $this->setSecurity(Core_Application::get('Security'));
        }
        return $this->_security;
    }

    /**
     * @param Core_Event_Interface $event
     *
     * @throws Core_Application_ForbiddenException
     * @throws Core_Application_UnauthorizedException
     * @return void
     */
    public function securityHandler(Core_Event_Interface $event)
    {
        /** @var $location Core_Dispatcher_Location_Interface */
        $location   = $event->getParam('location');
        /** @var $controller Core_Controller_Interface */
        $controller = $event->getParam('controller');
        /** @var $user Core_User */
        $user       = $this->getUser();
        /** @var $security Core_Security */
        $security   = $this->getSecurity();

        $action     = $location->getAction();
        if (true !== $security->isAllowed($user, $controller, $action)) {
            $event->setIsProcessed(true);
            $resource = $controller->getSecurityResource();

            if (true !== $user->hasIdentity()) {
                $message = sprintf('Authentication required to access %s:%s', $resource, $action);
                throw new Core_Application_UnauthorizedException($message);
            } else {
                $message = sprintf('Forbidden to access %s:%s', $resource, $action);
                throw new Core_Application_ForbiddenException($message);
            }
        }
    }
}
