<?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.

`/var/www/installer/public_html/officity-source/apps/officity/shared/environment/environment-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 Officity_EnvironmentProcessor extends AbstractFactoryProcessor
	{
		/* PREPROCESSOR : ACTIVATION/DEACTIVATION/FOLDER NAME UPDATE */	
			
		public function preUpdate($data)
		{	
			// clean folder name
			$new_folder_name = $data->getValue('Folder');
			if (($clean_result = $this->cleanFolderName($new_folder_name)) !== true)
			{
				return $clean_result;
			}
			$data->setValue('Folder', $new_folder_name);
			
			// activation
			if (($data->getFormerValue('Published') == 0) && ($data->getValue('Published') == 1))
			{
				return $this->activate($data);
			}
			// deactivation
			if (($data->getFormerValue('Published') == 1) && ($data->getValue('Published') == 0))
			{
				return $this->deactivate($data);
			}
			
			if ($data->getFormerValue('Folder') != $new_folder_name)
			{
				return $this->folderChange($data, $new_folder_name);
			}			
			return new SusheeProcessorMessage('No activation/deactivation/folder modification requested');
		}
		
		/* folder name modification */
		protected function folderChange($data, $new_folder_name)
		{			
			$former_folder_name = $data->getFormerValue('Folder');
			$former_folder = new KernelFolder('/'.$former_folder_name);
			if (!$former_folder->exists())
			{
				return new SusheeProcessorException('Folder '.$former_folder_name.' does not exist!');
			}
			
			$new_folder = new KernelFolder('/'.$new_folder_name);			
			if ($new_folder->exists())
			{
				return new SusheeProcessorException('Folder '.$new_folder_name.' already exists!');
			}						
			
			if (!$former_folder->rename($new_folder_name))
			{
				return new SusheeProcessorException('Error renaming folder '.$former_folder_name.' to '.$new_folder_name.'!');
			}
			
			// update system config file
			if ($data->getValue('Type') != 'versions')
			{				
				if (($update_result = $this->updateSysConfigFile($new_folder_name, $data->getValue('Type'))) !== true)
				{
					return $update_result;
				}
			}
			
			if ($data->getValue('Type') == 'development')
			{
				/* execute server commands */

				$paths = array(
					'old_path' => ROOT_PATH.$former_folder_name.'/',
					'new_path' => ROOT_PATH.$new_folder_name.'/'
				);
				$return_message = $this->execServerCommands($data->getValue('RenameCommand'), $paths, 'Rename');
				
				return new SusheeProcessorMessage($return_message);
			}
		}
		
		/* retrieve given folder + versions folder (see activate) */
		protected function getRefFolder($type_pub, $type_notpub, &$ref_folder, &$versions_folder)
		{
			$nql = new Sushee_Shell(false);
			$nql->addCommand('
				<SEARCH>
					<OFFICITY:ENVIRONMENT />
					<RETURN>
						<INFO>
							<TYPE />
							<FOLDER />
							<PUBLISHED />
						</INFO>
					</RETURN>
				</SEARCH>
			');
			$nql->execute();
			
			$ref_folder = $nql->getElement('//OFFICITY:ENVIRONMENT[INFO/TYPE="'.$type_pub.'"]');
			if ($ref_folder && $ref_folder->valueOf('INFO/PUBLISHED') == '0')
			{
				$ref_folder = $nql->getElement('//OFFICITY:ENVIRONMENT[INFO/TYPE="'.$type_notpub.'"]');
			}
			
			$versions_folder = $nql->getElement('//OFFICITY:ENVIRONMENT[INFO/TYPE="versions"]');
		}
		
		/* retrieve versions folder */
		protected function getVersionsFolder(&$versions_folder)
		{
			$nql = new Sushee_Shell(false);
			$nql->addCommand('
				<SEARCH>
					<OFFICITY:ENVIRONMENT />
					<RETURN>
						<INFO>
							<TYPE />
							<FOLDER />
							<PUBLISHED />
						</INFO>
					</RETURN>
				</SEARCH>
			');
			$nql->execute();
			
			return $nql->getElement('//OFFICITY:ENVIRONMENT[INFO/TYPE="versions"]');
		}
		
		/* publish versions */
		protected function publishVersions($ver_folder_element)
		{
			if (empty($ver_folder_element))
			{
				return new SusheeProcessorMessage('Warning : cannot retrieve versions folder!');
			}

			// already published?
			if ($ver_folder_element->valueOf('INFO/PUBLISHED') == '1')
			{
				return true;
			}
						
			$env_ID = $ver_folder_element->valueOf('@ID');
					
			$ver_nql = new Sushee_Shell(false);
			$ver_nql->addCommand('
				<UPDATE>
					<OFFICITY:ENVIRONMENT ID="'.$env_ID.'">
						<INFO>
							<PUBLISHED>1</PUBLISHED>
						</INFO>
					</OFFICITY:ENVIRONMENT>
				</UPDATE>
			');
			$ver_nql->execute();
		
			$message = $ver_nql->getElement("/RESPONSE/MESSAGE");
			if (($message !== false) &&
				($message->valueOf("@msgType") == '0') && 
				($message->valueOf("@elementID") == $env_ID))
			{
				return true;
			}
			
			return false;
		}
		
		protected function updateSysConfigFile($folder_name, $env_type)
		{
			$php_file_path = '/'.$folder_name.'/system/config/system.config.php';
			
			$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)."'APPS_FOLDER',".PHP_EOL.
								chr(9).chr(9)."'$folder_name'".PHP_EOL.
								chr(9).");".PHP_EOL.PHP_EOL.
								chr(9)."define(".PHP_EOL.
								chr(9).chr(9)."'SYSTEM_ENV',".PHP_EOL.
								chr(9).chr(9)."'$env_type'".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 system config file : '.$php_file_path.' has not been created!');
			}
			
			return true;
		}
		
		/* activation */
		protected function activate($data)
		{
			$folder_name = $data->getValue('Folder');
			$folder = new KernelFolder('/'.$folder_name);
			if ($folder->exists())
			{
				return new SusheeProcessorException('Folder '.$folder_name.' already exists!');
			}
			
			$type = $data->getValue('Type');
			switch ($type)
			{
				case 'production':
					return new SusheeProcessorException('Cannot activate production environment! Check installation.');
					break;
					
				case 'beta':
					// retrieve then copy ref folder
					$ref_folder_element = $ver_folder_element = null;
					$this->getRefFolder('development', 'production', $ref_folder_element, $ver_folder_element);
					if (empty($ref_folder_element))
					{
						return new SusheeProcessorException('Cannot retrieve reference folder (dev or prod)!');
					}
					
					$ref_folder_name = $ref_folder_element->valueOf('INFO/FOLDER');
					$ref_folder = new KernelFolder('/'.$ref_folder_name);
					if (!$ref_folder->exists())
					{
						return new SusheeProcessorException('Reference folder '.$ref_folder_name.' does not exist!');
					}
					
					if (!$ref_folder->copy($folder))
					{
						return new SusheeProcessorException('Error copying reference folder '.$ref_folder_name.'!');
					}		

					// update system config file
					if (($update_result = $this->updateSysConfigFile($folder_name, $type)) !== true)
					{
						return $update_result;
					}

					// create versions if not published
					if (($create_ver_result = $this->publishVersions($ver_folder_element)) !== true)
					{
						return $create_ver_result;
					}
					break;
					
				case 'development':
					// retrieve then copy ref folder
					$ref_folder_element = $ver_folder_element = null;
					$this->getRefFolder('beta', 'production', $ref_folder_element, $ver_folder_element);
					if (empty($ref_folder_element))
					{
						return new SusheeProcessorException('Cannot retrieve reference folder (beta or prod)!');
					}
					
					$ref_folder_name = $ref_folder_element->valueOf('INFO/FOLDER');
					$ref_folder = new KernelFolder('/'.$ref_folder_name);
					if (!$ref_folder->exists())
					{
						return new SusheeProcessorException('Reference folder '.$ref_folder_name.' does not exist!');
					}
					
					if (!$ref_folder->copy($folder))
					{
						return new SusheeProcessorException('Error copying reference folder '.$ref_folder_name.'!');
					}
					
					// update system config file
					if (($update_result = $this->updateSysConfigFile($folder_name, $type)) !== true)
					{
						return $update_result;
					}
					
					// create versions if not published
					if (($create_ver_result = $this->publishVersions($ver_folder_element)) !== true)
					{
						return $create_ver_result;
					}
					
					/* execute server commands */
						
					$paths = array(ROOT_PATH.$folder_name.'/');
					$return_message = $this->execServerCommands($data->getValue('CreateCommand'), $paths, 'Create');					
					return new SusheeProcessorMessage($return_message);
					break;
					
				case 'versions':
					$folder->create();
					if (!$folder->exists())
					{
						return new SusheeProcessorException('Error creating folder '.$folder_name.'!');
					}
					break;
					
				default:
					return new SusheeProcessorException('Invalid environment type '.$type.'!');
					break;
			}
			
			return new SusheeProcessorMessage('Activation completed');
		}
		
		/* deactivation */
		protected function deactivate($data)
		{
			$folder_name = $data->getValue('Folder');
			$folder = new KernelFolder('/'.$folder_name);
			if (!$folder->exists())
			{
				return new SusheeProcessorException('Folder '.$folder_name.' does not exist!');
			}
			
			$type = $data->getValue('Type');
			switch ($type)
			{
				case 'production':
				case 'beta':
				case 'development':
					$ver_folder_element = $this->getVersionsFolder();
					
					// create versions if not published
					if (($create_ver_result = $this->publishVersions($ver_folder_element)) !== true)
					{
						return $create_ver_result;
					}
					$ver_folder_name = $ver_folder_element->valueOf('INFO/FOLDER');
					$ver_folder = new KernelFolder('/'.$ver_folder_name);

					// backup : copy then compress
					if (!$folder->copy($ver_folder))
					{
						return new SusheeProcessorException('Error copying folder '.$folder_name.' to '.$ver_folder_name.'!');
					}
					
					$backup_folder = $ver_folder->getChild($folder_name);
					$backup_folder_name = 'BAK-'.date('Ymd-His-').$folder_name;					
					if (!$backup_folder->rename($backup_folder_name))
					{
						return new SusheeProcessorException('Error renaming folder '.$folder_name.' to '.$backup_folder_name.'!');
					}
					
					if (!$backup_folder->compress())
					{
						return new SusheeProcessorException('Error compressing backup folder '.$backup_folder_name.'!');
					}
					
					// cleanup
					$backup_folder->delete();
					if ($backup_folder->exists())
					{
						return new SusheeProcessorException('Error deleting backup folder '.$backup_folder_name.'!');
					}
					
					$folder->delete();
					if ($folder->exists())
					{
						return new SusheeProcessorException('Error deleting original folder '.$folder_name.'!');
					}
					
					if ($type == 'development')
					{
						/* execute server commands */
							
						$paths = array(ROOT_PATH.$folder_name.'/');
						$return_message = $this->execServerCommands($data->getValue('DeleteCommand'), $paths, 'Delete');
						return new SusheeProcessorMessage($return_message);
					}
					break;
					
				case 'versions':
					if ($folder->countFiles() > 0)
					{
						return new SusheeProcessorException('Folder '.$folder_name.' is not empty!');
					}
					$folder->delete();
					if ($folder->exists())
					{
						return new SusheeProcessorException('Error deleting folder '.$folder_name.'!');
					}
					break;
					
				default:
					return new SusheeProcessorException('Invalid environment type '.$type.'!');
					break;
			}
		
			return new SusheeProcessorMessage('Deactivation completed');
		}
	}
?>