<?php
/**
* @version	$Id: event.php 12734 2009-10-20 19:28:11Z alex $
* @package	In-Portal
* @copyright	Copyright (C) 1997 - 2009 Intechnic. All rights reserved.
* @license      GNU/GPL
* In-Portal is Open Source software.
* This means that this software may have been modified pursuant
* the GNU General Public License, and as distributed it includes
* or is derivative of works licensed under the GNU General Public License
* or other free or open source software licenses.
* See http://www.in-portal.org/license for copyright notices and details.
*/

	defined('FULL_PATH') or die('restricted access!');

	class kEvent extends kBase {

		/**
		 * Event reference, that
		 * created this event
		 *
		 * @var kEvent
		 * @access public
		 */
		var $MasterEvent;

		/**
		 * Event name
		 *
		 * @var string
		 * @access public
		 */
		var $Name;

		/**
		 * Pseudo class name
		 *
		 * @var string
		 * @access public
		 */
		//var $Prefix;

		/**
		 * Special, that is recognized
		 * by class with pseudo class
		 * equals to $Prefix attrbute.
		 *
		 * @var string
		 * @access public
		 */
		//var $Special;

		/**
		 * Joined prefix and special,
		 * usually taken directly from
		 * tag beeing processes, to use
		 * in recallObject method
		 *
		 * @var string
		 */
		var $Prefix_Special;

		/**
		 * Do not execute Before hooks
		 * while processing main event
		 *
		 * @var bool
		 * @access public
		 */
		var $SkipBeforeHooks = false;

		/**
		 * Do not execute After hooks
		 * while processing main event
		 *
		 * @var bool
		 * @access public
		 */
		var $SkipAfterHooks = false;

		/**
		 * Redirect is allowed after
		 * this event
		 *
		 * @var bool
		 * @access public
		 */
		var $redirect = true;

		/**
		 * Params passed to redirect on succsessfull event
		 *
		 * @var bool
		 * @access public
		 */
		var $redirect_params = null;

		/**
		 * php file to redirect to
		 *
		 * @var string
		 * @access public
		 */
		var $redirect_script = null;

		/**
		 * Event processing result
		 *
		 * @var int
		 * @access public
		 */
		var $status = erSUCCESS;

		/**
		 * Each event specific only params,
		 * that they use for communication
		 *
		 * @var Array
		 * @access public
		 */
		var $specificParams = Array();

		/**
		 * Pseudo class used to create object,
		 * in case if one is not already created
		 *
		 * @var string
		 * @access public
		 */
		var $pseudoClass = '';

		/**
		 * Create event based on params passed
		 *
		 * @param Array $params
		 * @return kEvent
		 * @access public
		 */
		function kEvent($params=Array(), $specificParams=null)
		{
			parent::kBase();
			if($params && is_array($params))
			{
				$prefix = isset($params['prefix']) ? $params['prefix'] : false;
				$special = isset($params['special']) ? $params['special'] : false;
				if($prefix) $this->Init($prefix,$special);
				$this->Name = getArrayValue($params,'name');
			}
			elseif ($params && is_string($params)) {
				if (preg_match('/([^.:]*)[.]{0,1}([^:]*):(.*)/', $params, $regs)) {
					$prefix = $regs[1];
					$special = $regs[2];
					if($prefix) $this->Init($prefix,$special);
					$this->Name = $regs[3];
				}
				else {
					trigger_error('Invalid event string '.$params.' should be prefix[.special]:OnEvent ', E_USER_ERROR);
				}
			}
			if (isset($specificParams)) $this->specificParams = $specificParams;
		}

		function setEventParam($name,$value)
		{
			$this->specificParams[$name]=$value;
		}

		function getEventParam($name)
		{
			$args = func_get_args();
			if (count($args) > 1) {
				array_unshift_ref($args, $this->specificParams);

				return call_user_func_array('getArrayValue', $args); // getArrayValue($this->specificParams, $name);
			}
			return isset($this->specificParams[$name]) ? $this->specificParams[$name] : false;
		}

		function getPrefixSpecial($from_submit=false)
		{
			$separator=!$from_submit?'.':'_';
			$ret=$this->Prefix.$separator.$this->Special;
			return rtrim($ret,$separator);
		}

		/**
		 * Set's pseudo class that differs from
		 * the one specified in $Prefix
		 *
		 * @param string $appendix
		 * @access public
		 */
		function setPseudoClass($appendix)
		{
			$this->pseudoClass = $this->Prefix.$appendix;
		}

		function Init($prefix, $special = '')
		{
			$this->Prefix = $prefix;
			$this->pseudoClass = $prefix; // default value
			$this->Special = $special;
			$this->Prefix_Special = rtrim($this->Prefix.'.'.$this->Special,'.');
		}

		/**
		 * Returns object used in event
		 *
		 * @access public
		 * @return kDBBase
		 */
		function &getObject($params = Array())
		{
			$object =& $this->Application->recallObject($this->Prefix_Special, $this->pseudoClass, $params);
			return $object;
		}

		/**
		 * Calls passed event by name in current prefix/special environment
		 * Called event gets this event as MasterEvent,
		 * but its results (status and redirect* properties are copied back to current event)
		 *
		 * @param string $name EventName to call
		 */
		function CallSubEvent($name)
		{
			$child_event = new kEvent();
			$child_event->MasterEvent =& $this;
			$child_event->Prefix = $this->Prefix;
			$child_event->Special = $this->Special;
			$child_event->Prefix_Special = $this->Prefix_Special;
			$child_event->redirect = $this->redirect;
			$child_event->redirect_params = $this->redirect_params;
			$child_event->redirect_script = $this->redirect_script;
			$child_event->Name = $name;

			$this->Application->HandleEvent( $child_event );

			$this->status = $child_event->status;
			$this->redirect = $child_event->redirect;
			$this->redirect_params = $child_event->redirect_params;
			$this->redirect_script = $child_event->redirect_script;
		}

		/**
		 * Set's redirect param for event
		 *
		 * @param string $name
		 * @param string $value
		 * @access public
		 */
		function SetRedirectParam($name, $value)
		{
			$this->redirect_params[$name] = $value;
		}

		/**
		 * Allows to merge passed redirect params hash with existing ones
		 *
		 * @param Array $params
		 * @access public
		 */
		function setRedirectParams($params)
		{
			$this->redirect_params = array_merge_recursive2($this->redirect_params, $params);
		}

		/**
		 * Returns Master event name if any
		 *
		 * @return mixed
		 * @access public
		 */
		function hasMasterEvent()
		{
			return is_object($this->MasterEvent) ? $this->MasterEvent->Name : false;
		}

		/**
		 * Allows to tell if this event was called some how (e.g. subevent, hook) from event requested
		 *
		 * @param string $event_key event key in format [prefix[.special]:]event_name
		 * @return unknown
		 */
		function hasAncestor($event_key)
		{
			$event_manager =& $this->Application->recallObject('EventManager');
			if (strpos($event_key, ':') === false) {
				$event_key = $this->getPrefixSpecial().':'.$event_key;
			}

			return $event_manager->eventRunning($event_key);
		}

		/**
		 * Returns section for current event
		 *
		 * @return string
		 */
		function getSection()
		{
			$perm_section = $this->getEventParam('PermSection');
			if ($perm_section) {
				return $perm_section;
			}

			// 1. get section by current top_prefix
			$top_prefix = $this->getEventParam('top_prefix');
			if ($top_prefix == false) {
				$top_prefix = $this->Application->GetTopmostPrefix($this->Prefix, true);
				$this->setEventParam('top_prefix', $top_prefix);
			}
			$section = $this->Application->getUnitOption($top_prefix.'.main', 'PermSection');

			// 2. check if this section has perm_prefix mapping to other prefix
			$sections_helper =& $this->Application->recallObject('SectionsHelper');
			/* @var $sections_helper kSectionsHelper */

			$section_data =& $sections_helper->getSectionData($section);
			if ($section_data && isset($section_data['perm_prefix']) && $section_data['perm_prefix'] != $top_prefix) {
				$this->setEventParam('top_prefix', $section_data['perm_prefix']);
				$section = $this->Application->getUnitOption($section_data['perm_prefix'].'.main', 'PermSection');
			}

			if (!$section) {
				if ($this->Application->isDebugMode()) {
					$this->Application->Debugger->appendTrace();
				}
				trigger_error('Permission <b>section</b> not specified for prefix <b>'.$top_prefix.'</b>', E_USER_ERROR);
			}
			return $section;
		}

	}