<?php
/**
* @version	$Id: languages_item.php 15012 2012-01-06 20:38:49Z 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 LanguagesItem extends kDBItem
	{
		function generateID()
		{
			$sql = 'SELECT MAX('.$this->IDField.') FROM '.$this->Application->getUnitOption($this->Prefix, 'TableName');
			return $this->Conn->GetOne($sql) + 1;
		}

		/**
		 * Set's current language as new primary and return previous primary language
		 *
		 * @param bool $reset_primary
		 * @param bool $admin_language
		 * @return int
		 */
		function setPrimary($reset_primary = true, $admin_language = false)
		{
			$prev_primary = false;
			$primary_field = $admin_language ? 'AdminInterfaceLang' : 'PrimaryLang';

			if ($reset_primary) {
				$sql = 'SELECT ' . $this->IDField . '
						FROM ' . $this->TableName . '
						WHERE ' . $primary_field . ' = 1';
				$prev_primary = $this->Conn->GetOne($sql);

				$sql = 'UPDATE '.$this->TableName.'
						SET '.$primary_field.' = 0';
				$this->Conn->Query($sql);
			}

			$sql = 'UPDATE '.$this->TableName.'
					SET '.$primary_field.' = 1, Enabled = 1
					WHERE '.$this->IDField.' = '.$this->GetID();
			$this->Conn->Query($sql);

			// in case, when Update method is called for this langauge object
			$this->SetDBField($primary_field, 1);
			$this->SetDBField('Enabled', 1);

			// increment serial by hand, since no Update method is called
			$this->Application->incrementCacheSerial($this->Prefix);
			$this->Application->incrementCacheSerial($this->Prefix, $this->GetID());

			return $prev_primary;
		}

		/**
		 * Copies missing data on current language from given language
		 *
		 * @param int $from_language
		 */
		function copyMissingData($from_language)
		{
			if ( !is_numeric($from_language) || ($from_language == $this->GetID()) ) {
				// invalid or same language
				return ;
			}

			$ml_helper =& $this->Application->recallObject('kMultiLanguageHelper');
			/* @var $ml_helper kMultiLanguageHelper */

			$to_language = $this->GetID();
			$this->Application->UnitConfigReader->ReReadConfigs();

			foreach ($this->Application->UnitConfigReader->configData as $prefix => $config_data) {
				$ml_helper->copyMissingData($prefix, $from_language, $to_language);
			}
		}

		/**
		 * Allows to format number according to regional settings
		 *
		 * @param float $number
		 * @param int $precision
		 * @return float
		 */
		function formatNumber($number, $precision = null)
		{
			if (is_null($precision)) {
				$precision = preg_match('/[\.,]+/', $number) ? strlen(preg_replace('/^.*[\.,]+/', '', $number)) : 0;
			}
			return number_format($number, $precision, (string)$this->GetDBField('DecimalPoint'), (string)$this->GetDBField('ThousandSep'));
		}

		/**
		 * Returns language id based on HTTP header "Accept-Language"
		 *
		 * @return int
		 */
		function processAcceptLanguage()
		{
			if (!array_key_exists('HTTP_ACCEPT_LANGUAGE', $_SERVER) || !$_SERVER['HTTP_ACCEPT_LANGUAGE']) {
				return false;
			}

			$accepted_languages = Array ();
			$language_string = explode(',', strtolower($_SERVER['HTTP_ACCEPT_LANGUAGE']));

			foreach ($language_string as $mixed_language) {
				if (strpos($mixed_language, ';') !== false) {
					list ($language_locale, $language_quality) = explode(';', $mixed_language);
					$language_quality = (float)substr($language_quality, 2); // format "q=4.45"
				}
				else {
					$language_locale = $mixed_language;
					$language_quality = 1.00;
				}

				$accepted_languages[ trim($language_locale) ] = trim($language_quality);
			}

			arsort($accepted_languages, SORT_NUMERIC);

			foreach ($accepted_languages as $language_locale => $language_quality) {
				$language_id = $this->getAvailableLanguage($language_locale);

				if ($language_id) {
					return $language_id;
				}
			}

			return false;
		}

		/**
		 * Returns language ID based on given locale
		 *
		 * @param string $locale
		 * @return int
		 */
		function getAvailableLanguage($locale)
		{
			$cache_key = 'available_languages[%LangSerial%]';
			$available_languages = $this->Application->getCache($cache_key);

			if ($available_languages === false) {
				$this->Conn->nextQueryCachable = true;
				$sql = 'SELECT LanguageId, LOWER(Locale) AS Locale
						FROM ' . TABLE_PREFIX . 'Languages
						WHERE Enabled = 1';
				$available_languages = $this->Conn->GetCol($sql, 'Locale');
				$this->Application->setCache($cache_key, $available_languages);
			}

			if (strpos($locale, '-') !== false) {
				// exact language match requested
				$language_id = array_key_exists($locale, $available_languages) ? $available_languages[$locale] : false;

				if ($language_id && $this->siteDomainLanguageEnabled($language_id)) {
					return $language_id;
				}

				return false;
			}

			// partial (like "en" matches "en-GB" and "en-US") language match required
			foreach ($available_languages as $language_code => $language_id) {
				list ($language_code, ) = explode('-', $language_code);

				if (($locale == $language_code) && $this->siteDomainLanguageEnabled($language_id)) {
					return $language_id;
				}
			}

			return false;
		}

		public function Load($id, $id_field_name = null, $cachable = true)
		{
			$default = false;
			if ($id == 'default') {
				// domain based primary language
				$default = true;
				$id = $this->Application->siteDomainField('PrimaryLanguageId');

				if ($id) {
					$res = parent::Load($id, $id_field_name, $cachable);
				}
				else {
					$res = parent::Load(1, 'PrimaryLang', $cachable);
				}

				if (
					!$this->Application->isAdmin && !defined('GW_NOTIFY') && preg_match('/[\/]{0,1}index.php[\/]{0,1}/', $_SERVER['PHP_SELF']) &&
					$this->Application->HttpQuery->isEmptyUrl() && $this->Application->ConfigValue('UseContentLanguageNegotiation')
				) {
					$language_id = $this->processAcceptLanguage();

					if ($language_id != $this->GetID()) {
						// redirect to same page with found language
						$url_params = Array (
							'm_cat_id' => 0, 'm_cat_page' => 1,
							'm_lang' => $language_id, 'm_opener' => 's',
							'pass' => 'm'
						);

						$this->Application->Redirect('', $url_params);
					}
				}
			}
			else {
				$res = parent::Load($id, $id_field_name, $cachable);
			}

			if ($res) {
				if (!$this->siteDomainLanguageEnabled($this->GetID())) {
					// language isn't allowed in site domain
					return $this->Clear();
				}
			}

			if ($default) {
				if (!$res) {
					if ($this->Application->isAdmin) {
						$res = parent::Load(1, $id_field_name, false);
					}
					else {
						if (defined('IS_INSTALL')) {
							// during first language import prevents sql errors
							$this->setID(1);
							$res = true;
						}
						else {
							$this->Application->ApplicationDie('No Primary Language Selected');
						}
					}
				}
				$this->Application->SetVar('lang.current_id', $this->GetID() );
				$this->Application->SetVar('m_lang', $this->GetID() );
			}

			return $res;
		}

		/**
		 * Checks, that language is enabled in site domain
		 *
		 * @param int $id
		 * @return bool
		 */
		function siteDomainLanguageEnabled($id)
		{
			$available_languages = $this->Application->siteDomainField('Languages');

			if ($available_languages) {
				return strpos($available_languages, '|'  .$id . '|') !== false;
			}

			return true;
		}
	}