<?php
class Page extends MY_Model
{
	const DB_TABLE = 'pages';
    const DB_TABLE_PK = 'page_id';

    public $fields = array();

    public function __construct()
    {
    	parent::__construct();

		$this->published             = 1;
		$this->content_type_id       = 1;
		$this->page_info             = 1;
		$this->title_heading_level   = 1;
		$this->searchable            = 1;
		$this->rss                   = 0;
		$this->allow_url_segments    = 0;
		$this->allow_url_query       = 0;
		$this->show_date 			 = 0;
		$this->content_type          = "Blank Page";
		$this->content_type_filename = "default";
	}

    public function load($id)
	{
		$this->load->model("page_tag");
		$query = $this->db->query("SELECT p.*, t.content_type, t.filename AS content_type_filename, t.page_info
	  	                          FROM pages AS p
	  	                          INNER JOIN content_types AS t USING(content_type_id)
	  	                          WHERE `page_id`=?",
	  	                          array($id));

		$success = $this->populate($query->row());
		$this->tags = $this->page_tag->loadByPageID($this->page_id);
		$this->load_fields();

		return $success;
	}

    public function populate($row)
	{
		$success = parent::populate($row);
		$this->load_fields();
		return $success;
	}

	private function load_fields()
	{
		$this->load->model("content_value");
		$fields = $this->content_value->LoadByPageID($this->page_id);

		$this->fields = array();

		foreach($fields as $field)
		{
			$this->fields[$field->key] = $field;
		}
	}

    function LoadBySitePageID($site_id, $page_id)
	{
		$this->load->model("page_tag");

		$key = "page:" . $site_id . ":" . $page_id;

		if(($query = $this->cache->get($key)) === false)
	  	{
	  		$query = $this->db->query("SELECT p.*, t.content_type, t.filename AS content_type_filename
		  	                          FROM pages AS p
		  	                          INNER JOIN content_types AS t USING(content_type_id)
		  	                          WHERE p.published=1 AND site_id=? AND (url=? OR page_id=?)
		  	                          GROUP BY p.page_id
		  							  ORDER BY `title`",
		  	                          array($site_id, $page_id, $page_id));

		  	if($query->num_rows() > 0)
		  	{
		  		foreach($query->result() as $row)
		  		{
		  			//load the first item
			  		$success = $this->populate($row);
			  		$this->tags = $this->page_tag->loadByPageID($this->page_id);
					$this->load_fields();
					$this->cache->save($key, $row, 86400);
			  		return $success;
		  		}
		  	}
		}

	  	$success = $this->populate($query);
	  	$this->tags = $this->page_tag->loadByPageID($this->page_id);
		$this->load_fields();
		return $success;
	}

    function checkURL($site_id, $page_id, $url)
	{
		// Check if there is already a page with this URL which is not the page we're asking about.
		$query = $this->db->query("SELECT page_id
	  	                          FROM pages AS p
	  	                          WHERE `site_id`=? AND `url`=? AND `page_id`!=?",
	  	                          array($site_id, $url, $page_id));

	  	return ($query->num_rows() == 0);
	}

    function LoadBySiteID($id, $user, $orderby="p.`title`")
	{
		if($user == null)
		{
			// Simulate an admin user
			$user = new User();
			$user->roles = array(3);
		}
		else if(!isset($user->roles) || count($user->roles) == 0)
    	{
    		$user->roles = array(1); // Public
    	}

		$query = $this->db->query("SELECT p.*, c.name AS category_name
	  								FROM pages AS p
	  								INNER JOIN `acl` AS a USING(page_id)
									LEFT JOIN categories AS c ON p.category_id=c.category_id
	  								WHERE p.published=1 AND p.site_id=? AND a.read=1 AND a.acl_role_id IN ?
	  								GROUP BY p.page_id
	  								ORDER BY " . $orderby,
	  								array($id, $user->roles));

		return $query->result();
	}

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

		$query = $this->db->query("SELECT p.*, IF(mp.module_page_id IS NULL, '0', '1') AS module_installed
				FROM pages AS p
				INNER JOIN `acl` AS a USING(page_id)
				LEFT JOIN modules_pages AS mp ON (p.page_id=mp.page_id AND mp.module_instance_id=?)
				WHERE p.site_id=? AND a.read=1 AND a.acl_role_id IN ?
				GROUP BY p.page_id
	  			ORDER BY p.`title`",
				array($module_instance_id, $site_id, $user->roles));

		return $query->result();
	}

	function LoadByCategoryContentTypeTagID($site_id, $category_id, $content_type_id, $tag_ids, $tag_logic="OR", $orderby="`created` DESC", $q="", $user, $ignore_searchable=0)
	{
		return $this->LoadByCategoryContentTypeTagIDYear($site_id, $category_id, $content_type_id, $tag_ids, $tag_logic, null, $orderby, $q, $user, $ignore_searchable);
	}

	function LoadByCategoryContentTypeTagIDYear($site_id, $category_id, $content_type_id, $tag_ids, $tag_logic="OR", $year, $orderby="`created` DESC", $q="", $user, $ignore_searchable=0)
	{
		if(!isset($user->roles) || count($user->roles) == 0)
    	{
    		$user->roles = array(1); // Public
    	}

		$where 		= "p.published=1 " . ($ignore_searchable ? "" : "AND p.searchable=1") . " AND a.read=1 AND a.acl_role_id IN(" . implode(",", $user->roles) . ")";
		$select 	= "";
		$having 	= "";
		$groupby 	= "p.page_id";

		if($site_id)
		{
			$where .= " AND p.`site_id`='" . $this->db->escape_str($site_id) . "'";
		}
		if($category_id)
		{
			$where .= " AND p.`category_id`='" . $this->db->escape_str($category_id) . "'";
		}
		if($content_type_id)
		{
			$where .= " AND p.`content_type_id`='" . $this->db->escape_str($content_type_id) . "'";
		}
		if($tag_ids)
		{
			// If tag_ids isn't already an array, split on commas if they exist.
			// If tag_ids is an integer we'll get an array of one element.
			if(!is_array($tag_ids))
			{
				$tag_ids = explode(",", $tag_ids);
			}

			$having_tags = "";

			// Match on ALL or ANY of the supplied tags, based on $tag_logic.
			foreach($tag_ids as $tag_id)
			{
				$having_tags .= ($having_tags ? " " . $tag_logic . " " : "") . "`tag_ids` REGEXP '^([0-9]+,){0,100}(" . $tag_id . ")(,[0-9]+){0,100}$'";
			}

			$having .= ($having ? " AND " : "") . "(" . $having_tags . ")";
		}
		if($year)
		{
			$where .= " AND SUBSTRING(p.`created`, 1, 4)='" . $this->db->escape_str($year) . "'";
		}
		if($q)
		{
			$q 			 = strtolower($q);
			$keywords 	 = explode(" ", $q);
			// Add the full query as the last keyword so that a full match gets more points.
			$keywords[]  = $q;
			$keywords 	 = array_unique($keywords);
			$select  	 = ', 0';

			// Tally up the number of occurrances for each keyword in a few of our fields.
			foreach($keywords as $q)
			{
				// Skip keywords that are a single letter because they return basically everything.
				if(strlen($q) == 1)
				{
					continue;
				}
				$select .= ' + (LENGTH(p.`title`) - LENGTH(REPLACE(LOWER(p.`title`), "' . $this->db->escape_str($q) . '", ""))) / LENGTH("' . $this->db->escape_str($q) . '")';
				$select .= ' + (LENGTH(p.`url`) - LENGTH(REPLACE(LOWER(p.`url`), "' . $this->db->escape_str($q) . '", ""))) / LENGTH("' . $this->db->escape_str($q) . '")';
				$select .= ' + (LENGTH(v.`value`) - LENGTH(REPLACE(LOWER(v.`value`), "' . $this->db->escape_str($q) . '", ""))) / LENGTH("' . $this->db->escape_str($q) . '")';
			}
			$select 	.= ' AS points';
			$orderby 	 = "points DESC, " . $orderby;
			$having 	.= ($having ? " AND " : "") . "points > 0";
		}

		$query = $this->db->query("SELECT p.*, t.content_type, t.filename AS content_type_filename,
		        				tp.tag_id, GROUP_CONCAT(DISTINCT tp.tag_id) AS tag_ids" . $select . ",
		                        COUNT(p.page_id) AS total
								FROM pages AS p
								INNER JOIN `acl` AS a USING(page_id)
								INNER JOIN content_types AS t USING(content_type_id)
								INNER JOIN `content_values` AS v ON p.page_id=v.page_id
								LEFT JOIN `tag_page` AS tp ON p.page_id=tp.page_id
					  	        WHERE " . $where .
					  	        ($groupby ? " GROUP BY " . $groupby : "") .
					  	        ($having ? " HAVING " . $having : "") . "
								ORDER BY $orderby");

		return $query->result();
	}

	function LoadForRSSFeed($site_id)
	{
		$query = $this->db->query("SELECT p.*, c.name AS category_name
	  								FROM pages AS p
	  								LEFT JOIN categories AS c ON p.category_id=c.category_id
	  								WHERE p.published=1 AND p.site_id=? AND p.rss='1'
	  								GROUP BY p.page_id
	  								ORDER BY p.`created` DESC",
	  								array($site_id));

		return $query->result();
	}

	public function getUnlinked($site_id)
	{
		$q = $this->db->query("SELECT p.*, IF(p.category_id IS NULL, 'Uncategorized', c.name) AS category_name
		                      FROM pages AS p
		                      LEFT JOIN menu_items AS i USING(page_id)
		                      LEFT JOIN categories AS c USING(category_id)
		                      WHERE p.site_id=? AND i.menu_item_id IS NULL
		                      GROUP BY p.page_id
		                      ORDER BY category_name, p.title",
		                      array($site_id));
		return $q->result();
	}

	public function getUnlinkedByMenuID($site_id, $menu_id)
	{
		$q = $this->db->query("SELECT p.*, IF(p.category_id IS NULL, 'Uncategorized', c.name) AS category_name
		                      FROM pages AS p

		                      LEFT JOIN menu_items AS i ON p.page_id=i.page_id AND i.menu_id=?
		                      LEFT JOIN categories AS c USING(category_id)
		                      WHERE p.site_id=? AND i.menu_item_id IS NULL
		                      GROUP BY p.page_id
		                      ORDER BY category_name, p.title",
		                      array($menu_id, $site_id));
		return $q->result();
	}

	public function delete_all($site_id)
    {
    	$this->db->query("DELETE FROM pages WHERE site_id=?", array($site_id));
    }

    public function delete_others($site_id, $ids)
    {
    	$this->db->query("DELETE FROM pages WHERE site_id=? AND page_id NOT IN ($ids)", array($site_id));
    }

    function search($q, $site_id, $user)
	{
		if($q == null)
		{
			return array();
		}

		if(!isset($user->roles) || count($user->roles) == 0)
    	{
    		$user->roles = array(1); // Public
    	}

		$q = $this->db->escape_str($q);

		$query = $this->db->query("SELECT p.*
		                          FROM pages AS p
		                          INNER JOIN `acl` AS a USING(page_id)
		                          WHERE (p.site_id=? AND a.read=1 AND a.acl_role_id IN ?) AND
			                          p.title LIKE '%$q%' OR
			                          p.url LIKE '%$q%' OR
			                          p.description LIKE '%$q%' OR
			                          p.content LIKE '%$q%'
		                          GROUP BY p.page_id
		                          ORDER BY title",
		                          array($site_id, $user->roles));

		return $query->result();
	}

	public function url()
	{
		return $this->url;
	}

	function field($key, $default="")
	{
		if(isset($this->fields["$key"]))
		{
		 	return $this->fields["$key"]->value;
		}
		else
		{
			return $default;
		}
	}
}
