<?php
require_once "class-notification.php";

/**
 * Navigation manager
 * 
 * Support for context navigation & persistance of POST and GET data
 * @author tm - Advantis Solutions
 * @version 1.0.1
 * @package Base
 */
class Navigation {
	const LASTKEY = "baknav"; // Tag that specifies to a context script that is a return navigation
	const NEXTKEY = "retnav"; // Tag that specifies toa context where the navigation comes from. For back/cancel navigations.
	const NOTIFKEY = "navigation_notification"; // Tag used in session storage of each context which stores any message to present in present context.
	const TYPEKEY = "navigation_type"; // Tag that defines if the navigation to store or recover should POST or GET
	const CONTEXTKEY = "navigation_ctx"; // Tag that stores the context name to save in the session storage hash of navigations for each context
	const BACKPOSTKEY = "nav_backpost"; // Tag that specifies to a context that the current iteration comes from a self navigation as result of a self action.
	const BACKPOST_TYPE_POST = 'post';
	const BACKPOST_TYPE_GET = 'get';
	
	/**
	 * Stores all the navigation information required for a specific context.
	 *
	 * Used to set navigation context to return info after specific action on another context.
	 * Used also to set navigation context before jumping to another context, preparing the return navigation and subsquently recovering all info status
	 *
	 * SET_STEP should be used after RESOLVE_STEP.
	 *
	 * @param string $contextname        	
	 * @param string $type
	 *        	// use const BACKPOST_TYPE_POST or BACKPOST_TYPE_GET
	 * @param string $notification
	 *        	// use helper functions to get string errors ex : getError ("msg_error_invalid_records_new_cluster" );
	 *        	
	 * @return string //if correctly set should return Tag retnav = contextname to set views properties
	 */
	public static function set_step($contextname, $type, $notification = null) {
		
		// get from the session hash the current navigation info for this context
		$current = Session::get_navigationstep ( $contextname );
		
		// If exists unserialize the object from session
		if (isset ( $current )) {
			$curstep = unserialize ( $current );
		}
		
		// Treatment of navigations type POST
		if ($type == self::BACKPOST_TYPE_POST) {
			$_POST [self::NOTIFKEY] = $notification; // stores notification in $_POST
			$_POST [self::TYPEKEY] = $type; // stores navigation type in $_POST
			                               
			// checks if this navigation results from a postback and mantains the nextkey navigation
			if ($_POST [self::BACKPOSTKEY] == 1 && isset ( $curstep )) {
				$_GET [self::NEXTKEY] = $curstep ['self::NEXTKEY'];
			}
			// In case of the return navigation context is passed via url is process and kept in the POST session storage object
			if (isset ( $_GET [self::NEXTKEY] )) {
				$_POST [self::NEXTKEY] = $_GET [self::NEXTKEY];
			}
			
			$_POST [self::CONTEXTKEY] = $contextname; // stores the context
			                                         
			// serializes $_POST and stores it in the navgation session hash
			Session::add_navigationstep ( serialize ( $_POST ), $contextname );
			
			// returns the string needed to pass to next context, allowing it to know the previous context to return
			return self::NEXTKEY . "=" . $contextname;
		}
		
		// Treatment of navigations type GET
		if ($type == self::BACKPOST_TYPE_GET) {
			$_GET [self::NOTIFKEY] = $notification; // stores notification in $_GET
			$_GET [self::TYPEKEY] = $type; // stores navigation type in $_GET
			$_GET [self::CONTEXTKEY] = $contextname; // stores the context
			                                        
			// checks if this navigation results from a postback and mantains the nextkey navigation
			if ($_POST [self::BACKPOSTKEY] == 1 && isset ( $curstep )) {
				$_GET [self::NEXTKEY] = $curstep ['self::NEXTKEY'];
			}
			
			// serializes $_GET and stores it in the navgation session hash
			Session::add_navigationstep ( serialize ( $_GET ), $contextname );
			
			// returns the string needed to pass to next context, allowing it to know the previous context to return
			return self::NEXTKEY . "=" . $contextname;
		}
		
		// Any other type not supported
		return "";
	}
	
	/**
	 * If the current context navigation has been set to have a return context then it returns the string necessary
	 * to allow a jump location.
	 * Jumps to the specific context with flag backnav=1 to request the recovery of navigation object from session hash
	 *
	 * @param string $contextname
	 *
	 * @return string // ex : context?backnav=1
	 */
	 
	 
	public static function get_backurl($contextname=null) {
		
		$resp = null;
		if (isset ( $_REQUEST [self::NEXTKEY] )) {
			$resp = $_REQUEST [self::NEXTKEY] . "?" . self::LASTKEY . "=1";
		} elseif (isset($contextname)) {
			$current = Session::check_navigationstep ( $contextname );
			if (isset ( $current )) {
				$curstep = unserialize ( $current );
				
				$resp = (isset($curstep [self::NEXTKEY])) ? $curstep [self::NEXTKEY]."?".self::LASTKEY . "=1" : "";
			}
			
		}
		
		return $resp;
	}
	
	/**
	 * Returns the string necessary to allow a jump location.
	 *
	 * Jumps to the specific context by param with flag backnav=1 to request the recovery of navigation object from session hash
	 *
	 * @param string $contextname        	
	 * @return string
	 */
	public static function get_selfbackurl($contextname) {
		return $contextname . "?" . self::LASTKEY . "=1";
	}
	
	/**
	 * Stores all the navigation information required for a specific context.
	 * Used to set navigation context to return info after specific action on another context.
	 * Used also to set navigation context before jumping to another context, preparing the return navigation and subsquently recovering all info status
	 *
	 * RESOLVE_STEP should be used before SET_STEP.
	 *
	 * @param string $contextname
	 *        	// Receives object reference of context class
	 *        	
	 * @return string //if correctly set should return Tag retnav = contextname to set views properties (for back or cancel purposes)
	 */
	public static function resolve_step(&$ocontext) {
		$nav = "";
		
		// checks if there is a navigation for this context by getting it from the session navigation hash
		$current = Session::check_navigationstep ( $ocontext->contextname );
		
		// In case of success unserializes the object as the current step
		if (isset ( $current )) {
			$curstep = unserialize ( $current );
		}
		
		// If the current context received the Backnav TAG = 1 then its a request to navigate back to the current context.
		// And if has a stored navgation info then must restore it
		if ($_GET [self::LASTKEY] == 1 && isset ( $curstep )) {
			if ($curstep [self::NOTIFKEY] != '') { // if has a stored notification then it must be set to the current context object passed by param
				setError ( $ocontext, $curstep [self::NOTIFKEY] );
			}
			// If its a GET navigation type then it restores the object by adding or replacing $_GET keys from the stored object
			if ($curstep [self::TYPEKEY] == self::BACKPOST_TYPE_GET) {
				$_GET = array_replace ( $_GET, $curstep );
			} 			// If its a POST navigation type then it restores the object by adding or replacing $_POST keys from the stored object
			else if ($curstep [self::TYPEKEY] == self::BACKPOST_TYPE_POST) {
				$_POST = array_replace ( $_POST, $curstep );
			}
		}
		
		// If it's a return context and it's a backpost then maintains the same information for return navigation retnav
		if (isset ( $_POST [self::NEXTKEY] ) && $_POST [self::BACKPOSTKEY] == 1 && isset ( $curstep )) {
			$next = $curstep [self::NEXTKEY];
		} else { // Upon entry via POST or GET sets return navigation
			$next = isset ( $_POST [self::NEXTKEY] ) ? $_POST [self::NEXTKEY] : $_GET [self::NEXTKEY];
		}
		
		// If the return navigation was set then returns it to set the view navigation properties
		if (isset ( $next )) {
			
			$nav = $next . "?" . self::LASTKEY . "=1";
		}
		
		return $nav;
	}
	
	
	/**
	 * Gets from $_REQUEST return navigation key
	 * 	  
	 * @return string // ex : retnav=context
	 */
	public static function get_returnkey() {
	
		$resp = null;
		if (isset ( $_REQUEST [self::NEXTKEY] )) {
			$resp = self::NEXTKEY . "=" . $_REQUEST [self::NEXTKEY];
		} 
	
		return $resp;
	}
}

?>