<?php
/*
Officity - Web application platform - Version 6.0 - 2011-07-05

François Dispaux, Boris Verdeyen, Thomas Hermant,
Jérémie Roy, Grégory Meurice, Abdelila Harbi, 
Marc Mignonsin, Jonathan Sanchez, Julien Gonzalez, Pierre Fouchez

Sushee and Officity is © Copyright 2011 Nectil SA.

`/sushee/shared/namespace/namespace-processors.class.php` is part of Officity.

Sushee is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

Officity and Sushee are distributed in the hope that they will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with Sushee. If not, see <http://www.gnu.org/licenses/>.
*/
	require_once(dirname(__FILE__).'/../../../sushee/shared/class/AbstractFactoryProcessor.class.php');
	
	/* *** */
	
	class Sushee_NamespaceProcessor extends AbstractFactoryProcessor
	{
		/* PREPROCESSOR : CREATION  */
		
		public function preCreate($data)
		{	
			// clean namespace chars
			$new_namespace = $data->getValue('Namespace');
			$new_namespace = removeaccents($new_namespace);
			$new_namespace = strtolower($new_namespace);
			$new_namespace = preg_replace('/[^a-z]/', '', $new_namespace);
			if (empty($new_namespace))
			{
				return new SusheeProcessorException('Namespace '.$data->getValue('Namespace').' is invalid! Only chars from a to z (lower-case) are authorized.');
			}
			
			$data->setValue('Namespace', $new_namespace);
			
			// 1st: check if unique
			$nql = new Sushee_Shell(false);
			$nql->addCommand('
				<SEARCH>
					<NAMESPACE namespace="'.$new_namespace.'" />
					<RETURN>
						<NOTHING />
					</RETURN>
				</SEARCH>
			');
			$nql->execute();
			if ($nql->valueOf('/RESPONSE/RESULTS/@hits') >= 1)
			{
				return new SusheeProcessorException('Namespace '.$new_namespace.' already exists!');
			}
			
			// 2nd: check if publisher exists => register?
			$nql = new Sushee_Shell(false);
			$nql->addCommand('
				<SEARCH>
					<NECTIL:PUBLISHER namespace="'.$new_namespace.'" />
					<RETURN>
						<NOTHING />
					</RETURN>
				</SEARCH>
			');
			$nql->execute();
			if ($nql->valueOf('/RESPONSE/RESULTS/@hits') >= 1)
			{
				$data->setValue('Registered', 1);
			}
			else
			{
				$data->setValue('Registered', 0);
			}
			
			// 3rd: check environments/packages
			$env_elements = $this->getPublishedEnvironments();
			if (empty($env_elements))
			{
				return new SusheeProcessorException('Cannot retrieve published environments!');
			}
			
			foreach ($env_elements as $env)
			{
				$env_folder_name = $env->valueOf('INFO/FOLDER');
				$editor_folder_path = '/'.$env_folder_name.'/'.$new_namespace;
				
				$editor_folder = new KernelFolder($editor_folder_path);
				if ($editor_folder->exists())
				{
					return new SusheeProcessorException('Folder '.$editor_folder_path.' already exists!');
				}				
				
				$package_path = '/'.$env_folder_name.'/system/packages/editor';
				$package_folder = new KernelFolder($package_path);
				if (!$package_folder->exists())
				{
					return new SusheeProcessorException('Package folder '.$package_path.' not found!');
				}
			}
			
			// 4th: create folders
			$editor_elements = $this->getEditors();
			if (empty($editor_elements))
			{
				return new SusheeProcessorException('Cannot retrieve editors!');
			}
			
			foreach ($env_elements as $env)
			{
				$env_folder_name = $env->valueOf('INFO/FOLDER');
				$package_path = '/'.$env_folder_name.'/system/packages/editor';
				$package_folder = new KernelFolder($package_path);
				
				if (!$package_folder->copy('/'.$env_folder_name))
				{
					return new SusheeProcessorException('Error copying package folder to '.$env_folder_name.'!');
				}
				
				$new_folder_path = '/'.$env_folder_name.'/editor';
				$new_folder = new KernelFolder($new_folder_path);
				if (!$new_folder->rename($new_namespace))
				{
					return new SusheeProcessorException('Error renaming package folder '.$new_folder_path.' to '.$new_namespace.'!');
				}
				
				// update system includers files
				if (($update_result = $this->updateSysIncludersFiles($env_folder_name, $editor_elements, $new_namespace)) !== true)
				{
					return $update_result;
				}
				
				// update editor config file
				if (($update_result = $this->updateEditorConfigFile($env_folder_name, $new_namespace, $data->getValue('Editor'))) !== true)
				{
					return $update_result;
				}
			}
						
			/* execute server commands */
			
			if (($dev_env = $this->getDevEnvironment()) == false)
			{
				return new SusheeProcessorMessage('Development environment not published. No server commands executed.');
			}		
			
			$dev_env_folder = ROOT_PATH.$dev_env->valueOf('INFO/FOLDER').'/';
			$paths = array($dev_env_folder.$new_namespace.'/');
			$return_message = $this->execServerCommands($dev_env->valueOf('INFO/CREATECOMMAND'), $paths, 'Create');
			
			$paths = array(
				$dev_env_folder.'system/config/system.editors.elements.classes.includer.php',
				$dev_env_folder.'system/config/system.editors.elements.definitions.includer.xsl'
			);
			$return_message .= $this->execServerCommands($dev_env->valueOf('INFO/UPDATECOMMAND'), $paths, 'Update');
			
			return new SusheeProcessorMessage($return_message);
		}
		
		/* PREPROCESSOR : UPDATE  */
		
		public function preUpdate($data)
		{	
			// 1st: check NAMESPACE modification
			$new_namespace = $data->getValue('Namespace');
			if ($data->getFormerValue('Namespace') != $new_namespace)
			{
				//$data->setValue('Namespace', $previous_namespace_value);
				return new SusheeProcessorException('Modifiying the NAMESPACE field value is not authorized! Please keep the current value.');
			}	

			// 2nd: check if publisher exists => register?
			$nql = new Sushee_Shell(false);
			$nql->addCommand('
				<SEARCH>
					<NECTIL:PUBLISHER namespace="'.$new_namespace.'" />
					<RETURN>
						<NOTHING />
					</RETURN>
				</SEARCH>
			');
			$nql->execute();
			if ($nql->valueOf('/RESPONSE/RESULTS/@hits') >= 1)
			{
				$data->setValue('Registered', 1);
			}
			else
			{
				$data->setValue('Registered', 0);
			}
			
			// 3rd: check EDITOR modification
			if ($data->getFormerValue('Editor') != $data->getValue('Editor'))
			{
				// update editors configs in all published environments
				$env_elements = $this->getPublishedEnvironments();
				if (empty($env_elements))
				{
					return new SusheeProcessorException('Cannot retrieve published environments!');
				}
				
				foreach ($env_elements as $env)
				{
					$env_folder_name = $env->valueOf('INFO/FOLDER');
					
					// update editor config file
					if (($update_result = $this->updateEditorConfigFile($env_folder_name, $new_namespace, $data->getValue('Editor'))) !== true)
					{
						return $update_result;
					}
				}
				
				/* execute server commands */
				
				if (($dev_env = $this->getDevEnvironment()) == false)
				{
					return new SusheeProcessorMessage('Development environment not published. No server commands executed.');
				}		

				$paths = array(ROOT_PATH.$dev_env->valueOf('INFO/FOLDER').'/'.$new_namespace.'/config/editor.config.php');
				$return_message = $this->execServerCommands($dev_env->valueOf('INFO/UPDATECOMMAND'), $paths, 'Update');
				
				return new SusheeProcessorMessage($return_message);
			}	
			
			return new SusheeProcessorMessage('Update processed');
		}
		
		/* PRE/POSTPROCESSOR : DELETE */
		
		public function preDelete($data)
		{
			// 1st: deletion of all elements in dependency => trigger APP processors
			$nql = new Sushee_Shell(false);
			$nql->addCommand('
				<COUNT>
					<APP>
						<WHERE>
							<DEPENDENCIES>
								<DEPENDENCY type="officity:appNamespaces">
									<NAMESPACE ID="'.$data->getID().'" />
								</DEPENDENCY>
							</DEPENDENCIES>
						</WHERE>
					</APP>
				</COUNT>
			');
			$nql->execute();
			
			// prevent error : KILL will return an error message if there are no applications
			if ($nql->valueOf('/RESPONSE/RESULTS/@hits') > 0)
			{
				$nql->reset();
				$nql->addCommand('
					<KILL>
						<APP>
							<WHERE>
								<DEPENDENCIES>
									<DEPENDENCY type="officity:appNamespaces">
										<NAMESPACE ID="'.$data->getID().'" />
									</DEPENDENCY>
								</DEPENDENCIES>
							</WHERE>
						</APP>
					</KILL>
				');
				$nql->execute();
				$message = $nql->valueOf('/RESPONSE/MESSAGE[@msgType!=0]');
				if (!empty($message))
				{
					return new SusheeProcessorException('Error deleting applications : '.$message);
				}		
			}	
			
			// 2nd: folders deletion
            $namespace = $data->getValue('Namespace');
            
			$env_elements = $this->getPublishedEnvironments();
			if (empty($env_elements))
			{
				return new SusheeProcessorException('Cannot retrieve published environments!');
			}
			
			$editor_elements = $this->getEditors($namespace);
			if (empty($editor_elements))
			{
				return new SusheeProcessorException('Cannot retrieve editors!');
			}		
			
			foreach ($env_elements as $env)
			{
				$env_folder_name = $env->valueOf('INFO/FOLDER');
				$editor_folder_path = '/'.$env_folder_name.'/'.$namespace;
				
				$editor_folder = new KernelFolder($editor_folder_path);
				if ($editor_folder->exists())
				{
					$editor_folder->delete();
					if ($editor_folder->exists())
					{
						return new SusheeProcessorException('Error deleting folder '.$editor_folder_path.'!');
					}
					
					// update system includers files
					if (($update_result = $this->updateSysIncludersFiles($env_folder_name, $editor_elements)) !== true)
					{
						return $update_result;
					}
				}
			}
			
			/* execute server commands */
			
			if (($dev_env = $this->getDevEnvironment()) == false)
			{
				return new SusheeProcessorMessage('Development environment not published. No server commands executed.');
			}		
			
			$dev_env_folder = ROOT_PATH.$dev_env->valueOf('INFO/FOLDER').'/';
			$paths = array($dev_env_folder.$namespace.'/');
			$return_message = $this->execServerCommands($dev_env->valueOf('INFO/DELETECOMMAND'), $paths, 'Delete');
			
			$paths = array(
				$dev_env_folder.'system/config/system.editors.elements.classes.includer.php',
				$dev_env_folder.'system/config/system.editors.elements.definitions.includer.xsl'
			);
			$return_message .= $this->execServerCommands($dev_env->valueOf('INFO/UPDATECOMMAND'), $paths, 'Update');
			
			return new SusheeProcessorMessage($return_message);
		}
		
		public function postDelete($data)
		{	
			// full DB deletion to avoid unique constraint failure in the future
			$ID = $data->getID();
            $sql_query  = "DELETE FROM `namespaces` WHERE `ID` = '$ID' ";
                        
            $db_connection = db_connect();
            if ($db_connection->Execute($sql_query) == false)
            {
                return new SusheeProcessorException($db_connection->ErrorMsg());
            }
            
            return new SusheeProcessorMessage('Deletion post-processed');
		}
		
		// ...
		protected function getEditors($namespace_2_remove=null)
		{
			$nql = new Sushee_Shell(false);
			$nql->addCommand('
				<SEARCH>
					<NAMESPACE />
					<RETURN>
						<INFO>
							<NAMESPACE />
						</INFO>
					</RETURN>
				</SEARCH>
			');
			$nql->execute();
			
			if ($namespace_2_remove != null)
			{
				return $nql->getElements('/RESPONSE/RESULTS/NAMESPACE[INFO/NAMESPACE!="'.$namespace_2_remove.'"]');
			}
			
			return $nql->getElements('/RESPONSE/RESULTS/NAMESPACE');
		}
		
		// ... 
		protected function updateSysIncludersFiles($env_folder_name, $editor_elements, $editor_2_add=null)
		{
			$sys_folder_name = 'system';
			$sys_config_folder_name = 'config';			

			$php_file_name = 'system.editors.elements.classes.includer.php';
			$php_file_path = '/'.$env_folder_name.'/'.$sys_folder_name.'/'.$sys_config_folder_name.'/'.$php_file_name;
			$php_includes = '';

			$xsl_file_name = 'system.editors.elements.definitions.includer.xsl';
			$xsl_file_path = '/'.$env_folder_name.'/'.$sys_folder_name.'/'.$sys_config_folder_name.'/'.$xsl_file_name;
			$xsl_includes = '';
			
			// collect editors includes
			foreach ($editor_elements as $editor)
			{
				$editor_folder = $editor->valueOf('INFO/NAMESPACE');	
				$php_includes .= chr(9)."require_once(dirname(__FILE__).'/../../$editor_folder/shared/shared.elements.classes.php');".PHP_EOL;
				$xsl_includes .= chr(9).'<xsl:import href="../../'.$editor_folder.'/shared/shared.elements.definitions.xsl"/>'.PHP_EOL;
			}
			
			if ($editor_2_add != null)
			{
				$php_includes .= chr(9)."require_once(dirname(__FILE__).'/../../$editor_2_add/shared/shared.elements.classes.php');".PHP_EOL;
				$xsl_includes .= chr(9).'<xsl:import href="../../'.$editor_2_add.'/shared/shared.elements.definitions.xsl"/>'.PHP_EOL;				
			}
			
			// 1st: PHP file
			$php_config_script = "<?php".PHP_EOL.
				chr(9)."/* file automatically generated by the system on ".date('d-m-Y @ H:i:s').' */'.PHP_EOL.
				$php_includes.
			"?>";
					
			$php_file = new KernelFile($php_file_path);			
			$php_file->save($php_config_script);
			if (!$php_file->exists())
			{
				return new SusheeProcessorException('Error updating system config file : '.$php_file_path.' has not been created!');
			}
			
			// 2nd: XSL file
			$xsl_config_script = '<?xml version="1.0" encoding="utf-8"?>'.PHP_EOL.				
				'<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">'.PHP_EOL.
					chr(9).'<!-- file automatically generated by the system on '.date('d-m-Y @ H:i:s').' -->'.PHP_EOL.
					$xsl_includes.
				'</xsl:stylesheet>';
					
			$xsl_file = new KernelFile($xsl_file_path);			
			$xsl_file->save($xsl_config_script);
			if (!$xsl_file->exists())
			{
				return new SusheeProcessorException('Error updating system config file : '.$xsl_file_path.' has not been created!');
			}
			
			return true;
		}
		
		// ...
		protected function updateEditorConfigFile($env_folder, $editor_folder, $editor_name)
		{
			$php_file_name = 'editor.config.php';
			$php_file_path = $env_folder.'/'.$editor_folder.'/config/'.$php_file_name;
			
			$config_script = "<?php".PHP_EOL.
								chr(9)."/* file automatically generated by the system on ".date('d-m-Y @ H:i:s').' */'.PHP_EOL.
								chr(9)."define(".PHP_EOL.
								chr(9).chr(9)."'EDITOR_NAME',".PHP_EOL.
								chr(9).chr(9)."'$editor_name'".PHP_EOL.
								chr(9).");".PHP_EOL.
								chr(9)."define(".PHP_EOL.
								chr(9).chr(9)."'EDITOR_FOLDER',".PHP_EOL.
								chr(9).chr(9)."'$editor_folder'".PHP_EOL.
								chr(9).");".PHP_EOL.
								"?>";
			
			$php_file = new KernelFile($php_file_path);
			$php_file->save($config_script);
			if (!$php_file->exists())
			{
				return new SusheeProcessorException('Error updating editor config file : '.$php_file_path.' has not been created!');
			}
			
			return true;
		}
	}
?>