<?php
class Acl extends MY_Model
{
	const DB_TABLE = 'acl';
    const DB_TABLE_PK = 'acl_id';

    private static $cache = null;

    public function loadByPageID($id)
    {
    	$query = $this->db->query("SELECT a.acl_id, r.acl_role_id, r.role,
    	                          IF(a.acl_id IS NULL, 0, a.`read`) AS `read`,
    	                          IF(a.acl_id IS NULL, 0, a.`write`) AS `write`
    	                          FROM `acl_role` AS r
    	                          LEFT JOIN `acl` AS a ON r.acl_role_id=a.acl_role_id AND a.page_id=?
    	                          ORDER BY r.`role`",
    	                          array($id));
    	return $query->result();
    }

    public function loadByModuleInstanceID($id)
    {
    	$query = $this->db->query("SELECT a.acl_id, r.acl_role_id, r.role,
    	                          IF(a.acl_id IS NULL, 0, a.`read`) AS `read`,
    	                          IF(a.acl_id IS NULL, 0, a.`write`) AS `write`
    	                          FROM `acl_role` AS r
    	                          LEFT JOIN `acl` AS a ON r.acl_role_id=a.acl_role_id AND a.module_instance_id=?
    	                          ORDER BY r.`role`",
    	                          array($id));
    	return $query->result();
    }

    public function loadByDocumentID($id)
    {
    	$query = $this->db->query("SELECT a.acl_id, r.acl_role_id, r.role,
    	                          IF(a.acl_id IS NULL, 0, a.`read`) AS `read`,
    	                          IF(a.acl_id IS NULL, 0, a.`write`) AS `write`
    	                          FROM `acl_role` AS r
    	                          LEFT JOIN `acl` AS a ON r.acl_role_id=a.acl_role_id AND a.document_id=?
    	                          ORDER BY r.`role`",
    	                          array($id));
    	return $query->result();
    }

    public function loadByMenuItemID($id)
    {
    	$query = $this->db->query("SELECT a.acl_id, r.acl_role_id, r.role,
    	                          IF(a.acl_id IS NULL, 0, a.`read`) AS `read`,
    	                          IF(a.acl_id IS NULL, 0, a.`write`) AS `write`
    	                          FROM `acl_role` AS r
    	                          LEFT JOIN `acl` AS a ON r.acl_role_id=a.acl_role_id AND a.menu_item_id=?
    	                          ORDER BY r.`role`",
    	                          array($id));
    	return $query->result();
    }

    public function loadByPageRoleID($page_id, $acl_role_id)
    {
    	$query = $this->db->query("SELECT * FROM `acl` WHERE `page_id`=? AND `acl_role_id`=?",
    	                          array($page_id, $acl_role_id));

    	foreach($query->result() as $row)
    	{
    		return $this->populate($row);
    	}

    	return false;
    }

    public function loadByModuleRoleID($module_instance_id, $acl_role_id)
    {
    	$query = $this->db->query("SELECT * FROM `acl` WHERE `module_instance_id`=? AND `acl_role_id`=?",
    	                          array($module_instance_id, $acl_role_id));

    	foreach($query->result() as $row)
    	{
    		return $this->populate($row);
    	}

    	return false;
    }

    public function loadByDocumentRoleID($document_id, $acl_role_id)
    {
    	$query = $this->db->query("SELECT * FROM `acl` WHERE `document_id`=? AND `acl_role_id`=?",
    	                          array($document_id, $acl_role_id));

    	foreach($query->result() as $row)
    	{
    		return $this->populate($row);
    	}

    	return false;
    }

    public function loadByMenuItemRoleID($menu_item_id, $acl_role_id)
    {
    	$query = $this->db->query("SELECT * FROM `acl` WHERE `menu_item_id`=? AND `acl_role_id`=?",
    	                          array($menu_item_id, $acl_role_id));

    	foreach($query->result() as $row)
    	{
    		return $this->populate($row);
    	}

    	return false;
    }

    public function checkPage($page_id, $user, $permission)
    {
    	if(!isset($user->roles) || count($user->roles) == 0)
    	{
    		$user->roles = array(1); // Public
    	}

    	if(!$page_id)
    	{
    		return $user->has(ACTION_PAGES);
    	}

    	if(!self::$cache)
    	{
    		$this->buildCache();
    	}

    	foreach(self::$cache as $c)
    	{
    		if($c->{$permission} == 1 AND $c->page_id == $page_id && in_array($c->acl_role_id, $user->roles))
    		{
    			return true;
    		}
    	}

    	return false;
    }

    public function checkModule($module_instance_id, $user, $permission)
    {
    	if(!isset($user->roles) || count($user->roles) == 0)
    	{
    		$user->roles = array(1); // Public
    	}

    	if(!$module_instance_id)
    	{
    		return $user->has(ACTION_MODULES);
    	}

    	if(!self::$cache)
    	{
    		$this->buildCache();
    	}

    	foreach(self::$cache as $c)
    	{
    		if($c->{$permission} == 1 AND $c->module_instance_id == $module_instance_id && in_array($c->acl_role_id, $user->roles))
    		{
    			return true;
    		}
    	}

    	return false;
    }

    public function checkDocument($document_id, $user, $permission)
    {
    	if(!isset($user->roles) || count($user->roles) == 0)
    	{
    		$user->roles = array(1); // Public
    	}

    	if(!$document_id)
    	{
    		return $user->has(ACTION_DOCUMENTS);
    	}

    	if(!self::$cache)
    	{
    		$this->buildCache();
    	}

    	foreach(self::$cache as $c)
    	{
    		if($c->{$permission} == 1 AND $c->document_id == $document_id && in_array($c->acl_role_id, $user->roles))
    		{
    			return true;
    		}
    	}

    	return false;
    }

    public function checkMenuItem($menu_item_id, $user, $permission)
    {
    	if(!isset($user->roles) || count($user->roles) == 0)
    	{
    		$user->roles = array(1); // Public
    	}

    	if(!$menu_item_id)
    	{
    		return $user->has(ACTION_MENUS);
    	}

    	if(!self::$cache)
    	{
    		$this->buildCache();
    	}

    	foreach(self::$cache as $c)
    	{
    		if($c->{$permission} == 1 AND $c->menu_item_id == $menu_item_id && in_array($c->acl_role_id, $user->roles))
    		{
    			return true;
    		}
    	}

    	return false;
    }

    private function buildCache()
    {
    	$key = "acl";

    	if((self::$cache = $this->cache->get($key)) === false)
    	{
    		$cache = $this->db->query("SELECT * FROM `acl`");
    		self::$cache = $cache->result();
    		$this->cache->save($key, self::$cache, 86400);
    	}
    }
}
