/**
	 * Constructor
	 *
	 * @access protected
	 * @param object $plugin the plugin object
	 * @since 1.0
	 */
	protected function __construct($plugin)
	{
		$this->_className = get_class($plugin);
		$this->_code = strtolower($this->_className);
		$pluginsXML = SLS_PluginsManager::returnPluginsXML();
		if (count($pluginsXML->getTags("//plugins/plugin[@code='".$this->_code."']/@id")) == 0)
			SLS_Tracing::addTrace(new Exception("Cannot find plugin Configuration for ".$this->_className));				
		else 
		{
			$this->_id = array_shift($pluginsXML->getTags("//plugins/plugin[@code='".$this->_code."']/@id"));
			$this->_pluginManager = new SLS_PluginsManager($this->_id);
			$this->_xml = $this->_pluginManager->getXML();
			$this->_version = $this->_pluginManager->_version;
		}
	}
	/**
	 * Action Home
	 *
	 */
	public function action() 
	{
		$coreXML = $this->_generic->getCoreXML('sls');
		$serverPres = $coreXML->getTags("//sls_configs/prerequies/server[@name='apache']/mod");
		$apache = apache_get_modules();
		foreach ($serverPres as $serverPre)
		{
			if (!in_array($serverPre, $apache))
				SLS_Tracing::addTrace(new Exception("You need apache module: ".$serverPre));
		}
		$phpPres = $coreXML->getTags("//sls_configs/prerequies/php/mod");
		$php = get_loaded_extensions();
		foreach ($phpPres as $phpPre)
		{
			if (!in_array($phpPre, $php))
				SLS_Tracing::addTrace(new Exception("You need PHP Extension : ".$phpPre));
		}
		$this->_generic->registerLink('dircheck', 'SLS_Init', 'DirRights');		
	}
	public function action()
	{
		$user 	= $this->hasAuthorative();
		$tpls 	= $this->getAppTpls();
		
		$tpl = SLS_String::trimSlashesFromString($this->_http->getParam("name"),"_");
		
		if (in_array($tpl,$tpls))
		{
			try {
				unlink($this->_generic->getPathConfig("viewsTemplates").$tpl.".xsl");
			}
			catch (Exception $e)
			{
				SLS_Tracing::addTrace($e);
			}
		}
		
		$this->_generic->goDirectTo("SLS_Bo","Templates");
	}	
	/**
	 * Constructor, start the session
	 *
	 * @access public
	 * @param bool $remote true if you want to access sillysmart in a isolated way like web-services, else false (default)
	 * @since 1.0
	 */
	public function __construct($remote=false)
	{
		$domainSession = SLS_Generic::getInstance()->getSiteConfig("domainSession");
		
		// If we have a session sharing between domains
		if (!empty($domainSession))
		{
			try
			{
				ini_set("session.cookie_domain",$domainSession);
			}
			catch (Exception $e)
			{
				SLS_Tracing::addTrace($e);
			}
		}
		
		// If not a remote access
		if (!$remote && PHP_SAPI !== 'cli')
			session_start();
	}
	public function action()
	{
		$user = $this->hasAuthorative();
		$xml = $this->getXML();
		$xml = $this->makeMenu($xml);
		$langs = $this->_generic->getObjectLang()->getSiteLangs();
		$listing = true;
		$errors = array();
		$controllersXML = $this->_generic->getControllersXML();
		$controller = SLS_String::trimSlashesFromString($this->_http->getParam('Controller'));
		
		if ($controller != 'Home' && $controller != 'Default')
		{
		// We want to delete the controller
		
			$controllers = $controllersXML->getTags("//controllers/controller[@side='user' and @name='".$controller."']");
			if (count($controllers) == 1)
			{
				$controllerId = array_shift($controllersXML->getTags("//controllers/controller[@side='user' and @name='".$controller."']/@id"));
				// Delete all files
				// Views Header
				(is_dir($this->_generic->getPathConfig("viewsHeaders").$controller)) ? $this->_generic->rm_recursive($this->_generic->getPathConfig("viewsHeaders").$controller) : SLS_Tracing::addTrace(new Exception("Directory ".$this->_generic->getPathConfig("viewsHeaders").$controller." cannot be removed"));
				// Views Body
				(is_dir($this->_generic->getPathConfig("viewsBody").$controller)) ? $this->_generic->rm_recursive($this->_generic->getPathConfig("viewsBody").$controller) : SLS_Tracing::addTrace(new Exception("Directory ".$this->_generic->getPathConfig("viewsBody").$controller." cannot be removed"));
				// Langs
				(is_dir($this->_generic->getPathConfig("actionLangs").$controller)) ? $this->_generic->rm_recursive($this->_generic->getPathConfig("actionLangs").$controller) : SLS_Tracing::addTrace(new Exception("Directory ".$this->_generic->getPathConfig("actionLangs").$controller." cannot be removed"));
				// Delete controller Directory
				(is_dir($this->_generic->getPathConfig("actionsControllers").$controller)) ? $this->_generic->rm_recursive($this->_generic->getPathConfig("actionsControllers").$controller) : SLS_Tracing::addTrace(new Exception("Directory ".$this->_generic->getPathConfig("actionsControllers").$controller." cannot be removed"));
				// Delete XML Informations
				$controllersXML->deleteTags("//controllers/controller[@side='user' and @name='".$controller."']");
				file_put_contents($this->_generic->getPathConfig('configSecure')."controllers.xml", $controllersXML->getXML());
				$metasXML = $this->_generic->getCoreXML('metas');
				$metasXML->deleteTags("//sls_configs/action[@id='".$controllerId."']");
				file_put_contents($this->_generic->getPathConfig('configSls')."metas.xml", $metasXML->getXML());
			}
		}
		$this->_generic->forward('SLS_Bo', 'Controllers');
		$this->saveXML($xml);
	}
	/**
	 * Get the stack tracing of the exception	 
	 *
	 * @access public static
	 * @param array $trace trace array recovered at the Exception raise
	 * @param bool $html if we want a HTML render (version dev)
	 * @return array $stack strack tracing shaped (html or plain)
	 * @since 1.0
	 */
	public static function stackTracing($trace,$html=false)
	{
		$stack = array();						
		foreach ($trace as $k => $line) 
		{
			$callInfo = ($k < count($trace) - 1) ? SLS_Tracing::getTraceInfo($trace[$k + 1],$html) : "";
			$stack[$k]["call"] = $callInfo . ' (' .basename($line['file']) .':'.$line['line'].')';
			$stack[$k]["file"] = 'in file '.$line['file'].' at line '.$line['line'];
		}
		return $stack;
	}
    /**
     * Open the smtp connection, call the server and authenticate (optional)     
     * 
     * @access public    
     * @since 1.0
     */
	public function openConnection() 
	{
		// If it doesn't already have a smtp connexion open
	  	if (empty($this->server) && !empty($this->hostname))
		{
			try {
				$this->server = fsockopen($this->hostaddr,$this->smtpport);
			}
			catch (Exception $e)
			{
				SLS_Tracing::addTrace($e);
			}
			
	  		// Open log file
	   		$this->openLogFile();
		    	
		  	fputs($this->server,"HELO {$this->hostname}\r\n");      
		  	
		  	// Log smtp response
	  		$response = $this->readAndLogServerResponse('CONNECT:'.' IP: '.$this->hostaddr.', PORT: '.$this->smtpport,-1);
			        		
			if(substr($response,0,3) != "220")
	  			return $this->error("Could not connect to SMTP server.");
			  
	  		// Log smtp response
	  		$this->readAndLogServerResponse('HELO:',-1);
		  
	  		if ($this->login != "" && $this->password != "")
	  		{      
			    fputs($this->server,"AUTH LOGIN\r\n");
			    // Log smtp response
			    $this->readAndLogServerResponse('AUTH LOGIN:'******'LOGIN:'******'PASS:',-1);      
	  		}		
		}
	}
	/**
	 * Check if is valid date
	 *
	 * @access public static	 
	 * @param string $month the month number
	 * @param string $day the day number
	 * @param string $year the year
	 * @return bool $valid true if yes, else false
	 * @see SLS_Date::isDate
	 * @see SLS_Date::isDateTime
	 * @see SLS_Date::isTimestamp
	 * @since 1.0
	 * @example 
	 * var_dump(SLS_Date::isValidDate("04","12","1972"));
	 * // will produce : true
	 * @example 
	 * var_dump(SLS_Date::isValidDate("02","29","1995"));
	 * // will produce : false
	 */
	public static function isValidDate($month,$day,$year)
	{
		try 
		{
			return checkdate(intval($month),intval($day),intval($year));
		}
		catch (Exception $e)
		{
			SLS_Tracing::addTrace($e);
			return false;
		}
	}
	/**
	 * Return status & informations regarding one or more table
	 *
	 * @access public
	 * @param string $table the table to list
	 * @return array $infos array of table(s) informations
	 * @since 1.0
	 */
	public function showTables($table=false) 
	{	
		if (!$this->checkConnexion())
			return false;	
		
		$return = array();
		$currentDbHost = $this->_generic->getDbConfig("base",$this->_currentDb);
		$session = $this->_generic->getObjectSession();
		$dbInfos = $session->getParam("sls_db_infos");
		
		if (empty($dbInfos))
			$dbInfos = array();
		if (!empty($dbInfos) && is_array($dbInfos) && array_key_exists($this->_currentDb,$dbInfos))
		{
			if ($table === false)
				$return = $dbInfos[$this->_currentDb];
			else
			{
				$tables = $dbInfos[$this->_currentDb];
				for($i=0 ; $i<$count=count($tables) ; $i++)
				{
					if ($tables[$i]->Name == $table) 
					{
						$return = $tables[$i];
						break;
					}
				}
			}
		}
		else	
		{
			$this->_generic->_time_checkpoint = microtime(true);
			
			$sql =  "SHOW "."\n".
					"    TABLE STATUS "."\n".
					"FROM "."\n".
					"    `".$currentDbHost."` ";
			
			try
			{
				$tables = $this->select($sql);
				$dbInfos[$this->_currentDb] = $tables;
				$session->setParam("sls_db_infos",$dbInfos);
			}
			catch (Exception $e)
			{
				SLS_Tracing::addTrace($e,true);
				return false;
			}
			
			for($i=0 ; $i<$count=count($tables) ; $i++)
			{
				if ($table === false) 			
					$return[] = $tables[$i];			
				else  
				{
					if ($tables[$i]->Name == $table) 
					{
						$return = $tables[$i];
						break;
					}
				}				
			}
			
			$this->_generic->logTime($this->_generic->monitor($this->_generic->_time_checkpoint),"MySQL Query SHOW_TABLE_STATUS","Query: ".$sql,"MySQL Query");
		}
		
		return $return;
	}
	/**
	 * Set the current template you want to use with your action
	 *
	 * @access public
	 * @param string $tpl the template name
	 * @return bool $set true if ok, else false
	 * @see SLS_Generic::getCurrentTpl
	 * @since 1.0.1
	 */
	public function setCurrentTpl($tpl)
	{
		$templates = array();
		
		$handle = opendir($this->getPathConfig(($this->_side == "user") ? "viewsTemplates" : "coreViewsTemplates"));
		while($file = readdir($handle))
		{
			if (is_file($this->getPathConfig(($this->_side == "user") ? "viewsTemplates" : "coreViewsTemplates").$file) && substr($file, 0, 1) != ".")
			{
				$fileName 	= SLS_String::substrBeforeLastDelimiter($file,".");
				$extension 	= SLS_String::substrAfterLastDelimiter($file,".");
				
				if ($extension == "xsl")
					array_push($templates,$fileName);
			}
		}
		closedir($handle);
		
		if (in_array($tpl,$templates))
		{
			$this->_currentTpl = $tpl;
			return true;
		}
		else
		{			
			SLS_Tracing::addTrace(new Exception("Warning: you choose an unknown template ('".$tpl."')"));
			return false;
		}
	}
	/**
	 * Load & call the statics XSL (Head or Body)
	 *
	 * @access private
	 * @param string $type 'headers' or 'body'
	 * @return string xslCode the xsl code to invoke
	 * @since 1.0
	 */
	private function loadStaticsXsl($type="headers") 
	{
		if ($type != "headers" && $type != "body" && $type != "coreHeaders" && $type != "coreBody")
			SLS_Tracing::addTrace(new Exception("Warning, incorrect argument in loadStaticsXsl() View.class.php"));
		
		$string = "";
		
		foreach ($this->_staticsXsl['loaded'][$type]['name'] as $templateName)
		{
			if (!empty($templateName))
				$string .= "<xsl:call-template 
								name=\"".$templateName."\" />\n";
		}
		return $string;
	}
	/**
	 * Check if a recordset described by a column doesn't already exists
	 *
	 * @access public
	 * @param string $column the column name
	 * @param string $value the column value
	 * @param string $table the table to check (current table model if empty)
	 * @param string $excludedColumn the column name to exclude
	 * @param string $excludedValue the column value to exclude
	 * @return bool $isUnique true if no recordset has been found, else false
	 * @since 1.0
	 */
	public function isUnique($column,$value,$table,$excludedColumn="",$excludedValue="")
	{
		$sql = "SELECT "."\n".
				"    COUNT(*) AS total "."\n".
				"FROM "."\n".
				"    `".$this->_table."` "."\n".
				"WHERE "."\n".
				"    `".$column."` = ".$this->_db->quote($value)." "."\n";
		if ($this->_isMultilanguage)
			$sql .= "    AND `pk_lang` = ".$this->_db->quote($this->_modelLanguage)." "."\n";
		if (!empty($excludedColumn) && !empty($excludedValue))		
			$sql .= "    AND `".$excludedColumn."` != ".$this->_db->quote($excludedValue)." "."\n";		
		try
		{
			$result =  array_shift($this->_db->select($sql));
			return $result->total;
		}
		catch (Exception $e)
		{			
			SLS_Tracing::addTrace($e,true);
			return false;
		}
	}
	/**
	 * Call the action's function
	 * 
	 * @access public
	 * @param string $path the controllers path
	 * @since 1.0
	 */
	public function loadScontroller($path)
	{		
		// If the file exist
		if (is_file($this->_generic->getPathConfig($path).$this->_generic->getGenericControllerName()."/".$this->_scontroller.".controller.php"))
		{
			$controllerName = $this->_generic->getGenericControllerName().$this->_scontroller;
			if (is_file($this->_generic->getPathConfig($path)."__site.protected.php"))
				include_once($this->_generic->getPathConfig($path)."__site.protected.php");
			else 
				SLS_Tracing::addTrace(new Exception("A generic File is missing '__site.protected.php' for the current Action. Controller: '".$this->_generic->getGenericControllerName()."' ; Action : '".$this->_scontroller."'"));			
			
			if (is_file($this->_generic->getPathConfig($path).$this->_generic->getGenericControllerName()."/"."__".$this->_generic->getGenericControllerName().".protected.php"))
				include_once($this->_generic->getPathConfig($path).$this->_generic->getGenericControllerName()."/"."__".$this->_generic->getGenericControllerName().".protected.php");
			else
				SLS_Tracing::addTrace(new Exception("A generic File is missing '__".$this->_generic->getGenericControllerName().".protected.php' for the current Action. Controller: '".$this->_generic->getGenericControllerName()."' ; Action : '".$this->_scontroller."'"));			
			
			$url = strtolower(SLS_String::substrBeforeFirstDelimiter($_SERVER['SERVER_PROTOCOL'],'/')).'://'.$_SERVER['HTTP_HOST'].'';
			foreach($this->_generic->getObjectHttpRequest()->getParams() as $key => $value)				
				$url .= ((is_string($value)) ? ((!in_array($key,array('mode','smode'))) ? '/'.$key : '').'/'.$value : '');
			
			if (PHP_SAPI !== 'cli')
			{
				$robots = $this->_generic->getCoreXML('metas')->getTag("//sls_configs/action[@id='".$this->_generic->getActionId()."']/robots");
				header("X-Robots-Tag: ".$robots, true);
			}
				
			include_once($this->_generic->getPathConfig($path).$this->_generic->getGenericControllerName()."/".$this->_scontroller.".controller.php");
			$this->_runningController = new $controllerName();
			$this->_generic->logTime($this->_generic->monitor($this->_generic->_time_checkpoint),"Resolve Mapping (".$this->_generic->getGenericControllerName()."/".$this->_generic->getGenericScontrollerName().")","Url: ".$url.'.'.$this->_generic->getSiteConfig("defaultExtension")."|n|".str_replace("[","|t| |t|[",(string)print_r($this->_generic->getObjectHttpRequest()->getParams(),true)),"Controller Front");
						
			// Sls cached enabled and Action cache enabled ?
			$runAction = true;
			$cacheOptions = $this->_cache->getAction();
			if ($this->_generic->isCache() && 
				$this->_generic->getSide() == "user" &&				   
				$this->_generic->getGenericControllerName() != "Default" &&
				is_array($cacheOptions) && 
				count($cacheOptions) == 4)
			{
				$actionCacheVisibility 	= $cacheOptions[0];
				$actionCacheScope 		= $cacheOptions[1];
				$actionCacheResponsive  = $cacheOptions[2];
				$actionCacheExpiration 	= $cacheOptions[3];
				
				// Get partial xml action cache
				if ($actionCacheScope == "partial" && false !== ($actionCached = $this->_cache->getCachePartial($actionCacheExpiration,"action","action_".SLS_String::substrAfterFirstDelimiter($this->_generic->getActionId(),"a_"),$actionCacheVisibility,$actionCacheResponsive)))
					$runAction = false;
			}
			
			if ($runAction)
			{
				$this->_generic->_time_checkpoint = microtime(true);		
				$this->_runningController->init();
				$this->_generic->logTime($this->_generic->monitor($this->_generic->_time_checkpoint),"Executing Init","","Controller Init");
				$this->_generic->_time_checkpoint = microtime(true);
				$this->_runningController->action();
				$this->_generic->logTime($this->_generic->monitor($this->_generic->_time_checkpoint),"Executing Action","","Controller Action");
			}
		}
		
		// Reset sls_db_infos in session
		$this->_generic->getObjectSession()->delParam("sls_db_infos");
	}
	/**
	 * Return all parameters (GET, POST or FILES)
	 *
	 * @access public	 
	 * @param string $type the type you want ('ALL','POST','GET','FILES')
	 * @return array $params array of all paramters
	 * @since 1.0
	 * @example 
	 * var_dump($this->_http->getParams());
	 * // will produce :
	 * array(
  	 * 		"mode"		=> "Home",
  	 * 		"smode"		=> "Welcome",
  	 * 		"..."		=> "..."
	 * )
	 */
	public function getParams($type='all') 
	{
		$type = strtoupper($type);
		if ($type != 'ALL' && $type != 'POST' && $type != 'GET' && $type != 'FILES')
			SLS_Tracing::addTrace(new Exception("To use the method SLS_HttpRequest::getParams(), you need to specify a correct type of value ('all', 'post', 'get' or 'files')"));
		else
		{
			if ($type == 'ALL') 
				return $this->_params;
			elseif ($type == 'POST')			
				return $_POST;
			elseif ($type == 'GET')
			{
				$params = $_GET;
			
				// Strip extension if exists		
				if (SLS_String::endsWith($params['smode'], SLS_Generic::getInstance()->getSiteConfig('defaultExtension')))		
					$params['smode'] = SLS_String::substrBeforeLastDelimiter($params['smode'], '.'.SLS_Generic::getInstance()->getSiteConfig('defaultExtension'));
				// Get smode        
				$explode = explode("/", $params['smode']);
				$params['smode'] = array_shift($explode);		
				// Transform url in classic queryString '?param1=value1&param2=value2...'
				$queryString = "";
				$params = array_chunk($explode, 2);		
				for($i=0 ; $i<$count=count($params) ; $i++)		
					if (count($params[$i]) == 2)
						$queryString .= (($i == 0) ? '' : '&').$params[$i][0].'='.(($params[$i][1] != "|sls_empty|") ? $params[$i][1] : "");		
				// Get all params/values
				parse_str($queryString,$params);		
				if (!empty($params))
				{
					foreach($params as $key => $value)
						$params[$key] = $value;
				}				
				return $params;
			}			
			elseif ($type == 'FILES')
				return $_FILES;
			else 
				return $this->_params;
		}
	}
    /**
     * Create directories recursivly based on path
     * 
     * @access public static
     * @param string $fileName path to file (strip after the last /)
     * @return bool true if created, else false
     * @since 1.0.9
     */
    public static function createDir($fileName)
    {
    	$directories = explode("/",$fileName);		
		array_pop($directories);
    	if (!file_exists(implode("/",$directories)))
    	{
    		try {    	
				@mkdir(implode("/",$directories),0777,true);
    		}
			catch (Exception $e) {
				SLS_Tracing::addTrace($e);
			}
    	}
    }
	/**
	 * Format XML for the current recordset
	 * 
	 * @access public
	 * @param SLS_XMLToolbox $xml current controller's XML
	 * @param array $options transformations on some columns - delimited by ":". each function can be methods of SLS' classes or php standard function
	 * <code>
     * // Complete example
	 * $xml = $news->toXML($xml, array( "news_excerpt" 	=> array("php:strip_tags", "SLS_String:trimStringToLength:100"),
	 *									"news_date" 	=> array("SLS_Date:getDate:FULL_LITTERAL_TIME", "php:ucwords"),
	 *									"news_photo" 	=> "SLS_String:getUrlFileImg:_0",
	 *									"news_pdf" 		=> "SLS_String:getUrlFile",
	 *									"news_title" 	=> "php:trim",
	 *									"news_link"		=> array("/Item/",
	 *															 "news_title" => "SLS_String:stringToUrl:_",
	 *															 "-",
	 *															 "news_id" => array("php:intval","php:pow:2"),
	 *															 "/User/",
	 *															 "user_id"))
	 *						, true, "news");
	 * </code>    
	 * @param mixed $fks (bool: if true all fks, if false only current Model) - array fks you want to extract params
	 * @param string $nodeName the root node of your model, by default it's your classname in lowercase
	 * @param array $properties all columns/values of your choice if you don't want to take it from getParams() function of the current instance
	 * @return SLS_XMLToolbox $xml current controller's XML updated
	 * @see SLS_FrontModel::getParams
	 * @see SLS_FrontModel::pdoToXML
	 * @since 1.0.8	 
	 */
	public function toXML($xml,$options=array(),$fks=false,$nodeName="",$properties=array())
	{
		$nodeName 	= (empty($nodeName)) ? strtolower($this->getTable()) : $nodeName;
		$properties = (empty($properties)) ? $this->getParams($fks) : $properties;
		
		$xml->startTag($nodeName);
		foreach($properties as $column => $value)
		{
			if (in_array($column,$columns=array_keys($options)))
			{
				$filters = (is_array($options[$column])) ? $options[$column] : array($options[$column]);
				
				foreach($filters as $filter)
				{
					$option = explode(":",$filter);
					switch($option[0])
					{
						case SLS_String::startsWith($option[0],"SLS_"):
							if (!class_exists($option[0]))
								SLS_Tracing::addTrace(new Exception("Error: you want to use an undefined class `".$option[0]."` for the column `".$column."` of `".$this->getTable()."` table"));
							else
							{
								if (!method_exists($option[0],((count($option)> 1) ? $option[1] : "")))
									SLS_Tracing::addTrace(new Exception("Error: you want to use an undefined function `".$option[1]."` of class `".$option[0]."` for the column `".$column."` of `".$this->getTable()."` table"));
								else
								{
									$ref = new ReflectionMethod($option[0],$option[1]);
									$nbRequiredParams = $ref->getNumberOfRequiredParameters();
									if ($nbRequiredParams > (count($option)-1))									
										SLS_Tracing::addTrace(new Exception("Error: function `".$option[1]."` of class `".$option[0]."` needs ".$nbRequiredParams." required parameters for the column `".$column."` of `".$this->getTable()."` table"),true);
									else
									{										
										$params = array_slice($option,2);
										array_unshift($params,$value);
										
										// Case "SLS_Date::getDate"
										if ($option[0] == "SLS_Date" && $option[1] == "getDate")
										{											
											$option[0] = new SLS_Date($value);
											array_shift($params);											
										}
										// Case "SLS_String::getUrlFileImg"
										if ($option[0] == "SLS_String" && $option[1] == "getUrlFileImg" && count($option) > 2)
										{
											$xml->addFullTag($column."_original",SLS_String::getUrlFile($value,(count($option) > 3) ? $option[3] : ""),true);
											$column = $column.$option[2];											
										}
										
										$value = $ref->invokeArgs(($ref->isStatic()) ? null : $option[0],$params);
										
									}									
								}	
							}	
							break;				
						case "php":
							if (count($option) < 2)
								SLS_Tracing::addTrace(new Exception("Error: you must specify the name of the PHP's function you want to apply on the column `".$column."` of `".$this->getTable()."` table"));
							else
							{
								if (function_exists($option[1]))
								{
									$ref = new ReflectionFunction($option[1]);
									$nbRequiredParams = $ref->getNumberOfRequiredParameters();
									if ($nbRequiredParams > (count($option)-1))									
										SLS_Tracing::addTrace(new Exception("Error: the PHP's function `".$option[1]."` needs ".$nbRequiredParams." required parameters for the column `".$column."` of `".$this->getTable()."` table"),true);
									else
									{
										$params = array_slice($option,2);
										array_unshift($params,$value);
										$value = $ref->invokeArgs($params);
									}
								}
								else
									SLS_Tracing::addTrace(new Exception("Error: the PHP's function '".$option[1]."' you want to use on the column `".$column."` of `".$this->getTable()."` table doesn't exist"));
							}
							break;
						default:
							SLS_Tracing::addTrace(new Exception("Error: you want to apply an unknown filter on the column `".$column."` of `".$this->getTable()."` table doesn't exist"));
							break;
					}
				}
			}
			$xml->addFullTag($column,$value,true);
		}		
		foreach($options as $col => $concat)
		{
			if (!in_array($col,array_keys($properties)) && is_array($concat))
			{
				$values = array();				
				foreach($concat as $column => $filter)
				{
					if (is_int($column) && !empty($filter) && !is_array($filter))
					{
						$column = $filter;
						$filter = "";
					}
					$value = "";
					$filters = (is_array($filter)) ? $filter : ((empty($filter)) ? "" : array($filter));					
					if (in_array($column,array_keys($properties)))
						$value .= $properties[$column];
					else
						$value .= $column;
					
					if (!empty($filters))
					{
						foreach($filters as $filter)
						{
							$option = explode(":",$filter);
							
							switch($option[0])
							{
								case SLS_String::startsWith($option[0],"SLS_"):
									if (!class_exists($option[0]))
										SLS_Tracing::addTrace(new Exception("Error: you want to use an undefined class `".$option[0]."` for the column `".$column."` of `".$this->getTable()."` table"));
									else
									{
										if (!method_exists($option[0],((count($option)> 1) ? $option[1] : "")))
											SLS_Tracing::addTrace(new Exception("Error: you want to use an undefined function `".$option[1]."` of class `".$option[0]."` for the column `".$column."` of `".$this->getTable()."` table"));
										else
										{
											$ref = new ReflectionMethod($option[0],$option[1]);
											$nbRequiredParams = $ref->getNumberOfRequiredParameters();
											if ($nbRequiredParams > (count($option)-1))									
												SLS_Tracing::addTrace(new Exception("Error: function `".$option[1]."` of class `".$option[0]."` needs ".$nbRequiredParams." required parameters for the column `".$column."` of `".$this->getTable()."` table"),true);
											else
											{										
												$params = array_slice($option,2);
												array_unshift($params,$value);
												
												// Case "SLS_Date::getDate"
												if ($option[0] == "SLS_Date" && $option[1] == "getDate")
												{											
													$option[0] = new SLS_Date($value);
													array_shift($params);											
												}
												// Case "SLS_String::getUrlFileImg"
												if ($option[0] == "SLS_String" && $option[1] == "getUrlFileImg" && count($option) > 2)
												{
													$xml->addFullTag($column."_original",SLS_String::getUrlFile($value),true);
													$column = $column.$option[2];											
												}
												
												$value = $ref->invokeArgs(($ref->isStatic()) ? null : $option[0],$params);
												
											}									
										}	
									}	
									break;				
								case "php":
									if (count($option) < 2)
										SLS_Tracing::addTrace(new Exception("Error: you must specify the name of the PHP's function you want to apply on the column `".$column."` of `".$this->getTable()."` table"));
									else
									{
										if (function_exists($option[1]))
										{
											$ref = new ReflectionFunction($option[1]);
											$nbRequiredParams = $ref->getNumberOfRequiredParameters();
											if ($nbRequiredParams > (count($option)-1))									
												SLS_Tracing::addTrace(new Exception("Error: the PHP's function `".$option[1]."` needs ".$nbRequiredParams." required parameters for the column `".$column."` of `".$this->getTable()."` table"),true);
											else
											{
												$params = array_slice($option,2);
												array_unshift($params,$value);
												$value = $ref->invokeArgs($params);
											}
										}
										else
											SLS_Tracing::addTrace(new Exception("Error: the PHP's function '".$option[1]."' you want to use on the column `".$column."` of `".$this->getTable()."` table doesn't exist"));
									}
									break;
								default:
									SLS_Tracing::addTrace(new Exception("Error: you want to apply an unknown filter on the column `".$column."` of `".$this->getTable()."` table doesn't exist"));
									break;
							}
						}
					}
					$values[] = $value;
				}
				$xml->addFullTag($col,implode("",$values),true);
			}
		}
		$xml->endTag($nodeName);
		
		return $xml;
	}
	/**
	 * Set The output of your action
	 *
	 * @access protected
	 * @param string $type
	 * @param string $xml the XML String witch be used in case of RSS, ATOM and XML
	 * @since 1.0
	 */
	protected function setOutput($type, $xml=null)
	{
		$type = strtolower($type);
		if ($type != "xhtml" && $type != "xml" && $type != "json" && $type != "rss" && $type != "atom")
			SLS_Tracing::addTrace(new Exception("The type requested is not supported: ".$type));
		if (($type == "rss" || $type == "atom") && is_null($xml))
			SLS_Tracing::addTrace(new Exception("You need to give an XML String to configure your Output ".$type));
		if (!is_null($xml))
			$this->_outputOptions = $xml;
		$this->_output = $type;
	}
	/**
	 * Parse final HTML with SLS_Dtd
	 * 
	 * @access public
	 * @param string $html the HTML content
	 * @return string the HTML content parsed
	 * @since 1.0.8
	 */
	public function parseHtml($html)
	{
		$delimiters = SLS_String::getBoundContent($html,"|||sls:","|||");
		$arraySearch = array();
		$arrayReplace = array();
		
		$dtd = new SLS_Dtd(null);
		
		// Foreach delimiters found, search if we can map a function of SLS_Dtd's class with this delimiter
		foreach($delimiters as $delimiter)
		{
			$dtd_mask = $delimiter;
			$delimiter = explode(":",$delimiter);
			$method = array_shift($delimiter);
			$args = $delimiter;			
			
			$ref = new ReflectionMethod($dtd,$method);			
			$nbRequiredParams = $ref->getNumberOfRequiredParameters();
			$nbMaxParams = $ref->getNumberOfParameters();
			
			if ($nbRequiredParams > count($args))			
				SLS_Tracing::addTrace(new Exception("Error: Specific SLS_Dtd function `".$method."` needs at least ".$nbRequiredParams." required parameters"),true);
			if ($nbMaxParams < count($args))
				SLS_Tracing::addTrace(new Exception("Warning: Specific SLS_Dtd function `".$method."` has only ".$nbMaxParams." parameters, you call it with ".count($args)." parameters"),true);
			
			if (method_exists($dtd,$method) && $nbRequiredParams <= count($args))
			{
				array_push($arraySearch,"|||sls:".$dtd_mask."|||");
				array_push($arrayReplace,$ref->invokeArgs($dtd,$args));
			}
			else
				SLS_Tracing::addTrace(new Exception("Warning: the delimiter |||sls:".$method."||| doesn't match with any function of class SLS_Dtd"));
		}
		return str_replace($arraySearch,$arrayReplace,$html);
	}