Login   Register  
PHP Classes
elePHPant
Icontem

File: class_history_links.inc

Recommend this page to a friend!
Stumble It! Stumble It! Bookmark in del.icio.us Bookmark in del.icio.us
  Classes of Vladimir Kudryavtsev  >  History links  >  class_history_links.inc  >  Download  
File: class_history_links.inc
Role: Class source
Content type: text/plain
Description: Class History links
Class: History links
Keep track and link to pages browsed by user
Author: By
Last change: + Add functions:
get_history_go($step)
is_history_go($step)
get_always_go($step)
is_always_go($step)
if $step>0 then next_step else back_step

+ Add param integer ($is_back_next_param) in constructor
if 1 - Use of additional parameters in URL (default), if 0 - not use additional parameters in URL
!!!!! Correctly works only for one step !!!!!
Date: 8 years ago
Size: 21,261 bytes
 

Contents

Class file image Download
<?php 
/**
* history class, navigation on a site, emulation: javascript:history.go().
* Ignoring of the chosen pages, ignoring of pages with query POST.
* 
* @author   Vladimir Kudryavtsev <volodia@webart.kz>
* @version  1.3.1
* 
* 
* 
* 
* small example 
* =========================================
* #all parameters see in class or example
* $arr=array();
* $max_url_history=100;
* require_once('class_history_links.inc');
* 
* echo '<html><body>
* -------------------------------------------<br>
* Step, as in javascript:history.go()<br>
* -------------------------------------------<br>
* 
* <a href="'.$h->get_history_back().'">back page</a> or <a href="'.$h->get_history_go(-1).'">(go)back page</a><br>
* <a href="'.$h->get_history_next().'">next page</a> or <a href="'.$h->get_history_go(1).'">(go)next page</a><p>
* 
* <a href="'.$h->get_history_back(2).'">back page with step(2)</a> or <a href="'.$h->get_history_go(-2).'">(go)back page with step(2)</a><br>
* <a href="'.$h->get_history_next(2).'">next page with step(2)</a> or <a href="'.$h->get_history_go(2).'">(go)next page with step(2)</a><p>
* 
* <a href="'.$h->get_history_backs().'">first page</a><br>
* <a href="'.$h->get_history_nexts().'">last page</a><p>
* 
* '.($h->is_history_back()?'back page exist':'back page not exist').'<br>
* '.($h->is_history_next()?'next page exist':'next page not exist').'<p>
* 
* '.($h->is_history_back(2)?'back page with step(2) exist':'back page with step(2) not exist').'</a><br>
* '.($h->is_history_next(3)?'next page with step(3) exist':'next page with step(3) not exist').'</a><p>
* 
* -------------------------------------------<br>
* Always step, exact as in javascript:history.go()<br>
* -------------------------------------------<br>
* 
* <a href="'.$h->get_always_back().'">back page</a> or <a href="'.$h->get_always_go(-1).'">(go)back page</a><br>
* <a href="'.$h->get_always_next().'">next page</a> or <a href="'.$h->get_always_go(1).'">(go)next page</a><p>
* 
* <a href="'.$h->get_always_back(2).'">back page with step(2)</a> or <a href="'.$h->get_always_go(-2).'">(go)back page with step(-2)</a><br>
* <a href="'.$h->get_always_next(2).'">next page with step(2)</a> or <a href="'.$h->get_always_go(2).'">(go)next page with step(2)</a><p>
* 
* <a href="'.$h->get_always_backs().'">first page</a><br>
* <a href="'.$h->get_always_nexts().'">last page</a><p>
* 
* '.($h->is_always_back()?'back page exist':'back page not exist').'<br>
* '.($h->is_always_next()?'next page exist':'next page not exist').'<p>
* 
* '.($h->is_always_back(2)?'back page with step(2) exist':'back page with step(2) not exist').'</a><br>
* '.($h->is_always_next(3)?'next page with step(3) exist':'next page with step(3) not exist').'</a><p>
* 
* -------------------------------------------<br>
* Step, external parameters for step (for javascript), see example<br>
* -------------------------------------------<br>
* 
* <a href="'.$h->get_history_header().'&b=1">back page</a><br>
* <a href="'.$h->get_history_header().'&n=1">next page</a><p>
* 
* <a href="'.$h->get_history_header().'&b=3">back page with step(3)</a><br>
* <a href="'.$h->get_history_header().'&n=2">next page with step(2)</a><p>';
* 
* #set start page if needed
* #$h->set_history_start(0); #if 1 to clear history array
* echo '</body></html>';
* =========================================
* 
* 
* 
* tiny example 
* =========================================
* #all parameters see in class or example
* $arr=array();
* $max_url_history=100;
* $back_next_param=0; #not use additional parameters in URL
* require_once('class_history_links.inc');
* 
* echo '<html><body>
* -------------------------------------------<br>
* Step, as in javascript:history.go()<br>
* -------------------------------------------<br>
* 
* <a href="'.$h->get_history_back().'">back page</a> or <a href="'.$h->get_history_go(-1).'">(go)back page</a><br>
* <a href="'.$h->get_history_next().'">next page</a> or <a href="'.$h->get_history_go(1).'">(go)next page</a><p>
* 
* <a href="'.$h->get_history_back(2).'">back page with step(2)</a> or <a href="'.$h->get_history_go(-2).'">(go)back page with step(2)</a><br>
* <a href="'.$h->get_history_next(2).'">next page with step(2)</a> or <a href="'.$h->get_history_go(2).'">(go)next page with step(2)</a><p>
* 
* <a href="'.$h->get_history_backs().'">first page</a><br>
* <a href="'.$h->get_history_nexts().'">last page</a><p>
* 
* #set start page if needed
* #$h->set_history_start(0); #if 1 to clear history array
* echo '</body></html>';
* =========================================
* 
* 
* @access public
*/
@session_start();

$h=new history_links(
	0,	#unique for several classes on one page
	(isset($max_url_history)?$max_url_history:100),	#the maximal history
	(isset($arr)?$arr:array()),
	(isset($back_next_param)?$back_next_param:1)
);

class history_links{
	var $arr;
	var $max_arr;
	var $request_uri;
	var $request_method;
	var $request_query;
	var $class_ident;
	var $arr_select=
		array(
			'start'=>'',			#Start page for tracking, absolute "url" is recommended
			'name_back_param'=>'b',	#Name for "back" parameter (default: b) -> page.html?b=1
			'name_next_param'=>'n',	#Name for "next" parameter (default: n) -> page.html?n=1
			'header_param'=>'h_p',	#Name for "header()" (default: h_p) -> header("Location: page.html?h_p");
			'page_back'=>array(),	#Skip of page if back step
			'page_full'=>array(),	#Skip of page if back step or next step
			'param_back'=>array(),	#Skip of page if back step -> the page "page.html?param2=1" will be skipped
			'param_full'=>array(),	#Skip of page if back step or next step -> the page "page.html?param4=1" will be skipped
			'value_back'=>array(),	#Skip of page if back step -> the page "page.html?param=content3" will be skipped
			'value_full'=>array(),	#Skip of page if back step or next step -> the page "page.html?param=content4" will be skipped
			'post'=>0				#Will track page without "POST-request" (default: 0, always will skip page with POST)
		);
	var $next=0;
	var $back=0;
	var $page_start='';
	var $is_back_next_param=1;		#Use of additional parameters in URL (name_back_param,name_next_param) 
									#if 0, not use additional parameters in URL
									#!!!!! Correctly works only for one step !!!!!
	/**
	* constructor
    *
    * @param string $max (the maximal history)
	* @param integer $class_ident (must be unique for several classes on one page)
	* @param array(string, array(string), ...) $arr_select (the description above on page)
	* @param integer $back_next_param (Use of additional parameters in URL), if 0 - not use additional parameters in URL
	*/
	function history_links($class_ident=0,$max=100,$arr_select=array(),$back_next_param=1){
		
		$this->request_uri=$_SERVER['REQUEST_URI'];
		$this->request_method=$_SERVER['REQUEST_METHOD'];
		$this->request_query=$_SERVER['QUERY_STRING'];
		$this->class_ident=intval($class_ident);
		$this->max_arr=$max;
		$this->is_back_next_param=$back_next_param;
		
		$this->arr_select=array_merge($this->arr_select,$arr_select);
		
		#set back and step
		if(isset($_GET[$this->arr_select['name_back_param']]))$this->back=intval($_GET[$this->arr_select['name_back_param']]);
		if(isset($_GET[$this->arr_select['name_next_param']]))$this->next=intval($_GET[$this->arr_select['name_next_param']]);
		
		if(!isset($_SESSION['history_links'][$this->class_ident]))$this->set_history_start(1);
		$this->arr=$_SESSION['history_links'][$this->class_ident];
		
		#header
		if(isset($_GET[$this->arr_select['header_param']])){
			if(isset($_GET[$this->arr_select['name_back_param']])){
				header("location: ".$this->get_history_back($_GET[$this->arr_select['name_back_param']]));
				exit;
			}
			if(isset($_GET[$this->arr_select['name_next_param']])){
				header("location: ".$this->get_history_next($_GET[$this->arr_select['name_next_param']]));
				exit;
			}
		}
		
		$this->_set_history($_SESSION['history_links'][$this->class_ident]);
	}
	/**
	* Processing URL of page
	*
	* @param &array(string) $arr_history (array of a history of navigation on pages)
	* @access   private
	*/
	function _set_history(&$arr_history){
		if(!isset($this->request_uri))return;
		
		
		#check of a step back
		if($this->back){
			if($this->is_history_back($this->back))$this->arr[0][0]-=$this->back;
			else $this->arr[0][0]=0;
			if($this->is_always_back($this->back))$this->arr[0][1]-=$this->back;
			else $this->arr[0][1]=0;
		}
		
		#check of a step next
		elseif($this->next){
			if($this->is_history_next($this->next))$this->arr[0][0]+=$this->next;
			else $this->arr[0][0]=count($this->arr[1])-1;
			if($this->is_always_next($this->next))$this->arr[0][1]+=$this->next;
			else $this->arr[0][1]=count($this->arr[2])-1;
		}
		
		else{
			$this->_set_history_track_always();
			$this->_set_history_track();
		}
		$arr_history=$this->arr;
	}
	/**
	* Processing URL of page (normal history)
	*
	* @access   private
	*/
	function _set_history_track(){
		#tracking start page
		if(!empty($this->arr_select['start']) and preg_match("'".preg_quote($this->arr_select['start'],"'")."$'",$this->request_uri)){
			$this->arr[1][0]=$this->request_uri;
			$this->arr[0][0]=0;
		}
		
		#if back step
		elseif(
			$this->arr[0][0] and 
			!strcasecmp($this->request_method, 'get') and 
			!strcmp($this->request_uri, $this->arr[1][$this->arr[0][0]-1]) 
			){
			$this->arr[0][0]--;
		}
		
		#if next step
		elseif(
			isset($this->arr[1][$this->arr[0][0]+1]) and 
			!strcasecmp($this->request_method, 'get') and 
			!strcmp($this->request_uri, $this->arr[1][$this->arr[0][0]+1]) 
			){
			$this->arr[0][0]++;
		}
		
		else{
			$this->_skip_processing(
				$this->arr[1],
				$this->arr[0][0],
				$this->request_uri,
				$this->request_query
			);
		}
	}
	/**
	* Processing URL of page (always history)
	*
	* @access   private
	*/
	function _set_history_track_always(){
		#always tracking start page (uncomment if neddet)
		/*
		$always_uri=$this->_cut_back_next_string($this->request_uri);
		if(!empty($this->arr_select['start']) and preg_match("'".preg_quote($this->arr_select['start'],"'")."$'",$always_uri)){
			$this->arr[2][0]=$always_uri;
			$this->arr[0][1]=0;
		}
		else 
		*/
		#if back step
		if(
			$this->is_back_next_param!=1 and 
			$this->arr[0][1] and 
			!strcasecmp($this->request_method, 'get') and 
			!strcmp($this->request_uri, $this->arr[2][$this->arr[0][1]-1]) 
			){
			$this->arr[0][1]--;
		}
		
		#if next step
		elseif(
			$this->is_back_next_param!=1 and 
			isset($this->arr[2][$this->arr[0][1]+1]) and 
			!strcasecmp($this->request_method, 'get') and 
			!strcmp($this->request_uri, $this->arr[2][$this->arr[0][1]+1]) 
			){
			$this->arr[0][1]++;
		}
		
		else{
			#always tracking
			$this->_skip_processing(
				$this->arr[2],
				$this->arr[0][1],
				$this->_cut_back_next_string($this->request_uri),
				$this->_cut_back_next_string($this->request_query)
			);
			#(always) fix dublicate
			if(
				$this->arr[0][1]>0 and 
				count($this->arr[2])==$this->arr[0][1]+1 and 
				!strcmp($this->arr[2][$this->arr[0][1]],$this->arr[2][$this->arr[0][1]-1])
				){
				$this->arr[2]=array_slice($this->arr[2], 0, $this->arr[0][1]);
				$this->arr[0][1]--;
			}
		}
	}
	/**
	* To compare for ignoring or skip
	*
	* @param 	array (string) (history array) 
	* @param 	integer $index (step)
	* @param 	string $request_uri ($REQUEST_URI)
	* @param 	string $request_query ($REQUEST_QUERY)
	* @access   private
	*/
	function _skip_processing(&$arr,&$index,$request_uri,$request_query){
		#ignore itself
		if(!strcmp($request_uri, $arr[$index])){}
		
		#if skip
		elseif(
			!(!$this->arr_select['post'] and strcasecmp($this->request_method, 'get')) and
			!$this->_test_compare(array('\/','(\?|$)'),$this->arr_select['page_full'],$request_uri,$index) and
			!$this->_test_compare(array('(^|\&)','(\=|$)'),$this->arr_select['param_full'],$request_query,$index) and
			!$this->_test_compare(array('\=','(\&|$)'),$this->arr_select['value_full'],$request_query,$index)
			){
			
			#if replace
			$request_q=preg_split("/\?/",$arr[$index]);
			if(
				$this->_test_compare(array('\/','(\?|$)'),$this->arr_select['page_back'],$arr[$index],$index) or
				(isset($request_q[1]) and $this->_test_compare(array('(^|\&)','(\=|$)'),$this->arr_select['param_back'],end($request_q),$index)) or
				(isset($request_q[1]) and $this->_test_compare(array('\=','(\&|$)'),$this->arr_select['value_back'],end($request_q),$index))
				){
				$index--;
			}
			$index++;
			$arr=array_slice($arr, 0, $index+1);
			$arr[$index]=$request_uri;
			
			#if overflow of the array
			if(count($arr)>$this->max_arr){
				$first=array_shift($arr);
				$temp=array_shift($arr);
				array_unshift($arr,$first);
				$index--;
			}
		}
	}
	/**
	* preparation of a array for regular functions
	*
	* @param 	array (string) $arr 
	* @return	boolean (presence or absence of a array)
	* @access   private
	*/
	function _quote(&$arr){
		reset($arr);
        while(list($i,)=each($arr)){
			$arr[$i]=preg_quote($arr[$i], "/");
		}
		return (count($arr)!=0);
	}
	/**
	* Compare
	*
	* @param 	array 
	* @param 	&array $arr_select 
	* @param 	string $source 
	* @return	boolean
	* @access   private
	*/
	function _test_compare($arr_test,$arr_select,&$source,&$index){
		return (
			$index>0 and
			$this->_quote($arr_select) and
			preg_match("/".$arr_test[0]."((".implode(")|(",$arr_select)."))".$arr_test[1]."/",$source)
		);
	}
	function _cut_back_next_string($uri){
		if($this->back or $this->next){
			return preg_replace("/[\?\&]((".preg_quote($this->arr_select['name_back_param'],"/").")|(".preg_quote($this->arr_select['name_next_param'],"/")."))\=\d+$/","",$uri);
		}
		return $uri;
	}
	/**
	* Addition of parameter of step
	*
	* @param 	string $link
	* @param 	string $param
	* @param 	string $value
	* @return	string
	* @access   private
	*/
	function _add_back_param($link,$param,$value){
		if($this->is_back_next_param!=1)return $link;
		if(strrpos($link,'?')===false)return $link.'?'.$param.'='.$value;
		return $link.'&'.$param.'='.$value;
	}
		/**
	* URL for back_step
	*
	* @param	integer $back (back_step)
	* @param	array $arr (history array)
	* @param	integer $index (step)
	* @return	string 
	* @access   private
	*/
	function _get_history_back(&$back,&$arr,&$index){#$this->arr[1],$this->arr[0]
		$back=abs(intval($back));
		if($this->is_history_back($back))return $this->_add_back_param($arr[$index-$back],$this->arr_select['name_back_param'],$back);
		return $this->_add_back_param($arr[0],$this->arr_select['name_back_param'],$back);
	}
	/**
	* URL for next_step
	*
	* @param	integer $next (next_step)
	* @param	array $arr (history array)
	* @param	integer $index (step)
	* @return	string 
	* @access   private
	*/
	function _get_history_next(&$next,&$arr,&$index){#$this->arr[1],$this->arr[0]
		$next=abs(intval($next));
		if($this->is_history_next($next))return $this->_add_back_param($arr[$index+$next],$this->arr_select['name_next_param'],$next);
		return $this->_add_back_param(end($arr),$this->arr_select['name_next_param'],$next);
	}
	/**
	* URL exists?
	*
	* @param	integer $back (back_step)
	* @param	integer $index (step)
	* @return	boolean 
	* @access   private
	*/
	function _is_history_back(&$back,&$index){#$this->arr[0]
		$back=abs(intval($back));
		if($back<=$index)return true;
		return false;
	}
	/**
	* URL exists?
	*
	* @param	integer $next (next_step)
	* @param	array $arr (history array)
	* @param	integer $index (step)
	* @return	boolean 
	* @access   private
	*/
	function _is_history_next(&$next,&$arr,&$index){
		$next=abs(intval($next));
		if($next<count($arr)-$index)return true;
		return false;
	}
	/**
	* URL for back_step
	*
	* @param	integer $back (back_step)
	* @return	string 
	* @access   public
	*/
	function get_history_back($back=1){
		return $this->_get_history_back($back,$this->arr[1],$this->arr[0][0]);
	}
	/**
	* deprecated, see function get_history_back
	*/
	function get_history($back=1){
		return $this->get_history_back($back);
		#or 
		#return $this->get_always_back($back); #exact as in javascript:history.go()
	}
	/**
	* URL for next_step
	*
	* @param	integer $next (next_step)
	* @return	string 
	* @access   public
	*/
	function get_history_next($next=1){
		return $this->_get_history_next($next,$this->arr[1],$this->arr[0][0]);
	}
	/**
	* URL for next or back step
	*
	* @param	integer $go (next or back step), if $go>0 then next_step else back_step
	* @return	string 
	* @access   public
	*/
	function get_history_go($go=-1){
		$go=intval($go);
		return $go>0?$this->_get_history_next($go,$this->arr[1],$this->arr[0][0]):$this->_get_history_back(abs($go),$this->arr[1],$this->arr[0][0]);
	}
	/**
	* URL exists?
	*
	* @param	integer $back (back_step)
	* @return	boolean 
	* @access   public
	*/
	function is_history_back($back=1){
		return $this->_is_history_back($back,$this->arr[0][0]);
	}
	/**
	* URL exists?
	*
	* @param	integer $next (next_step)
	* @return	boolean 
	* @access   public
	*/
	function is_history_next($next=1){
		return $this->_is_history_next($next,$this->arr[1],$this->arr[0][0]);
	}
	/**
	* URL exists?
	*
	* @param	integer $go (next or back step)
	* @return	boolean 
	* @access   public
	*/
	function is_history_go($go=-1){
		$go=intval($go);
		return $go>0?$this->_is_history_next($go,$this->arr[1],$this->arr[0][0]):$this->_is_history_back(abs($go),$this->arr[0][0]);
	}
	/**
	* URL for step to start_page
	*
	* @return	string 
	* @access   public
	*/
	function get_history_backs(){
		return $this->get_history_back($this->max_arr);
	}
	/**
	* URL for step to end_page
	*
	* @return	string 
	* @access   public
	*/
	function get_history_nexts(){
		return $this->get_history_next($this->max_arr);
	}
	/**
	* URL for header_step
	*
	* @return	string 
	* @access   public
	*/
	function get_history_header(){
		$str=current(preg_split("/\?/",$this->request_uri));
		return $str.'?'.$this->arr_select['header_param'];
	}
	
	#######
	#Always step, exact as in javascript:history.go()
	#####################################
	/**
	* URL for "always" back_step
	*
	* @param	integer $back (back_step)
	* @return	string 
	* @access   public
	*/
	function get_always_back($back=1){
		return $this->_get_history_back($back,$this->arr[2],$this->arr[0][1]);
	}
	/**
	* URL for "always" next_step
	*
	* @param	integer $next (next_step)
	* @return	string 
	* @access   public
	*/
	function get_always_next($next=1){
		return $this->_get_history_next($next,$this->arr[2],$this->arr[0][1]);
	}
	/**
	* URL for "always" next or back step
	*
	* @param	integer $go (next or back)
	* @return	string 
	* @access   public
	*/
	function get_always_go($go=-1){
		$go=intval($go);
		return $go>0?$this->_get_history_next($go,$this->arr[2],$this->arr[0][1]):$this->_get_history_back(abs($go),$this->arr[2],$this->arr[0][1]);
	}
	/**
	* URL exists? ("always")
	*
	* @param	integer $back (back_step)
	* @return	boolean 
	* @access   public
	*/
	function is_always_back($back=1){
		return $this->_is_history_back($back,$this->arr[0][1]);
	}
	/**
	* URL exists? ("always")
	*
	* @param	integer $next (next_step)
	* @return	boolean 
	* @access   public
	*/
	function is_always_next($next=1){
		return $this->_is_history_next($next,$this->arr[2],$this->arr[0][1]);
	}
	/**
	* URL exists? ("always")
	*
	* @param	integer $go (next or back)
	* @return	boolean 
	* @access   public
	*/
	function is_always_go($go=-1){
		$go=intval($go);
		return $go>0?$this->_is_history_next($go,$this->arr[2],$this->arr[0][1]):$this->_is_history_back(abs($go),$this->arr[0][1]);
	}
	/**
	* URL for step to start_page
	*
	* @return	string 
	* @access   public
	*/
	function get_always_backs(){
		return $this->get_always_back($this->max_arr);
	}
	/**
	* URL for step to end_page
	*
	* @return	string 
	* @access   public
	*/
	function get_always_nexts(){
		return $this->get_always_next($this->max_arr);
	}
	######################################
	/**
	* Set start page
	*
	* @param	integer $clear (assign 1 to clear history array)
	* @access   public
	*/
	function set_history_start($clear=0){
		if($clear!=0)$_SESSION['history_links'][$this->class_ident][0]=array(0,0);
		
		#If session is lost
		if($this->back or $this->next){
			$param=$this->back?$this->arr_select['name_back_param']:$this->arr_select['name_next_param'];
			$this->request_uri=preg_replace("/[\?\&]".preg_quote($param,"/")."=\d+$/","",$this->request_uri);
		}
		
		if(!empty($this->arr_select['start']))$start=$this->arr_select['start'];
		else $start=$this->request_uri;
		
		if($clear!=0){
			$_SESSION['history_links'][$this->class_ident][1]=array($start);
			$_SESSION['history_links'][$this->class_ident][2]=array($start);
		}
		else{
			$_SESSION['history_links'][$this->class_ident][1][0]=$start;
			$_SESSION['history_links'][$this->class_ident][2][0]=$start;
		}
	}
	/**
	* Get tracker
	*
	* @param	integer $ident (assign 0 to get default, 1 to get "always")
	* @return	integer
	* @access   public
	*/
	function get_history_tracker($ident=0){
		return $_SESSION['history_links'][$this->class_ident][0][intval($ident)];
	}
	/**
	* Get history array
	*
	* @param	integer $ident (assign 0 to get default, 1 to get "always")
	* @return	array
	* @access   public
	*/
	function get_history_array($ident=0){
		return $_SESSION['history_links'][$this->class_ident][intval($ident)+1];
	}
}

?>