<?php
namespace library;

use models\IUser;

/**
 * Authorization class
 * @author Jérôme Brilland
 * @version 3.0
 * @copyright (c) 2019-2022, Jérôme Brilland
 * @license http://www.gnu.org/licenses/gpl.txt GNU General Public License
 */
class Authorization implements \IAuthorization {

    /**
     * @var IUser
     * @access protected
     */
    protected $user;
    
    /**
     * @var array
     * @access private
     */
    private $policies = [];

    /**
     * Class constructor
     * @param IUser $user
     * @access public
     */
    public function __construct( IUser $user ) {
        $this->user = $user;
    }

    /**
     * @param mixed $activity
     * @param mixed $object
     */
    public function authorize( $activity, $object = null ) {
        if ( DEVELOPMENT_ENVIRONMENT ) {
            $logger = \IoC::resolve( 'logger' );
            $logger->write( sprintf( '[%s] [%s] [%s] %s',  date( 'Y-m-d H:i:s' ), __FILE__, 'debug', "Authorization::authorize( $activity )" ) );
        }
        if ( !$this->isAuthorized( $activity, $object ) ) {
            if ( !$this->user->isAuthenticated() ) {
                if ( DEVELOPMENT_ENVIRONMENT ) {
                    \IoC::resolve( 'logger' )->write( sprintf( '[%s] [%s] [%s] %s',  date( 'Y-m-d H:i:s' ), __FILE__, 'debug', 'Not logged in' ) );
                }
                $_SESSION['return_to'] = $_SERVER['REQUEST_URI'];
                header( 'Location: ' . BASE_URL . 'login' );
                exit();
            } else {
                if ( DEVELOPMENT_ENVIRONMENT ) {
                    \IoC::resolve( 'logger' )->write( sprintf( '[%s] [%s] [%s] %s',  date( 'Y-m-d H:i:s' ), __FILE__, 'debug', '403 Forbidden' ) );
                }
                $_SESSION['return_to'] = parse_url( $_SERVER['REQUEST_URI'], PHP_URL_PATH );
                header( 'Location: ' . BASE_URL . 'error/403' );
                exit();
            }
        }
    }
    
    /**
     * @param mixed $activity
     * @param mixed $object
     * @return boolean True if the user is authorized, false otherwise
     */
    public function isAuthorized( $activity, $object = null ) {
        if ( DEVELOPMENT_ENVIRONMENT ) {
            $logger = \IoC::resolve( 'logger' );
            $logger->write( sprintf( '[%s] [%s] [%s] %s',  date( 'Y-m-d H:i:s' ), __FILE__, 'debug', "Authorization::isAuthorized( $activity )" ) );
            $logger->write( sprintf( '[%s] [%s] [%s] %s',  date( 'Y-m-d H:i:s' ), __FILE__, 'debug', join( ', ', $this->user->getPermissions() ) ) );
        }
        if ( array_key_exists( $activity, $this->policies ) ) {
            return $this->policies[$activity]( $this->user, $object );
        } else {
            return ( $this->user->hasPermission( $activity ) );
        }
    }
    
    /**
     * @param mixed $activity
     * @param Closure $callback
     * @access public
     */
    public function define( $activity, \Closure $callback ) {
        $this->policies[$activity] = $callback;
    }
}
