<?php
/**
* @version	$Id: minput_helper.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 MInputHelper extends kHelper {


		/**
		 * Returns user education table name
		 *
		 * @param kDBItem $object
		 * @return string
		 */
		function getTable($prefix, $temp=false)
		{
			$table_name = $this->Application->getUnitOption($prefix, 'TableName');
			return $temp ? $this->Application->GetTempName($table_name, 'prefix:'.$prefix) : $table_name;
		}

		function prepareMInputXML($records, $use_fields)
		{
			$xml = '';
			foreach ($records as $record) {
				$xml .= '<record>';
				foreach ($record as $field_name => $field_value) {
					if (!in_array($field_name, $use_fields)) {
						continue;
					}
					$xml .= '<field name="' . $field_name . '">' . htmlspecialchars($field_value) . '</field>';
				}
				$xml .= '</record>';
			}

			return $xml ? '<records>'.$xml.'</records>' : '';
		}

		/**
		 * Returns validation errors in XML format
		 *
		 * @param kDBItem $object
		 * @param Array $fields_hash
		 * @return string
		 */
		function prepareErrorsXML(&$object, $fields_hash)
		{
			$xml = '';
			$errors = Array ();

			foreach ($fields_hash as $field_name => $field_value) {
				if (!$object->ValidateField($field_name)) {
					$field_options = $object->GetFieldOptions($field_name);
					$error_field = array_key_exists('error_field', $field_options) ? $field_options['error_field'] : $field_name;

					$errors[$error_field] = '<field name="'.$error_field.'">'.$object->GetErrorMsg($error_field, false).'</field>';
				}
			}

			return '<errors>'.implode('', $errors).'</errors>';
		}

		/**
		 * Validates MInput control fields
		 *
		 * @param kEvent $event
		 */
		function OnValidateMInputFields(&$event)
		{
			$object =& $event->getObject();
			/* @var $object kDBItem */

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

				foreach ($field_values as $field_name => $field_value) {
					$object->SetField($field_name, $field_value);
				}

				$event_mapping = Array (
					'AddRecord' => 'OnBeforeItemCreate',
					'SaveRecord' => 'OnBeforeItemUpdate',
				);

				$request_type = $this->Application->GetVar('request_type');

				if (array_key_exists($request_type, $event_mapping)) {
					$event->CallSubEvent($event_mapping[$request_type]);
				}

				echo $this->prepareErrorsXML($object, $field_values);
			}

			$event->status = erSTOP;
		}

		function parseMInputXML($xml)
		{
			$xml_helper =& $this->Application->recallObject('kXMLHelper');
			/* @var $xml_helper kXMLHelper */

			$root_node =& $xml_helper->Parse($xml);
			$root_node =& $root_node->FindChild('records');
			if (!$root_node || !$root_node->firstChild) {
				return false;
			}

			$records = Array ();
			$current_node = $root_node->firstChild;
			/* @var $current_node kXMLNode */

			do {
				$record = Array();
				$sub_node =& $current_node->firstChild;
				/* @var $current_node kXMLNode */

				do {
					$record[$sub_node->Attributes['NAME']] = $sub_node->Data;

				}while ( ($sub_node =& $sub_node->NextSibling()) );

				$records[] = $record;
			} while (($current_node =& $current_node->NextSibling()));

			return $records;
		}

		/**
		 * Loads selected values from sub_prefix to main item virtual field.
		 * Called from OnAfterItemLoad of main prefix.
		 *
		 * @param kEvent $event
		 * @param string $store_field main item's field name, to store values into
		 * @param string $sub_prefix prefix used to store info about selected items
		 * @param Array $use_fields fields, used in value string building
		 */
		function LoadValues(&$event, $store_field, $sub_prefix, $use_fields)
		{
			$object =& $event->getObject();
			/* @var $object kDBItem */

			$sub_item =& $this->Application->recallObject($sub_prefix, null, Array('skip_autoload' => true));
			/* @var $sub_item kDBItem */

			$foreign_key = $this->Application->getUnitOption($sub_prefix, 'ForeignKey');

			$sql = 'SELECT *
					FROM '.$this->getTable($sub_prefix, $object->IsTempTable()).'
					WHERE '.$foreign_key.' = '.$object->GetID();

			$selected_items = $this->Conn->Query($sql);

			$field_names = array_keys( $sub_item->GetFieldValues() );

			foreach ($selected_items as $key => $fields_hash) {
				$sub_item->Clear();
				$sub_item->SetDBFieldsFromHash($fields_hash);

				// to fill *_date and *_time fields from main date fields
				$sub_item->UpdateFormattersSubFields();

				foreach ($field_names as $field) {
					$field_options = $sub_item->GetFieldOptions($field);
					$formatter = array_key_exists('formatter', $field_options) ? $field_options['formatter'] : false;

					if ($formatter == 'kDateFormatter') {
						$selected_items[$key][$field] = $sub_item->GetField($field, $field_options['input_format']);
					}
					else {
						$selected_items[$key][$field] = $sub_item->GetDBField($field);
					}
				}
			}

			$object->SetDBField($store_field, $this->prepareMInputXML($selected_items, $use_fields));
		}

		/**
		 * Saves data from minput control to subitem table (used from subitem hook)
		 *
		 * @param kEvent $sub_event
		 * @param string $store_field
		 */
		function SaveValues(&$sub_event, $store_field)
		{
			$main_object =& $sub_event->MasterEvent->getObject();
			$affected_field = $main_object->GetDBField($store_field);

			$object =& $this->Application->recallObject($sub_event->getPrefixSpecial(), null, Array('skip_autoload' => true));
			/*@var $object kDBItem*/

			$sub_table = $object->TableName;
			$foreign_key = $this->Application->getUnitOption($sub_event->Prefix, 'ForeignKey');

			$sql = 'DELETE FROM '.$sub_table.'
					WHERE '.$foreign_key.' = '.$main_object->GetID();

			$this->Conn->Query($sql);

			if ($affected_field) {
				$records = $this->parseMInputXML($affected_field);
				$main_id = $main_object->GetID();

				foreach ($records as $fields_hash) {
					$object->Clear();
					$fields_hash[$foreign_key] = $main_id;
					$object->SetDBFieldsFromHash($fields_hash);
					$object->Create();
				}
			}
		}
	}