<?php

/**
 * main translate class
 */
class translate
{
    private static $setupTranslations = false;
	public static $translations = array();
    
    // setup the initial translation constants
    static function setUpTranslationConstants()
    {
        if(self::$setupTranslations == true)
        {
            return true;
        }
        
        if (!defined("SITE_CONFIG_SITE_LANGUAGE"))
        {
            define("SITE_CONFIG_SITE_LANGUAGE", "English (en)");
        }

		$db = Database::getDatabase();
        if (isset($_SESSION['_t']))
		{
			$languageId = (int)self::getCurrentLanguageId();
		}
		else
		{
			$languageId = (int)$db->getValue("SELECT id FROM language WHERE languageName = " . $db->quote(SITE_CONFIG_SITE_LANGUAGE));
		}
		
        if (!(int) $languageId)
        {
            return false;
        }

        translate::updateAllLanguageContent($languageId);

        /* load in the content */
        $rows = $db->getRows("SELECT language_key.languageKey, language_content.content FROM language_content LEFT JOIN language_key ON language_content.languageKeyId = language_key.id WHERE language_content.languageId = " . (int) $languageId.' AND language_key.languageKey IS NOT NULL');
        if (COUNT($rows))
        {
            foreach ($rows AS $row)
            {
                $constantName = strtoupper(trim($row['languageKey']));
                if(!isset(self::$translations[$constantName]))
                {
                    self::$translations[$constantName] = $row['content'];
                }
            }
        }

        self::$setupTranslations = true;
    }

    /* translation function for JS */
    static function generateJSLanguageCode()
	{
		self::setUpTranslationConstants();

		/* setup js */
		$js   = array();
		$js[] = "/* translation function */";
		$js[] = "function t(key){ ";
		$js[] = "l = {";

		/* load in the content */
		$ljs = array();
		foreach (self::$translations AS $k=>$row)
		{
			$itemKey = strtolower(str_replace(array("\r", "\n"), "", $k));
			if(strlen($itemKey) == 0)
			{
				continue;
			}
			$ljs[] = "\"" . addslashes($itemKey) . "\":\"" . addslashes(str_replace(array("\r", "\n"), "", $row)) . "\"";
		}
		$js[] = implode(", ", $ljs);
		$js[] = "};";

		$js[] = "return l[key.toLowerCase()];";
		$js[] = "}";
		return implode("\n", $js);
	}

    static function updateAllLanguageContent($languageId)
    {
        $db             = Database::getDatabase();
        /* make sure we have all content records populated */
        $getMissingRows = $db->getRows("SELECT id, languageKey, defaultContent FROM language_key WHERE NOT EXISTS (SELECT 1 FROM language_content WHERE languageId = " . (int) $languageId . ")");
        if (is_array($getMissingRows) && COUNT($getMissingRows))
        {
            foreach ($getMissingRows AS $getMissingRow)
            {
                $dbInsert                = new DBObject("language_content", array("languageKeyId", "languageId", "content"));
                $dbInsert->languageKeyId = $getMissingRow['id'];
                $dbInsert->languageId    = (int) $languageId;
                $dbInsert->content       = $getMissingRow['defaultContent'];
                $dbInsert->insert();
            }
        }
    }

    static function getTranslation($key, $defaultContent = null, $isAdminArea = 0, $replacements = array(), $overwriteDefault = false)
    {
        /* are we in language debug mode */
        if (SITE_CONFIG_LANGUAGE_SHOW_KEY == "key")
        {
            return $key;
        }
        
        // setup translations
        self::setUpTranslationConstants();

        /* return the language translation if we can find it */
        $constantName = strtoupper(trim($key));
        if (!isset(self::$translations[$constantName]) || ($overwriteDefault == true))
        {
            if ($defaultContent !== null)
            {
				$db = Database::getDatabase();
                if (isset($_SESSION['_t']))
                {
					$languageId = (int)self::getCurrentLanguageId();
                }
				else
				{
					$languageId = (int)$db->getValue("SELECT id FROM language WHERE languageName = " . $db->quote(SITE_CONFIG_SITE_LANGUAGE));
				}
				
                if (!(int) $languageId)
                {
                    return false;
                }

				// clear default value
				$db->query('DELETE FROM language_content WHERE languageKeyId IN (SELECT id FROM language_key WHERE languageKey='.$db->quote($key).')');
				$db->query('DELETE FROM language_key WHERE languageKey='.$db->quote($key).' LIMIT 1');
				
                // insert default key value
                $dbInsert                 = new DBObject("language_key", array("languageKey", "defaultContent", "isAdminArea"));
                $dbInsert->languageKey    = $key;
                $dbInsert->defaultContent = $defaultContent;
                $dbInsert->isAdminArea    = (int) $isAdminArea;
                $dbInsert->insert();
				
				$dbInsert2                = new DBObject("language_content", array("languageKeyId", "languageId", "content"));
                $dbInsert2->languageKeyId = $dbInsert->id;
                $dbInsert2->languageId    = (int) $languageId;
                $dbInsert2->content       = $defaultContent;
                $dbInsert2->insert();

                // set constant
                self::$translations[strtoupper($key)] = $defaultContent;

                // do replacements
                if (COUNT($replacements))
                {
                    foreach ($replacements AS $k => $replacement)
                    {
                        $defaultContent = str_replace('[[[' . strtoupper($k) . ']]]', $replacement, $defaultContent);
                    }
                }

                if (SITE_CONFIG_LANGUAGE_SHOW_KEY == "key title text")
                {
                    $defaultContent = self::addTitleText($defaultContent, strtoupper($key));
                }
                
                return $defaultContent;
            }
            
            return "<font style='color:red;'>SITE ERROR: MISSING TRANSLATION *** <strong>" . $key . "</strong> ***</font>";
        }

        // do replacements
        $text = self::$translations[$constantName];
        if (COUNT($replacements))
        {
            foreach ($replacements AS $k => $replacement)
            {
                $text = str_replace('[[[' . strtoupper($k) . ']]]', $replacement, $text);
            }
        }

        if (SITE_CONFIG_LANGUAGE_SHOW_KEY == "key title text")
        {
            $text = self::addTitleText($text, strtoupper($key));
        }

        return $text;
    }
    
    static function addTitleText($baseText, $titleText)
    {
        return '<span title="'.validation::safeOutputToScreen($titleText).'">'.$baseText.'</span>';
    }
    
    static function extractTranslationsFromText($str)
    {
        $rs = array();
        $patterns = array('/\.\s*t\s*\(\s*\'(.*?)\'\s*\s*\)/i', "/\.\s*t\s*\(\s*\\\"(.*?)\\\"\s*\s*\)/i", '/\.\s*t\s*\(\s*\'(.*?)\'\s*\s*\,/i', "/\.\s*t\s*\(\s*\\\"(.*?)\\\"\s*\s*\,/i", '/\(\s*t\s*\(\s*\'(.*?)\'\s*\s*\)/i', "/\(\s*t\s*\(\s*\\\"(.*?)\\\"\s*\s*\)/i", '/\(\s*t\s*\(\s*\'(.*?)\'\s*\s*\,/i', "/\(\s*t\s*\(\s*\\\"(.*?)\\\"\s*\s*\,/i", '/ t\s*\(\s*\'(.*?)\'\s*\s*\)/i', "/ t\s*\(\s*\\\"(.*?)\\\"\s*\s*\)/i", '/ t\s*\(\s*\'(.*?)\'\s*\s*\,/i', "/ t\s*\(\s*\\\"(.*?)\\\"\s*\s*\,/i", '/\:\:t\s*\(\s*\'(.*?)\'\s*\s*\)/i', "/\:\:t\s*\(\s*\\\"(.*?)\\\"\s*\s*\)/i", '/\:\:t\s*\(\s*\'(.*?)\'\s*\s*\,/i', "/\:\:t\s*\(\s*\\\"(.*?)\\\"\s*\s*\,/i");
        foreach($patterns AS $pattern)
        {
            preg_match_all($pattern, $str, $matches);
            if(COUNT($matches))
            {
                $funcCalls = $matches[1];
                if(COUNT($funcCalls))
                {
                    foreach($funcCalls AS $funcCall)
                    {
                        $funcCall = str_replace(array('\', \'', '","', '\',\'', '\',"', '",\'', '\', "', '", \''), '", "', $funcCall);
                        $funcCall = str_replace(array('\', $', '", $', '\',$', '",$'), '", "$', $funcCall);
                        $funcCall = str_replace(array('\', array', '", array'), '", "array', $funcCall);

                        $tmpExp = explode('", "', $funcCall);
                        
                        $defaultContent = $tmpExp[1];
                        if(substr($defaultContent, 0, 1) == '$')
                        {
                            continue;
                        }
                        if(strpos($tmpExp{0}, '$') !== false)
                        {
                            continue;
                        }
                        
                        // if not set by previous pattern
                        if((!isset($rs[$tmpExp{0}])) && (strlen($defaultContent) > 0))
                        {
                            $rs[$tmpExp{0}] = (string)$defaultContent;
                        }
                    }
                }
            }
        }

        return $rs;
    }
    
    static function rebuildTranslationsFromCode()
    {
        // get database
        $db         = Database::getDatabase();
        
        // prepare total file list
        $filesToCheck = array();

        // get all files with translations, start with the base
        $dirFiles = adminFunctions::getDirectoryList(SITE_TEMPLATES_PATH, null, true);
        if($dirFiles)
        {
            foreach($dirFiles AS $dirFile)
            {
                if(is_file($dirFile))
                {
                    $filesToCheck[] = $dirFile;
                }
            }
        }

        // add sub folders
        $subFolders = array('api', 'core/includes', 'core/page', PLUGIN_DIRECTORY_NAME);
        foreach($subFolders AS $subFolder)
        {
            $dirFiles = adminFunctions::getDirectoryList(DOC_ROOT.'/'.$subFolder, null, true);
            $filesToCheck = array_merge($filesToCheck, $dirFiles);
        }

        // only keep .php files
        $total = COUNT($filesToCheck);
        for($i=0; $i<$total; $i++)
        {
            $fileName = str_replace(DOC_ROOT, '', $filesToCheck[$i]);
            $fileName = strtolower($fileName);
            if((strpos($fileName, '.php') == false) && (strpos($fileName, '.html') == false))
            {
                unset($filesToCheck[$i]);
            }
        }

        // loop files and pick up any translations
        $translations = array();
        foreach($filesToCheck AS $filePath)
        {
            // get contents of file
            $fileContents = file_get_contents($filePath);
            $rs = translate::extractTranslationsFromText($fileContents);
            if(COUNT($rs))
            {
                $shortFileName = str_replace(DOC_ROOT.'/', '', $filePath);
                foreach($rs AS $k=>$item)
                {
                    if(!isset($translations[$k]))
                    {
                        $translations[$k] = array('default_content'=>$item, 'file_source'=>array($shortFileName));
                    }
                    else
                    {
                        $translations[$k]['file_source'] = $shortFileName;
                    }
                }
            }
        }

        // loop translations and populate default translation content
        translate::setUpTranslationConstants();
        $foundTotal = 0;
        $addedTotal = 0;
        $db->query('UPDATE language_key SET foundOnScan = 0');
        foreach($translations AS $translationKey => $translation)
        {
            /* return the language translation if we can find it */
            $constantName = strtoupper($translationKey);
            if (!isset(self::$translations[$constantName]))
            {
                if (strlen($translation['default_content']))
                {
                    // figure out if admin
                    $isAdminArea = 1;
                    foreach($translation['file_source'] AS $fileSource)
                    {
                        if(strpos($fileSource, ADMIN_FOLDER_NAME) === false)
                        {
                            $isAdminArea = 0;
                        }
                    }

                    // insert default key value
                    $dbInsert                 = new DBObject("language_key", array("languageKey", "defaultContent", "isAdminArea", "foundOnScan"));
                    $dbInsert->languageKey    = $translationKey;
                    $dbInsert->defaultContent = $translation['default_content'];
                    $dbInsert->isAdminArea    = (int) $isAdminArea;
                    $dbInsert->foundOnScan    = 1;
                    $dbInsert->insert();

                    $addedTotal++;

                    // set constant
                    self::$translations[strtoupper($translationKey)] = $translation['default_content'];
                }
            }
            else
            {
                $db->query('UPDATE language_key SET foundOnScan = 1 WHERE languageKey='.$db->quote($translationKey).' LIMIT 1');
            }

            $foundTotal++;
        }

        return array('foundTotal' => $foundTotal, 'addedTotal' => $addedTotal);
    }
	
	static function getCurrentLanguageId()
    {
		if(!defined('SITE_CURRENT_LANGUAGE_ID'))
		{
			// get database
			$db = Database::getDatabase();
			$languageId = (int)$db->getValue("SELECT id FROM language WHERE isActive = 1 AND languageName = " . $db->quote($_SESSION['_t']) . " LIMIT 1");
			define('SITE_CURRENT_LANGUAGE_ID', $languageId);
		}
		
		return (int)SITE_CURRENT_LANGUAGE_ID;
	}
}
