<?php
/**
* @version	$Id: custom_fields_event_handler.php 14241 2011-03-16 20:24:35Z 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 CustomFieldsEventHandler extends kDBEventHandler {

		/**
		 * Changes permission section to one from REQUEST, not from config
		 *
		 * @param kEvent $event
		 */
		function CheckPermission(&$event)
		{
			$sql = 'SELECT Prefix
					FROM '.TABLE_PREFIX.'ItemTypes
					WHERE ItemType = '.$this->Conn->qstr( $this->Application->GetVar('cf_type') );
			$main_prefix = $this->Conn->GetOne($sql);

			$section = $this->Application->getUnitOption($main_prefix.'.custom', 'PermSection');
			$event->setEventParam('PermSection', $section);

			return parent::CheckPermission($event);
		}

		/**
		 * Apply any custom changes to list's sql query
		 *
		 * @param kEvent $event
		 * @access protected
		 * @see OnListBuild
		 */
		function SetCustomQuery(&$event)
		{
			$object =& $event->getObject();
			/* @var $object kDBList */

			$item_type = $this->Application->GetVar('cf_type');
			if (!$item_type) {
				$prefix = $event->getEventParam('SourcePrefix');
				$item_type = $this->Application->getUnitOption($prefix, 'ItemType');
			}

			if ($event->Special == 'general') {
				$object->addFilter('generaltab_filter', '%1$s.OnGeneralTab = 1');
			}

			if ($item_type) {
				$hidden_fields = array_map(Array(&$this->Conn, 'qstr'), $this->_getHiddenFiels($event));

				if ($hidden_fields) {
					$object->addFilter('hidden_filter', '%1$s.FieldName NOT IN (' . implode(',', $hidden_fields) . ')');
				}

				$object->addFilter('itemtype_filter', '%1$s.Type = '.$item_type);
			}

			if (!($this->Application->isDebugMode() && $this->Application->isAdminUser)) {
				$object->addFilter('user_filter', '%1$s.IsSystem = 0');
			}
		}

		/**
		 * Returns prefix, that custom fields are printed for
		 *
		 * @param kEvent $event
		 * @return string
		 */
		function _getSourcePrefix(&$event)
		{
			$prefix = $event->getEventParam('SourcePrefix');
			if (!$prefix) {
				$sql = 'SELECT Prefix
						FROM ' . TABLE_PREFIX . 'ItemTypes
						WHERE ItemType = ' . $this->Conn->qstr( $this->Application->GetVar('cf_type') );
				$prefix = $this->Conn->GetOne($sql);
			}

			return $prefix;
		}

		/**
		 * Get custom fields, that should no be shown anywhere
		 *
		 * @param kEvent $event
		 * @return Array
		 */
		function _getHiddenFiels(&$event)
		{
			$prefix = $this->_getSourcePrefix($event);

			$virtual_fields = $this->Application->getUnitOption($prefix, 'VirtualFields', Array ());
			$custom_fields = $this->Application->getUnitOption($prefix, 'CustomFields', Array ());

			$hidden_fields = Array ();
			foreach ($custom_fields as $custom_field) {
				$check_field = 'cust_' . $custom_field;
				$show_mode = array_key_exists('show_mode', $virtual_fields[$check_field]) ? $virtual_fields[$check_field]['show_mode'] : true;

				if (($show_mode === false) || (($show_mode === smDEBUG) && !(defined('DEBUG_MODE') && DEBUG_MODE))) {
					$hidden_fields[] = $custom_field;
				}
			}

			return $hidden_fields;
		}

		/**
		 * Prevents from duplicate item creation
		 *
		 * @param kEvent $event
		 */
		function OnBeforeItemCreate(&$event)
		{
			$object =& $event->getObject();

			$live_table = $this->Application->getUnitOption($event->Prefix, 'TableName');
			$sql = 'SELECT COUNT(*)
					FROM '.$live_table.'
					WHERE FieldName = '.$this->Conn->qstr($object->GetDBField('FieldName')).' AND Type = '.$object->GetDBField('Type');
			$found = $this->Conn->GetOne($sql);

			if ($found) {
				$event->status = erFAIL;
				$object->SetError('FieldName', 'duplicate', 'la_error_CustomExists');
			}
		}

		/**
		 * Occurse after deleting item, id of deleted item
		 * is stored as 'id' param of event
		 *
		 * @param kEvent $event
		 * @access public
		 */
		function OnAfterItemDelete(&$event)
		{
			$object =& $event->getObject();
			$main_prefix = $this->getPrefixByItemType($object->GetDBField('Type'));

			$ml_helper =& $this->Application->recallObject('kMultiLanguageHelper');
			/* @var $ml_helper kMultiLanguageHelper */

			// call main item config to clone cdata table
			$this->Application->getUnitOption($main_prefix, 'TableName');
			$ml_helper->deleteField($main_prefix.'-cdata', $event->getEventParam('id'));
		}

		/**
		 * Get config prefix based on item type
		 *
		 * @param unknown_type $item_type
		 * @return unknown
		 */
		function getPrefixByItemType($item_type)
		{
			$sql = 'SELECT Prefix
					FROM '.TABLE_PREFIX.'ItemTypes
					WHERE ItemType = '.$item_type;
			return $this->Conn->GetOne($sql);
		}

		/**
		 * Enter description here...
		 *
		 * @param kEvent $event
		 */
		function OnSaveCustomField(&$event)
		{
			if ($event->MasterEvent->status != erSUCCESS) {
				return false;
			}

			$object =& $event->getObject();
			$main_prefix = $this->getPrefixByItemType($object->GetDBField('Type'));

			$ml_helper =& $this->Application->recallObject('kMultiLanguageHelper');
			/* @var $ml_helper kMultiLanguageHelper */

			// call main item config to clone cdata table
			define('CUSTOM_FIELD_ADDED', 1); // used in cdata::scanCustomFields method
			$this->Application->getUnitOption($main_prefix, 'TableName');
			$ml_helper->createFields($main_prefix.'-cdata');
		}

		function OnMassDelete(&$event)
		{
			parent::OnMassDelete($event);
			$event->redirect_params = Array('opener' => 's');
		}

		/**
		 * Prepare temp tables for creating new item
		 * but does not create it. Actual create is
		 * done in OnPreSaveCreated
		 *
		 * @param kEvent $event
		 */
		function OnPreCreate(&$event)
		{
			parent::OnPreCreate($event);

			$object =& $event->getObject();
			$object->SetDBField('Type', $this->Application->GetVar('cf_type'));
		}

		/**
		 * Prepares ValueList field's value as xml for editing
		 *
		 * @param kEvent $event
		 */
		function OnAfterItemLoad(&$event)
		{
			parent::OnAfterItemLoad($event);

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

			if (!in_array($object->GetDBField('ElementType'), $this->_getMultiElementTypes())) {
				return ;
			}

			$custom_field_helper =& $this->Application->recallObject('InpCustomFieldsHelper');
			/* @var $custom_field_helper InpCustomFieldsHelper */

			$options = $custom_field_helper->GetValuesHash( $object->GetDBField('ValueList'), VALUE_LIST_SEPARATOR, false );

			$records = Array ();

			$option_key = key($options);
			if ($option_key === '' || $option_key == 0) {
				// remove 1st empty option, and add it later, when options will be saved, but allow string option keys
				unset($options[$option_key]); // keep index, don't use array_unshift!
			}

			foreach ($options as $option_key => $option_title) {
				$records[] = Array ('OptionKey' => $option_key, 'OptionTitle' => $option_title);
			}

			$minput_helper =& $this->Application->recallObject('MInputHelper');
			/* @var $minput_helper MInputHelper */

			$xml = $minput_helper->prepareMInputXML($records, Array ('OptionKey', 'OptionTitle'));
			$object->SetDBField('Options', $xml);
		}

		/**
		 * Returns custom field element types, that will use minput control
		 *
		 * @return unknown
		 */
		function _getMultiElementTypes()
		{
			return Array ('select', 'multiselect', 'radio');
		}

		/**
		 * Saves minput content to ValueList field
		 *
		 * @param kEvent $event
		 */
		function OnBeforeItemUpdate(&$event)
		{
			parent::OnBeforeItemUpdate($event);

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

			if (!in_array($object->GetDBField('ElementType'), $this->_getMultiElementTypes())) {
				return ;
			}

			$minput_helper =& $this->Application->recallObject('MInputHelper');
			/* @var $minput_helper MInputHelper */

			$ret = $object->GetDBField('ElementType') == 'select' ? Array ('' => '=+') : Array ();
			$records = $minput_helper->parseMInputXML($object->GetDBField('Options'));

			if ($object->GetDBField('SortValues')) {
				usort($records, Array (&$this, '_sortValues'));
				ksort($records);
			}

			foreach ($records as $record) {
				if (substr($record['OptionKey'], 0, 3) == 'SQL') {
					$ret[] = $record['OptionTitle'];
				}
				else {
					$ret[] = $record['OptionKey'] . '=' . $record['OptionTitle'];
				}
			}

			$object->SetDBField('ValueList', implode(VALUE_LIST_SEPARATOR, $ret));
		}

		function _sortValues($record_a, $record_b)
		{
			return strcasecmp($record_a['OptionTitle'], $record_b['OptionTitle']);
		}
	}