<?php
/**
* @version	$Id: site_domain_eh.php 16513 2017-01-20 14:10:53Z alex $
* @package	In-Portal
* @copyright	Copyright (C) 1997 - 2010 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 SiteDomainEventHandler extends kDBEventHandler {

		/**
		 * Checks user permission to execute given $event
		 *
		 * @param kEvent $event
		 * @return bool
		 * @access public
		 */
		public function CheckPermission(kEvent $event)
		{
			if ( $event->Name == 'OnItemBuild' ) {
				// check permission without using $event->getSection(),
				// so first cache rebuild won't lead to "ldefault_Name" field being used
				return true;
			}

			return parent::CheckPermission($event);
		}

		/**
		 * Returns ID of site domain, that matches current url
		 *
		 * @param kEvent $event
		 * @return int
		 * @access public
		 */
		public function getPassedID(kEvent $event)
		{
			if ( $event->Special == 'current' ) {
				if ( $this->Application->isAdmin ) {
					$event->setEventParam('raise_warnings', 0);
				}
				else {
					if ( PROTOCOL == 'https://' ) {
						return $this->querySiteDomain('SSLUrl', rtrim($this->Application->BaseURL(), '/'));
					}

					return $this->querySiteDomain('DomainName', $_SERVER['HTTP_HOST']);
				}
			}

			return parent::getPassedID($event);
		}

		function querySiteDomain($field, $value)
		{
			/** @var SiteHelper $site_helper */
			$site_helper = $this->Application->recallObject('SiteHelper');

			$site_domains = $site_helper->getSiteDomains();
			$domain_by_name = $site_helper->getDomainByName($field, $value);
			$domain_by_ip = $site_helper->getDomainByIP();

			if ($domain_by_ip) {
				$site_domain = $site_domains[$domain_by_ip];
				$redirect_mode = $site_domain['RedirectOnIPMatch'];

				if (($redirect_mode == SITE_DOMAIN_REDIRECT_EXTERNAL) && ($domain_by_ip == $domain_by_name)) {
					// redirect to external url (when visiting protected domain)
					$external_url = $site_domain['ExternalUrl'];

					if (preg_match('/^http[s]{0,1}:\/\//', $external_url)) {
						$this->Application->Redirect('external:' . $external_url);
					}
					else {
						$this->Application->Redirect('external:' . PROTOCOL . $external_url . $_SERVER['REQUEST_URI']);
					}
				}
				elseif (($redirect_mode == SITE_DOMAIN_REDIRECT_CURRENT) && ($domain_by_ip != $domain_by_name)) {
					// redirect to a domain detected by IP (when not already on it)
					if ((PROTOCOL == 'https://') && !$site_domain['SSLUrlUsesRegExp'] && $site_domain['SSLUrl']) {
						// need to remove sub folder from ssl url
						$ssl_url = preg_replace('/^(https:\/\/[^\/]*)(\/.*){0,1}$/', '\\1', $site_domain['SSLUrl']);
						$this->Application->Redirect('external:' . $ssl_url . $_SERVER['REQUEST_URI']);
					}
					elseif ((PROTOCOL == 'http://') && !$site_domain['DomainNameUsesRegExp']) {
						$this->Application->Redirect('external:http://' . $site_domain['DomainName'] . $_SERVER['REQUEST_URI']);
					}
				}

				return $domain_by_ip;
			}

			return $domain_by_name;
		}

		/**
		 * Load item if id is available
		 *
		 * @param kEvent $event
		 * @return void
		 * @access protected
		 */
		protected function LoadItem(kEvent $event)
		{
			if ( $this->Application->isAdmin ) {
				// don't load domain data from cache
				parent::LoadItem($event);

				return;
			}

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

			$id = (int)$this->getPassedID($event);

			if ( $object->isLoaded() && ($object->GetID() == $id) ) {
				// object is already loaded by same id
				return;
			}

			/** @var SiteHelper $site_helper */
			$site_helper = $this->Application->recallObject('SiteHelper');

			$site_domains = $site_helper->getSiteDomains();
			$domain_data = array_key_exists($id, $site_domains) ? $site_domains[$id] : false;

			if ( $object->LoadFromHash($domain_data) ) {
				/** @var Params $actions */
				$actions = $this->Application->recallObject('kActions');

				$actions->Set($event->getPrefixSpecial() . '_id', $object->GetID());
			}
			else {
				$object->setID($id);
			}
		}

		/**
		 * Removes In-Commerce related fields, when it's not installed
		 *
		 * @param kEvent $event
		 * @return void
		 * @access protected
		 */
		protected function OnAfterConfigRead(kEvent $event)
		{
			parent::OnAfterConfigRead($event);

			if (!$this->Application->isModuleEnabled('In-Commerce')) {
				$remove_fields = Array (
					'BillingCountry', 'ShippingCountry',
					'PrimaryCurrencyId', 'Currencies',
					'PrimaryPaymentTypeId', 'PaymentTypes'
				);

				// remove field definitions
				$fields = $this->Application->getUnitOption($event->Prefix, 'Fields');

				foreach ($remove_fields as $remove_field) {
					unset($fields[$remove_field]);
				}

				$this->Application->setUnitOption($event->Prefix, 'Fields', $fields);

				// remove grid columns
				/** @var Array $grids */
				$grids = $this->Application->getUnitOption($event->Prefix, 'Grids', Array ());

				foreach ($grids as $grid_name => $grid_info) {
					foreach ($remove_fields as $remove_field) {
						if (array_key_exists($remove_field, $grid_info['Fields'])) {
							unset($grids[$grid_name]['Fields'][$remove_field]);
						}
					}
				}

				$this->Application->setUnitOption($event->Prefix, 'Grids', $grids);
			}
		}

		/**
		 * Delete cached information about site domains
		 *
		 * @param kEvent $event
		 * @return void
		 * @access protected
		 */
		protected function OnSave(kEvent $event)
		{
			parent::OnSave($event);

			if ( $event->status == kEvent::erSUCCESS ) {
				$this->_deleteCache();
			}
		}

		/**
		 * Deletes cached information about site domains
		 */
		function _deleteCache()
		{
			if ( $this->Application->isCachingType(CACHING_TYPE_MEMORY) ) {
				$this->Application->rebuildCache('master:domains_parsed', kCache::REBUILD_LATER, CacheSettings::$domainsParsedRebuildTime);
			}
			else {
				$this->Application->rebuildDBCache('domains_parsed', kCache::REBUILD_LATER, CacheSettings::$domainsParsedRebuildTime);
			}

			$sql = 'DELETE FROM ' . TABLE_PREFIX . 'CachedUrls';
			$this->Conn->Query($sql);
		}

		/**
		 * Sets required fields based on redirect mode
		 *
		 * @param kEvent $event
		 * @return void
		 * @access protected
		 */
		protected function OnAfterItemLoad(kEvent $event)
		{
			parent::OnAfterItemLoad($event);

			$this->_setRequired($event);
		}

		/**
		 * Set's required fields based on redirect mode
		 *
		 * @param kEvent $event
		 * @return void
		 * @access protected
		 */
		protected function OnBeforeItemCreate(kEvent $event)
		{
			parent::OnBeforeItemCreate($event);

			$this->_itemChanged($event);
		}

		/**
		 * Set's required fields based on redirect mode
		 *
		 * @param kEvent $event
		 * @return void
		 * @access protected
		 */
		protected function OnBeforeItemUpdate(kEvent $event)
		{
			parent::OnBeforeItemUpdate($event);

			$this->_itemChanged($event);
		}

		/**
		 * Deletes site domain cache
		 *
		 * @param kEvent $event
		 * @return void
		 * @access protected
		 */
		protected function OnAfterItemDelete(kEvent $event)
		{
			parent::OnAfterItemDelete($event);

			$this->_deleteCache();
		}

		/**
		 * Occurs before item is changed
		 *
		 * @param kEvent $event
		 */
		function _itemChanged($event)
		{
			/** @var kDBItem $object */
			$object = $event->getObject();

			$email_event_data = $this->Application->GetVar('email-template_' . $event->Prefix);
			$object->SetDBField('DefaultEmailRecipients', $email_event_data[0]['Recipients']);

			$this->_setRequired($event);
		}

		/**
		 * Set's required fields
		 *
		 * @param kEvent $event
		 */
		function _setRequired($event)
		{
			/** @var kDBItem $object */
			$object = $event->getObject();

			$redirect_mode = $object->GetDBField('RedirectOnIPMatch');
			$object->setRequired('ExternalUrl', $redirect_mode == SITE_DOMAIN_REDIRECT_EXTERNAL);
			$object->setRequired('DomainIPRange', $redirect_mode > 0);
		}
	}
