Вход Регистрация
Файл: library/XenForo/Model/Language.php
Строк: 761
<?php

class XenForo_Model_Language extends XenForo_Model
{
    public function 
getLanguageById($id$fetchMaster false)
    {
        if (
strval($id) === '0')
        {
            if (
$fetchMaster)
            {
                return array(
                    
'language_id' => 0,
                    
'title' => new XenForo_Phrase('master_language'),
                    
'parent_id' => 0
                
);
            }
            else
            {
                return 
false;
            }
        }

        
$localCacheKey 'language_' $id;
        if ((
$data $this->_getLocalCacheData($localCacheKey)) === false)
        {
            
$data $this->_getDb()->fetchRow('
                SELECT *
                FROM xf_language
                WHERE language_id = ?
            '
$id);

            
$this->setLocalCacheData($localCacheKey$data);
        }

        return 
$data;
    }

    public function 
getAllLanguages()
    {
        if ((
$languages $this->_getLocalCacheData('allLanguages')) === false)
        {
            
$languages $this->fetchAllKeyed('
                SELECT *
                FROM xf_language
                ORDER BY title
            '
'language_id');

            
$this->setLocalCacheData('allLanguages'$languages);
        }

        return 
$languages;
    }

    
/**
     * Return results for admin quick search
     *
     * @param string Keywords for which to search
     *
     * @return array
     */
    
public function getLanguagesForAdminQuickSearch($searchText)
    {
        return 
$this->fetchAllKeyed('
            SELECT *
            FROM xf_language
            WHERE title LIKE ' 
XenForo_Db::quoteLike($searchText'lr'$this->_getDb()) . '
            ORDER BY title
        '
'language_id');
    }

    
/**
     * Gets the parent => language associations from a flat list of language info.
     *
     * @param array $languageList
     *
     * @return array [parent id][] => language id
     */
    
public function getLanguageTreeAssociations(array $languageList)
    {
        
$parents = array();
        foreach (
$languageList AS $language)
        {
            
$parents[$language['parent_id']][] = $language['language_id'];
        }

        return 
$parents;
    }

    
/**
     * Gets a list of child language IDs that are direct children of the specified language.
     *
     * @param integer $languageId
     *
     * @return array Array of language IDs
     */
    
public function getDirectChildLanguageIds($languageId)
    {
        
$languages $this->getAllLanguages();
        
$languageTree $this->getLanguageTreeAssociations($languages);

        if (isset(
$languageTree[$languageId]))
        {
            return 
$languageTree[$languageId];
        }
        else
        {
            return array();
        }
    }

    
/**
     * Gets all children of a language ID, no matter how many levels below.
     *
     * @param integer $languageId
     *
     * @return array Array of language IDs
     */
    
public function getAllChildLanguageIds($languageId)
    {
        
$languages $this->getAllLanguages();
        
$languageTree $this->getLanguageTreeAssociations($languages);

        if (isset(
$languageTree[$languageId]))
        {
            return 
$this->_getAllChildLanguageIds($languageId$languageTree);
        }
        else
        {
            return array();
        }
    }

    
/**
     * Internal handler to get call child language IDs.
     *
     * @param integer $parentId Parent language ID
     * @param array $languageTree Tree of languages ([parent id][] => language id)
     *
     * @return array
     */
    
protected function _getAllChildLanguageIds($parentId, array $languageTree)
    {
        if (!isset(
$languageTree[$parentId]))
        {
            return array();
        }

        
$children = array();
        foreach (
$languageTree[$parentId] AS $childId)
        {
            
$children[] = $childId;
            
$children array_merge($children$this->_getAllChildLanguageIds($childId$languageTree));
        }

        return 
$children;
    }

    
/**
     * Gets a list of languages in the form of a flattened tree. The return
     * is an array containing all languages and their related info. Each language
     * additionally includes a "depth" element that repesents the depth from
     * the (implicit) master. Children of the master have a depth 0, unless
     * $baseDepth is overridden.
     *
     * @param integer $baseDepth Starting depth value.
     *
     * @return array Format: [language id] => (array) language info, including depth
     */
    
public function getAllLanguagesAsFlattenedTree($baseDepth 0)
    {
        
$languages $this->getAllLanguages();
        
$tree $this->getLanguageTreeAssociations($languages);

        return 
$this->_buildFlattenedLanguageTree($languages$tree0$baseDepth);
    }

    
/**
     * Returns an array of all languages, suitable for use in ACP template syntax as options source.
     *
     * @param array $languageTree
     *
     * @return array
     */
    
public function getLanguagesForOptionsTag($selectedId null$languageTree null)
    {
        if (
$languageTree === null)
        {
            
$languageTree $this->getAllLanguagesAsFlattenedTree();
        }

        
$languages = array();
        foreach (
$languageTree AS $id => $language)
        {
            
$languages[$id] = array(
                
'value' => $id,
                
'label' => $language['title'],
                
'selected' => ($selectedId == $id),
                
'depth' => $language['depth']
            );
        }

        return 
$languages;
    }

    
/**
     * Builds the flattened tree recursively, incrementing the depth each time.
     *
     * @param array $languageList List of languages and their information
     * @param array $tree Tree structure of languages ([parent id][] => language id)
     * @param integer $root Where to start in the tree
     * @param integer $depth Current/starting depth
     *
     * @return array List of languages with additional depth key
     */
    
protected function _buildFlattenedLanguageTree(array $languageList, array $tree$root 0$depth 0)
    {
        if (!isset(
$tree[$root]) || !is_array($tree[$root]))
        {
            return array();
        }

        
$output = array();

        foreach (
$tree[$root] AS $languageId)
        {
            
$output[$languageId] = $languageList[$languageId];
            
$output[$languageId]['depth'] = $depth;

            
$output += $this->_buildFlattenedLanguageTree($languageList$tree$languageId$depth 1);
        }

        return 
$output;
    }

    
/**
     * Gets the base parent list for a language. This list starts with the *parent* of the given language ID, then
     * works up the tree, eventually ending with 0.
     *
     * @param integer $languageId
     *
     * @return array List of parent language IDs (including 0)
     */
    
public function getLanguageBaseParentList($languageId)
    {
        
$languages $this->getAllLanguages();

        
$parents = array();
        while (isset(
$languages[$languageId]) && $language $languages[$languageId])
        {
            
$parents[] = $language['parent_id'];
            
$languageId $language['parent_id'];
        }

        return 
$parents;
    }

    
/**
     * Recursively rebuilds the parent list in part of the language tree.
     *
     * @param integer $languageId First language to start with. All child will be rebuild.
     */
    
public function rebuildLanguageParentListRecursive($languageId)
    {
        
$languages $this->getAllLanguages();

        if (isset(
$languages[$languageId]))
        {
            
$languageTree $this->getLanguageTreeAssociations($languages);

            
$baseParentList $this->getLanguageBaseParentList($languageId);
            
$this->_rebuildLanguageParentListRecursive($languageId$baseParentList$languages$languageTree);
        }
    }

    
/**
     * Internal function to rebuild the language parent list recursively.
     *
     * @param integer $languageId Base lanaguage Id
     * @param array $baseParentList Base parent list for the language. Should not include this language ID in it.
     * @param array $languages List of languages
     * @param array $languageTree Language tree
     */
    
protected function _rebuildLanguageParentListRecursive($languageId, array $baseParentList, array $languages, array $languageTree)
    {
        if (isset(
$languages[$languageId]))
        {
            
$parentList $baseParentList;
            
array_unshift($parentList$languageId);

            
$db $this->_getDb();
            
$db->update(
                
'xf_language',
                array(
'parent_list' => implode(','$parentList)),
                
'language_id = ' $db->quote($languageId)
            );

            if (isset(
$languageTree[$languageId]))
            {
                foreach (
$languageTree[$languageId] AS $childLanguageId)
                {
                    
$this->_rebuildLanguageParentListRecursive($childLanguageId$parentList$languages$languageTree);
                }
            }
        }
    }

    
/**
     * Rebuilds the global phrase cache for all languages.
     *
     * @param array|null $globalPhraseTitles List of phrases that should be included. If null, uses flag from phrase table.
     */
    
public function rebuildLanguageGlobalPhraseCache(array $globalPhraseTitles null)
    {
        
$phraseModel $this->_getPhraseModel();

        if (
$globalPhraseTitles === null)
        {
            
$globalPhraseTitles $phraseModel->getGlobalPhraseCacheTitles();
        }

        
$db $this->_getDb();

        
$languages $this->getAllLanguages();
        
$globalPhrases $phraseModel->getEffectivePhraseValuesInAllLanguages($globalPhraseTitles);

        foreach (
$languages AS $languageId => $language)
        {
            if (isset(
$globalPhrases[$languageId]))
            {
                
$phrases $globalPhrases[$languageId];
            }
            else
            {
                
$phrases = array();
            }

            
$db->update('xf_language',
                array(
'phrase_cache' => serialize($phrases)),
                
'language_id = ' $db->quote($languageId)
            );
        }
    }

    
/**
    * Helper to determine whether the master language should be shown in lists.
    *
    * @return boolean
    */
    
public function showMasterLanguage()
    {
        return 
XenForo_Application::debugMode();
    }

    
/**
    * Helper to get the default language
    *
    * @return array
    */
    
public function getDefaultLanguage()
    {
        return array(
            
'language_id' => 0,
            
'parent_id' => 0,
            
'parent_list' => '',
            
'title' => '',
            
'date_format' => 'M j, Y',
            
'time_format' => 'g:i A',
            
'decimal_point' => '.',
            
'thousands_separator' => ',',
            
'text_direction' => 'LTR',
            
'language_code' => 'en-US'
        
);
    }

    
/**
     * Gets all languages in the format expected by the language cache.
     *
     * @return array Format: [language id] => info, with phrase cache as array
     */
    
public function getAllLanguagesForCache()
    {
        
$this->resetLocalCacheData('allLanguages');

        
$languages $this->getAllLanguages();
        foreach (
$languages AS &$language)
        {
            
$language['phrase_cache'] = unserialize($language['phrase_cache']);
        }

        return 
$languages;
    }

    
/**
     * Rebuilds the full language cache.
     *
     * @return array Format: [language id] => info, with phrase cache as array
     */
    
public function rebuildLanguageCache()
    {
        
$this->resetLocalCacheData('allLanguages');

        
$languages $this->getAllLanguagesForCache();

        
$this->_getDataRegistryModel()->set('languages'$languages);

        return 
$languages;
    }

    
/**
     * Rebuilds all language caches (including global phrase cache).
     */
    
public function rebuildLanguageCaches()
    {
        
$this->rebuildLanguageGlobalPhraseCache();
        
$this->rebuildLanguageCache();
    }

    
/**
     * Generates the date and time format examples based on the
     * current time.
     *
     * @return array [0] => date formats, [1] => time formats; keyed by format string
     */
    
public function getLanguageFormatExamples()
    {
        
$dateFormatsRaw = array(
            
'M j, Y',
            
'F j, Y',
            
'j M Y',
            
'j F Y',
            
'j/n/y',
            
'n/j/y'
        
);

        
$dateFormats = array();
        foreach (
$dateFormatsRaw AS $dateFormat)
        {
            
$dateFormats[$dateFormat] = XenForo_Locale::getFormattedDate(XenForo_Application::$time$dateFormat);
        }

        
$timeFormatsRaw = array(
            
'g:i A',
            
'H:i'
        
);

        
$timeFormats = array();
        foreach (
$timeFormatsRaw AS $timeFormat)
        {
            
$timeFormats[$timeFormat] = XenForo_Locale::getFormattedDate(XenForo_Application::$time$timeFormat);
        }

        return array(
$dateFormats$timeFormats);
    }

    
/**
     * Returns the total number of phrases in the master language
     *
     * @return integer
     */
    
public function countMasterPhrases()
    {
        return 
$this->_getDb()->fetchOne('SELECT COUNT(*) FROM xf_phrase WHERE language_id = 0');
    }

    
/**
     * Counts the number of translated phrases in each non-master language
     *
     * @param array $languages Array of languages
     *
     * @return array The $languages array including a phraseCount key
     */
    
public function countTranslatedPhrasesPerLanguage(array $languages = array())
    {
        
$totals $this->_getDb()->fetchPairs('
            SELECT language_id, COUNT(*) AS phraseCount
            FROM xf_phrase
            WHERE language_id <> 0
            GROUP BY language_id
        '
);

        foreach (
$totals AS $languageId => $phraseCount)
        {
            if (isset(
$languages[$languageId]))
            {
                
$languages[$languageId]['phraseCount'] = $phraseCount;
            }
        }

        return 
$languages;
    }

    
/**
     * Gets the DOM document that represents a language file.
     * This must be turned into XML (or HTML) by the caller.
     *
     * @param array $language
     * @param string|null $limitAddOnId If specified, only exports phrases from the specified add-on
     * @param boolean $getUntranslated If true, gets untranslated phrases in this language
     *
     * @return DOMDocument
     */
    
public function getLanguageXml(array $language$limitAddOnId null$getUntranslated false)
    {
        
$document = new DOMDocument('1.0''utf-8');
        
$document->formatOutput true;

        
$rootNode $document->createElement('language');
        
$rootNode->setAttribute('title'$language['title']);
        
$rootNode->setAttribute('date_format'$language['date_format']);
        
$rootNode->setAttribute('time_format'$language['time_format']);
        
$rootNode->setAttribute('decimal_point'$language['decimal_point']);
        
$rootNode->setAttribute('thousands_separator'$language['thousands_separator']);
        
$rootNode->setAttribute('language_code'$language['language_code']);
        
$rootNode->setAttribute('text_direction'$language['text_direction']);
        if (
$limitAddOnId !== null)
        {
            
$rootNode->setAttribute('addon_id'$limitAddOnId);
        }
        
$document->appendChild($rootNode);

        
$db $this->_getDb();

        if (
$getUntranslated)
        {
            
$phrases $db->fetchAll('
                SELECT phrase.*,
                    IF(master.phrase_id, master.addon_id, phrase.addon_id) AS addon_id
                FROM xf_phrase_map AS map
                INNER JOIN xf_phrase AS phrase ON (map.phrase_id = phrase.phrase_id)
                LEFT JOIN xf_phrase AS master ON (master.title = phrase.title AND master.language_id = 0)
                WHERE map.language_id = ?
                    AND ' 
. ($limitAddOnId === null '1=1' 'master.addon_id = ' $db->quote($limitAddOnId)) . '
                ORDER BY map.title
            '
$language['language_id']);
        }
        else
        {
            
$phrases $db->fetchAll('
                SELECT phrase.*,
                    IF(master.phrase_id, master.addon_id, phrase.addon_id) AS addon_id
                FROM xf_phrase AS phrase
                LEFT JOIN xf_phrase AS master ON (master.title = phrase.title AND master.language_id = 0)
                WHERE phrase.language_id = ?
                    AND ' 
. ($limitAddOnId === null '1=1' 'master.addon_id = ' $db->quote($limitAddOnId)) . '
                ORDER BY phrase.title
            '
$language['language_id']);
        }

        foreach (
$phrases AS $phrase)
        {
            
$phraseNode $document->createElement('phrase');
            
$phraseNode->setAttribute('title'$phrase['title']);
            
$phraseNode->setAttribute('addon_id'$phrase['addon_id']);
            if (
$phrase['global_cache'])
            {
                
$phraseNode->setAttribute('global_cache'$phrase['global_cache']);
            }
            
$phraseNode->setAttribute('version_id'$phrase['version_id']);
            
$phraseNode->setAttribute('version_string'$phrase['version_string']);
            
$phraseNode->appendChild($document->createCDATASection($phrase['phrase_text']));

            
$rootNode->appendChild($phraseNode);
        }

        return 
$document;
    }

    
/**
     * Imports a language XML file.
     *
     * @param SimpleXMLElement $document
     * @param integer $parentLanguageId If not overwriting, the ID of the parent lang
     * @param integer $overwriteLanguageId If non-0, parent lang is ignored
     */
    
public function importLanguageXml(SimpleXMLElement $document$parentLanguageId 0$overwriteLanguageId 0)
    {
        if (
$document->getName() != 'language')
        {
            throw new 
XenForo_Exception(new XenForo_Phrase('provided_file_is_not_valid_language_xml'), true);
        }

        
$title = (string)$document['title'];
        if (
$title === '')
        {
            throw new 
XenForo_Exception(new XenForo_Phrase('provided_file_is_not_valid_language_xml'), true);
        }

        
$db $this->_getDb();
        
XenForo_Db::beginTransaction($db);

        
$limitAddOnId = (string)$document['addon_id'];

        if (
$overwriteLanguageId)
        {
            
$db->delete('xf_phrase',
                
'language_id = ' $db->quote($overwriteLanguageId)
                    . (
$limitAddOnId != '' ' AND addon_id = ' $db->quote($limitAddOnId) : '')
            );

            
$existingPhrases $this->_getPhraseModel()->getAllPhrasesInLanguage($overwriteLanguageId);
        }
        else
        {
            
$existingPhrases = array();
        }

        
$writer XenForo_DataWriter::create('XenForo_DataWriter_Language');
        if (
$overwriteLanguageId)
        {
            
$writer->setExistingData($overwriteLanguageId);
        }
        else
        {
            
$writer->set('title', (string)$document['title']);
            
$writer->set('parent_id'$parentLanguageId);

            
$textDirection = (string)$document['text_direction'];
            
$writer->bulkSet(array(
                
'date_format' => (string)$document['date_format'],
                
'time_format' => (string)$document['time_format'],
                
'decimal_point' => (string)$document['decimal_point'],
                
'thousands_separator' => (string)$document['thousands_separator'],
                
'language_code' => (string)$document['language_code'],
                
'text_direction' => ($textDirection $textDirection 'LTR')
            ));
        }

        
$writer->save();

        
$languageId $writer->get('language_id');

        
$this->_getPhraseModel()->importPhrasesXml($document$languageIdnull$existingPhrases);

        
$this->triggerLanguageRebuildDeferred();

        
XenForo_Db::commit($db);
    }

    public function 
triggerLanguageRebuildDeferred()
    {
        
XenForo_Application::defer('Atomic',
            array(
'simple' => array('Phrase''Template''AdminTemplate''EmailTemplate')),
            
'languageRebuild'true
        
);
    }

    
/**
     * Fetches $languageId from cookie if it's available, or returns the default language ID.
     *
     * @return integer
     */
    
public function getLanguageIdFromCookie()
    {
        
$languageId XenForo_Helper_Cookie::getCookie('edit_language_id');
        if (
$languageId === false)
        {
            
$languageId = (XenForo_Application::debugMode()
                ? 
0
                
XenForo_Application::get('options')->defaultLanguageId
            
);
        }

        if (!
XenForo_Application::debugMode() && !$languageId)
        {
            
$languageId XenForo_Application::get('options')->defaultLanguageId;
        }

        return 
$languageId;
    }

    
/**
     * @return XenForo_Model_Phrase
     */
    
protected function _getPhraseModel()
    {
        return 
$this->getModelFromCache('XenForo_Model_Phrase');
    }
}
Онлайн: 1
Реклама