/**
	 * 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;
	}
	/**
	 * Format Errors
	 *
	 * @access protected
	 * @param array $errors list of errors <code>array("error1", "error2")</code>
	 * @param SLS_XMLToolbox $currentXML the current xml
	 * @return SLS_XMLToolbox $currentXML the current xml modified
	 * @since 1.0
	 */
	protected function insertErrors($errors, $currentXML)
	{
		if (!empty($errors))
		{
			$currentXML->startTag("errors");
				foreach ($errors as $error)
					$currentXML->addFullTag("error", $error, true);
			$currentXML->endTag("errors");
		}
		return $currentXML;
	}
	/**
	 * Recursive Fields
	 *
	 * @access private
	 * @param string $xpath the xpath way
	 * @param SLS_XMLToolbox $xml xml object
	 * @return SLS_XMLToolbox $xml xml object
	 * @see SLS_PluginsManager::getFields
	 * @since 1.0
	 */
	private function recursiveFields($xpath, $xml)
	{
		$childs = $this->_pluginXML->getChilds($xpath);
		$fields = array();
		$editField = $this->_generic->getTranslatedController('SLS_Bo', 'EditPluginField');
		foreach ($childs as $child)
		{
			if (array_shift($this->_pluginXML->getTags($xpath."/".$child."/@writable")) == 1)
			{
				$tag = array_shift(explode("[", $child));
				if (key_exists($tag, $fields))
					$fields[$tag]++;
				else 
					$fields[$tag] = 1;
				$xml->startTag('field');
				$xml->addFullTag('tag', $tag, true);
				$xml->addFullTag('path', str_replace("/", "|||", str_replace("]", "|#|", str_replace("[", "#|#", str_replace("//", "", $xpath))))."|||".str_replace("]", "|#|", str_replace("[", "#|#", $child)), true);
				$xml->addFullTag('label', array_shift($this->_pluginXML->getTags($xpath."/".$child."/@label")), true);
				$xml->addFullTag('clonable', (array_shift($this->_pluginXML->getTags($xpath."/".$child."/@clonable")) == '1') ? 'true' : 'false', true);
				if (array_shift($this->_pluginXML->getTags($xpath."/".$child."/@clonable")) == '1')
				{
					$xml->addFullTag('linkAdd', $editField['protocol']."://".$this->_generic->getSiteConfig('domainName')."/".$editField['controller']."/".$editField['scontroller']."/Action/add/Plugin/".$this->_id."/Field/".str_replace("/", "|||", str_replace("]", "|$|", str_replace("[", "$|$", str_replace("//", "", $xpath))))."|||".str_replace("]", "|$|", str_replace("[", "$|$", $child)).".sls", true);
					$xml->addFullTag('linkDel', $editField['protocol']."://".$this->_generic->getSiteConfig('domainName')."/".$editField['controller']."/".$editField['scontroller']."/Action/del/Plugin/".$this->_id."/Field/".str_replace("/", "|||", str_replace("]", "|$|", str_replace("[", "$|$", str_replace("//", "", $xpath))))."|||".str_replace("]", "|$|", str_replace("[", "$|$", $child)).".sls", true);
					
				}
				$xml->addFullTag('index', $fields[$tag], true);
				$xml->addFullTag('value', array_shift($this->_pluginXML->getTags($xpath."/".$child)), true);
				$xml->addFullTag('alias', array_shift($this->_pluginXML->getTags($xpath."/".$child."/@alias")), true);
				$type = (array_shift($this->_pluginXML->getTags($xpath."/".$child."/@type")) == "") ? "part" : array_shift($this->_pluginXML->getTags($xpath."/".$child."/@type"));
				$xml->addFullTag('type', $type, true);
				if ($type == 'select' || $type == "radio" || $type == "check")
				{
					$xml->startTag("values");
						$values = explode("|||", array_shift($this->_pluginXML->getTags($xpath."/".$child."/@values")));
						foreach ($values as $value)
							$xml->addFullTag('value', $value, true);
					$xml->endTag("values");
				}
				
				if ($this->_pluginXML->countChilds($xpath."/".$child) > 0)
					$xml = $this->recursiveFields($xpath."/".$child, $xml);
				
				$xml->endTag('field');
			}
		}
		
		return $xml;
	}	
	/**
	 * Format the notifications
	 * 
	 * @param SLS_XMLToolbox $xml the XML object
	 * @return SLS_XMLToolbox the XML updated
	 */
	public function formatNotif($xml)
	{	
		$notifications = $this->_session->getParam("SLS_BO_NOTIFICATIONS");
		if (empty($notifications))
			$notifications = array("success" 		=> array(),
								   "warning" 		=> array(),
								   "error" 			=> array(),
								   "information" 	=> array());
			
		$xml->startTag("notifications");
		foreach($notifications as $type => $msgs)
		{
			$msgs = (is_array($msgs)) ? $msgs : array($msgs);
			foreach($msgs as $msg)
				$xml->addFullTag("notification",$msg,true,array("type"=>$type));
		}
		$xml->endTag("notifications");
		
		$this->_session->delParam("SLS_BO_NOTIFICATIONS");
		
		return $xml;
	}
	public function action()
	{
		$user 	= $this->hasAuthorative();
		$xml 	= $this->getXML();
		$xml	= $this->makeMenu($xml);
		$reload = $this->_http->getParam("reload");
		$action = $this->_http->getParam("Action");
		$errors = array();
		$slsXml = $this->_generic->getCoreXML('sls');
		$syncServer = array_shift($slsXml->getTags("slsnetwork"));
		$slsVersion = array_shift($slsXml->getTags("version"));
		$edit = $this->_generic->getTranslatedController('SLS_Bo', 'EditPlugin');		
		$editAppli = $this->_generic->getTranslatedController('SLS_Bo', 'CreatePlugin');		
		
		$pluginsXML = $this->_generic->getPluginXml("plugins");
		// List own Plugins
		if ($action == "")
		{
			$deleteController = $this->_generic->getTranslatedController("SLS_Bo", "DeletePlugin");
			if (($count = count($pluginsXML->getTags("//plugins/plugin[@beta='1']"))) > 0)
			{
				$xml->startTag("own_plugin");
					for($i=1;$i<=$count;$i++)
					{
						$id = array_shift($pluginsXML->getTags("//plugins/plugin[@beta='1'][".$i."]/@id"));
						$xml->startTag("plugin", array("code"=>array_shift($pluginsXML->getTags("//plugins/plugin[@beta='1'][".$i."]/@code")),"id"=>$id));
						$xml->addFullTag("description", array_shift($pluginsXML->getTags("//plugins/plugin[@beta='1'][".$i."]/description")), true);
						$xml->addFullTag("custom", array_shift($pluginsXML->getTags("//plugins/plugin[@beta='1'][".$i."]/@customizable")), true);
						$xml->addFullTag("edit", $edit['protocol']."://".$this->_generic->getSiteConfig('domainName')."/".$edit['controller']."/".$edit['scontroller']."/Plugin/".$id.".sls", true);
						$xml->addFullTag("name", array_shift($pluginsXML->getTags("//plugins/plugin[@beta='1'][".$i."]/name")), true);
						$xml->addFullTag("delete", $deleteController['protocol']."://".$this->_generic->getSiteConfig("domainName")."/".$deleteController['controller']."/".$deleteController['scontroller']."/Plugin/".$id.".sls", true);
						$xml->addFullTag("editAppli", $editAppli['protocol']."://".$this->_generic->getSiteConfig("domainName")."/".$editAppli['controller']."/".$editAppli['scontroller']."/Plugin/".$id."/Action/Edit.sls", true);						
						$xml->endTag("plugin");
						
					}
				$xml->endTag("own_plugin");
			}
			$this->registerLink("CREATE", "SLS_Bo", "CreatePlugin", array("Action"=>"Create"));
			$xml->addFullTag("step", "list", true);
		}
		// Create a new Plugin
		elseif ($action == "Create")
		{
			if ($reload == "true")
			{
				$name = SLS_String::trimSlashesFromString($this->_http->getParam("name"));
				$code = SLS_String::stringToUrl(strtolower(SLS_String::getSafeFilename(SLS_String::trimSlashesFromString($this->_http->getParam("code")))), "", true);
				$output = SLS_String::trimSlashesFromString($this->_http->getParam("output"));
				$custom = SLS_String::trimSlashesFromString($this->_http->getParam("custom"));
				$path = SLS_String::trimSlashesFromString($this->_http->getParam("path"));
				$pathName = SLS_String::stringToUrl(SLS_String::getSafeFilename(ucwords(SLS_String::trimSlashesFromString($this->_http->getParam("code")))), "", false);
				$description = SLS_String::trimSlashesFromString($this->_http->getParam("full_description"));
				
				// Get Plugins Versions
				$serversJSON = @file_get_contents($syncServer);
				$pluginsAvailable = array();
				$filesReserved = array();
				$dirsReserved = array();
				if ($serversJSON !== false && !empty($serversJSON))
				{					
					$servers = json_decode($serversJSON);
					$pluginsServers = $servers->servers->plugins;
					$plugins = array();
					
					foreach ($pluginsServers as $pluginsServer)
					{						
						$serverContent = @file_get_contents($pluginsServer->url);
						if ($serverContent !== false && !empty($serverContent))
						{
							$serverContent = json_decode($serverContent);
							$plugs = $serverContent->plugins;
							foreach ($plugs as $plug)
							{
								$pluginsAvailable[] = $plug->code;
								if ($plug->type == 'file')
									$filesReserved[] = $plug->path;
								else 
									$dirsReserved[] = $plug->path;
							}
						}
					}
				}
				
				$xml->startTag("form");
					$xml->addFullTag("name", $name, true);
					$xml->addFullTag("code", $code, true);
					$xml->addFullTag("custom", $custom, true);
					$xml->addFullTag("path", $path, true);
					$xml->addFullTag("path_name", $pathName, true);
					$xml->addFullTag("fill_description", $description, true);
					if (empty($name))
						$errors[] = "You must fill the common name";
					if (empty($code))
						$errors[] = "You must fill the code name";
					if (empty($output) || ($output != 'yes' && $output != 'no'))
						$errors[] = "Choose if your plugin is an output type";
					if (empty($custom) || ($custom != 'yes' && $custom != 'no'))
						$errors[] = "Choose if your plugin will be customizable";
					if (empty($path) || ($path != 'file' && $path != 'dir'))
						$errors[] = "Choose if your plugin require only a file or multiple files in a directory";	
					if (empty($pathName))
						$errors[] = "You must choose a filename or a directory name";	
					if (empty($description))
						$errors[] = "You must fill the full description in English";	
					if (empty($errors))
					{
						if (in_array($code, $pluginsAvailable))
							$errors[] = "This code name is already in use for another plugin";
						if ($path == 'file' && in_array($pathName.".class.php", $filesReserved))
							$errors[] = "This file name is already in use for another plugin";
						if ($path == 'dir' && in_array($pathName, $dirsReserved))
							$errors[] = "This directory name is already in use for another plugin";
						
						if (empty($errors))
						{
							
							$newId = md5(uniqid($this->_generic->getSiteConfig("privateKey")));
							$pathFile = $this->_generic->getPathConfig("plugins");
							if ($path =="dir")
								$pathFile .= $pathName."/";
							
							if ($output == 'no')
							{
								$str = '<?php'."\n".
										'/**'."\n".
										' * Plugin '.$name."\n". 
										' * '.str_replace("<br />", "\\n * ", nl2br($description))."\n".
										' *'."\n".
										' * @package Plugins'."\n".
										' * @since 1.0'."\n".
										' */'."\n". 
										'class '.$pathName.' extends SLS_PluginGeneric implements SLS_IPlugin'."\n".
										'{'."\n".
										t(1).'public function __construct()'."\n".
										t(1).'{'."\n".
											t(2).'parent::__construct($this);'."\n".
											t(2).'$this->checkDependencies();'."\n".
										t(1).'}'."\n\n".
										t(1).'public function checkDependencies()'."\n".
										t(1).'{'."\n".
										t(1).'}'."\n".
										'}'."\n".
										'?>';
							}
							else 
							{
								$str = '<?php'."\n".
										'/**'."\n".
										' * Plugin '.$name."\n". 
										' * '.str_replace("<br />", "\\n * ", nl2br($description))."\n".
										' *'."\n".
										' * @package Plugins'."\n".
										' * @since 1.0'."\n".
										' */'."\n". 
										'class '.$pathName.' extends SLS_PluginGeneric implements SLS_IPlugin, SLS_IPluginOutput'."\n".
										'{'."\n".
										t(1).'public function __construct()'."\n".
										t(1).'{'."\n".
											t(2).'parent::__construct($this);'."\n".
											t(2).'$this->checkDependencies();'."\n".
										t(1).'}'."\n\n".
										t(1).'public function checkDependencies()'."\n".
										t(1).'{'."\n".
										t(1).'}'."\n".
										'}'."\n".
										'?>';
							}
							
							if (@file_put_contents($pathFile.$pathName.".class.php", $str) === false)
								$errors[] = "Plugin Creation failed";
									
							
							if (empty($errors))
							{
								if ($custom == "yes")
								{
									$str = "<?xml version=\"1.0\" encoding=\"utf-8\"?><plugin><exemple_part writable=\"1\" label=\"Exemple Part\" clonable=\"1\" alias=\"main\"><exemple_row writable=\"1\" label=\"Exemple Row\" type=\"string\" clonable=\"0\" /></exemple_part></plugin>";
									if (@file_put_contents($this->_generic->getPathConfig("configPlugins").$newId."_".$code.".xml", $str) === false)
										$errors[] = "Plugin Creation failed";
								}
								
							}
							if (empty($errors))
							{
								$newPlugin = new SLS_XMLToolbox(false);
								$newPlugin->startTag("plugin", array(
									"beta"=>"1",
									"code"=>$code,
									"id"=>$newId,
									"version"=>"0.1",
									"compability"=>$slsVersion,
									"customizable"=>($custom=="yes")?"1":"0",
									"output"=>($output=="yes")?"1":"0",
									"file"=>($path=="file")?"1":"0",
									"path"=>($path=="file")?$pathName.".class.php" : $pathName
								));
								$newPlugin->addFullTag("name", $name, true);
								$newPlugin->addFullTag("description", $description, true);
								$newPlugin->addFullTag("author", "Me", true);
								$newPlugin->addFullTag("dependencies", "", false);
								$newPlugin->endTag("plugin");
								$pluginsXML->appendXMLNode("//plugins", $newPlugin->getXML('noHeader'));
								file_put_contents($this->_generic->getPathConfig("configPlugins")."plugins.xml", $pluginsXML->getXML());
								$this->goDirectTo("SLS_Bo", "CreatePlugin");
							}
							
						}
						
					}
					
				$xml->endTag("form");
			}
			$xml->addFullTag("step", "create", true);
		}
		elseif ($action == "Edit")
		{
			
			$pluginID = $this->_http->getParam("Plugin");
			if (SLS_PluginsManager::isExists($pluginID) === false)
				$this->goDirectTo("SLS_Bo", "CreatePlugin");
			
			$originalPlugin = new SLS_PluginsManager($pluginID);
				
			if ($reload == "true")
			{
				
				$name = SLS_String::trimSlashesFromString($this->_http->getParam("name"));
				$code = SLS_String::stringToUrl(strtolower(SLS_String::getSafeFilename(SLS_String::trimSlashesFromString($this->_http->getParam("code")))), "", true);
				$output = SLS_String::trimSlashesFromString($this->_http->getParam("output"));
				$custom = SLS_String::trimSlashesFromString($this->_http->getParam("custom"));
				$path = SLS_String::trimSlashesFromString($this->_http->getParam("path"));
				$pathName = SLS_String::stringToUrl(SLS_String::getSafeFilename(ucwords(SLS_String::trimSlashesFromString($this->_http->getParam("code")))), "", false);
				$description = SLS_String::trimSlashesFromString($this->_http->getParam("full_description"));
				
				// Get Plugins Versions
				$serversJSON = @file_get_contents($syncServer);
				$pluginsAvailable = array();
				$filesReserved = array();
				$dirsReserved = array();
				if ($serversJSON !== false && !empty($serversJSON))
				{					
					$servers = json_decode($serversJSON);
					$pluginsServers = $servers->servers->plugins;
					$plugins = array();
					
					foreach ($pluginsServers as $pluginsServer)
					{						
						$serverContent = @file_get_contents($pluginsServer->url);
						if ($serverContent !== false && !empty($serverContent))
						{
							$serverContent = json_decode($serverContent);
							$plugs = $serverContent->plugins;
							foreach ($plugs as $plug)
							{
								$pluginsAvailable[] = $plug->code;
								if ($plug->type == 'file')
									$filesReserved[] = $plug->path;
								else 
									$dirsReserved[] = $plug->path;
							}
						}
					}
				}
				
				$xml->startTag("form");
					$xml->addFullTag("name", $name, true);
					$xml->addFullTag("code", $code, true);
					$xml->addFullTag("custom", $custom, true);
					$xml->addFullTag("path", $path, true);
					$xml->addFullTag("path_name", $pathName, true);
					$xml->addFullTag("fill_description", $description, true);
					if (empty($name))
						$errors[] = "You must fill the common name";
					if (empty($code))
						$errors[] = "You must fill the code name";
					if (empty($output) || ($output != 'yes' && $output != 'no'))
						$errors[] = "Choose if your plugin is an output type";
					if (empty($custom) || ($custom != 'yes' && $custom != 'no'))
						$errors[] = "Choose if your plugin will be customizable";
					if (empty($path) || ($path != 'file' && $path != 'dir'))
						$errors[] = "Choose if your plugin require only a file or multiple files in a directory";	
					if (empty($pathName))
						$errors[] = "You must choose a filename or a directory name";	
					if (empty($description))
						$errors[] = "You must fill the full description in English";	
					if (empty($errors))
					{
						if ($code != $originalPlugin->_code && in_array($code, $pluginsAvailable))
							$errors[] = "This code name is already in use for another plugin";
						if ($pathName.".class.php" != $originalPlugin->_path && $path == 'file' && in_array($pathName.".class.php", $filesReserved))
							$errors[] = "This file name is already in use for another plugin";
						if ($pathName != $originalPlugin->_path && $path == 'dir' && in_array($pathName, $dirsReserved))
							$errors[] = "This directory name is already in use for another plugin";
						if (empty($errors))
						{
							if ($originalPlugin->_file == 1 && $path == 'dir')
							{
								if (!is_dir($this->_generic->getPathConfig("plugins").$originalPlugin->_path))
									mkdir($this->_generic->getPathConfig("plugins").$pathName);
								if (is_file($this->_generic->getPathConfig("plugins").$originalPlugin->_path))
									@unlink($this->_generic->getPathConfig("plugins").$originalPlugin->_path);
								
							}
							if ($originalPlugin->_file == 0 && $path == 'file')
							{
								if (is_dir($this->_generic->getPathConfig("plugins").$originalPlugin->_path))
									$this->_generic->rm_recursive($this->_generic->getPathConfig("plugins").$originalPlugin->_path);
								if ($output == 'no')
								{
									$str = '<?php'."\n".
											'/**'."\n".
											' * Plugin '.$name."\n". 
											' * '.str_replace("<br />", "\\n * ", nl2br($description))."\n".
											' *'."\n".
											' * @package Plugins'."\n".
											' * @since 1.0'."\n".
											' */'."\n". 
											'class '.$pathName.' extends SLS_PluginGeneric implements SLS_IPlugin'."\n".
											'{'."\n".
											t(1).'public function __construct()'."\n".
											t(1).'{'."\n".
												t(2).'parent::__construct($this);'."\n".
												t(2).'$this->checkDependencies();'."\n".
											t(1).'}'."\n\n".
											t(1).'public function checkDependencies()'."\n".
											t(1).'{'."\n".
											t(1).'}'."\n".
											'}'."\n".
											'?>';
								}
								else 
								{
									$str = '<?php'."\n".
											'/**'."\n".
											' * Plugin '.$name."\n". 
											' * '.str_replace("<br />", "\\n * ", nl2br($description))."\n".
											' *'."\n".
											' * @package Plugins'."\n".
											' * @since 1.0'."\n".
											' */'."\n". 
											'class '.$pathName.' extends SLS_PluginGeneric implements SLS_IPlugin, SLS_IPluginOutput'."\n".
											'{'."\n".
											t(1).'public function __construct()'."\n".
											t(1).'{'."\n".
												t(2).'parent::__construct($this);'."\n".
												t(2).'$this->checkDependencies();'."\n".
											t(1).'}'."\n\n".
											t(1).'public function checkDependencies()'."\n".
											t(1).'{'."\n".
											t(1).'}'."\n".
											'}'."\n".
											'?>';
								}
								
								if (@file_put_contents($this->_generic->getPathConfig("plugins").$pathName.".class.php", $str) === false)
									$errors[] = "Plugin Creation failed";
							}
							if ($originalPlugin->_file == 1 && $path == 'file' && $pathName.".class.php" != $originalPlugin->_path)
							{
								if (is_file($this->_generic->getPathConfig("plugins").$originalPlugin->_path))
									rename($this->_generic->getPathConfig("plugins").$originalPlugin->_path, $this->_generic->getPathConfig("plugins").$pathName.".class.php");
							}
							if ($originalPlugin->_file == 0 && $path == 'dir' && $pathName != $originalPlugin->_path)
							{
								if (is_dir($this->_generic->getPathConfig("plugins").$originalPlugin->_path))
									rename($this->_generic->getPathConfig("plugins").$originalPlugin->_path, $this->_generic->getPathConfig("plugins").$pathName);
							}
							if (empty($errors))
							{
								if ($custom == "yes" && $originalPlugin->_customizable == false)
								{
									$str = "<?xml version=\"1.0\" encoding=\"utf-8\"?><plugin><exemple_part writable=\"1\" label=\"Exemple Part\" clonable=\"1\" alias=\"main\"><exemple_row writable=\"1\" label=\"Exemple Row\" type=\"string\" clonable=\"0\" /></exemple_part></plugin>";
									if (@file_put_contents($this->_generic->getPathConfig("configPlugins").$originalPlugin->_id."_".$code.".xml", $str) === false)
										$errors[] = "Plugin Creation failed";
								}
								if ($custom == "no" && $originalPlugin->_customizable == true)
								{
									if (is_file($this->_generic->getPathConfig("configPlugins").$originalPlugin->_id."_".$originalPlugin->_code.".xml"))
										unlink($this->_generic->getPathConfig("configPlugins").$originalPlugin->_id."_".$originalPlugin->_code.".xml");
								}
								
							}
							if (empty($errors))
							{
								if ($code != $originalPlugin->_code)
								{
									$pluginsXML->setTagAttributes("//plugins/plugin[@beta='1' and @id='".$pluginID."']", array("code"=>$code));
									if (is_file($this->_generic->getPathConfig("configPlugins").$originalPlugin->_id."_".$originalPlugin->_code.".xml"))
										rename($this->_generic->getPathConfig("configPlugins").$originalPlugin->_id."_".$originalPlugin->_code.".xml", $this->_generic->getPathConfig("configPlugins").$originalPlugin->_id."_".$code.".xml");
								}
								if (($output == "yes" && $originalPlugin->_output == 0) || ($output == "no" && $originalPlugin->_output == 1))
									$pluginsXML->setTagAttributes("//plugins/plugin[@beta='1' and @id='".$pluginID."']", array("output"=>($output=="yes")?"1":"0"));
								if (($custom == "yes" && $originalPlugin->_customizable == false) || ($custom == "no" && $originalPlugin->_customizable == true))
									$pluginsXML->setTagAttributes("//plugins/plugin[@beta='1' and @id='".$pluginID."']", array("customizable"=>($custom=="yes")?"1":"0"));
								if (($originalPlugin->_file == 1 && $path == 'dir') || ($originalPlugin->_file == 0 && $path == 'file'))
									$pluginsXML->setTagAttributes("//plugins/plugin[@beta='1' and @id='".$pluginID."']", array("file"=>($path=="file")?"1":"0"));
								if (($path == 'file' && $originalPlugin->_path != $pathName.".class.php") || ($path == 'dir' && $originalPlugin->_path != $pathName))
									$pluginsXML->setTagAttributes("//plugins/plugin[@beta='1' and @id='".$pluginID."']", array("path"=>($path=="file")?$pathName.".class.php" : $pathName));
								if ($originalPlugin->_name != $name)
									$pluginsXML->setTag("//plugins/plugin[@beta='1' and @id='".$pluginID."']/name", $name, true);
								if ($originalPlugin->_description != $description)
									$pluginsXML->setTag("//plugins/plugin[@beta='1' and @id='".$pluginID."']/description", $description, true);
								
								file_put_contents($this->_generic->getPathConfig("configPlugins")."plugins.xml", $pluginsXML->getXML());
								$this->goDirectTo("SLS_Bo", "CreatePlugin");
							}
							
						}
						
					}
					
				$xml->endTag("form");
			}
			$originalPlugin = new SLS_PluginsManager($pluginID);
			$xml->startTag("plugin");
				$xml->addFullTag("name", $originalPlugin->_name, true);
				$xml->addFullTag("code", $originalPlugin->_code, true);
				$xml->addFullTag("output", ($originalPlugin->_output == 1)?"yes":"no", true);
				$xml->addFullTag("custom", ($originalPlugin->_customizable)?"yes":"no", true);
				$xml->addFullTag("path", ($originalPlugin->_file==1)?'file':'dir', true);
				$xml->addFullTag("path_name", ($originalPlugin->_file==1)?SLS_String::substrBeforeLastDelimiter($originalPlugin->_path, ".class.php"):$originalPlugin->_path, true);
				$xml->addFullTag("fill_description", $originalPlugin->_description, true);
			$xml->endTag("plugin");
			$xml->addFullTag("step", "edit", true);
		}
		
		if (!empty($errors))
		{
			$xml->startTag("errors");
			foreach ($errors as $error)
				$xml->addFullTag("error", $error, true);
			$xml->endTag("errors");
		}
		
		$this->saveXML($xml);		
	}
	public function action()
	{
		$user 	= $this->hasAuthorative();
		$xml = $this->makeMenu($this->getXML());
		$slsXml = $this->_generic->getCoreXML('sls');
		$errors = array();
		$syncServer = array_shift($slsXml->getTags("slsnetwork"));
		$action = $this->_http->getParam('Action');
		$serverID = $this->_http->getParam("Server");
		$pluginID = $this->_http->getParam("Plugin");
		$this->registerLink("CREATE", "SLS_Bo", "CreatePlugin");
		$controllers = $this->_generic->getTranslatedController('SLS_Bo', 'SearchPlugin');
		
		$serversJSON = @file_get_contents($syncServer);
		if ($serversJSON === false ||empty($serversJSON))
			$errors[] = "You are not connected to internet or synchronisation server is temporaly unavailable";
		else 
		{			
			$servers = json_decode($serversJSON);
			$pluginsServers = $servers->servers->plugins;
			$plugins = array();
			
			$xml->startTag("servers");
			
			foreach ($pluginsServers as $pluginsServer)
			{				
				$serverContent = @file_get_contents($pluginsServer->url);				
				
				$xml->startTag("server", array("name"=>$pluginsServer->name,"id"=>$pluginsServer->id));
					$xml->addFullTag("url", $pluginsServer->url, true, array("status"=>($serverContent === false || empty($serverContent)) ? "0" : "1"));

					if ($serverContent !== false && !empty($serverContent))
					{
						$serverContent = json_decode($serverContent);
						
						
						$xml->startTag("plugins");
						$plugs = $serverContent->plugins;
						foreach ($plugs as $plug)
						{
							
							// If we want to download this Plugin
							if ($action == "Download" && $pluginsServer->id == $serverID && $plug->id == $pluginID)
							{
								$way = $this->_http->getParam('Way');
								$pluginXML = $this->_generic->getPluginXml("plugins");
								if (count($pluginXML->getTags("//plugins/plugin[@id = '".$plug->id."']")) == 0 && count($pluginXML->getTags("//plugins/plugin[@code = '".$plug->code."' and @beta='1']")) == 0)
								{
									if (SLS_Remote::remoteFileExists($plug->file) != 0)
										$errors[] = $plug->name." is unavailable";
									else 
									{
										$filename = $this->_generic->getPathConfig("coreTmpDownload")."Plugins/".SLS_String::substrAfterLastDelimiter($plug->file, "/");
										if (!is_dir($this->_generic->getPathConfig("coreTmpDownload")."Plugins"))
											mkdir($this->_generic->getPathConfig("coreTmpDownload")."Plugins");
										$result = @copy($plug->file, $filename);
										if ($result === false)
											$errors[] = "The download of ".$plug->name." has failed";
										else 
										{
											$tar = new SLS_Tar();
											if ($tar->openTAR($filename) === false)
												$errors[] = "Plugin archive is corrupted";
											else 
											{
												$hasConf = false;
												$isFile = true;
												$pathName = "";
												foreach ($tar->directories as $directory)
												{
													if (SLS_String::startsWith($directory['name'], "Sources/"))
													{
														$dirName = SLS_String::substrAfterFirstDelimiter($directory['name'], "Sources/");
														if (!empty($dirName))
														{
															if (!is_dir($this->_generic->getPathConfig("plugins").$dirName))
																mkdir($this->_generic->getPathConfig("plugins").$dirName);
															if (empty($pathName))
																$pathName = (strpos($dirName, "/") !== false) ? SLS_String::substrBeforeLastDelimiter($dirName, "/") : $dirName;
															
															$isFile = false;
														}
													}
												}
												
												foreach ($tar->files as $file)
												{
													
													$copy = true;
													if (SLS_String::startsWith($file['name'], "Configs/") && SLS_String::endsWith($file['name'], ".xml"))
													{
														$hasConf = true;
														$copy = @file_put_contents($this->_generic->getPathConfig("configPlugins").$plug->id."_".$plug->code.".xml", $file['file']);
													}
													if (SLS_String::startsWith($file['name'], 'Sources/'))
													{
														if ($isFile === true && $pathName == "")
															$pathName = SLS_String::substrAfterFirstDelimiter($file['name'], "Sources/");
														$realPathFile = $this->_generic->getPathConfig("plugins").SLS_String::substrAfterFirstDelimiter($file['name'], "Sources/");
														$copy = @file_put_contents($realPathFile, $file['file']);
													}
													if ($copy === false)
													{
														$errors[] = "The copy of ".$file['name']." has failed";
													}
												}
												
												if (empty($errors))
												{
													$newPlugin = new SLS_XMLToolbox(false);
													$newPlugin->startTag("plugin", array("code"=>$plug->code,"id"=>$plug->id,"version"=>$plug->version,"compability"=>$plug->compability,"customizable"=>($hasConf) ? "1" : "0","file"=>($isFile)?"1":"0","path"=>$pathName));
														$newPlugin->addFullTag("name", $plug->name, true);
														$newPlugin->addFullTag("description", $plug->desc, true);
														$newPlugin->addFullTag("author", $plug->author, true);
														$newPlugin->addFullTag("dependencies", "", false);
													$newPlugin->endTag("plugin");
													$pluginXML->appendXMLNode("//plugins", $newPlugin->getXML('noHeader'));
													file_put_contents($this->_generic->getPathConfig("configPlugins")."plugins.xml", $pluginXML->getXML());
												}
												if (is_file($filename))
													unlink($filename);
											}
										}
									}
								}
								if ($way == "Maj")
								{
									$this->goDirectTo("SLS_Bo", "Plugins");
								}
								
							}//  /If we want to download this Plugin
							
							// We list all Plugins available on this server
							$exist = SLS_PluginsManager::isExists($plug->id);
							if ($exist)
							{
								$plugin = new SLS_PluginsManager($plug->id);
							}
							$xml->startTag("plugin", array("version"=>$plug->version,"code"=>$plug->code,"id"=>$plug->id,"compability"=>((float)$plug->compability<=(float)array_shift($slsXml->getTags("version"))) ? "1" : "0","has"=>($exist)?"1":"0"));
							$xml->addFullTag("name", $plug->name, true);
							$xml->addFullTag("doc", $pluginsServer->domain.$plug->doc, true);
							$xml->addFullTag("dl", $controllers['protocol']."://".$this->_generic->getSiteConfig("domainName")."/".$controllers['controller']."/".$controllers['scontroller']."/Action/Download/Server/".$pluginsServer->id."/Plugin/".$plug->id.".sls");
							$xml->addFullTag("desc", $plug->desc, true);
							$xml->addFullTag("author", $plug->author, true);
							$xml->endTag("plugin");
						}
						$xml->endTag("plugins");
					}
					
				$xml->endTag("server");
			}
			$xml->endTag("servers");
		}
		if (!empty($errors))
		{
			$xml->startTag("errors");
			foreach ($errors as $error)
				$xml->addFullTag("error", $error, true);
			$xml->endTag("errors");
		}		
		$this->saveXML($xml);
	}