Page MenuHomeIn-Portal Phabricator

phrases_cache.php
No OneTemporary

File Metadata

Created
Sat, Sep 27, 7:23 PM

phrases_cache.php

<?php
/**
* @version $Id: phrases_cache.php 16156 2015-04-29 06:57:02Z 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 kPhraseCache extends kBase
{
var $Phrases = Array();
var $Ids = Array();
var $OriginalIds = Array(); //for comparing cache
var $LanguageId = null;
/**
* Administrator's language, when visiting site (from frame)
*
* @var int
*/
var $AdminLanguageId = null;
var $fromTag = false;
/**
* Allows to edit existing phrases
*
* @var bool
*/
var $_editExisting = false;
/**
* Allows to edit missing phrases
*
* @var bool
*/
var $_editMissing = false;
/**
* Template, used for phrase adding/editing
*
* @var string
*/
var $_phraseEditTemplate = 'languages/phrase_edit';
/**
* Use simplified form for phrase editing
*
* @var bool
*/
var $_simpleEditingMode = false;
/**
* HTML tag used to translate phrases
*
* @var string
*/
var $_translateHtmlTag = 'a';
/**
* Phrases, that are in cache, but are not in database
*
* @var Array
*/
var $_missingPhrases = Array ();
/**
* Mask for editing link
*
* @var string
*/
var $_editLinkMask = '';
/**
* Escape phrase name, before placing it in javascript translation link
*
* @var string
*/
var $_phraseEscapeStrategy = kUtil::ESCAPE_JS;
/**
* Sets phrase editing mode, that corresponds current editing mode
*
*/
function setPhraseEditing()
{
if (!$this->Application->isAdmin && (EDITING_MODE == EDITING_MODE_CONTENT)) {
// front-end viewed in content mode
$this->_editExisting = $this->_editMissing = true;
$this->_simpleEditingMode = !$this->Application->isDebugMode();
$this->_translateHtmlTag = 'span';
}
$this->_editLinkMask = $this->getRawEditLink('#LABEL#');
if (defined('DEBUG_MODE') && DEBUG_MODE && !$this->Application->GetVar('admin')) {
// admin and front-end while not viewed using content mode (via admin)
$this->_editMissing = defined('DBG_PHRASES') && DBG_PHRASES;
if (!$this->Application->isAdmin) {
$this->_phraseEditTemplate = 'phrases_edit';
$url_params = Array (
'm_opener' => 'd',
'phrases_label' => '#LABEL#',
'phrases_event' => 'OnPreparePhrase',
'next_template' => 'external:' . $_SERVER['REQUEST_URI'],
'pass' => 'm,phrases'
);
$this->_phraseEscapeStrategy = kUtil::ESCAPE_URL;
$this->_editLinkMask = $this->Application->HREF($this->_phraseEditTemplate, '', $url_params);
}
}
}
/**
* Returns raw link for given phrase editing.
*
* @param string $label Phrase label.
*
* @return string
*/
protected function getRawEditLink($label)
{
$function_params = array(
$label,
$this->_phraseEditTemplate,
array('event' => 'OnPreparePhrase', 'simple_mode' => $this->_simpleEditingMode),
);
return 'javascript:translate_phrase(' . implode(',', array_map('json_encode', $function_params)) . ');';
}
/**
* Returns final link (using mask) for given phrase editing.
*
* @param string $label Phrase label.
*
* @return string
*/
protected function getEditLink($label)
{
$escaped_label = kUtil::escape($label, $this->_phraseEscapeStrategy);
return str_replace('#LABEL#', $escaped_label, $this->_editLinkMask);
}
/**
* Returns HTML code for label editing.
*
* @param string $url Phrase editing url.
* @param string $text Link text to show (usually label in upper case).
* @param string $alt Text to display when hovered over the link.
*
* @return string
*/
protected function getEditHtmlCode($url, $text, $alt)
{
$url = kUtil::escape($url, kUtil::ESCAPE_HTML);
$ret = '<' . $this->_translateHtmlTag . ' href="' . $url . '" name="cms-translate-phrase" title="' . $alt . '">' . $text . '</' . $this->_translateHtmlTag . '>';
return $this->fromTag ? $this->escapeTagReserved($ret) : $ret;
}
/**
* Loads phrases from current language
* Method is called manually (not from kFactory class) too
*
* @param string $prefix
* @param string $special
* @param int $language_id
* @param Array $phrase_ids
*/
public function Init($prefix, $special = '', $language_id = null, $phrase_ids = null)
{
parent::Init($prefix, $special);
if (kUtil::constOn('IS_INSTALL')) {
$this->LanguageId = 1;
}
else {
if ( !isset($language_id) ) {
if ($this->Application->isAdmin) {
$language_id = $this->Application->Session->GetField('Language');
$this->AdminLanguageId = $language_id; // same languages, when used from Admin Console
}
else {
$language_id = $this->Application->GetVar('m_lang');
}
}
$this->LanguageId = $language_id;
if (!$this->Application->isAdmin && $this->Application->GetVar('admin')) {
$admin_session = $this->Application->recallObject('Session.admin');
/* @var $admin_session Session */
$this->AdminLanguageId = $admin_session->GetField('Language');
}
}
$this->LoadPhrases($phrase_ids);
}
function LoadPhrases($ids)
{
if ( !is_array($ids) || !implode('', $ids) ) {
return ;
}
$sql = 'SELECT l' . $this->LanguageId . '_Translation AS Translation, l' . $this->LanguageId . '_HintTranslation AS HintTranslation, l' . $this->LanguageId . '_ColumnTranslation AS ColumnTranslation, PhraseKey
FROM ' . TABLE_PREFIX . 'LanguageLabels
WHERE PhraseId IN (' . implode(',', $ids) . ') AND l' . $this->LanguageId . '_Translation IS NOT NULL';
$this->Phrases = $this->Conn->Query($sql, 'PhraseKey');
$this->Ids = $this->OriginalIds = $ids;
}
function AddCachedPhrase($label, $value, $allow_editing = true)
{
// uppercase phrase name for cases, when this method is called outside this class
$cache_key = ($allow_editing ? '' : 'NE:') . mb_strtoupper($label);
$this->Phrases[$cache_key] = Array ('Translation' => $value, 'HintTranslation' => $value, 'ColumnTranslation' => $value);
}
function NeedsCacheUpdate()
{
return is_array($this->Ids) && count($this->Ids) > 0 && $this->Ids != $this->OriginalIds;
}
/**
* Returns translation of given label
*
* @param string $label
* @param bool $allow_editing return translation link, when translation is missing on current language
* @param bool $use_admin use current Admin Console language to translate phrase
* @return string
* @access public
*/
public function GetPhrase($label, $allow_editing = true, $use_admin = false)
{
if ( !isset($this->LanguageId) ) {
//actually possible when custom field contains references to language labels and its being rebuilt in OnAfterConfigRead
//which is triggered by Sections rebuild, which in turn read all the configs and all of that happens BEFORE seeting the language...
return 'impossible case';
}
// cut exclamation marks - deprecated form of passing phrase name from templates
$label = preg_replace('/^!(.*)!$/', '\\1', $label);
if ( strlen($label) == 0 ) {
return '';
}
$original_label = $label;
list ($field_prefix, $label) = $this->parseLabel($label);
$translation_field = mb_convert_case($field_prefix, MB_CASE_TITLE) . 'Translation';
$uppercase_label = mb_strtoupper($label);
$cache_key = ($allow_editing ? '' : 'NE:') . $uppercase_label;
if ( isset($this->Phrases[$cache_key]) ) {
$translated_label = $this->Phrases[$cache_key][$translation_field];
if ($this->_editExisting && $allow_editing && !array_key_exists($uppercase_label, $this->_missingPhrases)) {
// option to change translation for Labels
$edit_link = $this->getRawEditLink($label);
$translated_label = $this->getEditHtmlCode($edit_link, $translated_label, 'Edit translation');
}
return $translated_label;
}
$this->LoadPhraseByLabel($uppercase_label, $original_label, $allow_editing, $use_admin);
return $this->GetPhrase($original_label, $allow_editing);
}
function LoadPhraseByLabel($uppercase_label, $original_label, $allow_editing = true, $use_admin = false)
{
if ( !$allow_editing && !$use_admin && !isset($this->_missingPhrases[$uppercase_label]) && isset($this->Phrases[$uppercase_label]) ) {
// label is already translated, but it's version without on the fly translation code is requested
$this->Phrases['NE:' . $uppercase_label] = $this->Phrases[$uppercase_label];
return true;
}
$language_id = $use_admin ? $this->AdminLanguageId : $this->LanguageId;
$sql = 'SELECT PhraseId, l' . $language_id . '_Translation AS Translation, l' . $language_id . '_HintTranslation AS HintTranslation, l' . $language_id . '_ColumnTranslation AS ColumnTranslation
FROM ' . TABLE_PREFIX . 'LanguageLabels
WHERE (PhraseKey = ' . $this->Conn->qstr($uppercase_label) . ') AND (l' . $language_id . '_Translation IS NOT NULL)';
$res = $this->Conn->GetRow($sql);
if ($res === false || count($res) == 0) {
$translation = '!' . $uppercase_label . '!';
if ($this->_editMissing && $allow_editing) {
list (, $original_label) = $this->parseLabel($original_label);
$edit_url = $this->getEditLink($original_label);
$translation = $this->getEditHtmlCode($edit_url, $translation, 'Translate');
$this->_missingPhrases[$uppercase_label] = true; // add as key for faster accessing
}
// add it as already cached, as long as we don't need to cache not found phrase
$this->AddCachedPhrase($uppercase_label, $translation, $allow_editing);
return false;
}
$cache_key = ($allow_editing ? '' : 'NE:') . $uppercase_label;
$this->Phrases[$cache_key] = $res;
array_push($this->Ids, $res['PhraseId']);
$this->Ids = array_unique($this->Ids); // just to make sure
return true;
}
/**
* Parse label into translation field prefix and actual label.
*
* @param string $label Phrase label.
*
* @return array
*/
protected function parseLabel($label)
{
if ( strpos($label, ':') === false || preg_match('/^(HINT|COLUMN):(.*)$/i', $label, $regs) == 0 ) {
return array('', $label);
}
return array($regs[1], $regs[2]);
}
/**
* Sort params by name and then by length
*
* @param string $a
* @param string $b
* @return int
* @access private
*/
function CmpParams($a, $b)
{
$a_len = mb_strlen($a);
$b_len = mb_strlen($b);
if ($a_len == $b_len) return 0;
return $a_len > $b_len ? -1 : 1;
}
/**
* Replace language tags in exclamation marks found in text
*
* @param string $text
* @param bool|null $force_escaping force escaping, not escaping of resulting string
* @return mixed
* @access public
*/
public function ReplaceLanguageTags($text, $force_escaping = null)
{
$this->fromTag = true;
if( isset($force_escaping) ) {
$this->fromTag = $force_escaping;
}
preg_match_all("(!(la|lu|lc)[^!]+!)", $text, $res, PREG_PATTERN_ORDER);
$language_tags = $res[0];
uasort($language_tags, Array(&$this, 'CmpParams'));
$i = 0;
$values = Array();
foreach ($language_tags as $label) {
array_push($values, $this->GetPhrase($label) );
//array_push($values, $this->Application->Phrase($label) );
$language_tags[$i] = '/' . $language_tags[$i] . '/';
$i++;
}
$this->fromTag = false;
return preg_replace($language_tags, $values, $text);
}
/**
* Escape chars in phrase translation, that could harm parser to process tag
*
* @param string $text
* @return string
* @access private
*/
function escapeTagReserved($text)
{
$reserved = Array('"', "'"); // =
$replacement = Array('\"', "\'"); // \=
return str_replace($reserved, $replacement, $text);
}
}

Event Timeline