<?php
/**
* Pages, has all page controls
*
* @name Pages
* @verision --
* @package --
* @author Rashaud Teague <rashaud.teague@gmail.com>
* @since 03/05/2009
* @license GNU GPL
*/

class Pages {
	public $page_que = array();
	
	public function get_sections(&$tbl_contents, $parent = '') {
		global $db;
	
		$sql = "SELECT id, title FROM pages WHERE ";
		if ($parent != '') {
			$sql .= "parent = '".$this->get_id_by_title($parent)."'";
		} else {
			$sql .= "parent = '0'";
		}
		$sql .= " ORDER BY p_order";
		$db->exe_sql($sql);
		//print $sql;die();
		if ($db->num_rows() > 0)
			while ($row = $db->fetch_array())
				$tbl_contents[$row['id'].':'.stripslashes($row['title'])] = '';
	}

	public function get_children(&$tbl_contents) {
		global $db;
		
		if ($tbl_contents != NULL) {
			if (gettype($tbl_contents) != 'array')
				die('ERROR: Parse error... \$tbl_contents is not an array type. '. gettype($tbl_contents));
			
			foreach ($tbl_contents as $parentID => $parentName) {
				$sql = "SELECT id, title FROM pages WHERE parent = '$parentID' ORDER BY p_order";
				$db->exe_sql($sql);
		
				$children = array();
				if ($db->num_rows() > 0) {
					while ($row = $db->fetch_array())
						$children[] = stripslashes($row['title']);
					$tbl_contents[$parentID] = $children;
				}
			}
		}
	}

	public function display_tbl_contents($tbl_contents, $lvl = 0) {
		global $security;
		$link_style = 'tblclinks';
		if (!preg_match("/Linux/i", getenv('HTTP_USER_AGENT')))
			$link_style = 'tblclinks2';
		if ($tbl_contents != NULL) {
			if (gettype($tbl_contents) != 'array')
				die('ERROR: Invalid type passed in display_tbl_contents(). '.gettype($tbl_contents));
			$op = '';
			if (sizeof($tbl_contents) > 0) {
				$op .= 'Table of Contents';
				$op .= ' <a class = "'.$link_style.'" 
				id = "showhide" href = "javascript:show_hide();" 
				title = "Show/Hide Table of Contents">Hide</a>';
				if ($security->check_session())
					$op .= ' | <a class = "'.$link_style.'" 
					href = "'.APP_DIR.'?p=order&lvl='.$lvl.'" title = "Re-order pages">Re-order</a>
					| <a class = "'.$link_style.'" href = "'.APP_DIR.'?p=new_page&parent='.$lvl.'" 
					title = "Add a new page to the documentation">Add a page</a>';
				$op .= '<div id = "tbllist">
				<ul>';
				foreach ($tbl_contents as $parent => $children) {
					if (!preg_match("/:/i", $parent))
						die('ERROR: Parse error with the Parent parameters.');
			
					$parent_vals = explode(':', $parent, 2);
					if (!is_numeric($parent_vals[0]))
						die('ERROR: ...');
					if ($this->is_hidden($parent_vals[1])) {
						if ($security->check_session()) {
							$op .= '<li><a class = "hid" href = "'.APP_DIR.'?p='.str_replace(' ', '_', $parent_vals[1]).'" 
							title = "'.$parent_vals[1].'">'
							.$parent_vals[1].'</a></li>';
						} else {
							$op .= '';
						}
					} else {
						$op .= '<li><a href = "'.APP_DIR.'?p='.str_replace(' ', '_', $parent_vals[1]).'" 
						title = "'.$parent_vals[1].'">'
						.$parent_vals[1].'</a></li>';
					}
					if (gettype($children) == 'array' && sizeof($children) > 0) {
						if (!$this->is_hidden($parent_vals[1])) {
							$op .= '<ul>';
						} else {
							if ($security->check_session())
								$op .= '<ul>';
						}
						foreach ($children as $child => $child_title) {
							if ($this->is_hidden($child_title)) {
								if ($security->check_session()) {
									$op .= '<li><a class = "hid" href = "'.APP_DIR.'?p='
									.str_replace(' ', '_', $child_title).'" 
									title = "'.$child_title.'">'
									.$child_title.'</a></li>';
								} else {
									$op .= '';
								}
							} else {
								$op .= '<li><a href = "'.APP_DIR.'?p='.str_replace(' ', '_', $child_title).'" 
								title = "'.$child_title.'">'
								.$child_title.'</a></li>';
							}
						}
						if (!$this->is_hidden($parent_vals[1])) {
							$op .= '</ul>';
						} else {
							if ($security->check_session())
								$op .= '</ul>';
						}
					}
				}
				$op .= '</ul>
				</div>';
			}
		} else {
			$op .= 'Table of Contents';
			$op .= ' <a class = "'.$link_style.'" 
			id = "showhide" href = "javascript:;" onclick = "show_hide(); return false;" 
			title = "Show/Hide Table of Contents">Hide</a>';
				if ($security->check_session())
					$op .= ' | <a class = "'.$link_style.'" 
					href = "'.APP_DIR.'?p=order&lvl='.$lvl.'" title = "Re-order pages">Re-order</a>
					| <a class = "'.$link_style.'" href = "'.APP_DIR.'?p=new_page&parent='.$lvl.'" 
					title = "Add a new page to the documentation">Add a page</a>';
				$op .= '<div id = "tbllist">
				<ul>
					<li><a href = "'.APP_DIR.'?p=new_page&parent='.$lvl.'" 
					title = "Add a new page to the documentation">Add a page</a>.</li>
				</ul>
				</div>';
		}
		return $op;
	}

	public function get_page_data($id_page) {
		global $db, $sys;
	
		$sql = "SELECT
		*
		FROM pages
		WHERE";
		if (is_numeric($id_page)) {
			$sql .= " id = '$id_page'";
		} else {
			$sql .= " id = '".$this->get_id_by_title($id_page)."' LIMIT 1";
		}
		$db->exe_sql($sql);
		
		if (!is_numeric($id_page)) {
			if ($db->num_rows() == 0) {
				$db->free();
				unset($sql);
				$sql = "SELECT * FROM pages
				WHERE id = '".$this->get_id_by_title($id_page)."' LIMIT 1";
				$db->exe_sql($sql);
			}
		}
	
		$op = array();
		
		if ($db->num_rows() > 0) {
			$row = $db->fetch_array();
			$op['id'] = $row['id'];
			$op['title'] = stripslashes($row['title']);
			$op['content'] = '';
			if (!isset($_GET['a']) && $_GET['a'] != 'edit') {
				$op['content'] = $sys->text_parse($row['content']);
				/* Add in RSURL lookup */
				RSURL_lookup($op['content']);
			} else {
				$op['content'] .= htmlspecialchars_decode(stripslashes($row['content']));
			}
			
			$op['post_date'] = date('M-d Y H:i:s A', $row['post_date']);
			$op['last_update'] = date('M-d Y H:i:s A', $row['last_update']);
			$op['parent'] = $row['parent'];
			$op['last_ip'] = $row['last_ip'];
			$op['p_order'] = $row['p_order'];
			$op['hidden'] = $row['hidden'];
			$op['views'] = $row['views'];
			$op['locked'] = $row['locked'];
		}
	
		return $op;
	}
	
	public function page_exists($title) {
		global $db;
		$sql = "SELECT id FROM pages WHERE id = '".$this->get_id_by_title($title)."'";
		$db->exe_sql($sql);
		return ($db->num_rows() > 0) ? true : false;
	}
	
	public function is_hidden($title) {
		global $db;
		$sql = "SELECT hidden FROM pages WHERE id = '".$this->get_id_by_title($title)."'";
		$db->exe_sql($sql);
		$row = $db->fetch_array();
		return ($row['hidden'] == 1) ? true : false;
	}

	public function get_id_by_title($title) {
		global $db;
	
		$sql = "SELECT id FROM pages WHERE title = '".mysql_real_escape_string(str_replace('_', ' ', $title))."'";
		$db->exe_sql($sql);
		
		if ($db->num_rows() == 0) {
			$db->free();
			unset($sql);
			$sql = "SELECT id FROM pages WHERE title = '".mysql_real_escape_string($title)."'";
			$db->exe_sql($sql);
		}
		
		$row = $db->fetch_array();
	
		return $row['id'];
	}
	
	public function validate_page_edit($title, $content, $parent, $merge, $page) {
		global $security, $pv;
		
		$error_array = array();
		
		if (empty($title))
			$error_array[] = 'ERROR: The page title is empty.';
		if (empty($content))
			$content = 'Empty Page';
		
		if (sizeof($error_array) < 1) {
			$this->save_page($title, $content, $parent, $merge, $page);
			$security->redirect(APP_DIR.'?p='.str_replace(' ', '_', $page['title']));
		} else {
			$pv->edit_page_form($error_array, $page);
		}
	}
	
	public function save_page($title, $content, $parent, $merge, $data) {
		global $db, $security, $uc, $rsurl, $cache;
		
		/* REAL SHORT URL API USE */
		if ($rsurl->toggle())
			RSURL($content);
		
		if ($merge != 0) {
			$sql = "UPDATE pages SET hidden = '1' WHERE id = '".$data['id']."'";
			$db->exe_sql($sql);
			
			$pdata = $this->get_page_data($merge);
			$new_merged_content = $pdata['content']."\n\n";
			$new_merged_content .= '<strong>---- Merged Content from '
			.mysql_real_escape_string(trim($title)).' ----</strong>'."\n\n";
			$new_merged_content .= mysql_real_escape_string(htmlspecialchars($content));
			
			$sql = "UPDATE pages SET
			content = '$new_merged_content',
			last_update = '".time()."'
			WHERE id = '".$pdata['id']."'";
			$db->exe_sql($sql);
		}
		
		//do the check_orig_parent so we can set the right page order
		$this->check_orig_parent($parent, $data);
		$orig_parent = $data['parent'];
		$sql = "UPDATE pages SET
		title = '".mysql_real_escape_string(trim($title))."',
		content = '".mysql_real_escape_string(htmlspecialchars($content))."',
		parent = '$parent',
		last_update = '".time()."', ";
		if ($security->check_session()) {
			$udata = $uc->user_data($_SESSION['docu_user']);
			$sql .= "last_ip = '".$udata['username']."'";
		} else {
			$sql .= "last_ip = '".getenv('REMOTE_ADDR')."'";
		}
		$sql .= " WHERE id = '".$data['id']."'";
		//print $sql;die();
		$db->exe_sql($sql);
		//reset all page order under the original parent
		if ($data['parent'] != $parent)
			$this->fix_order($orig_parent);
		
		$cache->create($data['title'], true);
	}
	
	public function check_orig_parent($post_parent, $data) {
		global $db;
		
		if (!is_numeric($post_parent))
			die('ERROR: Wrong type passed in first parameter in Pages::check_orig_parent().');
		
		//check to see of the original parent is different than the post parent
		if ($data['parent'] != $post_parent) {
			//get the last p_order from the last page under this parent
			$sql = "SELECT p_order FROM pages WHERE ";
			if ($post_parent == 0) {
				$sql .= "parent = '0'";
			} else {
				$sql .= "parent = '$post_parent'";
			}
			$sql .= " ORDER BY p_order DESC LIMIT 1";
			$db->exe_sql($sql);
			$row = $db->fetch_array();
			$last_page_order = $row['p_order'];
			$this->reset_page_order($last_page_order, (int)$data['id']);
			//lets end the execution of the function right here
			return;
		}
	}
	
	public function reset_page_order($last_page, $page) {
		global $db;
		
		if (!is_numeric($page))
			die('ERROR: Wrong type passed in second parameter in Pages::reset_page_order().');
		$sql = "UPDATE pages SET p_order = '".($last_page + 1)."' WHERE id = '$page'";
		$db->exe_sql($sql);
	}
	
	public function validate_new_page($title, $content, $parent) {
		global $security, $pv;
		
		$error_array = array();
		
		if (empty($title))
			$error_array[] = 'ERROR: The page title is empty.';
		if ($this->page_exists($title))
			$error_array[] = 'ERROR: Page names must be unique.';
		if (empty($content))
			$content = 'Empty Page';
		
		if (sizeof($error_array) < 1) {
			$this->save_new_page($title, $content, $parent);
			$security->redirect(APP_DIR.'?p='.str_replace(' ', '_', $title));
		} else {
			$pv->new_page_form($error_array);
		}
	}
	
	public function save_new_page($title, $content, $parent) {
		global $db, $security, $uc, $rsurl, $cache;
		
		/* REAL SHORT URL API USE */
		if ($rsurl->toggle())
			RSURL($content);
		
		$p_order = $this->get_page_order_by_parent($parent);
		
		if ($security->check_session()) {
			$udata = $uc->user_data($_SESSION['docu_user']);
			$user = explode('@', $udata['username']);
			$last_ip = $user[0];
		} else {
			$last_ip = getenv('REMOTE_ADDR');
		}
		
		$sql = "INSERT INTO pages VALUES(
		'',
		'".mysql_real_escape_string(strip_tags(trim($title)))."',
		'".mysql_real_escape_string(htmlspecialchars($content))."',
		'".time()."',
		'".time()."',
		'$parent',
		'$last_ip',
		'$p_order',
		'0',
		'0',
		'0'
		)";
		
		$db->exe_sql($sql);
		
		$cache->create(strip_tags($title), true);
	}
	
	public function get_page_order_by_parent($parent) {
		global $db;
		
		if (!is_numeric($parent))
			die('ERROR: Wrong type passed in second parameter in Pages::get_page_order_by_parent().');
		$sql = "SELECT p_order FROM pages WHERE parent = '$parent' ORDER BY p_order DESC LIMIT 1";
		$db->exe_sql($sql);
		$row = $db->fetch_array();
		
		$new_page_p_order = $row['p_order'] + 1;
		return $new_page_p_order;
	}
	
	public function fix_order($parent) {
		global $db;
		
		$sql = "";
		
		$pages = $this->iterate_pages_by_parent($parent);
		$count = 1;
		foreach ($pages as $pID => $page) {
			$sql .= "UPDATE pages SET p_order = '$count' WHERE id = '$pID' AND parent = '$parent';";
			$count++;
		}
		$db->run_query($sql);
	}
	
	public function iterate_pages_by_parent($parent) {
		global $db;
		
		$pages = array();
		
		$sql = "SELECT id, title, p_order FROM pages WHERE parent = '$parent' ORDER BY p_order";
		$db->exe_sql($sql);
		
		while ($row = $db->fetch_array())
			$pages[$row['id']] = array(stripslashes($row['title']), $row['p_order']);
		
		return $pages;
	}
	
	public function move_order($page, $direction) {
		global $db;
		$possible_directions = array('up', 'down');
		if (!is_numeric($page))
			die('ERROR: Invalid type passed to Pages::move_order().');
		if (!in_array(strtolower($direction), $possible_directions))
			die('ERROR: Invalid direction in Pages::move_order().');
		
		//get everything about this page we need to know
		$data = $this->get_page_data($page);
				
		if (strtolower($direction) == 'up') {
			if ($data['p_order'] == 1)
				return;
			
			$sql = "UPDATE pages SET p_order = p_order + 1 WHERE parent = '".$data['parent']."'
					AND p_order = '".($data['p_order']-1)."';
					UPDATE pages SET p_order = p_order - 1 WHERE id = '$page'";
			//print $sql;die();
			$db->run_query($sql);
			
		} elseif (strtolower($direction) == 'down') {
			//pages under the current parent
			$pages_parent = $this->iterate_pages_by_parent($data['parent']);
			if (sizeof($pages_parent) == $data['p_order'])
				return;
			
			$sql = "UPDATE pages SET p_order = p_order - 1 WHERE parent = '".$data['parent']."'
					AND p_order = '".($data['p_order']+1)."';
					UPDATE pages SET p_order = p_order + 1 WHERE id = '$page'";
			$db->run_query($sql);
		}
	}
	
	public function get_left_page_nav($cur_page) {
		global $db;
		
		//page data
		$pdata = $this->get_page_data($cur_page);
		
		//check to see if this page is top level parent
		if ($pdata['parent'] == 0) {
			if ($pdata['p_order'] < 2)
				return array(APP_DIR.'?p=main' => 'Main');
			
			if ($pdata['p_order'] > 1) {
				$sql = "SELECT title FROM pages
				WHERE parent = '".$pdata['parent']."'
				AND p_order = '".($pdata['p_order']-1)."'";
				$db->exe_sql($sql);
				$row = $db->fetch_array();
				return array(APP_DIR.'?p='.str_replace(' ', '_', stripslashes($row['title'])) => stripslashes($row['title']));
			}
		} elseif ($pdata['parent'] != 0) {
			if ($pdata['p_order'] < 2) {
				//parent page data
				$ppdata = $this->get_page_data($pdata['parent']);	
				return array(APP_DIR.'?p='.str_replace(' ', '_', stripslashes($ppdata['title'])) => stripslashes($ppdata['title']));
			}
			
			if ($pdata['p_order'] > 1) {
				$sql = "SELECT title FROM pages
				WHERE parent = '".$pdata['parent']."'
				AND p_order = '".($pdata['p_order']-1)."'";
				$db->exe_sql($sql);
				$row = $db->fetch_array();
				return array(APP_DIR.'?p='.str_replace(' ', '_', stripslashes($row['title'])) => stripslashes($row['title']));
			}
		}
	}
	
	public function get_up_page_nav($cur_page) {
		//page data
		$pdata = $this->get_page_data($cur_page);
		
		if ($pdata['parent'] == 0)
			return array(APP_DIR.'?p=main' => 'Main');
		
		if ($pdata['parent'] != 0) {
			$ppdata = $this->get_page_data($pdata['parent']);
			return array(APP_DIR.'?p='.str_replace(' ', '_', stripslashes($ppdata['title'])) => stripslashes($ppdata['title']));
		}
	}
	
	public function get_right_page_nav($cur_page, $next = 0) {
		global $db, $security;
		
		//page data
		$pdata = $this->get_page_data($cur_page);
		
		if ($pdata['p_order'] == sizeof($this->iterate_pages_by_parent($pdata['parent']))) {
			$ppdata = $this->get_page_data($pdata['parent']);
			if (sizeof($this->iterate_pages_by_parent($ppdata['parent'])) > 1) {
				if ($ppdata['p_order'] < sizeof($this->iterate_pages_by_parent($ppdata['parent']))) {
					$next += 1;
					$sql = "SELECT title, hidden FROM pages
					WHERE parent = '".$ppdata['parent']."'
					AND p_order = '".($ppdata['p_order']+$next)."'";
					$db->exe_sql($sql);
					$row = $db->fetch_array();
					if ($row['hidden'] == 1 && !$security->check_session()) {
						if (($ppdata['p_order']+$next+1) < sizeof($this->iterate_pages_by_parent($ppdata['parent']))) {
							$this->get_right_page_nav($cur_page, $next);
						} else {
							$fpdata = $this->get_first_page($ppdata['parent']);
							return array(APP_DIR.'?p='.str_replace(' ', '_', $fpdata['title']) => $fpdata['title']);
						}
					}
					return array(APP_DIR.'?p='.str_replace(' ', '_', stripslashes($row['title'])) => stripslashes($row['title']));
				}
			}
			return array(APP_DIR.'?p='.str_replace(' ', '_', stripslashes($pdata['title'])) => stripslashes($pdata['title']));
		} elseif ($pdata['p_order'] < sizeof($this->iterate_pages_by_parent($pdata['parent']))) {
			$next += 1;
			$sql = "SELECT title, hidden FROM pages
					WHERE parent = '".$pdata['parent']."'
					AND p_order = '".($pdata['p_order']+$next)."'";
					$db->exe_sql($sql);
					$row = $db->fetch_array();
					if ($row['hidden'] == 1 && !$security->check_session()) {
						if (($pdata['p_order']+$next+1) < sizeof($this->iterate_pages_by_parent($pdata['parent']))) {
							$this->get_right_page_nav($cur_page, $next);
						} else {
							$fpdata = $this->get_first_page($pdata['parent']);
							return array(APP_DIR.'?p='.str_replace(' ', '_', $fpdata['title']) => $fpdata['title']);
						}
					}
					return array(APP_DIR.'?p='.str_replace(' ', '_', stripslashes($row['title'])) => stripslashes($row['title']));
		}
	}
	
	public function get_first_page($parent) {
		global $db;
		
		$sql = "
		SELECT
			title
		FROM
			pages
		WHERE
			parent = '$parent'
			AND p_order = '1'
		";
		$db->exe_sql($sql);
		$row = $db->fetch_array();
		$op = array();
		$op['title'] = stripslashes($row['title']);
		return $op;
	}
	
	public function unhide() {
		global $db;
		
		$sql = "";
		$size = sizeof($this->page_que) - 1;
		$count = 0;
		foreach ($this->page_que as $key => $val) {
			$sql .= "UPDATE pages SET hidden = '0' WHERE id = '$key'";
			if ($count < $size)
				$sql .= ";";
			$count++;
		}
		$db->run_query($sql);
	}
	
	public function hide() {
		global $db;
		
		$sql = "";
		$size = sizeof($this->page_que) - 1;
		$count = 0;
		foreach ($this->page_que as $key => $val) {
			$sql .= "UPDATE pages SET hidden = '1' WHERE id = '$key'";
			if ($count < $size)
				$sql .= ";";
			$count++;
		}
		$db->run_query($sql);
	}
	
	public function fill_page_que($start_page) {
		global $db;
		
		$pdata = $this->get_page_data($start_page);
		$this->page_que[$pdata['id']] = $pdata['title'];
		if ($this->has_children($pdata['title'])) {
			$children = $this->iterate_pages_by_parent($pdata['id']);
			foreach ($children as $tkey => $tval) {
				foreach ($tval as $lval) {
					$this->page_que[$tkey] = $tval[0];
					$this->fill_page_que($tval[0]);
				}
			}
		}
	}
	
	public function has_children($title) {
		global $db;
		$sql = "SELECT id FROM pages WHERE parent = '".$this->get_id_by_title($title)."'";
		$db->exe_sql($sql);
		return ($db->num_rows() > 0) ? true : false;
	}
	
	public function delete_page($page) {
		global $db, $cache;
		
		if (!is_array($page))
			die('ERROR: Invalid type passed in Pages::delete_page().');
		
		if ($this->has_children($page['title'])) {
			$start_porder = $this->get_page_order_by_parent($page['parent']);
			$children = $this->iterate_pages_by_parent($page['id']);
			$sql = "";
			$size = sizeof($this->page_que) - 1;
			$count = 0;
			foreach ($children as $tkey => $tval) {
				foreach ($tval as $lval) {
					$sql .= "UPDATE pages SET parent = '".$page['parent']."', p_order = '$start_porder' WHERE id = '$tkey'";
					if ($count < $size)
						$sql .= ";";
					$count++;
					$start_porder++;
				}
			}
			$db->run_query($sql);
		}
		if (isset($sql) && $sql != '')
			unset($sql);
		$sql = "DELETE FROM pages WHERE id = '".$page['id']."'";
		$db->exe_sql($sql);
		$this->fix_order($page['parent']);
	}
	
	public function delete_page_tree() {
		global $db, $cache;
		
		$sql = "";
		$size = sizeof($this->page_que) - 1;
		$count = 0;
		foreach ($this->page_que as $key => $val) {
			$sql .= "DELETE FROM pages WHERE id = '$key'";
			if ($count < $size)
				$sql .= ";";
			$count++;
		}
		$db->run_query($sql);
	}
	
	public function update_page_views($page) {
		global $db;
		
		$sql = "UPDATE pages SET views = views + 1 WHERE";
		$sql .= (is_array($page)) ? " id = '".$page['id']."'" : " id = '".$this->get_id_by_title($page)."'";
		$db->exe_sql($sql);
	}
	
	public function top_pages($limit) {
		global $db;
		
		$sql = "SELECT title, views FROM pages ORDER BY views DESC LIMIT $limit";
		$db->exe_sql($sql);
		
		$op = array();
		
		if ($db->num_rows() > 0) {
			while ($row = $db->fetch_array()) {
				$a = array();
				$a['title'] = stripslashes($row['title']);
				$a['views'] = $row['views'];
				
				$op[] = $a;
			}
		}
		return $op;
	}
	
	public function lock_page($page) {
		global $db;
		
		$sql = "UPDATE pages SET locked = '1' WHERE id = '".$page['id']."'";
		$db->exe_sql($sql);
	}
	
	public function unlock_page($page) {
		global $db;
		
		$sql = "UPDATE pages SET locked = '0' WHERE id = '".$page['id']."'";
		$db->exe_sql($sql);
	}
	
	public function page_locked($id) {
		global $db;
		
		$sql = "SELECT locked FROM pages WHERE id = '$id'";
		$db->exe_sql($sql);
		$row = $db->fetch_array();
		
		return ($row['locked'] == 1) ? true : false;
	}
}
?>