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

		/**
		 * Changes permission section to one from REQUEST, not from config
		 *
		 * @param kEvent $event
		 */
		function CheckPermission(&$event)
		{
			$event->setEventParam('PermSection', $this->Application->GetVar('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 */

			$module = $this->Application->GetVar('module');
			$section = $this->Application->GetVar('section');

			$object->addFilter('module_filter', '%1$s.ModuleOwner = '.$this->Conn->qstr($module));
			$object->addFilter('section_filter', '%1$s.Section = '.$this->Conn->qstr($section));

			if (!$this->Application->ConfigValue('AllowAdminConsoleInterfaceChange')) {
				$object->addFilter('interface_change_filter', '%1$s.VariableName <> "AdminConsoleInterface"');
			}

			if (defined('IS_INSTALL') && IS_INSTALL) {
				$object->addFilter('install_filter', '%1$s.Install = 1');
			}

			$object->addFilter('visible_filter', '%1$s.Heading <> ""');
		}

		/**
		 * Enter description here...
		 *
		 * @param kEvent $event
		 */
		function OnBeforeItemUpdate(&$event)
		{
			static $default_field_options = null;

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

			// ability to validate each configuration variable separately
			if (!isset($default_field_options)) {
				$default_field_options = $object->GetFieldOptions('VariableValue');
			}

			$new_field_options = $default_field_options;
			$validation = $object->GetDBField('Validation');
			if ($validation) {
				$new_field_options = array_merge($new_field_options, unserialize($validation));
			}
			$object->SetFieldOptions('VariableValue', $new_field_options);

			// if password field is empty, then don't update
			if ($object->GetDBField('ElementType') == 'password') {
				if (trim($object->GetDBField('VariableValue')) == '') {
					$field_options = $object->GetFieldOptions('VariableValue');
					$field_options['skip_empty'] = 1;
					$object->SetFieldOptions('VariableValue', $field_options);
				}else {
					$password_formatter =& $this->Application->recallObject('kPasswordFormatter');
					$object->SetDBField('VariableValue', $password_formatter->EncryptPassword($object->GetDBField('VariableValue'), 'b38'));
				}
			}

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

			$state_country_hash = Array (
				'Comm_State' => 'Comm_Country',
				'Comm_Shipping_State' => 'Comm_Shipping_Country'
			);

			$field_name = $object->GetDBField('VariableName');
			if (array_key_exists($field_name, $state_country_hash)) {
				// if this is state field
				$sql = 'SELECT VariableId
						FROM ' . $this->Application->getUnitOption('conf', 'TableName') . '
						WHERE VariableName = "' . $state_country_hash[$field_name] . '"';
				$country_variable_id = $this->Conn->GetOne($sql);

				$check_state = $object->GetDBField('VariableValue');
				$check_country = $field_values[$country_variable_id]['VariableValue'];

				if (!$check_country || !$check_state) {
					return true;
				}

				$cs_helper =& $this->Application->recallObject('CountryStatesHelper');
				/* @var $cs_helper kCountryStatesHelper */

				$state_iso = $cs_helper->getStateIso($check_state, $check_country);

				if ($state_iso !== false) {
					$object->SetDBField('VariableValue', $state_iso);
				}
				else {
					// selected state doesn't belong to selected country
					$object->SetError('VariableValue', 'invalid_state', 'la_InvalidState');
				}
			}

			if ($object->GetDBField('VariableName') == 'AdminConsoleInterface') {
				$can_change = $this->Application->ConfigValue('AllowAdminConsoleInterfaceChange');

				if (($object->GetDBField('VariableValue') != $object->GetOriginalField('VariableValue')) && !$can_change) {
					$object->SetError('VariableValue', 'not_allowed', 'la_error_OperationNotAllowed');
				}

			}
		}

		/**
		 * Enter description here...
		 *
		 * @param kEvent $event
		 */
		function OnAfterItemUpdate(&$event)
		{
			$object =& $event->getObject();
			/* @var $object kDBItem */

			if ($object->GetDBField('ElementType') == 'password') {
				if (trim($object->GetDBField('VariableValue')) == '') {
					$field_options = $object->GetFieldOptions('VariableValue');
					unset($field_options['skip_empty']);
					$object->SetFieldOptions('VariableValue', $field_options);
				}
			}

			// allows to check if variable's value was changed now
			$variable_name = $object->GetDBField('VariableName');
			$variable_value = $object->GetDBField('VariableValue');
			$watch_variables = Array (
				'Require_AdminSSL', 'AdminSSL_URL', 'AdvancedUserManagement',
				'Site_Name', 'AdminConsoleInterface', 'UsePopups'
			);

			if (in_array($variable_name, $watch_variables)) {
				$changed = $this->Application->GetVar($event->getPrefixSpecial() . '_changed', Array ());

				if ($variable_value != $object->GetOriginalField('VariableValue')) {
					$changed[] = $variable_name;
					$this->Application->SetVar($event->getPrefixSpecial() . '_changed', $changed);
				}

				switch ($variable_name) {
					case 'Require_AdminSSL':
					case 'AdminSSL_URL':
						static $skin_deleted = false;

						if (in_array($variable_name, $changed) && !$skin_deleted) {
							// when administrative console is moved to SSL mode, then delete skin
							$skin_helper =& $this->Application->recallObject('SkinHelper');
							/* @var $skin_helper SkinHelper */

							$skin_file = $skin_helper->getSkinPath();
							if (file_exists($skin_file)) {
								unlink($skin_file);
							}

							$skin_deleted = true;
						}
						break;
				}
			}

		}

		/**
		 * Enter description here...
		 *
		 * @param kEvent $event
		 */
		function OnUpdate(&$event)
		{
			if ($this->Application->CheckPermission('SYSTEM_ACCESS.READONLY', 1)) {
				$event->status = erFAIL;
				return ;
			}

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

			// 1. save user selected module root category
			$new_category_id = getArrayValue($items_info, 'ModuleRootCategory', 'VariableValue');
			if ($new_category_id !== false) {
				unset($items_info['ModuleRootCategory']);
			}

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

			if ($items_info) {
				$has_error = false;
				foreach ($items_info as $id => $field_values) {
					$object->Clear(); // clear validation errors from previous variable
					$object->Load($id);
	 				$object->SetFieldsFromHash($field_values);

					if (!$object->Update($id)) {
						// don't stop when error found !
						$has_error = true;
					}
				}

				$event->status = $has_error ? erFAIL : erSUCCESS;
			}

			if ($event->status == erSUCCESS) {
				if ($new_category_id !== false) {
					// root category was submitted
					$module = $this->Application->GetVar('module');
					$root_category_id = $this->Application->findModule('Name', $module, 'RootCat');

					if ($root_category_id != $new_category_id) {
						// root category differs from one in db
						$fields_hash = Array('RootCat' => $new_category_id);
						$this->Conn->doUpdate($fields_hash, TABLE_PREFIX.'Modules', 'Name = '.$this->Conn->qstr($module));
					}
				}

				// reset cache
				$changed = $this->Application->GetVar($event->getPrefixSpecial() . '_changed', Array ());
				$require_refresh = Array (
					'AdvancedUserManagement', 'Site_Name', 'AdminConsoleInterface', 'UsePopups'
				);

				$refresh_sections = array_intersect($require_refresh, $changed);
				$require_full_refresh = Array ('Site_Name', 'AdminConsoleInterface');

				if (array_intersect($require_full_refresh, $changed)) {
					$event->SetRedirectParam('refresh_all', 1);
				} elseif ($refresh_sections) {
					// reset sections too, because of AdvancedUserManagement
					$event->SetRedirectParam('refresh_tree', 1);
				}

				$this->Application->UnitConfigReader->ResetParsedData($refresh_sections ? true : false);
			}
			elseif ($this->Application->GetVar('errors_' . $event->getPrefixSpecial())) {
				// because we have list out there, and this is item
				$this->Application->removeObject( $event->getPrefixSpecial() );
			}

			// keeps module and section in REQUEST to ensure, that last admin template will work
			$event->SetRedirectParam('module', $this->Application->GetVar('module'));
			$event->SetRedirectParam('section', $this->Application->GetVar('section'));
		}

		/**
		 * Enter description here...
		 *
		 * @param kEvent $event
		 */
		/*function OnChangeCountry(&$event)
		{
			$event->setPseudoClass('_List');
			$object = &$event->getObject( Array('per_page'=>-1) );
			$object->Query();
			$array_records =& $object->Records;
			foreach($array_records as $i=>$record){
				if ($record['VariableName']=='Comm_Country'){
					$values = $this->Application->GetVar('conf');
					$array_records[$i]['VariableValue'] = $values['Comm_Country']['VariableValue'];
				}
			}

			$event->redirect_params = Array('opener' => 's', 'pass'=>'all,conf'); //stay!
			$event->redirect = false;
		}*/

		/**
		 * Process items from selector (selected_ids var, key - prefix, value - comma separated ids)
		 *
		 * @param kEvent $event
		 */
		function OnProcessSelected(&$event)
		{
			$selected_ids = $this->Application->GetVar('selected_ids');
			$this->Application->StoreVar('ModuleRootCategory', $selected_ids['c']);

			$event->SetRedirectParam('opener', 'u');
		}

	}