<?php
/**
 * An abstract class for controller bouncer filters.
 *
 * This class provides a basic white/black listing function for determining
 * whether a user is granted and denied controller access.
 */
abstract class controller_filter_bouncer extends controller_filter
{
    /**
     * @var array The granted list.
     */
    protected $grant;
    
    /**
     * @var array The denied list.
     */
    protected $deny;

    ////////////////////////////////////////////////////////////////////////////
    // Construct and destruct functions.

    /**
     * @param string/array (optional) $grant The granted list.
     * @param string/array (optional) $deny The denied list.
     */
    public function __construct($grant = '', $deny = '*')
    {
        if (!is_array($grant))
        {
            $grant = array($grant);
        }
        
        $this->grant = $grant;
        
        if (!is_array($deny))
        {
            $deny = array($deny);
        }
        
        $this->deny = $deny;
    }

    ////////////////////////////////////////////////////////////////////////////
    // Overload functions.

    ////////////////////////////////////////////////////////////////////////////
    // Interface functions.

    ////////////////////////////////////////////////////////////////////////////
    // Internal functions.
    
    /**
     * Checks if a user is granted or denied.
     * 
     * @param string $user The user.
     * @return boolean True if granted, else false.
     */
    protected function is_granted($user)
    {
        foreach ($this->grant as $g)
        {
            if (preg_match('/^' . strtr(addcslashes($g, '/\\.+^$(){}=!<>|'), array('*' => '.*', '?' => '.?')) . '$/i', $user))
            {
                return true;
            }
        }
        
        foreach ($this->deny as $d)
        {
            if (preg_match('/^' . strtr(addcslashes($d, '/\\.+^$(){}=!<>|'), array('*' => '.*', '?' => '.?')) . '$/i', $user))
            {
                return false;
            }
        }
        
        return true;
    }
}
