<?php
/**
* @version	$Id: selectors_event_handler.php 15145 2012-03-04 09:04:08Z 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 SelectorsEventHandler extends kDBEventHandler
	{
		/**
		 * Allows to override standard permission mapping
		 *
		 * @return void
		 * @access protected
		 * @see kEventHandler::$permMapping
		 */
		protected function mapPermissions()
		{
			parent::mapPermissions();

			$permissions = Array(
				'OnResetToBase'		=>	Array('subitem' => 'add|edit'),
				'OnMassResetToBase'	=>	Array('subitem' => 'add|edit'),

				'OnOpenStyleEditor'	=>	Array('subitem' => 'add|edit'),
				'OnSaveStyle'		=>	Array('subitem' => 'add|edit'),
			);

			$this->permMapping = array_merge($this->permMapping, $permissions);
		}

		/**
		 * Occurs before an item has been cloned
		 * Id of newly created item is passed as event' 'id' param
		 *
		 * @param kEvent $event
		 * @return void
		 * @access protected
		 */
		protected function OnBeforeClone(kEvent $event)
		{
			parent::OnBeforeClone($event);

			$event->Init($event->Prefix, '-item');

			$object = $event->getObject();
			/* @var $object kDBItem */

			$title_field = 'SelectorName';
			$new_name = $object->GetDBField($title_field);
			$original_checked = false;

			$foreign_key = $event->getEventParam('foreign_key'); // in case if whole stylesheet is cloned
			if ( $foreign_key === false ) {
				$foreign_key = $object->GetDBField('StylesheetId');
			} // in case if selector is copied ifself

			do {
				if ( preg_match('/(.*)-([\d]+)/', $new_name, $regs) ) {
					$new_name = $regs[1] . '-' . ($regs[2] + 1);
				}
				elseif ( $original_checked ) {
					$new_name = $new_name . '-1';
				}

				// if we are cloning in temp table this will look for names in temp table,
				// since object' TableName contains correct TableName (for temp also!)
				// if we are cloning live - look in live
				$query = '	SELECT ' . $title_field . '
							FROM ' . $object->TableName . '
							WHERE ' . $title_field . ' = ' . $this->Conn->qstr($new_name) . ' AND StylesheetId = ' . $foreign_key;

				$res = $this->Conn->GetOne($query);

				/*// if not found in live table, check in temp table if applicable
				if ($res === false && $object->Special == 'temp') {
					$query = 'SELECT '.$name_field.' FROM '.$this->GetTempName($master['TableName']).'
										WHERE '.$name_field.' = '.$this->Conn->qstr($new_name);
					$res = $this->Conn->GetOne($query);
				}*/

				$original_checked = true;
			} while ( $res !== false );
			$object->SetDBField($title_field, $new_name);
		}

		/**
		 * Show base styles or block styles
		 *
		 * @param kEvent $event
		 * @return void
		 * @access protected
		 * @see kDBEventHandler::OnListBuild()
		 */
		protected function SetCustomQuery(kEvent $event)
		{
			parent::SetCustomQuery($event);

			$object = $event->getObject();
			/* @var $object kDBList */

			switch ($event->Special) {
				case 'base':
					$object->addFilter('type_filter', '%1$s.Type = 1');
					break;

				case 'block':
					$object->addFilter('type_filter', '%1$s.Type = 2');
					break;
			}
		}

		/**
		 * Occurs before updating item
		 *
		 * @param kEvent $event
		 * @return void
		 * @access protected
		 */
		protected function OnBeforeItemUpdate(kEvent $event)
		{
			parent::OnBeforeItemUpdate($event);

			$this->SerializeSelectorData($event);
		}

		/**
		 * Occurs before creating item
		 *
		 * @param kEvent $event
		 * @return void
		 * @access protected
		 */
		protected function OnBeforeItemCreate(kEvent $event)
		{
			parent::OnBeforeItemCreate($event);

			$this->SerializeSelectorData($event);
		}

		/**
		 * Occurs after updating item
		 *
		 * @param kEvent $event
		 * @return void
		 * @access protected
		 */
		protected function OnAfterItemUpdate(kEvent $event)
		{
			parent::OnAfterItemUpdate($event);

			$this->UnserializeSelectorData($event);
		}

		/**
		 * Occurs after creating item
		 *
		 * @param kEvent $event
		 * @return void
		 * @access protected
		 */
		protected function OnAfterItemCreate(kEvent $event)
		{
			parent::OnAfterItemCreate($event);

			$this->UnserializeSelectorData($event);
		}

		/**
		 * Returns special of main item for linking with sub-item
		 *
		 * @param kEvent $event
		 * @return string
		 * @access protected
		 */
		protected function getMainSpecial(kEvent $event)
		{
			return '';
		}

		/**
		 * Save css-style name & description before opening css editor
		 *
		 * @param kEvent $event
		 */
		function OnOpenStyleEditor($event)
		{
			$this->SaveChanges($event);
			$event->redirect = false;
		}

		/**
		 * Saves Changes to Item
		 *
		 * @param kEvent $event
		 */
		function SaveChanges($event)
		{
			$object = $event->getObject( Array('skip_autoload' => true) );
			/* @var $object kDBItem */

			$items_info = $this->Application->GetVar($event->getPrefixSpecial(true));
			if ( $items_info ) {
				list($id, $field_values) = each($items_info);

				if ( $id == 0 ) {
					$parent_id = getArrayValue($field_values, 'ParentId');
					if ( $parent_id ) {
						$object->Load($parent_id);
					}

					$object->SetFieldsFromHash($field_values, $this->getRequestProtectedFields($field_values));
					$object->Create();

					$this->Application->SetVar($event->getPrefixSpecial() . '_id', $object->GetID());
				}
				else {
					$object->Load($id);
					$object->SetFieldsFromHash($field_values, $this->getRequestProtectedFields($field_values));
					$object->Update();
				}
			}
		}

		/**
		 * Save style changes from style editor
		 *
		 * @param kEvent $event
		 */
		function OnSaveStyle($event)
		{
			$this->SaveChanges($event);

			$object = $event->getObject();
			$this->Application->SetVar($event->getPrefixSpecial().'_id', $object->GetId() );

			$this->finalizePopup($event);
		}

		/**
		 * Extract styles
		 *
		 * @param kEvent $event
		 * @return void
		 * @access protected
		 */
		protected function OnAfterItemLoad(kEvent $event)
		{
			parent::OnAfterItemLoad($event);

			$object = $event->getObject();
			/* @var $object kDBItem */

			$selector_data = $object->GetDBField('SelectorData');

			if ( $selector_data ) {
				$selector_data = unserialize($selector_data);
				$object->SetDBField('SelectorData', $selector_data);
			}
			else {
				$selector_data = Array ();
			}

			$this->AddParentProperties($event, $selector_data);
		}

		/**
		 * Serialize item before saving to db
		 *
		 * @param kEvent $event
		 */
		function SerializeSelectorData($event)
		{
			$object = $event->getObject();
			/* @var $object kDBItem */

			$selector_data = $object->GetDBField('SelectorData');
			if ( !$selector_data ) {
				$selector_data = Array ();
			}

			$selector_data = $this->RemoveParentProperties($event, $selector_data);

			if ( !kUtil::IsSerialized($selector_data) ) {
				$selector_data = serialize($selector_data);
			}

			$object->SetDBField('SelectorData', $selector_data);
		}

		/**
		 * Unserialize data back when update was made
		 *
		 * @param kEvent $event
		 */
		function UnserializeSelectorData($event)
		{
			$object = $event->getObject();
			/* @var $object kDBItem */

			$selector_data = $object->GetDBField('SelectorData');

			if ( !$selector_data ) {
				$selector_data = Array ();
			}

			if ( kUtil::IsSerialized($selector_data) ) {
				$selector_data = unserialize($selector_data);
			}

			$selector_data = $this->AddParentProperties($event, $selector_data);

			$object->SetDBField('SelectorData', $selector_data);
		}

		/**
		 * Populate options based on temporary table :)
		 *
		 * @param kEvent $event
		 */
		function OnPrepareBaseStyles($event)
		{
			$object = $event->getObject();

			$parent_info = $object->getLinkedInfo();
			$title_field = $this->Application->getUnitOption($event->Prefix,'TitleField');
			$sql = 'SELECT '.$title_field.', '.$object->IDField.' FROM '.$object->TableName.' WHERE Type = 1 AND StylesheetId = '.$parent_info['ParentId'].' ORDER BY '.$title_field;

			$options = $this->Conn->GetCol($sql,$object->IDField);
			$object->SetFieldOption('ParentId', 'options', $options);
		}

		/**
		 * Remove properties of parent style that match by value from style
		 *
		 * @param kEvent $event
		 * @param Array $selector_data
		 * @return Array
		 */
		function RemoveParentProperties($event, $selector_data)
		{
			$object = $event->getObject();
			/* @var $object kDBItem */

			$parent_id = $object->GetDBField('ParentId');

			if ( $parent_id ) {
				$sql = 'SELECT SelectorData
						FROM ' . $object->TableName . '
						WHERE ' . $object->IDField . ' = ' . $parent_id;
				$base_selector_data = $this->Conn->GetOne($sql);

				if ( kUtil::IsSerialized($base_selector_data) ) {
					$base_selector_data = unserialize($base_selector_data);
				}

				foreach ($selector_data as $prop_name => $prop_value) {
					if ( !$prop_value || getArrayValue($base_selector_data, $prop_name) == $prop_value ) {
						unset($selector_data[$prop_name]);
					}
				}
			}
			else {
				foreach ($selector_data as $prop_name => $prop_value) {
					if ( !$prop_value ) {
						unset($selector_data[$prop_name]);
					}
				}
			}

			$object->SetDBField('SelectorData', $selector_data);

			return $selector_data;
		}

		/**
		 * Add back properties from parent style, that match this style property values
		 *
		 * @param kEvent $event
		 * @param Array $selector_data
		 * @return Array
		 */
		function AddParentProperties($event, $selector_data)
		{
			$object = $event->getObject();
			/* @var $object kDBItem */

			$parent_id = $object->GetDBField('ParentId');
			if ( $parent_id ) {
				$sql = 'SELECT SelectorData
						FROM ' . $object->TableName . '
						WHERE ' . $object->IDField . ' = ' . $parent_id;
				$base_selector_data = $this->Conn->GetOne($sql);

				if ( kUtil::IsSerialized($base_selector_data) ) {
					$base_selector_data = unserialize($base_selector_data);
				}

				$selector_data = kUtil::array_merge_recursive($base_selector_data, $selector_data);
				$object->SetDBField('SelectorData', $selector_data);

				return $selector_data;
			}

			return Array ();
		}

		/**
		 * Reset Style definition to base style -> no customizations
		 *
		 * @param kEvent $event
		 */
		function OnResetToBase($event)
		{
			$object = $event->getObject();
			/* @var $object SelectorsItem */

			$field_values = $this->getSubmittedFields($event);
			$object->SetFieldsFromHash($field_values, $this->getRequestProtectedFields($field_values));
			$object->ResetStyle();

			$event->SetRedirectParam('pass', 'all,' . $event->getPrefixSpecial());
		}

		/**
		 * Resets selected styles properties to values of their base classes
		 *
		 * @param kEvent $event
		 */
		function OnMassResetToBase($event)
		{
			$object = $event->getObject( Array('skip_autoload' => true) );
			/* @var $object SelectorsItem */

			$items_info = $this->Application->GetVar( $event->getPrefixSpecial(true) );

			if ( $items_info ) {
				foreach ($items_info as $id => $field_values) {
					$object->Load($id);
					$object->ResetStyle();
				}
			}
		}
	}