[BUGFIX] Language labels missing in Localization Overview
[Packages/TYPO3.CMS.git] / typo3 / sysext / frontend / Classes / Controller / TranslationStatusController.php
1 <?php
2 namespace TYPO3\CMS\Frontend\Controller;
3
4 /***************************************************************
5 * Copyright notice
6 *
7 * (c) 1999-2013 Kasper Skårhøj (kasperYYYY@typo3.com)
8 * All rights reserved
9 *
10 * This script is part of the TYPO3 project. The TYPO3 project is
11 * free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * The GNU General Public License can be found at
17 * http://www.gnu.org/copyleft/gpl.html.
18 * A copy is found in the text file GPL.txt and important notices to the license
19 * from the author is found in LICENSE.txt distributed with these scripts.
20 *
21 *
22 * This script is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 * GNU General Public License for more details.
26 *
27 * This copyright notice MUST APPEAR in all copies of the script!
28 ***************************************************************/
29
30 use TYPO3\CMS\Backend\Utility\BackendUtility;
31 use TYPO3\CMS\Backend\Utility\IconUtility;
32
33 /**
34 * Class for displaying translation status of pages in the tree.
35 *
36 * @author Kasper Skårhøj <kasperYYYY@typo3.com>
37 */
38 class TranslationStatusController extends \TYPO3\CMS\Backend\Module\AbstractFunctionModule {
39
40 /**
41 * Returns the menu array
42 *
43 * @return array
44 * @todo Define visibility
45 */
46 public function modMenu() {
47 global $LANG;
48 $menuArray = array(
49 'depth' => array(
50 0 => $LANG->getLL('depth_0'),
51 1 => $LANG->getLL('depth_1'),
52 2 => $LANG->getLL('depth_2'),
53 3 => $LANG->getLL('depth_3'),
54 999 => $LANG->sL('LLL:EXT:lang/locallang_core.xlf:labels.depth_infi')
55 )
56 );
57 // Languages:
58 $lang = $this->getSystemLanguages();
59 $menuArray['lang'] = array(
60 0 => '[All]'
61 );
62 foreach ($lang as $langRec) {
63 $menuArray['lang'][$langRec['uid']] = $langRec['title'];
64 }
65 return $menuArray;
66 }
67
68 /**
69 * MAIN function for page information of localization
70 *
71 * @return string Output HTML for the module.
72 * @todo Define visibility
73 */
74 public function main() {
75 global $BACK_PATH, $LANG, $SOBE;
76 $theOutput = $this->pObj->doc->header($LANG->sL('LLL:EXT:cms/web_info/locallang.xlf:lang_title'));
77 if ($this->pObj->id) {
78 // Depth selector:
79 $h_func = BackendUtility::getFuncMenu($this->pObj->id, 'SET[depth]', $this->pObj->MOD_SETTINGS['depth'], $this->pObj->MOD_MENU['depth']);
80 $h_func .= BackendUtility::getFuncMenu($this->pObj->id, 'SET[lang]', $this->pObj->MOD_SETTINGS['lang'], $this->pObj->MOD_MENU['lang']);
81 $theOutput .= $h_func;
82 // Add CSH:
83 $theOutput .= BackendUtility::cshItem('_MOD_web_info', 'lang', $GLOBALS['BACK_PATH'], '|<br />');
84 // Showing the tree:
85 // Initialize starting point of page tree:
86 $treeStartingPoint = (int)$this->pObj->id;
87 $treeStartingRecord = BackendUtility::getRecordWSOL('pages', $treeStartingPoint);
88 $depth = $this->pObj->MOD_SETTINGS['depth'];
89 // Initialize tree object:
90 $tree = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Backend\\Tree\\View\\PageTreeView');
91 $tree->init('AND ' . $GLOBALS['BE_USER']->getPagePermsClause(1));
92 $tree->addField('l18n_cfg');
93 // Creating top icon; the current page
94 $HTML = IconUtility::getSpriteIconForRecord('pages', $treeStartingRecord);
95 $tree->tree[] = array(
96 'row' => $treeStartingRecord,
97 'HTML' => $HTML
98 );
99 // Create the tree from starting point:
100 if ($depth) {
101 $tree->getTree($treeStartingPoint, $depth, '');
102 }
103 // Render information table:
104 $theOutput .= $this->renderL10nTable($tree);
105 }
106 return $theOutput;
107 }
108
109 /**
110 * Rendering the localization information table.
111 *
112 * @param array $tree The Page tree data
113 * @return string HTML for the localization information table.
114 * @todo Define visibility
115 */
116 public function renderL10nTable(&$tree) {
117 global $LANG;
118 // System languages retrieved:
119 $languages = $this->getSystemLanguages();
120 // Title length:
121 $titleLen = $GLOBALS['BE_USER']->uc['titleLen'];
122 // Put together the TREE:
123 $output = '';
124 $newOL_js = array();
125 $langRecUids = array();
126 foreach ($tree->tree as $data) {
127 $tCells = array();
128 $langRecUids[0][] = $data['row']['uid'];
129 // Page icons / titles etc.
130 $tCells[] = '<td' . ($data['row']['_CSSCLASS'] ? ' class="' . $data['row']['_CSSCLASS'] . '"' : '') . '>' . $data['HTML'] . htmlspecialchars(\TYPO3\CMS\Core\Utility\GeneralUtility::fixed_lgd_cs($data['row']['title'], $titleLen)) . ((string)$data['row']['nav_title'] !== '' ? ' [Nav: <em>' . htmlspecialchars(\TYPO3\CMS\Core\Utility\GeneralUtility::fixed_lgd_cs($data['row']['nav_title'], $titleLen)) . '</em>]' : '') . '</td>';
131 // DEFAULT language:
132 // "View page" link is created:
133 $viewPageLink = '<a href="#" onclick="' . htmlspecialchars(BackendUtility::viewOnClick(
134 $data['row']['uid'], $GLOBALS['BACK_PATH'], '', '', '', '&L=###LANG_UID###')
135 ) . '" title="' . $LANG->sL('LLL:EXT:cms/web_info/locallang.xlf:lang_renderl10n_viewPage') . '">' .
136 IconUtility::getSpriteIcon('actions-document-view') . '</a>';
137 $status = $data['row']['l18n_cfg'] & 1 ? 'c-blocked' : 'c-ok';
138 // Create links:
139 $info = '';
140 $editUid = $data['row']['uid'];
141 $params = '&edit[pages][' . $editUid . ']=edit';
142 $info .= '<a href="#" onclick="' . htmlspecialchars(BackendUtility::editOnClick(
143 $params, $GLOBALS['BACK_PATH'])
144 ) . '" title="' . $LANG->sL(
145 'LLL:EXT:cms/web_info/locallang.xlf:lang_renderl10n_editDefaultLanguagePage'
146 ) . '">' . IconUtility::getSpriteIcon('actions-document-open') . '</a>';
147 $info .= '<a href="#" onclick="' . htmlspecialchars(
148 'top.loadEditId(' . (int)$data['row']['uid'] . ',"&SET[language]=0"); return false;'
149 ) . '" title="' . $LANG->sL('LLL:EXT:cms/web_info/locallang.xlf:lang_renderl10n_editPage') . '">' .
150 IconUtility::getSpriteIcon('actions-page-open') . '</a>';
151 $info .= str_replace('###LANG_UID###', '0', $viewPageLink);
152 $info .= '&nbsp;';
153 $info .= $data['row']['l18n_cfg'] & 1 ? '<span title="' . $LANG->sL('LLL:EXT:cms/locallang_tca.xlf:pages.l18n_cfg.I.1', TRUE) . '">D</span>' : '&nbsp;';
154 $info .= \TYPO3\CMS\Core\Utility\GeneralUtility::hideIfNotTranslated($data['row']['l18n_cfg']) ? '<span title="' . $LANG->sL('LLL:EXT:cms/locallang_tca.xlf:pages.l18n_cfg.I.2', TRUE) . '">N</span>' : '&nbsp;';
155 // Put into cell:
156 $tCells[] = '<td class="' . $status . ' c-leftLine">' . $info . '</td>';
157 $tCells[] = '<td class="' . $status . '" title="' . $LANG->sL(
158 'LLL:EXT:cms/web_info/locallang.xlf:lang_renderl10n_CEcount'
159 ) . '" align="center">' . $this->getContentElementCount($data['row']['uid'], 0) . '</td>';
160 $modSharedTSconfig = BackendUtility::getModTSconfig($data['row']['uid'], 'mod.SHARED');
161 $disableLanguages = isset($modSharedTSconfig['properties']['disableLanguages']) ? \TYPO3\CMS\Core\Utility\GeneralUtility::trimExplode(',', $modSharedTSconfig['properties']['disableLanguages'], TRUE) : array();
162 // Traverse system languages:
163 foreach ($languages as $langRow) {
164 if ($this->pObj->MOD_SETTINGS['lang'] == 0 || (int)$this->pObj->MOD_SETTINGS['lang'] === (int)$langRow['uid']) {
165 $row = $this->getLangStatus($data['row']['uid'], $langRow['uid']);
166 $info = '';
167 if (is_array($row)) {
168 $langRecUids[$langRow['uid']][] = $row['uid'];
169 $status = $row['_HIDDEN'] ? (\TYPO3\CMS\Core\Utility\GeneralUtility::hideIfNotTranslated($data['row']['l18n_cfg']) || $data['row']['l18n_cfg'] & 1 ? 'c-blocked' : 'c-fallback') : 'c-ok';
170 $icon = IconUtility::getSpriteIconForRecord(
171 'pages_language_overlay',
172 $row,
173 array('class' => 'c-recIcon')
174 );
175 $info = $icon . htmlspecialchars(
176 \TYPO3\CMS\Core\Utility\GeneralUtility::fixed_lgd_cs($row['title'], $titleLen)
177 ) . ((string)$row['nav_title'] !== '' ? ' [Nav: <em>' . htmlspecialchars(
178 \TYPO3\CMS\Core\Utility\GeneralUtility::fixed_lgd_cs($row['nav_title'], $titleLen)
179 ) . '</em>]' : '') . ($row['_COUNT'] > 1 ? '<div>' . $LANG->sL(
180 'LLL:EXT:cms/web_info/locallang.xlf:lang_renderl10n_badThingThereAre'
181 ) . '</div>' : '');
182 $tCells[] = '<td class="' . $status . ' c-leftLine">' . $info . '</td>';
183 // Edit whole record:
184 $info = '';
185 $editUid = $row['uid'];
186 $params = '&edit[pages_language_overlay][' . $editUid . ']=edit';
187 $info .= '<a href="#" onclick="' . htmlspecialchars(
188 BackendUtility::editOnClick($params, $GLOBALS['BACK_PATH'])
189 ) . '" title="' . $LANG->sL(
190 'LLL:EXT:cms/web_info/locallang.xlf:lang_renderl10n_editLanguageOverlayRecord'
191 ) . '">' . IconUtility::getSpriteIcon('actions-document-open') . '</a>';
192 $info .= '<a href="#" onclick="' . htmlspecialchars(
193 'top.loadEditId(' . (int)$data['row']['uid'] . ',"&SET[language]=' . $langRow['uid'] . '"); return false;'
194 ) . '" title="' . $LANG->sL(
195 'LLL:EXT:cms/web_info/locallang.xlf:lang_renderl10n_editPageLang'
196 ) . '">' . IconUtility::getSpriteIcon('actions-page-open') . '</a>';
197 $info .= str_replace('###LANG_UID###', $langRow['uid'], $viewPageLink);
198 $tCells[] = '<td class="' . $status . '">' . $info . '</td>';
199 $tCells[] = '<td class="' . $status . '" title="' . $LANG->sL(
200 'LLL:EXT:cms/web_info/locallang.xlf:lang_renderl10n_CEcount'
201 ) . '" align="center">' . $this->getContentElementCount($data['row']['uid'], $langRow['uid']) . '</td>';
202 } else {
203 if (in_array($langRow['uid'], $disableLanguages)) {
204 // Language has been disabled for this page
205 $status = 'c-blocked';
206 $info = '';
207 } else {
208 $status = \TYPO3\CMS\Core\Utility\GeneralUtility::hideIfNotTranslated($data['row']['l18n_cfg']) || $data['row']['l18n_cfg'] & 1 ? 'c-blocked' : 'c-fallback';
209 $info = '<input type="checkbox" name="newOL[' . $langRow['uid'] . '][' . $data['row']['uid'] . ']" value="1" />';
210 $newOL_js[$langRow['uid']] .= '
211 +(document.webinfoForm[\'newOL[' . $langRow['uid'] . '][' . $data['row']['uid'] . ']\'].checked ? \'&edit[pages_language_overlay][' . $data['row']['uid'] . ']=new\' : \'\')
212 ';
213 }
214 $tCells[] = '<td class="' . $status . ' c-leftLine">&nbsp;</td>';
215 $tCells[] = '<td class="' . $status . '">&nbsp;</td>';
216 $tCells[] = '<td class="' . $status . '">' . $info . '</td>';
217 }
218 }
219 }
220 $output .= '
221 <tr class="bgColor4">
222 ' . implode('
223 ', $tCells) . '
224 </tr>';
225 }
226 // Put together HEADER:
227 $tCells = array();
228 $tCells[] = '<td>' . $LANG->sL('LLL:EXT:cms/web_info/locallang.xlf:lang_renderl10n_page') . ':</td>';
229 if (is_array($langRecUids[0])) {
230 $params = '&edit[pages][' . implode(',', $langRecUids[0]) . ']=edit&columnsOnly=title,nav_title,l18n_cfg,hidden';
231 $editIco = '<a href="#" onclick="' . htmlspecialchars(
232 BackendUtility::editOnClick($params, $GLOBALS['BACK_PATH'])
233 ) . '" title="' . $LANG->sL(
234 'LLL:EXT:cms/web_info/locallang.xlf:lang_renderl10n_editPageProperties'
235 ) . '">' . IconUtility::getSpriteIcon('actions-document-new') . '</a>';
236 } else {
237 $editIco = '';
238 }
239 $tCells[] = '<td class="c-leftLine" colspan="2">' . $LANG->sL(
240 'LLL:EXT:cms/web_info/locallang.xlf:lang_renderl10n_default'
241 ) . ':' . $editIco . '</td>';
242 foreach ($languages as $langRow) {
243 if ($this->pObj->MOD_SETTINGS['lang'] == 0 || (int)$this->pObj->MOD_SETTINGS['lang'] === (int)$langRow['uid']) {
244 // Title:
245 $tCells[] = '<td class="c-leftLine">' . htmlspecialchars($langRow['title']) . '</td>';
246 // Edit language overlay records:
247 if (is_array($langRecUids[$langRow['uid']])) {
248 $params = '&edit[pages_language_overlay][' .
249 implode(',', $langRecUids[$langRow['uid']]) .
250 ']=edit&columnsOnly=title,nav_title,hidden';
251 $tCells[] = '<td><a href="#" onclick="' . htmlspecialchars(
252 BackendUtility::editOnClick($params, $GLOBALS['BACK_PATH'])
253 ) . '" title="' . $LANG->sL(
254 'LLL:EXT:cms/web_info/locallang.xlf:lang_renderl10n_editLangOverlays'
255 ) . '">' . IconUtility::getSpriteIcon('actions-document-open') . '</a></td>';
256 } else {
257 $tCells[] = '<td>&nbsp;</td>';
258 }
259 // Create new overlay records:
260 $params = '\'' .
261 $newOL_js[$langRow['uid']] .
262 '+\'&columnsOnly=title,hidden,sys_language_uid&defVals[pages_language_overlay][sys_language_uid]=' .
263 $langRow['uid'];
264 $tCells[] = '<td><a href="#" onclick="' . htmlspecialchars(
265 BackendUtility::editOnClick($params, $GLOBALS['BACK_PATH'])
266 ) . '" title="' . $LANG->sL(
267 'LLL:EXT:cms/web_info/locallang.xlf:lang_getlangsta_createNewTranslationHeaders'
268 ) . '">' . IconUtility::getSpriteIcon('actions-document-new') . '</a></td>';
269 }
270 }
271 $output = '
272 <tr class="t3-row-header">
273 ' . implode('
274 ', $tCells) . '
275 </tr>' . $output;
276 $output = '
277
278 <table border="0" cellspacing="0" cellpadding="0" id="langTable" class="typo3-dblist">' . $output . '
279 </table>';
280 return $output;
281 }
282
283 /**
284 * Selects all system languages (from sys_language)
285 *
286 * @return array System language records in an array.
287 * @todo Define visibility
288 */
289 public function getSystemLanguages() {
290 if (!$GLOBALS['BE_USER']->user['admin'] && strlen($GLOBALS['BE_USER']->groupData['allowed_languages'])) {
291 $allowed_languages = array_flip(explode(',', $GLOBALS['BE_USER']->groupData['allowed_languages']));
292 }
293 $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('*', 'sys_language', '1=1' . BackendUtility::deleteClause('sys_language'));
294 $outputArray = array();
295 while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
296 if (is_array($allowed_languages) && count($allowed_languages)) {
297 if (isset($allowed_languages[$row['uid']])) {
298 $outputArray[] = $row;
299 }
300 } else {
301 $outputArray[] = $row;
302 }
303 }
304 return $outputArray;
305 }
306
307 /**
308 * Get an alternative language record for a specific page / language
309 *
310 * @param integer $pageId Page ID to look up for.
311 * @param integer $langId Language UID to select for.
312 * @return array pages_languages_overlay record
313 * @todo Define visibility
314 */
315 public function getLangStatus($pageId, $langId) {
316 $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
317 '*',
318 'pages_language_overlay',
319 'pid=' . (int)$pageId .
320 ' AND sys_language_uid=' . (int)$langId .
321 BackendUtility::deleteClause('pages_language_overlay') .
322 BackendUtility::versioningPlaceholderClause('pages_language_overlay')
323 );
324 $row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res);
325 BackendUtility::workspaceOL('pages_language_overlay', $row);
326 if (is_array($row)) {
327 $row['_COUNT'] = $GLOBALS['TYPO3_DB']->sql_num_rows($res);
328 $row['_HIDDEN'] = $row['hidden'] || (int)$row['endtime'] > 0 && (int)$row['endtime'] < $GLOBALS['EXEC_TIME'] || $GLOBALS['EXEC_TIME'] < (int)$row['starttime'];
329 }
330 return $row;
331 }
332
333 /**
334 * Counting content elements for a single language on a page.
335 *
336 * @param integer $pageId Page id to select for.
337 * @param integer $sysLang Sys language uid
338 * @return integer Number of content elements from the PID where the language is set to a certain value.
339 * @todo Define visibility
340 */
341 public function getContentElementCount($pageId, $sysLang) {
342 $count = $GLOBALS['TYPO3_DB']->exec_SELECTcountRows('uid', 'tt_content', 'pid=' . (int)$pageId . ' AND sys_language_uid=' . (int)$sysLang . BackendUtility::deleteClause('tt_content') . BackendUtility::versioningPlaceholderClause('tt_content'));
343 return $count ?: '-';
344 }
345
346 }