Index: branches/5.2.x/core/kernel/languages/phrases_cache.php =================================================================== diff -u -N -r15736 -r15856 --- branches/5.2.x/core/kernel/languages/phrases_cache.php (.../phrases_cache.php) (revision 15736) +++ branches/5.2.x/core/kernel/languages/phrases_cache.php (.../phrases_cache.php) (revision 15856) @@ -1,6 +1,6 @@ Application->isAdmin && (EDITING_MODE == EDITING_MODE_CONTENT)) { // front-end viewed in content mode - $this->_editExisting = true; - $this->_editMissing = true; + $this->_editExisting = $this->_editMissing = true; $this->_simpleEditingMode = !$this->Application->isDebugMode(); $this->_translateHtmlTag = 'span'; } - $this->_editLinkMask = 'javascript:translate_phrase(\'#LABEL#\', \'' . $this->_phraseEditTemplate . '\', {event: \'OnPreparePhrase\', simple_mode: ' . ($this->_simpleEditingMode ? 'true' : 'false') . '});'; + $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) @@ -113,17 +113,66 @@ 'm_opener' => 'd', 'phrases_label' => '#LABEL#', 'phrases_event' => 'OnPreparePhrase', - 'next_template' => urlencode('external:' . $_SERVER['REQUEST_URI']), + 'next_template' => kUtil::escape('external:' . $_SERVER['REQUEST_URI'], kUtil::ESCAPE_URL), 'pass' => 'm,phrases' ); - $this->_escapePhraseName = false; + $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 . '_translateHtmlTag . '>'; + + return $this->fromTag ? $this->escapeTagReserved($ret) : $ret; + } + + /** * Loads phrases from current language * Method is called manually (not from kFactory class) too * @@ -214,47 +263,36 @@ return ''; } - $original_label = $this->_escapePhraseName ? addslashes($label) : $label; - $label = mb_strtoupper($label); + $original_label = $label; - if ( substr($label, 0, 5) == 'HINT:' || substr($label, 0, 7) == 'COLUMN:' ) { - // don't just check for ":" since phrases could have ":" in their names (e.g. advanced permission labels) - list ($field_prefix, $label) = explode(':', $label, 2); - $translation_field = mb_convert_case($field_prefix, MB_CASE_TITLE) . 'Translation'; - } - else { - $translation_field = 'Translation'; - } + 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:') . $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($label, $this->_missingPhrases)) { + if ($this->_editExisting && $allow_editing && !array_key_exists($uppercase_label, $this->_missingPhrases)) { // option to change translation for Labels - $original_label = explode(':', $original_label, 2); - $edit_url = 'javascript:translate_phrase(\'' . end($original_label) . '\', \'' . $this->_phraseEditTemplate . '\', {event: \'OnPreparePhrase\', simple_mode: ' . ($this->_simpleEditingMode ? 'true' : 'false') . '});'; - $translated_label = '<' . $this->_translateHtmlTag . ' href="' . $edit_url . '" name="cms-translate-phrase" title="Edit translation">' . $translated_label . '_translateHtmlTag . '>'; - - if ($this->fromTag) { - $translated_label = $this->escapeTagReserved($translated_label); - } + $edit_link = $this->getRawEditLink($label); + $translated_label = $this->getEditHtmlCode($edit_link, $translated_label, 'Edit translation'); } return $translated_label; } - $this->LoadPhraseByLabel($label, $original_label, $allow_editing, $use_admin); + $this->LoadPhraseByLabel($uppercase_label, $original_label, $allow_editing, $use_admin); return $this->GetPhrase($original_label, $allow_editing); } - function LoadPhraseByLabel($label, $original_label, $allow_editing = true, $use_admin = false) + function LoadPhraseByLabel($uppercase_label, $original_label, $allow_editing = true, $use_admin = false) { - if ( !$allow_editing && !$use_admin && !isset($this->_missingPhrases[$label]) && isset($this->Phrases[$label]) ) { - // label is aready translated, but it's version without on the fly translation code is requested - $this->Phrases['NE:' . $label] = $this->Phrases[$label]; + 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; } @@ -263,31 +301,27 @@ $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($label) . ') AND (l' . $language_id . '_Translation IS NOT NULL)'; + 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 = '!' . $label . '!'; + $translation = '!' . $uppercase_label . '!'; if ($this->_editMissing && $allow_editing) { - $original_label = explode(':', $original_label, 2); - $edit_url = str_replace('#LABEL#', end($original_label), $this->_editLinkMask); - $translation = '<' . $this->_translateHtmlTag . ' href="' . $edit_url . '" name="cms-translate-phrase" title="Translate">!' . $label . '!_translateHtmlTag . '>'; + list (, $original_label) = $this->parseLabel($original_label); + $edit_url = $this->getEditLink($original_label); + $translation = $this->getEditHtmlCode($edit_url, $translation, 'Translate'); - if ($this->fromTag) { - $translation = $this->escapeTagReserved($translation); - } - - $this->_missingPhrases[$label] = true; // add as key for faster accessing + $this->_missingPhrases[$uppercase_label] = true; // add as key for faster accessing } - // add it as already cached, as long as we dont need to cache not found phrase - $this->AddCachedPhrase($label, $translation, $allow_editing); + // 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:') . $label; + $cache_key = ($allow_editing ? '' : 'NE:') . $uppercase_label; $this->Phrases[$cache_key] = $res; array_push($this->Ids, $res['PhraseId']); @@ -297,6 +331,22 @@ } /** + * 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 @@ -355,9 +405,10 @@ */ function escapeTagReserved($text) { - $reserved = Array('"',"'"); // = - $replacement = Array('\"',"\'"); // \= - return str_replace($reserved,$replacement,$text); + $reserved = Array('"', "'"); // = + $replacement = Array('\"', "\'"); // \= + + return str_replace($reserved, $replacement, $text); } } \ No newline at end of file