b218c6415342b2376bea31a3fda0f1619c9bce47
[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($GLOBALS['LANG']->getLL('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(
134 BackendUtility::viewOnClick($data['row']['uid'], $GLOBALS['BACK_PATH'], '', '', '', '&L=###LANG_UID###')) . '" title="' . $LANG->getLL('lang_renderl10n_viewPage', TRUE) . '">' . IconUtility::getSpriteIcon('actions-document-view') . '</a>';
135 $status = $data['row']['l18n_cfg'] & 1 ? 'c-blocked' : 'c-ok';
136 // Create links:
137 $info = '';
138 $editUid = $data['row']['uid'];
139 $params = '&edit[pages][' . $editUid . ']=edit';
140 $info .= '<a href="#" onclick="' . htmlspecialchars(
141 BackendUtility::editOnClick($params, $GLOBALS['BACK_PATH'])) . '" title="' . $LANG->getLL('lang_renderl10n_editDefaultLanguagePage', TRUE) . '">' . IconUtility::getSpriteIcon('actions-document-open') . '</a>';
142 $info .= '<a href="#" onclick="' . htmlspecialchars(('top.loadEditId(' . (int)$data['row']['uid'] . ',"&SET[language]=0"); return false;')) . '" title="' . $LANG->getLL('lang_renderl10n_editPage', TRUE) . '">' . IconUtility::getSpriteIcon('actions-page-open') . '</a>';
143 $info .= str_replace('###LANG_UID###', '0', $viewPageLink);
144 $info .= '&nbsp;';
145 $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;';
146 $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;';
147 // Put into cell:
148 $tCells[] = '<td class="' . $status . ' c-leftLine">' . $info . '</td>';
149 $tCells[] = '<td class="' . $status . '" title="' . $LANG->getLL('lang_renderl10n_CEcount', TRUE) . '" align="center">' . $this->getContentElementCount($data['row']['uid'], 0) . '</td>';
150 $modSharedTSconfig = BackendUtility::getModTSconfig($data['row']['uid'], 'mod.SHARED');
151 $disableLanguages = isset($modSharedTSconfig['properties']['disableLanguages']) ? \TYPO3\CMS\Core\Utility\GeneralUtility::trimExplode(',', $modSharedTSconfig['properties']['disableLanguages'], TRUE) : array();
152 // Traverse system languages:
153 foreach ($languages as $langRow) {
154 if ($this->pObj->MOD_SETTINGS['lang'] == 0 || (int)$this->pObj->MOD_SETTINGS['lang'] === (int)$langRow['uid']) {
155 $row = $this->getLangStatus($data['row']['uid'], $langRow['uid']);
156 $info = '';
157 if (is_array($row)) {
158 $langRecUids[$langRow['uid']][] = $row['uid'];
159 $status = $row['_HIDDEN'] ? (\TYPO3\CMS\Core\Utility\GeneralUtility::hideIfNotTranslated($data['row']['l18n_cfg']) || $data['row']['l18n_cfg'] & 1 ? 'c-blocked' : 'c-fallback') : 'c-ok';
160 $icon = IconUtility::getSpriteIconForRecord(
161 'pages_language_overlay',
162 $row,
163 array('class' => 'c-recIcon')
164 );
165 $info = $icon . htmlspecialchars(\TYPO3\CMS\Core\Utility\GeneralUtility::fixed_lgd_cs($row['title'], $titleLen)) . ((string)$row['nav_title'] !== '' ? ' [Nav: <em>' . htmlspecialchars(\TYPO3\CMS\Core\Utility\GeneralUtility::fixed_lgd_cs($row['nav_title'], $titleLen)) . '</em>]' : '') . ($row['_COUNT'] > 1 ? '<div>' . $LANG->getLL('lang_renderl10n_badThingThereAre', TRUE) . '</div>' : '');
166 $tCells[] = '<td class="' . $status . ' c-leftLine">' . $info . '</td>';
167 // Edit whole record:
168 $info = '';
169 $editUid = $row['uid'];
170 $params = '&edit[pages_language_overlay][' . $editUid . ']=edit';
171 $info .= '<a href="#" onclick="' . htmlspecialchars(
172 BackendUtility::editOnClick($params, $GLOBALS['BACK_PATH'])) . '" title="' . $LANG->getLL('lang_renderl10n_editLanguageOverlayRecord', TRUE) . '">' . IconUtility::getSpriteIcon('actions-document-open') . '</a>';
173 $info .= '<a href="#" onclick="' . htmlspecialchars(('top.loadEditId(' . (int)$data['row']['uid'] . ',"&SET[language]=' . $langRow['uid'] . '"); return false;')) . '" title="' . $LANG->getLL('lang_renderl10n_editPageLang', TRUE) . '">' . IconUtility::getSpriteIcon('actions-page-open') . '</a>';
174 $info .= str_replace('###LANG_UID###', $langRow['uid'], $viewPageLink);
175 $tCells[] = '<td class="' . $status . '">' . $info . '</td>';
176 $tCells[] = '<td class="' . $status . '" title="' . $LANG->getLL('lang_renderl10n_CEcount', TRUE) . '" align="center">' . $this->getContentElementCount($data['row']['uid'], $langRow['uid']) . '</td>';
177 } else {
178 if (in_array($langRow['uid'], $disableLanguages)) {
179 // Language has been disabled for this page
180 $status = 'c-blocked';
181 $info = '';
182 } else {
183 $status = \TYPO3\CMS\Core\Utility\GeneralUtility::hideIfNotTranslated($data['row']['l18n_cfg']) || $data['row']['l18n_cfg'] & 1 ? 'c-blocked' : 'c-fallback';
184 $info = '<input type="checkbox" name="newOL[' . $langRow['uid'] . '][' . $data['row']['uid'] . ']" value="1" />';
185 $newOL_js[$langRow['uid']] .= '
186 +(document.webinfoForm[\'newOL[' . $langRow['uid'] . '][' . $data['row']['uid'] . ']\'].checked ? \'&edit[pages_language_overlay][' . $data['row']['uid'] . ']=new\' : \'\')
187 ';
188 }
189 $tCells[] = '<td class="' . $status . ' c-leftLine">&nbsp;</td>';
190 $tCells[] = '<td class="' . $status . '">&nbsp;</td>';
191 $tCells[] = '<td class="' . $status . '">' . $info . '</td>';
192 }
193 }
194 }
195 $output .= '
196 <tr class="bgColor4">
197 ' . implode('
198 ', $tCells) . '
199 </tr>';
200 }
201 // Put together HEADER:
202 $tCells = array();
203 $tCells[] = '<td>' . $LANG->getLL('lang_renderl10n_page', TRUE) . ':</td>';
204 if (is_array($langRecUids[0])) {
205 $params = '&edit[pages][' . implode(',', $langRecUids[0]) . ']=edit&columnsOnly=title,nav_title,l18n_cfg,hidden';
206 $editIco = '<a href="#" onclick="' . htmlspecialchars(
207 BackendUtility::editOnClick($params, $GLOBALS['BACK_PATH'])) . '" title="' . $LANG->getLL('lang_renderl10n_editPageProperties', TRUE) . '">' . IconUtility::getSpriteIcon('actions-document-new') . '</a>';
208 } else {
209 $editIco = '';
210 }
211 $tCells[] = '<td class="c-leftLine" colspan="2">' . $LANG->getLL('lang_renderl10n_default', TRUE) . ':' . $editIco . '</td>';
212 foreach ($languages as $langRow) {
213 if ($this->pObj->MOD_SETTINGS['lang'] == 0 || (int)$this->pObj->MOD_SETTINGS['lang'] === (int)$langRow['uid']) {
214 // Title:
215 $tCells[] = '<td class="c-leftLine">' . htmlspecialchars($langRow['title']) . '</td>';
216 // Edit language overlay records:
217 if (is_array($langRecUids[$langRow['uid']])) {
218 $params = '&edit[pages_language_overlay][' .
219 implode(',', $langRecUids[$langRow['uid']]) .
220 ']=edit&columnsOnly=title,nav_title,hidden';
221 $tCells[] = '<td><a href="#" onclick="' . htmlspecialchars(
222 BackendUtility::editOnClick($params, $GLOBALS['BACK_PATH'])) . '" title="' . $LANG->getLL('lang_renderl10n_editLangOverlays', TRUE) . '">' . IconUtility::getSpriteIcon('actions-document-open') . '</a></td>';
223 } else {
224 $tCells[] = '<td>&nbsp;</td>';
225 }
226 // Create new overlay records:
227 $params = '\'' .
228 $newOL_js[$langRow['uid']] .
229 '+\'&columnsOnly=title,hidden,sys_language_uid&defVals[pages_language_overlay][sys_language_uid]=' .
230 $langRow['uid'];
231 $tCells[] = '<td><a href="#" onclick="' . htmlspecialchars(
232 BackendUtility::editOnClick($params, $GLOBALS['BACK_PATH'])) . '" title="' . $LANG->getLL('lang_getlangsta_createNewTranslationHeaders', TRUE) . '">' . IconUtility::getSpriteIcon('actions-document-new') . '</a></td>';
233 }
234 }
235 $output = '
236 <tr class="t3-row-header">
237 ' . implode('
238 ', $tCells) . '
239 </tr>' . $output;
240 $output = '
241
242 <table border="0" cellspacing="0" cellpadding="0" id="langTable" class="typo3-dblist">' . $output . '
243 </table>';
244 return $output;
245 }
246
247 /**
248 * Selects all system languages (from sys_language)
249 *
250 * @return array System language records in an array.
251 * @todo Define visibility
252 */
253 public function getSystemLanguages() {
254 if (!$GLOBALS['BE_USER']->user['admin'] && strlen($GLOBALS['BE_USER']->groupData['allowed_languages'])) {
255 $allowed_languages = array_flip(explode(',', $GLOBALS['BE_USER']->groupData['allowed_languages']));
256 }
257 $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery('*', 'sys_language', '1=1' . BackendUtility::deleteClause('sys_language'));
258 $outputArray = array();
259 while ($row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res)) {
260 if (is_array($allowed_languages) && count($allowed_languages)) {
261 if (isset($allowed_languages[$row['uid']])) {
262 $outputArray[] = $row;
263 }
264 } else {
265 $outputArray[] = $row;
266 }
267 }
268 return $outputArray;
269 }
270
271 /**
272 * Get an alternative language record for a specific page / language
273 *
274 * @param integer $pageId Page ID to look up for.
275 * @param integer $langId Language UID to select for.
276 * @return array pages_languages_overlay record
277 * @todo Define visibility
278 */
279 public function getLangStatus($pageId, $langId) {
280 $res = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
281 '*',
282 'pages_language_overlay',
283 'pid=' . (int)$pageId .
284 ' AND sys_language_uid=' . (int)$langId .
285 BackendUtility::deleteClause('pages_language_overlay') .
286 BackendUtility::versioningPlaceholderClause('pages_language_overlay')
287 );
288 $row = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($res);
289 BackendUtility::workspaceOL('pages_language_overlay', $row);
290 if (is_array($row)) {
291 $row['_COUNT'] = $GLOBALS['TYPO3_DB']->sql_num_rows($res);
292 $row['_HIDDEN'] = $row['hidden'] || (int)$row['endtime'] > 0 && (int)$row['endtime'] < $GLOBALS['EXEC_TIME'] || $GLOBALS['EXEC_TIME'] < (int)$row['starttime'];
293 }
294 return $row;
295 }
296
297 /**
298 * Counting content elements for a single language on a page.
299 *
300 * @param integer $pageId Page id to select for.
301 * @param integer $sysLang Sys language uid
302 * @return integer Number of content elements from the PID where the language is set to a certain value.
303 * @todo Define visibility
304 */
305 public function getContentElementCount($pageId, $sysLang) {
306 $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'));
307 return $count ?: '-';
308 }
309
310 }