<?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/OfficityShell.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/>.
*/	
	/*
	 * Officity_Shell Class
	 * 
	 * @since	2010-11-15
	 *
	*/

    class Officity_Shell extends Sushee_Shell
    {
    	const SUPER_ADMIN_KEYRING_ID = 2;
    	const SUPPORT_TEAM_ID = 131;
    	
        function __construct($include_navigation=false, $public=false)
        {
            parent::__construct($include_navigation, $public);
        }

		function __destruct()
		{
			if (method_exists('Sushee_Shell', '__destruct'))
            {
                parent::__destruct();
            }
		}

		/* *** */
		
        protected function dumpURLParams($data, $label)
    	{
    		uksort($data, "strnatcasecmp");
    		
        	$html = '
				<table class="dump-table">
					<tr class="label">
						<th colspan="2">'.$label.'</th>
					</tr>
					<tr>
						<th>KEY</th><th>VALUE</th>
					</tr>
        	';
			ob_start();
			$class = 'odd';
			foreach ($data as $key => $value)
	    	{
	    		echo '<tr class="'.$class.'">';
	    		echo '<td class="key">'.$key.'</td>';
	    		echo '<td class="value">';
	    		var_dump($value);
	    		echo '</td>';
	    		echo '</tr>';
	    		$class = ($class == 'odd') ? 'even' : 'odd';
	    	}
	    	$dump = ob_get_clean();
	    	$html .= $dump;
        	$html .= '
				</table>
        	';
        	
        	return $html;
    	}
		
		/* *** */
	
    	public function addParam2XML($key, $value)
    	{
    		$_GET[$key] = $value; // /RESPONSE/URL/key will be set to $value
    	}
    	
    	// TODO: use $shell->setParams();
		
		// outputType can be : query, echo, text, xml, params, xsl
		public function execute($outputType=false)
		{
			// !!! prevent from inifinite recursion calls when parent's class uses $this->execute()
			// see displayLogPanel()
			if ($this->result !== false) return $this->result;
			
			$outputType = ($outputType != false) ? 
							$outputType :
							URLParam::fetch('output', false);
					
			// check for output type then execute
			switch ($outputType)
			{
				// NB : does not work if you ask on an invalid query
				case 'query':					
					$xml = parent::getQuery();
					$xml_size = sizeToHuman(strlen($xml));	
					
					$this->addLogContent($xml, 'xSushee query ('.$xml_size.')');
					$this->displayLogPanel();
					break;
					
				case 'xml':
					require_once(SYSTEM_CLASS_PATH.'Timer.class.php');
				    Timer::start();    
					$xml = parent::execute();
					$exec_time = round(Timer::stop(false)*1000, 1);				
					$xml_size = sizeToHuman(strlen($xml));	
				
					$xml = preg_replace('/<\?xml.*\?>/','', $xml); // get rid of the XML header
					
					$this->addLogContent($xml, 'XML response (execution time: '.$exec_time.'ms, '.$xml_size.')');	
					$this->displayLogPanel();
					break;
					
				case 'params':
					parent::reset();
					parent::execute();
					
					$html = $this->dumpURLParams($_POST, '$_POST').'<br />';
	        		$html .= $this->dumpURLParams($_GET, '$_GET');	
	        		        		
					$this->addLogContent($html, 'URL parameters', false);	// content is not XML
					$this->displayLogPanel();
					break;
				
				default:
					break;
			}
			
			return parent::execute($outputType);
		}
		
        // outputType can be : query, echo, text, xml, params, xsl
		public function transform($template, $outputType=false)
		{
			// check for XSL template existence
			if (!file_exists($template))
			{
				throw new OfficityException('XSL template <strong>'.$template.'</strong> does not exist!');
			}
			
			$outputType = ($outputType != false) ? 
							$outputType :
							URLParam::fetch('output', false);
			
			if ($outputType == 'xsl')
			{
				$xsl = file_get_contents($template);
				$xsl_size = sizeToHuman(strlen($xsl));
				$xml = preg_replace('/<\?xml.*\?>/','', $xsl); // get rid of the XML header
				
				$this->addLogContent($xml, 'XSL : '.$template.' ('.$xsl_size.')');	
				$this->displayLogPanel();
			}
			
			$this->execute($outputType);
			
			// check for NQL execution result
			$message = $this->getElement('/RESPONSE/MESSAGE');
			if (($message !== false) && ($message->valueOf("@msgType") != '0'))
			{
				// get rid of the QUERY node
				$query = '';
				foreach ($this->operations as $op)
				{
					$query .= $op.PHP_EOL;
				}
				
				//$query = '<br />'.nl2br(htmlentities('<QUERY>'.$query.'</QUERY>'));
				$query = xmlpp('<QUERY>'.$query.'</QUERY>');
				
				$exception_msg = 'XSL transformation failed: <strong>'.$message->valueOf('.').'</strong><br /><br />';
				$exception_msg .= '<strong>xSushee query:</strong><br />'.$query.'';
				throw new OfficityAppException($exception_msg);
			}
			
			// daddy makes the rest...
			return parent::transform($template, $outputType);
		}
		
        public function logXML()
	    {
	        $this->execute();
	        die(htmlentities($this->getResponse()));
	    }
	
	    public function logQuery()
	    {
	        die(htmlentities($this->getQuery()));
	    }
		
        public function displayErrorPanel($error_msg, $error_title='Application error!')
	    {
	        $nql_command = '<RESULTS name="errorMessage" static="true">
	                            <TITLE>'.$error_title.'</TITLE>
	                            <MESSAGE>'.$error_msg.'</MESSAGE>
	                            <CLASS>critical-error</CLASS>
	                        </RESULTS>';
	
	        $this->addCommand($nql_command);
	
	        $error_template_path = SYSTEM_TEMPLATES_PATH.'/Error.xsl';
	        if (isset($_GET['editor']))
	        {
	            $editor_folder = $_GET['editor'];
	            $editor_error_template_path = APPS_PATH.$editor_folder.'/shared/templates/Error.xsl';
	            if (file_exists($editor_error_template_path))
	            {
	                $error_template_path = $editor_error_template_path;
	            }
	        }
	        
	        die($this->transform($error_template_path));	
	    }
	    
	    protected function displayLogPanel()
	    {
	    	// prevent from infinite recursive calls : will set $this->result to something !==false
			parent::execute();
	        die(parent::transform(SYSTEM_TOOLS_PATH.'/error/Log.xsl', false));
	    }
	    
		/* *** */
	    
        public function addSecurity()
	    {
	    	$this->addCommand('
	    		<GET name="userSecurity">
	    			<SECURITY />
	    		</GET>
	    	');
	    }
	    
	    public function addDetailsCommands($module, $ID)
	    {
	    	$module = strtoupper($module);
	    	
		    $nql_command = '
		        <GET name="item">
		            <'.$module.' ID="'.$ID.'"/>
		            <RETURN depth="2">
		                <INFO creator_info="small" modifier_info="small" owner_info="small"/>
		                <DEPENDENCIES/>
		                <DESCRIPTIONS>
		                	<DESCRIPTION languageID="all" />
	                	</DESCRIPTIONS>
		            </RETURN>
		        </GET>
		    ';
		    $this->addCommand($nql_command);
			
		    $this->addModuleFields($module);
		    //$this->addDependencyEntities($module);    
		    //$this->addPublishedLanguages();
		    $this->addLanguages();
		    $this->addCountries();
		    $this->addMonths();
		    $this->addAllLists();
	    }
	    
        public function addNewCommands($module)
	    {
			$this->addTemplateElement($module);			
		    $this->addModuleFields($module);    
		    //$this->addPublishedLanguages();
		    $this->addLanguages();
		    $this->addCountries();
		    $this->addMonths();
		    $this->addAllLists();
	    }
	    
	    public function addTemplateElement($module)
	    {    	
	    	$this->addCommand('
		        <GET name="item" refresh="monthly">
		            <'.$module.' ID="1"/>
		            <RETURN>
		                <INFO />
		                <DEPENDENCIES/>
		                <!--DESCRITPIONS/-->
		            </RETURN>
		        </GET>
	    	');
	    }
	    
	    /* *** */
		
        public function addModuleFields($module)
        {
            $this->addCommand('
                <SEARCH name="fields" refresh="monthly">
                    <FIELD module="'.$module.'" />
                    <RETURN>
                        <INFO>
                            <MODULE />
                            <DENOMINATION />
                            <TYPE />
                            <LISTNAME />
                            <TARGETMODULE />
                            <TARGETFIELD />
                            <DEFAULTVALUE />
                            <SEARCHABLE />
                            <DISPLAYABLE />
                        </INFO>
                        <DESCRIPTIONS>
                            <DESCRIPTION>
                                <TITLE/>
                                <SUMMARY />
                            </DESCRIPTION>
                        </DESCRIPTIONS>
                    </RETURN>
                </SEARCH>
            ');
        }
        
        public function addDependencyEntities($module)
        {
		    $this->addCommand('
		        <GET name="dependencies" refresh="monthly">
		            <DEPENDENCYENTITY from="'.$module.'" />
		        </GET>
		    ');
        }
        
        public function addLanguages($profile='SmallList')
        {
		    $this->addCommand('
		        <GET name="Languages" refresh="monthly">
		            <LANGUAGES profile="'.$profile.'"/>
		        </GET>
		    ');
        }
        
        public function addPublishedLanguages()
        {
		    $this->addCommand('
		        <SEARCH name="PublishedLanguages" refresh="monthly">
		            <LANGUAGES profile="Media"/>
		    	</SEARCH>
		    ');
        }
        
        public function addCountries()
        {
		    $this->addCommand('
		        <GET name="Countries" refresh="monthly">
		            <COUNTRIES />
		        </GET>
		    ');
        }
        
        public function addMonths()
        {
			$this->addCommand('
		        <GET refresh="monthly">
					<MONTHS/>
		        </GET>
		    ');
        }
        
        public function addAllLists($domain='')
        {
		    $list_command = '<SEARCH><LIST ';		    
            if (!empty($domain))
        	{
	        	$list_command .= 'domain="'.$domain.'" ';
        	}
        	$list_command .= '/></SEARCH>';
        	
        	$this->addCommand($list_command);
        }
        
        public function addList($name, $domain='')
        {
        	$list_command = '<SEARCH><LIST name="'.$name.'" ';
        	
        	if (!empty($domain))
        	{
	        	$list_command .= 'domain="'.$domain.'" ';
        	}
        	$list_command .= '/></SEARCH>';
        	
		    $this->addCommand($list_command);
        }
        
        public function addStatic($xml, $name='')
        {
            $this->addCommand('
            	<RESULTS name="'.$name.'" static="true">'.trim($xml).'</RESULTS>
            ');
        }
        
        public function addLogContent($xml, $title='Log', $isXML=true)
        {
        	if ($isXML) $_GET['logXML'] = true; // for XSLT
        	
            $this->addCommand('
            	<RESULTS name="log" static="true">
            		<TITLE>'.$title.'</TITLE>'.
            		'<MESSAGE>'.trim($xml).'</MESSAGE>'.
            	'</RESULTS>
            ');
        }
        
        public function addPaging()
        {
		    $this->addCommand('
		        <GET refresh="monthly">
		            <ENUM>
		                <START>1</START>
		                <END>20</END>
		            </ENUM>
		        </GET>
		    ');
        }
        
        public function addCategories()
        {
		    $this->addCommand('
		        <GET name="categories" refresh="monthly">
		            <CATEGORIES />
		        </GET>
		    ');
        }
        
        /* *** */
        
        public function addVisitor()
        {
        	$this->addCommand('
        		<GET>
        			<VISITOR />
        		</GET>
        	');
        }
        
        public function addGroups()
        {
            $this->addCommand('
			    <SEARCH name="groups" refresh="monthly">
			        <GROUP />
			        <RETURN>
			            <INFO>
			            	<DENOMINATION />
			            </INFO>
			        </RETURN>
			    </SEARCH>
            ');
        }
        
        public function addSuperAdmins()
        {
            $this->addCommand('
			    <GETCHILDREN type="keyringUsers" name="SuperAdmins">
			        <KEYRING ID="'.self::SUPER_ADMIN_KEYRING_ID.'" />
			        <RETURN>
			            <NOTHING />
			        </RETURN>
			    </GETCHILDREN>
            ');
        }
        
        public function addSupportTeam()
        {
            $this->addCommand('
				<GETCHILDREN type="groupMember" name="SupportTeam">
					<GROUP ID="'.self::SUPPORT_TEAM_ID.'" />
					<RETURN>
						<NOTHING />
					</RETURN>
				</GETCHILDREN>
            ');
        }
    }
?>