<?php
/**
* @version	$Id: custom_data_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 CustomDataEventHandler extends kDBEventHandler {

		/**
		 * [HOOK] Allows to apply custom fields functionality to specific config
		 * When main item is created, then cdata config is cloned
		 *
		 * @param kEvent $event
		 */
		function OnDefineCustomFields(&$event)
		{
			// 1. clone customdata table
			$clones = $this->Application->getUnitOption('cdata', 'Clones');
			$clones[$event->MasterEvent->Prefix.'-cdata'] = Array (
				'ParentPrefix' => $event->MasterEvent->Prefix,
				'TableName' => $this->Application->getUnitOption($event->MasterEvent->Prefix, 'TableName').'CustomData',
			);
			$this->Application->setUnitOption('cdata', 'Clones', $clones);

			// 2. add custom field information to main item
			$this->createCustomFields($event->MasterEvent->Prefix);
		}

		function scanCustomFields($prefix)
		{
			static $custom_fields = Array ();

			if (defined('IS_INSTALL') && IS_INSTALL && !$this->Application->TableFound('CustomField')) {
				return false;
			}

			if (!$prefix) {
				// prefix not specified
				return false;
			}

			$item_type = $this->Application->getUnitOption($prefix, 'ItemType');
			if (!$item_type) {
				// no main config of such type
				return false;
			}

			$no_caching = (defined('IS_INSTALL') && IS_INSTALL) || (defined('CUSTOM_FIELD_ADDED') && CUSTOM_FIELD_ADDED);

			if (!$custom_fields || $no_caching) {
				// query all custom fields at once -> saves 4 sqls queries

				if ($no_caching) {
					$all_custom_fields = $this->getCustomFields();
				}
				else {
					$cache_key = 'all_custom_fields[%CfSerial%][%ModSerial%]';
					$all_custom_fields = $this->Application->getCache($cache_key, false);

					if ($all_custom_fields === false) {
						$this->Conn->nextQueryCachable = true;
						$all_custom_fields = $this->getCustomFields();
						$this->Application->setCache($cache_key, $all_custom_fields);
					}
				}

				foreach ($all_custom_fields as $custom_field_id => $custom_field_data) {
					$cf_type = $custom_field_data['Type'];
					if (!array_key_exists($cf_type, $custom_fields)) {
						$custom_fields[$cf_type] = Array ();
					}

					$custom_fields[$cf_type][$custom_field_id] = $custom_field_data;
				}
			}

			return array_key_exists($item_type, $custom_fields) ? $custom_fields[$item_type] : false;
		}

		/**
		 * Returns sorted list of all custom fields
		 *
		 * @return Array
		 */
		function getCustomFields()
		{
			$sql = 'SELECT *
					FROM '.TABLE_PREFIX.'CustomField';
			$ret = $this->Conn->Query($sql, 'CustomFieldId');

			ksort($ret);

			return $ret;
		}

		/**
		 * Fills cloned cdata config with data from it's parent
		 *
		 * @param kEvent $event
		 */
		function OnAfterConfigRead(&$event)
		{
			$main_prefix = $this->Application->getUnitOption($event->Prefix, 'ParentPrefix');
			if (!$main_prefix) {
				return false;
			}

			$custom_fields = $this->scanCustomFields($main_prefix);
			if (!$custom_fields) {
				return false;
			}

			// 2. create fields (for customdata item)
			$fields = $this->Application->getUnitOption($event->Prefix, 'Fields', Array());
			$field_options = Array('type' => 'string', 'formatter' => 'kMultiLanguage', 'db_type' => 'text', 'default' => '');
			foreach ($custom_fields as $custom_id => $custom_params) {
				if (isset($fields['cust_'.$custom_id])) continue;
				$fields['cust_'.$custom_id] = $field_options;
				$fields['cust_'.$custom_id]['force_primary'] = !$custom_params['MultiLingual'];
			}
			$this->Application->setUnitOption($event->Prefix, 'Fields', $fields);
		}

		/**
		 * Creates "cust_<custom_name>" virtual fields for main item
		 *
		 * @param string $prefix
		 */
		function createCustomFields($prefix)
		{
			$custom_fields = $this->scanCustomFields($prefix);
			if (!$custom_fields) {
				return false;
			}

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

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

			$is_install = defined('IS_INSTALL') && IS_INSTALL;

			foreach ($custom_fields as $custom_id => $custom_params) {
				$custom_name = $custom_params['FieldName'];
				$field_options = Array('type' => 'string', 'default' => $custom_params['DefaultValue']);

				// raises warnings during 4.3.9 -> 5.0.0 upgrade, no fatal sqls though
				if ($custom_params['IsRequired']) {
					$field_options['required'] = 1;
				}

				switch ($custom_params['ElementType']) {
					case 'date':
						unset($field_options['options']);
						$field_options['formatter'] = 'kDateFormatter';
						$field_options['input_time_format'] = '';
						$field_options['time_format'] = '';
						break;

					case 'datetime':
						unset($field_options['options']);
						$field_options['formatter'] = 'kDateFormatter';
						break;

					case 'select':
					case 'multiselect':
					case 'radio':
						if ($custom_params['ValueList']) {
							// $is_install check prevents 335 bad phrase sql errors on upgrade to 5.1.0
							$field_options['options'] = $is_install ? Array () : $cf_helper->GetValuesHash($custom_params['ValueList']);
							$field_options['formatter'] = 'kOptionsFormatter';
							$field_options['multiple'] = $custom_params['ElementType'] == 'multiselect';
						}
						break;

					default:
						if ($custom_params['MultiLingual']) {
							$calculated_fields['cust_'.$custom_name.'_Primary'] = 'cust.'.$ml_formatter->LangFieldName('cust_'.$custom_id, true);
							$virtual_fields['cust_'.$custom_name.'_Primary'] = $field_options;
							$field_options['master_field'] = 'cust_'.$custom_name.'_Primary';
							$field_options['formatter'] = 'kCustomFieldFormatter';
						}
						break;
				}

				$calculated_fields['cust_'.$custom_name] = 'cust.'.$ml_formatter->LangFieldName('cust_'.$custom_id, !$custom_params['MultiLingual']);
				if (!isset($virtual_fields['cust_'.$custom_name])) {
					$virtual_fields['cust_'.$custom_name] = Array();
				}
				$virtual_fields['cust_'.$custom_name] = array_merge_recursive2($field_options, $virtual_fields['cust_'.$custom_name]);
				$custom_fields[$custom_id] = $custom_name;
			}

			$config_calculated_fields = $this->Application->getUnitOption($prefix, 'CalculatedFields', Array());
			foreach ($config_calculated_fields as $special => $special_fields) {
				if ($special == '-virtual') {
					continue;
				}

				$config_calculated_fields[$special] = array_merge_recursive2($config_calculated_fields[$special], $calculated_fields);
			}
			$this->Application->setUnitOption($prefix, 'CalculatedFields', $config_calculated_fields);

			$this->Application->setUnitOption($prefix, 'CustomFields', $custom_fields);
			$this->Application->setUnitOption($prefix, 'VirtualFields', $virtual_fields);
		}
	}