<?php
/**
* @version	$Id: country_states_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 kCountryStatesHelper extends kHelper
	{
		/**
		 * Returns countries, that have states
		 *
		 * @return Array
		 */
		function getCountriesWithStates()
		{
			static $cache = null;

			if (!isset($cache)) {
				$table_name = $this->Application->getUnitOption('country-state', 'TableName');

				$sql = 'SELECT DISTINCT cname.IsoCode, cid.StateCountryId
						FROM ' . $table_name . ' cid
						JOIN ' . $table_name . ' cname ON cname.CountryStateId = cid.StateCountryId
						WHERE cid.StateCountryId IS NOT NULL';
				$cache = $this->Conn->GetCol($sql, 'StateCountryId');
			}

			return $cache;
		}

		/**
		 * Checks, that country with given 3symbol ISO code has states
		 *
		 * @param string $country_code
		 * @return bool
		 */
		function CountryHasStates($country_code)
		{
			return $country_code ? in_array($country_code, $this->getCountriesWithStates()) : false;
		}

		/**
		 * Prepares states dropdown based on country selected
		 *
		 * @param kEvent $event
		 * @param string $state_field
		 * @param string $country_field
		 */
		function PopulateStates(&$event, $state_field, $country_field)
		{
			static $cache = Array ();

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

			$country_iso = $object->GetDBField($country_field);

			if (!$country_iso) {
				return ;
			}

			if (!array_key_exists($country_iso, $cache)) {
				$country_id = $this->getCountryStateId($country_iso, DESTINATION_TYPE_COUNTRY);

				if (!$country_id) {
					return ;
				}

				// don't use GetVar('m_lang') since it's always equals to default language on editing form in admin
				$current_language = $this->Application->Phrases->LanguageId;
				$primary_language = $this->Application->GetDefaultLanguageId();

				$sql = 'SELECT IF(l' . $current_language . '_Name = "", l' . $primary_language . '_Name, l' . $current_language . '_Name) AS Name, IsoCode
						FROM ' . $this->Application->getUnitOption('country-state', 'TableName') . '
						WHERE (Type = ' . DESTINATION_TYPE_STATE . ') AND (StateCountryId = ' . $country_id . ')
						ORDER BY Name ASC';
				$cache[$country_iso] = $this->Conn->GetCol($sql, 'IsoCode');
			}

			$field_options = $object->GetFieldOptions($state_field);

			$field_options['options'] = $cache[$country_iso];
			$field_options['options'][''] = '';

			$object->SetFieldOptions($state_field, $field_options);
		}

		/**
		 * Returns valid state ISO code for state name and country code passed
		 *
		 * @param string $state_name
		 * @param string $country_iso
		 * @return string
		 */
		function getStateIso($state_name, $country_iso)
		{
			if (!$this->CountryHasStates($country_iso)) {
				return $state_name;
			}

			$table_name = $this->Application->getUnitOption('country-state', 'TableName');
			$country_id = $this->getCountryStateId($country_iso, DESTINATION_TYPE_COUNTRY);

			// don't use GetVar('m_lang') since it's always equals to default language on editing form in admin
			$current_language = $this->Application->Phrases->LanguageId;
			$primary_language = $this->Application->GetDefaultLanguageId();

			$sql = 'SELECT IsoCode
					FROM ' . $table_name . '
					WHERE (Type = ' . DESTINATION_TYPE_STATE . ') AND (StateCountryId = %1$s) AND
						(
							(IsoCode = %2$s) OR (UPPER(l%3$s_Name) = %2$s) OR (UPPER(l%4$s_Name) = %2$s)
						)';

			$state_name = trim( mb_strtoupper($state_name) );
			$sql = sprintf($sql, $country_id, $this->Conn->qstr($state_name), $current_language, $primary_language);

			return $this->Conn->GetOne($sql);
		}

		function CheckStateField(&$event, $state_field, $country_field, $auto_required = true)
		{
			$object =& $event->getObject();
			/* @var $object kDBItem */

			$country_iso = $object->GetDBField($country_field);

			if ($auto_required) {
				$object->setRequired($state_field, $this->CountryHasStates($country_iso));
			}

			$state = $object->GetDBField($state_field);

			if ($country_iso && $state) {
				$state_iso = $this->getStateIso($state, $country_iso);

				if ($state_iso !== false) {
					// replace state name with it's ISO code
					$object->SetDBField($state_field, $state_iso);
				}
				else {
					// state not found by name -> report error
					$object->SetError($state_field, 'invalid_state', 'la_invalid_state');
				}
			}
		}

		/**
		 * Returns country/state id based on given iso code and it's type
		 *
		 * @param string $iso_code
		 * @param int $type
		 * @return int
		 */
		function getCountryStateId($iso_code, $type)
		{
			$sql = 'SELECT ' . $this->Application->getUnitOption('country-state', 'IDField') . '
					FROM ' . $this->Application->getUnitOption('country-state', 'TableName') . '
					WHERE (Type = ' . $type . ') AND (IsoCode = ' . $this->Conn->qstr($iso_code) . ')';

			return (int)$this->Conn->GetOne($sql);
		}

		/**
		 * Returns 3 symbols ISO code from 2 symbols ISO code or otherwise, when $from_short parameter is used
		 *
		 * @param string $iso_code
		 * @param bool $from_short
		 * @return string
		 */
		function getCountryIso($iso_code, $from_short = false)
		{
			if ($from_short) {
				$sql = 'SELECT IsoCode
						FROM ' . TABLE_PREFIX . 'CountryStates
						WHERE ShortIsoCode = ' . $this->Conn->qstr($iso_code) . ' AND `Type` = ' . DESTINATION_TYPE_COUNTRY;
			}
			else {
				$sql = 'SELECT ShortIsoCode
						FROM ' . TABLE_PREFIX . 'CountryStates
						WHERE IsoCode = ' . $this->Conn->qstr($iso_code) . ' AND `Type` = ' . DESTINATION_TYPE_COUNTRY;
			}

			return $this->Conn->GetOne($sql);
		}
	}