<?php
/*
	Aquí conrolamos las sesiones de la web
	@version 1.0
*/

class SuperSesion{
	
	private static $valores = array();
	private static $modificada = array();
	private static $alta = array();
	private static $borrada = array();
	private static $hashSesion = '';
	private static $reloadPage = false; //Si esta variable se pone a true, la web se recarga cuando se ejecuta webStore
	private static $sesionUpdated = false;
	//Esta función no necesita constructor ni destructor, los dejamos así por ahora
	function __construct(){
		
	}
	function __destruct() {

	}
	
	public static function getHashSesion(){
		//Si no está seteado lo cogemos de las cookies
		if (self::$hashSesion == NULL){
			self::$hashSesion = static::getCookieValue('hashSesion');
		}
		//Si en este punto seguimos sin hash es porque no está seteado y no se ha cogido de las cookies
		//Vamos a generar uno nuevo
		if (self::$hashSesion == NULL){
			//El hash de la sesión es nulo, hay que crearlo:
			self::$hashSesion = self::newHashSesion();
		}else{
			//Si el hash de la sesión no empieza por "webStore" entonces algo falla:
			if (substr(self::$hashSesion, 0, strlen(PALABRA)) != PALABRA){
				self::$hashSesion = self::newHashSesion();
			}
		}
		return(self::$hashSesion);
	}
	
	private static function newHashSesion(){
		self::$hashSesion = PALABRA . bin2hex(openssl_random_pseudo_bytes(24));
		//A las cookies de webStore les vamos a dar un poco más de tiempo de vida
		$tiempoVida = (Shop::$configuracion->segundos_sesion > 0) ? (time() + Shop::$configuracion->segundos_sesion) : 0;
		//echo("El tiempo de vida es: $tiempoVida<br />\n");
		//echo(time() . "<br />\n");
		//echo(Shop::$configuracion->segundos_sesion . "<br />\n");
		setcookie('hashSesion', self::$hashSesion, $tiempoVida, '/');
		return(self::$hashSesion);
	}
	
	//Vamos a definir el get y el set_error_handler
	public static function get($nombreVariable, $defaultValue = NULL){
		$retorno = $defaultValue;
		if (isset(self::$valores[$nombreVariable])){
			if (self::$borrada[$nombreVariable] == 0){
				$retorno = self::$valores[$nombreVariable];
			}
		}
		return($retorno);
	}
	public static function set($nombreVariable, $valor){
		if (!isset(self::$valores[$nombreVariable])){
			self::$alta[$nombreVariable] = 1;
			self::$modificada[$nombreVariable] = 0;
			self::$borrada[$nombreVariable] = 0;
		}else{
			self::$modificada[$nombreVariable] = 1;
			self::$alta[$nombreVariable] = 0;
			self::$borrada[$nombreVariable] = 0;
		}
		self::$valores[$nombreVariable] = $valor;
		self::$sesionUpdated = true;
	}
	
	public static function remove($nombreVariable){
		if (isset(self::$valores[$nombreVariable])){
			self::$modificada[$nombreVariable] = 0;
			self::$alta[$nombreVariable] = 0;
			self::$borrada[$nombreVariable] = 1;
			self::$sesionUpdated = true;
		}
	}
	
	public static function commit(){
		//include('comunes/globals.php');
		$hashSesion = self::getHashSesion();
		$sesionUpdated = self::$sesionUpdated;
		$bd = new BaseDatos();
		//Si hay conexión con la base de datos y hemos recibido un hash, entonces actualizamos
		if ( ($bd->isConectado()) && ($hashSesion != '' && $sesionUpdated) ){
			//Aquí vamos a hacer una macro update y/o insert y a ejecutarla
			$coma = '';
			$lista_elementos = '';
			$coma_borrado = '';
			$lista_borrar = '';
			foreach(self::$valores as $clave => $valor){
				if ((self::$modificada[$clave]) || (self::$alta[$clave])){
					//Serializamos el valor para guardarlo
					$valor = addslashes(serialize($valor));
					$lista_elementos .= $coma . '("' . $hashSesion . '", "' . $clave . '", "' . $valor . '", CURRENT_TIMESTAMP())';
					$coma = ',';
				}
				//Si sólo es borrado, la añadimos a la lista de borrado
				if (self::$borrada[$clave]){
					$lista_borrar .= $coma_borrado . '("' . $hashSesion . '", "' . $clave . '")';
					$coma_borrado = ',';
				}
			}
			//Primero borramos:
			if ($lista_borrar != ''){
				$sentenciaSQL = 'DELETE FROM sesion WHERE (hash, nombre) IN (' . $lista_borrar . ');';
				//echo("$sentenciaSQL\n<br />");
				$bd->setConsultaSQL($sentenciaSQL);
			}
			//Ahora creamos/modificamos
			if ($lista_elementos != ''){
				$sentenciaSQL = 'INSERT INTO sesion (hash, nombre, valor, ultimo_acceso) VALUES ' . $lista_elementos . 
				' ON DUPLICATE KEY UPDATE valor = VALUES(valor), ultimo_acceso = VALUES(ultimo_acceso);';
				//echo("$sentenciaSQL\n<br />");
				$bd->setConsultaSQL($sentenciaSQL);
			}
		}
		unset($bd);
	}
	
	public static function purge(){
		include('comunes/globals.php');
		$hashSesion = self::getHashSesion();
		$bd = new BaseDatos();
		//Si hay conexión con la base de datos y hemos recibido un hash, entonces actualizamos
		if ($bd->isConectado()){
			$sentenciaSQL = 'DELETE FROM sesion WHERE (ultimo_acceso < DATE_ADD(ultimo_acceso, INTERVAL ' . TIEMPO_VIDA_SESION . ');';
			$bd->setConsultaSQL($sentenciaSQL);
		}
		unset($bd);
	}
	
	public static function init(){
		include('comunes/globals.php');
		$hashSesion = self::getHashSesion();
		$objetos_a_serializar = array();
		if ($hashSesion != ''){
			$bd = new BaseDatos();
			$sentenciaSQL = 'SELECT nombre, valor FROM sesion WHERE hash = "' . $hashSesion . '";';
			//echo("$sentenciaSQL\n");
			if ($bd->isConectado()) {
				$bd->setConsultaSQL($sentenciaSQL);
				while ($fila = $bd->getFila()) {
					$nombreVariable = $fila['nombre'];
					$valor = $fila['valor'];
					self::init_value($nombreVariable, unserialize($valor));
				}
			}
			unset($bd);
		}
	}
	private static function init_value($clave, $valor){
		self::$valores[$clave] = $valor;
		self::$alta[$clave] = 0;
		self::$modificada[$clave] = 0;
		self::$borrada[$clave] = 0;
	}
	public static function clean($deleteFromBD = true){
		include('comunes/globals.php');
		if ($deleteFromBD){
			$hashSesion = self::getHashSesion();
			$bd = new BaseDatos();
			if ($bd->isConectado()){
				$sentenciaSQL = 'DELETE FROM sesion WHERE hash = "' . $hashSesion . '";';
				$bd->setConsultaSQL($sentenciaSQL);
			}
			unset($bd);
		}
		$valores = array();
		$modificada = array();
		$alta = array();
		$borrada = array();
		//Regeneramos el hash
		self::$hashSesion = self::newHashSesion();
		
	}
	
	public static function getCookieValue($cookie){
		$retorno = NULL;
		if (isset($_COOKIE[$cookie])){
			$retorno = $_COOKIE[$cookie];
		}
		return($retorno);	
	}

	public static function getReloadPage(){
		return(self::$reloadPage);
	}

	public static function setReloadPage($reload = true){
		self::$reloadPage = $reload;
		return(self::$reloadPage);
	}
	
	public static function reloadPage($url){
		//Cuando se recargue la sesión, debemos hacer un commit de la sesión por si hay cambios no guardados:
		self::commit();
		//Antes de hacer esto vamos a cerrar conexiones con la base de datos
		cerrar_conexion_bd();
		header('location:' . $url);
	}

	//--------------funciones remotas
	public static function remoteSet($data){
		$retorno = new stdClass();
		//Recibimos en data los valores a setear en formato Json
		if (is_object($data)){
			//Si trato como $data como un array puedo sacar los pares de "variable-valor"
			$retorno->paso = 'vamos a entrar en el bucle';
			foreach($data as $nombreVariable => $valorVaraiable){
				$retorno->$nombreVariable = $valorVaraiable;
				self::set($nombreVariable, $valorVaraiable);
			}
			self::commit();
		}
		return(json_encode($retorno));
	}
	
	public static function remoteGet($variableSet){
		//recibimos el el set de variables los nombres que queremos (array)
		$retorno = new stdClass();
		if (is_object($variableSet)){
			//Si trato como $variableSet como un array puedo sacar los pares de "variable-valor"
			foreach($variableSet as $nombreVariable => $defaultValue){
				$valor = self::get($nombreVariable, $defaultValue);
				$retorno->$nombreVariable = $valor;
			}
		}
		return(json_encode($retorno));
	}

}
?>