<?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/system/class/WIP.DataBot.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__).'/../system.include.php');

	/*
	 * Data Consistency Analyzer Classes
	 * 
	 * @since	2010-10-04
	 *
	*/
	
	/* *** */
	
	abstract class Command
	{
		protected $description;
		protected $result;
		
		function __construct()
		{
			
		}
		
		function __destruct()
		{
			unset($this->nql);
			$this->nql = null;
		}
		
		abstract public function execute($element=null);
		
		public function getResult()
		{
			return $this->result;
		}
		
		public function setDescription($description)
		{
			$this->descripton = $description;
		}
		
		public function getDescription()
		{
			return $this->descripton;
		}
	}
	
	class NQLCommand extends Command
	{
		protected $nql;
		 
		function __construct()
		{
			$this->nql = new Sushee_Shell(false);
		}
		
		protected function _logCommand()
		{
			echo(htmlentities($this->nql->getQuery()));
			echo '<br /><br />'; 
		}
		
		public function execute($element=null)
		{
			$this->_logCommand();
			
			$this->nql->execute();			
			$this->result = $this->nql;
			
			$message = $this->result->getElement("/RESPONSE/MESSAGE");
			if (($message !== false) && ($message->valueOf("@msgType") != '0'))
			{
				throw new Exception('NQL query failed: '.$message->valueOf('.'));
			}
			
			return $this->result;
		}
	}
	
	class SelectSocietiesCommand extends NQLCommand
	{
		function __construct()
		{
			$this->setDescription('Select societies and return staff contacts in dependency.');
			parent::__construct();
		}
		
		public function execute($element=null)
		{		
			$this->nql->reset();
			
			$info_criteria = !URLParam::exists('id') ? '
				<CONTACTTYPE operator="=">PM</CONTACTTYPE>
			' : '
				<ID operator="IN">'.URLParam::fetch('id').'</ID>
			';
			
			$this->nql->addCommand('
				<SEARCH name="list">
					<CONTACT>
						<INFO>'.$info_criteria.'</INFO>
					</CONTACT>
					<RETURN depth="2">
						<INFO>
						</INFO>
						<DEPENDENCIES>
							<DEPENDENCY type="contactWork">
								<INFO>
								</INFO>
							</DEPENDENCY>
						</DEPENDENCIES> 
					</RETURN>
					<SORT select="INFO/CREATIONDATE" order="ascending" />
					<PAGINATE display="'.URLParam::fetch('display', 10).'" page="'.URLParam::fetch('page', 1).'" />
				</SEARCH>
			');
			
			parent::execute();
			
			return $this->result->getElements('/RESPONSE/RESULTS/CONTACT');
		}
	}
	
	/* *** */
	
	class StaffCountFilter extends Command
	{
		protected $count;
				
		function __construct($count=1)
		{
			$this->count = $count;
			$this->setDescription('Verify if staff contacts > '.$this->count);
			parent::__construct();
		}
		
		public function execute($element=null)
		{
			$this->result = (count($element->getElements('DEPENDENCIES/DEPENDENCY[@type="contactWork"]/CONTACT')) > $this->count);
			return $this->result;
		}
	}
	
	class IDFilter extends Command
	{
		function __construct()
		{
			$this->setDescription('Verify if ID < 100');
			parent::__construct();
		}
		
		public function execute($element=null)
		{
			$this->result = $element->valueOf('@ID') < 100;
			return $this->result;
		}
	}
	
	/* *** */
	
	class RepairStaffCommand extends NQLCommand
	{
		function __construct()
		{
			$this->setDescription('Add staff');
			parent::__construct();
		}
		
		public function execute($element=null)
		{
			$this->nql->reset();
			$this->nql->addCommand('
				<UPDATE>
					<CONTACT ID="'.$element->valueOf('@ID').'" />
				</UPDATE>
			');
			parent::execute();
			return $this->result->getElement("/RESPONSE/MESSAGE");
		}
	}
	
	/* *** */
	
	class DataBot
	{
		var $select_command, $filter_command, $repair_command;
		var $elements, $ok_elements, $nok_elements, $repaired_elements;
		
		function __construct()
		{	
			$this->select_command = null;
			$this->filter_command = null;
			$this->repair_command = null;
			$this->elements = array();
			$this->ok_elements =  array();
			$this->nok_elements =  array();
			$this->repaired_elements =  array();
		}
		
		function __destruct()
		{
			
		}
		
		protected function addConsistencyNode($element)
		{
			if ($element->getElement('CONSISTENCYANALYSIS') === false)
			{
				$element->getElement('.')->appendChild('<CONSISTENCYANALYSIS />');
			}
		}

		protected function _logElement($name, $element, $profile)
		{	
			if ($profile == 'complete')
			{
				echo '<u>'.$name.'</u>:<br/>';
				echo(htmlentities($element->toString()));
				echo '<br /><br />';
			}
			else
			{
				echo $name.' ID='.$element->valueOf('@ID').'<br />';
			}
		}
		
		public function logElements($type='all', $profile='complete')
		{
			switch ($type)
			{
				case 'ok':
					foreach ($this->ok_elements as $element)
					{
						$this->_logElement('OK ELEMENT', $element, $profile);
					}
					break;
					
				case 'nok':
					foreach ($this->nok_elements as $element)
					{
						$this->_logElement('NOK ELEMENT', $element, $profile);
					}
					break;
					
				case 'repaired':
					foreach ($this->repaired_elements as $element)
					{
						$this->_logElement('REPAIRED ELEMENT', $element, $profile);
					}
					break;
					
				default:
					foreach ($this->elements as $element)
					{
						$this->_logElement('ELEMENT', $element, $profile);
					}
					break;
			}
		}
		
		public function select($select_command)
		{
			$this->select_command = $select_command;
			$this->elements = $this->select_command->execute();
		}
		
		public function analyze($filter_command)
		{
			$this->nok_elements = $this->ok_elements = null;
			
			$this->filter_command = $filter_command;
			foreach ($this->elements as $element)
			{	
				$this->addConsistencyNode($element);		

				$result = $this->filter_command->execute($element);
				$result_string = ($result == true) ? 'pass' : 'fail';
				
				$element->getElement('CONSISTENCYANALYSIS')->appendChild('
					<FILTER class="'.get_class($this->filter_command).'">
						<RESULT>'.$result_string.'</RESULT>
					</FILTER>
				');
				
				if ($result == false)
				{
					$this->nok_elements[] = $element;	
				}
				else 
				{
					$this->ok_elements[] = $element;	
				}
			}
		}
		
		public function repair($repair_command, $force_all=false)
		{
			$elements = ($force_all == true) ? $this->elements : $this->nok_elements;
			
			$this->repair_command = $repair_command;
			foreach ($elements as $element)
			{
				$result = $this->repair_command->execute($element);
				if ($result == false)
				{
					$this->repaired_elements[] = $element;
				}
			}
		}
		
		public function report()
		{
			echo 'ANALYSIS RESULTS:<hr />';
			echo '   Selection class <strong>'.get_class($this->select_command).'</strong>: <em>'.$this->select_command->getDescription().'</em><br />';
			echo '   <strong>'.count($this->elements).'</strong> element(s):<br />';
			
			if (!empty($this->elements))
			{
				$this->logElements('all', 'small');
				echo '<hr />';
			}
			
			if (!empty($this->ok_elements) || !empty($this->nok_elements))
			{
				echo '   Filter class <strong>'.get_class($this->filter_command).'</strong>: <em>'.$this->filter_command->getDescription().'</em><br />';
				
				echo '   Consistencies: <strong>'.count($this->ok_elements).'</strong> element(s)<br />';
				$this->logElements('ok', 'small');				
				echo '<hr />';
				
				echo '   Inconsistencies: <strong>'.count($this->nok_elements).'</strong> element(s)<br />';
				$this->logElements('nok');
				echo '<hr />';
			}
			
			if (!empty($this->repaired_elements))
			{
				echo '   Repair class <strong>'.get_class($this->repair_command).'</strong>: <em>'.$this->repair_command->getDescription().'</em><br />';
				echo '   Repaired: <strong>'.count($this->repaired_elements).'</strong> element(s)<br />';
				$this->logElements('repaired', 'small');
				echo '<hr />';
			}
		}
		
		public function notify($email, $only_on_inconsistencies=true)
		{
			if ($only_on_inconsistencies == true)
			{
				if (empty($this->nok_elements)) return;				
			}
			
			ob_start();
			$this->report();
			$body = encode_to_xml(ob_get_clean());
			
			$nql = new Sushee_Shell(false);
			$nql->addCommand('
                <CREATE>
                  <SERVERMAIL>
                    <SENDER email="feedback@nectil.com">feedback@nectil.com</SENDER>
                    <RECIPIENT>'.$email.'</RECIPIENT>
                    <SUBJECT>DataConsistencyAnalyzer report</SUBJECT>
                    <BODY>'.$body.'</BODY>
                  </SERVERMAIL>
                </CREATE>
			');
			$nql->execute();

			$message = $nql->getElement("/RESPONSE/MESSAGE");
			if (($message !== false) && ($message->valueOf("@msgType") != '0'))
			{
				throw new Exception('NQL query failed: '.$message->valueOf('.'));
			}
			
			echo 'Notification sent to <strong>'.$email.'</strong>';
		}
	}
	
	try 
	{
		$wally = new DataBot();
		
		$wally->select(new SelectSocietiesCommand());
		$wally->analyze(new IDFilter());
		$wally->report();
		
		$wally->notify('marc@nectil.com');
		
		//$wally->repair(new DeleteMshipsCommand());
	}
	catch (Exception $e)
	{
		echo $e->getMessage();
		die();
	}
?>