[FOLLOWUP][TASK] Introduce getter for $GLOBALS['LANG'] in EXT:cshmanual
[Packages/TYPO3.CMS.git] / typo3 / sysext / cshmanual / Classes / Controller / HelpModuleController.php
1 <?php
2 namespace TYPO3\CMS\Cshmanual\Controller;
3
4 /*
5 * This file is part of the TYPO3 CMS project.
6 *
7 * It is free software; you can redistribute it and/or modify it under
8 * the terms of the GNU General Public License, either version 2
9 * of the License, or any later version.
10 *
11 * For the full copyright and license information, please read the
12 * LICENSE.txt file that was distributed with this source code.
13 *
14 * The TYPO3 project - inspiring people to share!
15 */
16
17 use TYPO3\CMS\Backend\Utility\BackendUtility;
18 use TYPO3\CMS\Core\Utility\GeneralUtility;
19
20 /**
21 * Script Class for rendering the Context Sensitive Help documents,
22 * either the single display in the small pop-up window or the full-table view in the larger window.
23 *
24 * @author Kasper Skårhøj <kasperYYYY@typo3.com>
25 */
26 class HelpModuleController {
27
28 /**
29 * @var string
30 */
31 public $allowedHTML = '<strong><em><b><i>';
32
33 /**
34 * For these vars, see init()
35 * If set access to fields and tables is checked. Should be done for TRUE database tables.
36 *
37 * @var bool
38 */
39 public $limitAccess;
40
41 /**
42 * The "table" key
43 *
44 * @var string
45 */
46 public $table;
47
48 /**
49 * The "field" key
50 *
51 * @var string
52 */
53 public $field;
54
55 /**
56 * Key used to point to the right CSH resource
57 * In simple cases, is equal to $table
58 *
59 * @var string
60 */
61 protected $mainKey;
62
63 /**
64 * Internal, static: GPvar
65 * Table/Field id
66 *
67 * @var string
68 */
69 public $tfID;
70
71 /**
72 * Back (previous tfID)
73 *
74 * @var string
75 */
76 public $back;
77
78 /**
79 * If set, then in TOC mode the FULL manual will be printed as well!
80 *
81 * @var bool
82 */
83 public $renderALL;
84
85 /**
86 * Content accumulation
87 *
88 * @var string
89 */
90 public $content;
91
92 /**
93 * URL to help module
94 *
95 * @var string
96 */
97 protected $moduleUrl;
98
99 /**
100 * Initialize the class for various input etc.
101 *
102 * @return void
103 */
104 public function init() {
105 $this->moduleUrl = BackendUtility::getModuleUrl('help_cshmanual');
106 // Setting GPvars:
107 $this->tfID = GeneralUtility::_GP('tfID');
108 // Sanitizes the tfID using whitelisting.
109 if (!preg_match('/^[a-zA-Z0-9_\\-\\.\\*]*$/', $this->tfID)) {
110 $this->tfID = '';
111 }
112 $this->back = GeneralUtility::_GP('back');
113 $this->renderALL = GeneralUtility::_GP('renderALL');
114 // Set internal table/field to the parts of "tfID" incoming var.
115 $identifierParts = explode('.', $this->tfID);
116 // The table is the first item
117 $this->table = array_shift($identifierParts);
118 $this->mainKey = $this->table;
119 // The field is the second one
120 $this->field = array_shift($identifierParts);
121 // There may be extra parts for FlexForms
122 if (count($identifierParts) > 0) {
123 // There's at least one extra part
124 $extraIdentifierInformation = array();
125 $extraIdentifierInformation[] = array_shift($identifierParts);
126 // If the ds_pointerField contains a comma, it means the choice of FlexForm DS
127 // is determined by 2 parameters. In this case we have an extra identifier part
128 if (strpos($GLOBALS['TCA'][$this->table]['columns'][$this->field]['config']['ds_pointerField'], ',') !== FALSE) {
129 $extraIdentifierInformation[] = array_shift($identifierParts);
130 }
131 // The remaining parts make up the FlexForm field name itself
132 // (reassembled with dots)
133 $flexFormField = implode('.', $identifierParts);
134 // Assemble a different main key and switch field to use FlexForm field name
135 $this->mainKey .= '.' . $this->field;
136 foreach ($extraIdentifierInformation as $extraKey) {
137 $this->mainKey .= '.' . $extraKey;
138 }
139 $this->field = $flexFormField;
140 }
141 // limitAccess is checked if the $this->table really IS a table (and if the user is NOT a translator who should see all!)
142 $showAllToUser = BackendUtility::isModuleSetInTBE_MODULES('txllxmltranslateM1') && $GLOBALS['BE_USER']->check('modules', 'txllxmltranslateM1');
143 $this->limitAccess = isset($GLOBALS['TCA'][$this->table]) ? !$showAllToUser : FALSE;
144 $this->getLanguageService()->includeLLFile('EXT:lang/locallang_view_help.xlf');
145 }
146
147 /**
148 * Main function, rendering the display
149 *
150 * @return void
151 */
152 public function main() {
153 if ($this->field == '*') {
154 // If ALL fields is supposed to be shown:
155 $this->content .= $this->render_Table($this->mainKey);
156 } elseif ($this->tfID) {
157 // ... otherwise show only single field:
158 $this->content .= $this->render_Single($this->mainKey, $this->field);
159 } else {
160 // Render Table Of Contents if nothing else:
161 $this->content .= $this->render_TOC();
162 }
163
164 $this->doc = GeneralUtility::makeInstance(\TYPO3\CMS\Backend\Template\DocumentTemplate::class);
165 $this->doc->backPath = $GLOBALS['BACK_PATH'];
166 $this->doc->setModuleTemplate('EXT:cshmanual/Resources/Private/Templates/cshmanual.html');
167
168 $markers = array('CONTENT' => $this->content);
169
170 $this->content = $this->doc->moduleBody(array(), array(), $markers);
171 $this->content = $this->doc->render($this->getLanguageService()->getLL('title'), $this->content);
172 }
173
174 /**
175 * Outputting the accumulated content to screen
176 *
177 * @return void
178 */
179 public function printContent() {
180 echo $this->content;
181 }
182
183 /************************************
184 * Rendering main modes
185 ************************************/
186
187 /**
188 * Creates Table Of Contents and possibly "Full Manual" mode if selected.
189 *
190 * @return string HTML content
191 */
192 public function render_TOC() {
193 // Initialize:
194 $CSHkeys = array_flip(array_keys($GLOBALS['TCA_DESCR']));
195 $TCAkeys = array_keys($GLOBALS['TCA']);
196 $outputSections = array();
197 $tocArray = array();
198 // TYPO3 Core Features:
199 $this->getLanguageService()->loadSingleTableDescription('xMOD_csh_corebe');
200 $this->render_TOC_el('xMOD_csh_corebe', 'core', $outputSections, $tocArray, $CSHkeys);
201 // Backend Modules:
202 $loadModules = GeneralUtility::makeInstance(\TYPO3\CMS\Backend\Module\ModuleLoader::class);
203 $loadModules->load($GLOBALS['TBE_MODULES']);
204 foreach ($loadModules->modules as $mainMod => $info) {
205 $cshKey = '_MOD_' . $mainMod;
206 if ($CSHkeys[$cshKey]) {
207 $this->getLanguageService()->loadSingleTableDescription($cshKey);
208 $this->render_TOC_el($cshKey, 'modules', $outputSections, $tocArray, $CSHkeys);
209 }
210 if (is_array($info['sub'])) {
211 foreach ($info['sub'] as $subMod => $subInfo) {
212 $cshKey = '_MOD_' . $mainMod . '_' . $subMod;
213 if ($CSHkeys[$cshKey]) {
214 $this->getLanguageService()->loadSingleTableDescription($cshKey);
215 $this->render_TOC_el($cshKey, 'modules', $outputSections, $tocArray, $CSHkeys);
216 }
217 }
218 }
219 }
220 // Database Tables:
221 foreach ($TCAkeys as $table) {
222 // Load descriptions for table $table
223 $this->getLanguageService()->loadSingleTableDescription($table);
224 if (is_array($GLOBALS['TCA_DESCR'][$table]['columns']) && $GLOBALS['BE_USER']->check('tables_select', $table)) {
225 $this->render_TOC_el($table, 'tables', $outputSections, $tocArray, $CSHkeys);
226 }
227 }
228 // Extensions
229 foreach ($CSHkeys as $cshKey => $value) {
230 if (GeneralUtility::isFirstPartOfStr($cshKey, 'xEXT_') && !isset($GLOBALS['TCA'][$cshKey])) {
231 $this->getLanguageService()->loadSingleTableDescription($cshKey);
232 $this->render_TOC_el($cshKey, 'extensions', $outputSections, $tocArray, $CSHkeys);
233 }
234 }
235 // Other:
236 foreach ($CSHkeys as $cshKey => $value) {
237 if (!GeneralUtility::isFirstPartOfStr($cshKey, '_MOD_') && !isset($GLOBALS['TCA'][$cshKey])) {
238 $this->getLanguageService()->loadSingleTableDescription($cshKey);
239 $this->render_TOC_el($cshKey, 'other', $outputSections, $tocArray, $CSHkeys);
240 }
241 }
242
243 // COMPILE output:
244 $output = '';
245 $output .= '<h1>' . $this->getLanguageService()->getLL('manual_title', TRUE) . '</h1>';
246 $output .= '<p class="lead">' . $this->getLanguageService()->getLL('description', TRUE) . '</p>';
247
248 $output .= '<h2>' . $this->getLanguageService()->getLL('TOC', TRUE) . '</h2>' . $this->render_TOC_makeTocList($tocArray);
249 if (!$this->renderALL) {
250 $output .= '
251 <br/>
252 <p class="c-nav"><a href="' . htmlspecialchars($this->moduleUrl) . '&amp;renderALL=1">' . $this->getLanguageService()->getLL('full_manual', TRUE) . '</a></p>';
253 }
254 if ($this->renderALL) {
255 $output .= '
256
257 <h2>' . $this->getLanguageService()->getLL('full_manual_chapters', TRUE) . '</h2>' . implode('
258
259
260 <!-- NEW SECTION: -->
261 ', $outputSections);
262 }
263 $output .= '<hr /><p class="manual-title">' . BackendUtility::TYPO3_copyRightNotice() . '</p>';
264 return $output;
265 }
266
267 /**
268 * Creates a TOC list element and renders corresponding HELP content if "renderALL" mode is set.
269 *
270 * @param string $table CSH key / Table name
271 * @param string $tocCat TOC category keyword: "core", "modules", "tables", "other
272 * @param array $outputSections Array for accumulation of rendered HELP Content (in "renderALL" mode). Passed by reference!
273 * @param array $tocArray TOC array; Here TOC index elements are created. Passed by reference!
274 * @param array $CSHkeys CSH keys array. Every item rendered will be unset in this array so finally we can see what CSH keys are not processed yet. Passed by reference!
275 * @return void
276 */
277 public function render_TOC_el($table, $tocCat, &$outputSections, &$tocArray, &$CSHkeys) {
278 // Render full manual right here!
279 if ($this->renderALL) {
280 $outputSections[$table] = $this->render_Table($table);
281 if ($outputSections[$table]) {
282 $outputSections[$table] = '
283
284 <!-- New CSHkey/Table: ' . $table . ' -->
285 <p class="c-nav"><a name="ANCHOR_' . $table . '" href="#">' . $this->getLanguageService()->getLL('to_top', TRUE) . '</a></p>
286 <h2>' . $this->getTableFieldLabel($table) . '</h2>
287
288 ' . $outputSections[$table];
289 $tocArray[$tocCat][$table] = '<a href="#ANCHOR_' . $table . '">' . $this->getTableFieldLabel($table) . '</a>';
290 } else {
291 unset($outputSections[$table]);
292 }
293 } else {
294 // Only TOC:
295 $tocArray[$tocCat][$table] = '<p><a href="' . htmlspecialchars($this->moduleUrl) . '&amp;tfID=' . rawurlencode(($table . '.*')) . '">' . $this->getTableFieldLabel($table) . '</a></p>';
296 }
297 // Unset CSH key:
298 unset($CSHkeys[$table]);
299 }
300
301 /**
302 * Renders the TOC index as a HTML bullet list from TOC array
303 *
304 * @param array $tocArray ToC Array.
305 * @return string HTML bullet list for index.
306 */
307 public function render_TOC_makeTocList($tocArray) {
308 // The Various manual sections:
309 $keys = explode(',', 'core,modules,tables,extensions,other');
310 // Create TOC bullet list:
311 $output = '';
312 foreach ($keys as $tocKey) {
313 if (is_array($tocArray[$tocKey])) {
314 $output .= '
315 <li>' . $this->getLanguageService()->getLL(('TOC_' . $tocKey), TRUE) . '
316 <ul>
317 <li>' . implode('</li>
318 <li>', $tocArray[$tocKey]) . '</li>
319 </ul>
320 </li>';
321 }
322 }
323 // Compile TOC:
324 $output = '
325
326 <!-- TOC: -->
327 <div class="c-toc">
328 <ul>
329 ' . $output . '
330 </ul>
331 </div>';
332 return $output;
333 }
334
335 /**
336 * Render CSH for a full cshKey/table
337 *
338 * @param string $key Full CSH key (may be different from table name)
339 * @param string $table CSH key / table name
340 * @return string HTML output
341 */
342 public function render_Table($key, $table = NULL) {
343 $output = '';
344 // Take default key if not explicitly specified
345 if ($table === NULL) {
346 $table = $key;
347 }
348 // Load descriptions for table $table
349 $this->getLanguageService()->loadSingleTableDescription($key);
350 if (is_array($GLOBALS['TCA_DESCR'][$key]['columns']) && (!$this->limitAccess || $GLOBALS['BE_USER']->check('tables_select', $table))) {
351 // Initialize variables:
352 $parts = array();
353 // Reserved for header of table
354 $parts[0] = '';
355 // Traverse table columns as listed in TCA_DESCR
356 foreach ($GLOBALS['TCA_DESCR'][$key]['columns'] as $field => $_) {
357 $fieldValue = isset($GLOBALS['TCA'][$key]) && (string)$field !== '' ? $GLOBALS['TCA'][$key]['columns'][$field] : array();
358 if (is_array($fieldValue) && (!$this->limitAccess || !$fieldValue['exclude'] || $GLOBALS['BE_USER']->check('non_exclude_fields', $table . ':' . $field))) {
359 if (!$field) {
360 // Header
361 $parts[0] = $this->printItem($key, '', 1);
362 } else {
363 // Field
364 $parts[] = $this->printItem($key, $field, 1);
365 }
366 }
367 }
368 if (!$parts[0]) {
369 unset($parts[0]);
370 }
371 $output .= implode('<br />', $parts);
372 }
373 // TOC link:
374 if (!$this->renderALL) {
375 $tocLink = '<p class="c-nav"><a href="' . htmlspecialchars($this->moduleUrl) . '">' . $this->getLanguageService()->getLL('goToToc', TRUE) . '</a></p>';
376 $output = $tocLink . '
377 <br/>' . $output . '
378 <br />' . $tocLink;
379 }
380 return $output;
381 }
382
383 /**
384 * Renders CSH for a single field.
385 *
386 * @param string $key CSH key / table name
387 * @param string $field Sub key / field name
388 * @return string HTML output
389 */
390 public function render_Single($key, $field) {
391 $output = '';
392 // Load the description field
393 $this->getLanguageService()->loadSingleTableDescription($key);
394 // Render single item
395 $output .= $this->printItem($key, $field);
396 // Link to Full table description and TOC:
397 $getLLKey = $this->limitAccess ? 'fullDescription' : 'fullDescription_module';
398 $output .= '<br />
399 <p class="c-nav"><a href="' . htmlspecialchars($this->moduleUrl) . '&amp;tfID=' . rawurlencode(($key . '.*')) . '">' . $this->getLanguageService()->getLL($getLLKey, TRUE) . '</a></p>
400 <p class="c-nav"><a href="' . htmlspecialchars($this->moduleUrl) . '">' . $this->getLanguageService()->getLL('goToToc', TRUE) . '</a></p>';
401 return $output;
402 }
403
404 /************************************
405 * Rendering CSH items
406 ************************************/
407
408 /**
409 * Make seeAlso links from $value
410 *
411 * @param string $value See-also input codes
412 * @param string $anchorTable If $anchorTable is set to a tablename, then references to this table will be made as anchors, not URLs.
413 * @return string See-also links HTML
414 */
415 public function make_seeAlso($value, $anchorTable = '') {
416 // Split references by comma or linebreak
417 $items = preg_split('/[,' . LF . ']/', $value);
418 $lines = array();
419 foreach ($items as $val) {
420 $val = trim($val);
421 if ($val) {
422 $iP = explode(':', $val);
423 $iPUrl = GeneralUtility::trimExplode('|', $val);
424 // URL reference:
425 if (substr($iPUrl[1], 0, 4) == 'http') {
426 $lines[] = '<a href="' . htmlspecialchars($iPUrl[1]) . '" target="_blank"><em>' . htmlspecialchars($iPUrl[0]) . '</em></a>';
427 } elseif (substr($iPUrl[1], 0, 5) == 'FILE:') {
428 $fileName = GeneralUtility::getFileAbsFileName(substr($iPUrl[1], 5), 1, 1);
429 if ($fileName && @is_file($fileName)) {
430 $fileName = '../' . \TYPO3\CMS\Core\Utility\PathUtility::stripPathSitePrefix($fileName);
431 $lines[] = '<a href="' . htmlspecialchars($fileName) . '" target="_blank"><em>' . htmlspecialchars($iPUrl[0]) . '</em></a>';
432 }
433 } else {
434 // "table" reference
435 if (!isset($GLOBALS['TCA'][$iP[0]]) || (!$iP[1] || is_array($GLOBALS['TCA'][$iP[0]]['columns'][$iP[1]])) && (!$this->limitAccess || $GLOBALS['BE_USER']->check('tables_select', $iP[0]) && (!$iP[1] || !$GLOBALS['TCA'][$iP[0]]['columns'][$iP[1]]['exclude'] || $GLOBALS['BE_USER']->check('non_exclude_fields', $iP[0] . ':' . $iP[1])))) {
436 // Checking read access:
437 if (isset($GLOBALS['TCA_DESCR'][$iP[0]])) {
438 // Make see-also link:
439 $href = $this->renderALL || $anchorTable && $iP[0] == $anchorTable ? '#' . rawurlencode(implode('.', $iP)) : $this->moduleUrl . '&tfID=' . rawurlencode(implode('.', $iP)) . '&back=' . $this->tfID;
440 $label = $this->getTableFieldLabel($iP[0], $iP[1], ' / ');
441 $lines[] = '<a href="' . htmlspecialchars($href) . '">' . htmlspecialchars($label) . '</a>';
442 }
443 }
444 }
445 }
446 }
447 return implode('<br />', $lines);
448 }
449
450 /**
451 * Will return an image tag with description in italics.
452 *
453 * @param string $images Image file reference (list of)
454 * @param string $descr Description string (divided for each image by line break)
455 * @return string Image HTML codes
456 */
457 public function printImage($images, $descr) {
458 $code = '';
459 // Splitting:
460 $imgArray = GeneralUtility::trimExplode(',', $images, TRUE);
461 if (count($imgArray)) {
462 $descrArray = explode(LF, $descr, count($imgArray));
463 foreach ($imgArray as $k => $image) {
464 $descr = $descrArray[$k];
465 $absImagePath = GeneralUtility::getFileAbsFileName($image, 1, 1);
466 if ($absImagePath && @is_file($absImagePath)) {
467 $imgFile = \TYPO3\CMS\Core\Utility\PathUtility::stripPathSitePrefix($absImagePath);
468 $imgInfo = @getimagesize($absImagePath);
469 if (is_array($imgInfo)) {
470 $imgFile = '../' . $imgFile;
471 $code .= '<br /><img src="' . $imgFile . '" ' . $imgInfo[3] . ' class="c-inlineimg img-responsive" alt="" /><br />
472 ';
473 $code .= '<p><em>' . htmlspecialchars($descr) . '</em></p>
474 ';
475 } else {
476 $code .= '<div style="background-color: red; border: 1px solid black; color: white;">NOT AN IMAGE: ' . $imgFile . '</div>';
477 }
478 } else {
479 $code .= '<div style="background-color: red; border: 1px solid black; color: white;">IMAGE FILE NOT FOUND: ' . $image . '</div>';
480 }
481 }
482 }
483 return $code;
484 }
485
486 /**
487 * Returns header HTML content
488 *
489 * @param string $str Header text
490 * @param int $type Header type (1, 0)
491 * @return string The HTML for the header.
492 */
493 public function headerLine($str, $type = 0) {
494 switch ($type) {
495 case 1:
496 $str = '<h2>' . htmlspecialchars($str) . '</h2>
497 ';
498 break;
499 case 0:
500 $str = '<h3>' . htmlspecialchars($str) . '</h3>
501 ';
502 break;
503 }
504 return $str;
505 }
506
507 /**
508 * Returns prepared content
509 *
510 * @param string $str Content to format.
511 * @return string Formatted content.
512 */
513 public function prepareContent($str) {
514 return '<p>' . nl2br(trim(strip_tags($str, $this->allowedHTML))) . '</p>
515 ';
516 }
517
518 /**
519 * Prints a single $table/$field information piece
520 * If $anchors is set, then seeAlso references to the same table will be page-anchors, not links.
521 *
522 * @param string $key CSH key / table name
523 * @param string $field Sub key / field name
524 * @param bool $anchors If anchors is to be shown.
525 * @return string HTML content
526 */
527 public function printItem($key, $field, $anchors = FALSE) {
528 $out = '';
529 if ($key && (!$field || is_array($GLOBALS['TCA_DESCR'][$key]['columns'][$field]))) {
530 // Make seeAlso references.
531 $seeAlsoRes = $this->make_seeAlso($GLOBALS['TCA_DESCR'][$key]['columns'][$field]['seeAlso'], $anchors ? $key : '');
532 // Making item:
533 $out = '<a name="' . $key . '.' . $field . '"></a>' . $this->headerLine($this->getTableFieldLabel($key, $field), 1) . $this->prepareContent($GLOBALS['TCA_DESCR'][$key]['columns'][$field]['description']) . ($GLOBALS['TCA_DESCR'][$key]['columns'][$field]['details'] ? $this->headerLine(($this->getLanguageService()->getLL('details') . ':')) . $this->prepareContent($GLOBALS['TCA_DESCR'][$key]['columns'][$field]['details']) : '') . ($GLOBALS['TCA_DESCR'][$key]['columns'][$field]['syntax'] ? $this->headerLine(($this->getLanguageService()->getLL('syntax') . ':')) . $this->prepareContent($GLOBALS['TCA_DESCR'][$key]['columns'][$field]['syntax']) : '') . ($GLOBALS['TCA_DESCR'][$key]['columns'][$field]['image'] ? $this->printImage($GLOBALS['TCA_DESCR'][$key]['columns'][$field]['image'], $GLOBALS['TCA_DESCR'][$key]['columns'][$field]['image_descr']) : '') . ($GLOBALS['TCA_DESCR'][$key]['columns'][$field]['seeAlso'] && $seeAlsoRes ? $this->headerLine(($this->getLanguageService()->getLL('seeAlso') . ':')) . '<p>' . $seeAlsoRes . '</p>' : '') . ($this->back ? '<br /><p><a href="' . htmlspecialchars($this->moduleUrl . '&tfID=' . rawurlencode($this->back)) . '" class="typo3-goBack">' . htmlspecialchars($this->getLanguageService()->getLL('goBack')) . '</a></p>' : '') . '<br />';
534 }
535 return $out;
536 }
537
538 /**
539 * Returns labels for a given field in a given structure
540 *
541 * @param string $key CSH key / table name
542 * @param string $field Sub key / field name
543 * @return array Table and field labels in a numeric array
544 */
545 public function getTableFieldNames($key, $field) {
546 $this->getLanguageService()->loadSingleTableDescription($key);
547 // Define the label for the key
548 $keyName = $key;
549 if (is_array($GLOBALS['TCA_DESCR'][$key]['columns']['']) && isset($GLOBALS['TCA_DESCR'][$key]['columns']['']['alttitle'])) {
550 // If there's an alternative title, use it
551 $keyName = $GLOBALS['TCA_DESCR'][$key]['columns']['']['alttitle'];
552 } elseif (isset($GLOBALS['TCA'][$key])) {
553 // Otherwise, if it's a table, use its title
554 $keyName = $GLOBALS['TCA'][$key]['ctrl']['title'];
555 } else {
556 // If no title was found, make sure to remove any "_MOD_"
557 $keyName = preg_replace('/^_MOD_/', '', $key);
558 }
559 // Define the label for the field
560 $fieldName = $field;
561 if (is_array($GLOBALS['TCA_DESCR'][$key]['columns'][$field]) && isset($GLOBALS['TCA_DESCR'][$key]['columns'][$field]['alttitle'])) {
562 // If there's an alternative title, use it
563 $fieldName = $GLOBALS['TCA_DESCR'][$key]['columns'][$field]['alttitle'];
564 } elseif (isset($GLOBALS['TCA'][$key]) && isset($GLOBALS['TCA'][$key]['columns'][$field])) {
565 // Otherwise, if it's a table, use its title
566 $fieldName = $GLOBALS['TCA'][$key]['columns'][$field]['label'];
567 }
568 return array($keyName, $fieldName);
569 }
570
571 /**
572 * Returns composite label for table/field
573 *
574 * @param string $key CSH key / table name
575 * @param string $field Sub key / field name
576 * @param string $mergeToken Token to merge the two strings with
577 * @return string Labels joined with merge token
578 * @see getTableFieldNames()
579 */
580 public function getTableFieldLabel($key, $field = '', $mergeToken = ': ') {
581 // Get table / field parts:
582 list($tableName, $fieldName) = $this->getTableFieldNames($key, $field);
583 // Create label:
584 $labelString = $this->getLanguageService()->sL($tableName) . ($field ? $mergeToken . rtrim(trim($this->getLanguageService()->sL($fieldName)), ':') : '');
585 return $labelString;
586 }
587
588 /**
589 * Returns LanguageService
590 *
591 * @return \TYPO3\CMS\Lang\LanguageService
592 */
593 protected function getLanguageService() {
594 return $GLOBALS['LANG'];
595 }
596
597 }