[BUGFIX] Namespace: help_cshmanual references local_TYPO3
[Packages/TYPO3.CMS.git] / typo3 / sysext / cshmanual / Classes / Controller / HelpModuleController.php
1 <?php
2 namespace TYPO3\CMS\Cshmanual\Controller;
3
4 /**
5 * Script Class for rendering the Context Sensitive Help documents, either the single display in the small pop-up window or the full-table view in the larger window.
6 *
7 * @author Kasper Skårhøj <kasperYYYY@typo3.com>
8 * @package TYPO3
9 * @subpackage core
10 */
11 class HelpModuleController {
12
13 /**
14 * @todo Define visibility
15 */
16 public $allowedHTML = '<strong><em><b><i>';
17
18 // For these vars, see init()
19 // If set access to fields and tables is checked. Should be done for TRUE database tables.
20 /**
21 * @todo Define visibility
22 */
23 public $limitAccess;
24
25 // The "table" key
26 /**
27 * @todo Define visibility
28 */
29 public $table;
30
31 // The "field" key
32 /**
33 * @todo Define visibility
34 */
35 public $field;
36
37 /**
38 * Key used to point to the right CSH resource
39 * In simple cases, is equal to $table
40 *
41 * @var string
42 */
43 protected $mainKey;
44
45 // Internal, static: GPvar:
46 // Table/FIeld id.
47 /**
48 * @todo Define visibility
49 */
50 public $tfID;
51
52 // Back (previous tfID)
53 /**
54 * @todo Define visibility
55 */
56 public $back;
57
58 // If set, then in TOC mode the FULL manual will be printed as well!
59 /**
60 * @todo Define visibility
61 */
62 public $renderALL;
63
64 // Internal, dynamic:
65 // Content accumulation.
66 /**
67 * @todo Define visibility
68 */
69 public $content;
70
71 // Glossary words
72 /**
73 * @todo Define visibility
74 */
75 public $glossaryWords;
76
77 /**
78 * Initialize the class for various input etc.
79 *
80 * @return void
81 * @todo Define visibility
82 */
83 public function init() {
84 // Setting GPvars:
85 $this->tfID = \TYPO3\CMS\Core\Utility\GeneralUtility::_GP('tfID');
86 // Sanitizes the tfID using whitelisting.
87 if (!preg_match('/^[a-zA-Z0-9_\\-\\.\\*]*$/', $this->tfID)) {
88 $this->tfID = '';
89 }
90 $this->back = \TYPO3\CMS\Core\Utility\GeneralUtility::_GP('back');
91 $this->renderALL = \TYPO3\CMS\Core\Utility\GeneralUtility::_GP('renderALL');
92 // Set internal table/field to the parts of "tfID" incoming var.
93 $identifierParts = explode('.', $this->tfID);
94 // The table is the first item
95 $this->table = array_shift($identifierParts);
96 $this->mainKey = $this->table;
97 // The field is the second one
98 $this->field = array_shift($identifierParts);
99 // There may be extra parts for FlexForms
100 if (count($identifierParts) > 0) {
101 // There's at least one extra part
102 $extraIdentifierInformation = array();
103 $extraIdentifierInformation[] = array_shift($identifierParts);
104 // Load the TCA details of the table
105 \TYPO3\CMS\Core\Utility\GeneralUtility::loadTCA($this->table);
106 // If the ds_pointerField contains a comma, it means the choice of FlexForm DS
107 // is determined by 2 parameters. In this case we have an extra identifier part
108 if (strpos($GLOBALS['TCA'][$this->table]['columns'][$this->field]['config']['ds_pointerField'], ',') !== FALSE) {
109 $extraIdentifierInformation[] = array_shift($identifierParts);
110 }
111 // The remaining parts make up the FlexForm field name itself
112 // (reassembled with dots)
113 $flexFormField = implode('.', $identifierParts);
114 // Assemble a different main key and switch field to use FlexForm field name
115 $this->mainKey .= '.' . $this->field;
116 foreach ($extraIdentifierInformation as $extraKey) {
117 $this->mainKey .= '.' . $extraKey;
118 }
119 $this->field = $flexFormField;
120 }
121 // limitAccess is checked if the $this->table really IS a table (and if the user is NOT a translator who should see all!)
122 $showAllToUser = \TYPO3\CMS\Backend\Utility\BackendUtility::isModuleSetInTBE_MODULES('txllxmltranslateM1') && $GLOBALS['BE_USER']->check('modules', 'txllxmltranslateM1');
123 $this->limitAccess = isset($GLOBALS['TCA'][$this->table]) ? !$showAllToUser : FALSE;
124 $GLOBALS['LANG']->includeLLFile('EXT:lang/locallang_view_help.xlf', 1);
125 }
126
127 /**
128 * Main function, rendering the display
129 *
130 * @return void
131 * @todo Define visibility
132 */
133 public function main() {
134 // Start HTML output accumulation:
135 $GLOBALS['TBE_TEMPLATE']->divClass = 'typo3-view-help';
136 $this->content .= $GLOBALS['TBE_TEMPLATE']->startPage($GLOBALS['LANG']->getLL('title'));
137 if ($this->field == '*') {
138 // If ALL fields is supposed to be shown:
139 $this->createGlossaryIndex();
140 $this->content .= $this->render_Table($this->mainKey);
141 } elseif ($this->tfID) {
142 // ... otherwise show only single field:
143 $this->createGlossaryIndex();
144 $this->content .= $this->render_Single($this->mainKey, $this->field);
145 } else {
146 // Render Table Of Contents if nothing else:
147 $this->content .= $this->render_TOC();
148 }
149 // End page:
150 $this->content .= '<br/>';
151 $this->content .= $GLOBALS['TBE_TEMPLATE']->endPage();
152 }
153
154 /**
155 * Outputting the accumulated content to screen
156 *
157 * @return void
158 * @todo Define visibility
159 */
160 public function printContent() {
161 echo $this->content;
162 }
163
164 /************************************
165 *
166 * Rendering main modes
167 *
168 ************************************/
169 /**
170 * Creates Table Of Contents and possibly "Full Manual" mode if selected.
171 *
172 * @return string HTML content
173 * @todo Define visibility
174 */
175 public function render_TOC() {
176 // Initialize:
177 $CSHkeys = array_flip(array_keys($GLOBALS['TCA_DESCR']));
178 $TCAkeys = array_keys($GLOBALS['TCA']);
179 $outputSections = array();
180 $tocArray = array();
181 // TYPO3 Core Features:
182 $GLOBALS['LANG']->loadSingleTableDescription('xMOD_csh_corebe');
183 $this->render_TOC_el('xMOD_csh_corebe', 'core', $outputSections, $tocArray, $CSHkeys);
184 // Backend Modules:
185 $loadModules = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Backend\\Module\\ModuleLoader');
186 $loadModules->load($GLOBALS['TBE_MODULES']);
187 foreach ($loadModules->modules as $mainMod => $info) {
188 $cshKey = '_MOD_' . $mainMod;
189 if ($CSHkeys[$cshKey]) {
190 $GLOBALS['LANG']->loadSingleTableDescription($cshKey);
191 $this->render_TOC_el($cshKey, 'modules', $outputSections, $tocArray, $CSHkeys);
192 }
193 if (is_array($info['sub'])) {
194 foreach ($info['sub'] as $subMod => $subInfo) {
195 $cshKey = (('_MOD_' . $mainMod) . '_') . $subMod;
196 if ($CSHkeys[$cshKey]) {
197 $GLOBALS['LANG']->loadSingleTableDescription($cshKey);
198 $this->render_TOC_el($cshKey, 'modules', $outputSections, $tocArray, $CSHkeys);
199 }
200 }
201 }
202 }
203 // Database Tables:
204 foreach ($TCAkeys as $table) {
205 // Load descriptions for table $table
206 $GLOBALS['LANG']->loadSingleTableDescription($table);
207 if (is_array($GLOBALS['TCA_DESCR'][$table]['columns']) && $GLOBALS['BE_USER']->check('tables_select', $table)) {
208 $this->render_TOC_el($table, 'tables', $outputSections, $tocArray, $CSHkeys);
209 }
210 }
211 // Extensions
212 foreach ($CSHkeys as $cshKey => $value) {
213 if (\TYPO3\CMS\Core\Utility\GeneralUtility::isFirstPartOfStr($cshKey, 'xEXT_') && !isset($GLOBALS['TCA'][$cshKey])) {
214 $GLOBALS['LANG']->loadSingleTableDescription($cshKey);
215 $this->render_TOC_el($cshKey, 'extensions', $outputSections, $tocArray, $CSHkeys);
216 }
217 }
218 // Glossary
219 foreach ($CSHkeys as $cshKey => $value) {
220 if (\TYPO3\CMS\Core\Utility\GeneralUtility::isFirstPartOfStr($cshKey, 'xGLOSSARY_') && !isset($GLOBALS['TCA'][$cshKey])) {
221 $GLOBALS['LANG']->loadSingleTableDescription($cshKey);
222 $this->render_TOC_el($cshKey, 'glossary', $outputSections, $tocArray, $CSHkeys);
223 }
224 }
225 // Other:
226 foreach ($CSHkeys as $cshKey => $value) {
227 if (!\TYPO3\CMS\Core\Utility\GeneralUtility::isFirstPartOfStr($cshKey, '_MOD_') && !isset($GLOBALS['TCA'][$cshKey])) {
228 $GLOBALS['LANG']->loadSingleTableDescription($cshKey);
229 $this->render_TOC_el($cshKey, 'other', $outputSections, $tocArray, $CSHkeys);
230 }
231 }
232 // COMPILE output:
233 $output = '';
234 $output .= ('
235
236 <h1>' . $GLOBALS['LANG']->getLL('manual_title', 1)) . '</h1>';
237 $output .= ((('
238
239 <h2>' . $GLOBALS['LANG']->getLL('introduction', 1)) . '</h2>
240 <p>') . $GLOBALS['LANG']->getLL('description', 1)) . '</p>';
241 $output .= (('
242
243 <h2>' . $GLOBALS['LANG']->getLL('TOC', 1)) . '</h2>') . $this->render_TOC_makeTocList($tocArray);
244 if (!$this->renderALL) {
245 $output .= ('
246 <br/>
247 <p class="c-nav"><a href="mod.php?M=help_cshmanual&renderALL=1">' . $GLOBALS['LANG']->getLL('full_manual', 1)) . '</a></p>';
248 }
249 if ($this->renderALL) {
250 $output .= (('
251
252 <h2>' . $GLOBALS['LANG']->getLL('full_manual_chapters', 1)) . '</h2>') . implode('
253
254
255 <!-- NEW SECTION: -->
256 ', $outputSections);
257 }
258 $output .= ('<hr /><p class="manual-title">' . \TYPO3\CMS\Backend\Utility\BackendUtility::TYPO3_copyRightNotice()) . '</p>';
259 return $output;
260 }
261
262 /**
263 * Creates a TOC list element and renders corresponding HELP content if "renderALL" mode is set.
264 *
265 * @param string $table CSH key / Table name
266 * @param string $tocCat TOC category keyword: "core", "modules", "tables", "other
267 * @param array $outputSections Array for accumulation of rendered HELP Content (in "renderALL" mode). Passed by reference!
268 * @param array $tocArray TOC array; Here TOC index elements are created. Passed by reference!
269 * @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!
270 * @return void
271 * @todo Define visibility
272 */
273 public function render_TOC_el($table, $tocCat, &$outputSections, &$tocArray, &$CSHkeys) {
274 // Render full manual right here!
275 if ($this->renderALL) {
276 $outputSections[$table] = $this->render_Table($table);
277 if ($outputSections[$table]) {
278 $outputSections[$table] = (((((((('
279
280 <!-- New CSHkey/Table: ' . $table) . ' -->
281 <p class="c-nav"><a name="ANCHOR_') . $table) . '" href="#">') . $GLOBALS['LANG']->getLL('to_top', 1)) . '</a></p>
282 <h2>') . $this->getTableFieldLabel($table)) . '</h2>
283
284 ') . $outputSections[$table];
285 $tocArray[$tocCat][$table] = ((('<a href="#ANCHOR_' . $table) . '">') . $this->getTableFieldLabel($table)) . '</a>';
286 } else {
287 unset($outputSections[$table]);
288 }
289 } else {
290 // Only TOC:
291 $tocArray[$tocCat][$table] = ((('<p><a href="mod.php?M=help_cshmanual&tfID=' . rawurlencode(($table . '.*'))) . '">') . $this->getTableFieldLabel($table)) . '</a></p>';
292 }
293 // Unset CSH key:
294 unset($CSHkeys[$table]);
295 }
296
297 /**
298 * Renders the TOC index as a HTML bullet list from TOC array
299 *
300 * @param array $tocArray ToC Array.
301 * @return string HTML bullet list for index.
302 * @todo Define visibility
303 */
304 public function render_TOC_makeTocList($tocArray) {
305 // The Various manual sections:
306 $keys = explode(',', 'core,modules,tables,extensions,glossary,other');
307 // Create TOC bullet list:
308 $output = '';
309 foreach ($keys as $tocKey) {
310 if (is_array($tocArray[$tocKey])) {
311 $output .= ((('
312 <li>' . $GLOBALS['LANG']->getLL(('TOC_' . $tocKey), 1)) . '
313 <ul>
314 <li>') . implode('</li>
315 <li>', $tocArray[$tocKey])) . '</li>
316 </ul>
317 </li>';
318 }
319 }
320 // Compile TOC:
321 $output = ('
322
323 <!-- TOC: -->
324 <div class="c-toc">
325 <ul>
326 ' . $output) . '
327 </ul>
328 </div>';
329 return $output;
330 }
331
332 /**
333 * Render CSH for a full cshKey/table
334 *
335 * @param string $key Full CSH key (may be different from table name)
336 * @param string $table CSH key / table name
337 * @return string HTML output
338 * @todo Define visibility
339 */
340 public function render_Table($key, $table = NULL) {
341 $output = '';
342 // Take default key if not explicitly specified
343 if ($table === NULL) {
344 $table = $key;
345 }
346 // Load table TCA
347 \TYPO3\CMS\Core\Utility\GeneralUtility::loadTCA($key);
348 // Load descriptions for table $table
349 $GLOBALS['LANG']->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]) && strcmp($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 // Substitute glossary words:
374 $output = $this->substituteGlossaryWords($output);
375 // TOC link:
376 if (!$this->renderALL) {
377 $tocLink = ('<p class="c-nav"><a href="mod.php?M=help_cshmanual">' . $GLOBALS['LANG']->getLL('goToToc', 1)) . '</a></p>';
378 $output = ((($tocLink . '
379 <br/>') . $output) . '
380 <br />') . $tocLink;
381 }
382 return $output;
383 }
384
385 /**
386 * Renders CSH for a single field.
387 *
388 * @param string $key CSH key / table name
389 * @param string $field Sub key / field name
390 * @return string HTML output
391 * @todo Define visibility
392 */
393 public function render_Single($key, $field) {
394 $output = '';
395 // Load the description field
396 $GLOBALS['LANG']->loadSingleTableDescription($key);
397 // Render single item
398 $output .= $this->printItem($key, $field);
399 // Substitute glossary words:
400 $output = $this->substituteGlossaryWords($output);
401 // Link to Full table description and TOC:
402 $getLLKey = $this->limitAccess ? 'fullDescription' : 'fullDescription_module';
403 $output .= ((((('<br />
404 <p class="c-nav"><a href="mod.php?M=help_cshmanual&tfID=' . rawurlencode(($key . '.*'))) . '">') . $GLOBALS['LANG']->getLL($getLLKey, 1)) . '</a></p>
405 <p class="c-nav"><a href="mod.php?M=help_cshmanual">') . $GLOBALS['LANG']->getLL('goToToc', 1)) . '</a></p>';
406 return $output;
407 }
408
409 /************************************
410 *
411 * Rendering CSH items
412 *
413 ************************************/
414 /**
415 * Make seeAlso links from $value
416 *
417 * @param string $value See-also input codes
418 * @param string $anchorTable If $anchorTable is set to a tablename, then references to this table will be made as anchors, not URLs.
419 * @return string See-also links HTML
420 * @todo Define visibility
421 */
422 public function make_seeAlso($value, $anchorTable = '') {
423 // Split references by comma or linebreak
424 $items = preg_split(('/[,' . LF) . ']/', $value);
425 $lines = array();
426 foreach ($items as $val) {
427 $val = trim($val);
428 if ($val) {
429 $iP = explode(':', $val);
430 $iPUrl = \TYPO3\CMS\Core\Utility\GeneralUtility::trimExplode('|', $val);
431 // URL reference:
432 if (substr($iPUrl[1], 0, 4) == 'http') {
433 $lines[] = ((('<a href="' . htmlspecialchars($iPUrl[1])) . '" target="_blank"><em>') . htmlspecialchars($iPUrl[0])) . '</em></a>';
434 } elseif (substr($iPUrl[1], 0, 5) == 'FILE:') {
435 $fileName = \TYPO3\CMS\Core\Utility\GeneralUtility::getFileAbsFileName(substr($iPUrl[1], 5), 1, 1);
436 if ($fileName && @is_file($fileName)) {
437 $fileName = '../' . substr($fileName, strlen(PATH_site));
438 $lines[] = ((('<a href="' . htmlspecialchars($fileName)) . '" target="_blank"><em>') . htmlspecialchars($iPUrl[0])) . '</em></a>';
439 }
440 } else {
441 // "table" reference
442 \TYPO3\CMS\Core\Utility\GeneralUtility::loadTCA($iP[0]);
443 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])))) {
444 // Checking read access:
445 if (isset($GLOBALS['TCA_DESCR'][$iP[0]])) {
446 // Make see-also link:
447 $href = $this->renderALL || $anchorTable && $iP[0] == $anchorTable ? '#' . implode('.', $iP) : (('mod.php?M=help_cshmanual&tfID=' . rawurlencode(implode('.', $iP))) . '&back=') . $this->tfID;
448 $label = $this->getTableFieldLabel($iP[0], $iP[1], ' / ');
449 $lines[] = ((('<a href="' . htmlspecialchars($href)) . '">') . htmlspecialchars($label)) . '</a>';
450 }
451 }
452 }
453 }
454 }
455 return implode('<br />', $lines);
456 }
457
458 /**
459 * Will return an image tag with description in italics.
460 *
461 * @param string $images Image file reference (list of)
462 * @param string $descr Description string (divided for each image by line break)
463 * @return string Image HTML codes
464 * @todo Define visibility
465 */
466 public function printImage($images, $descr) {
467 $code = '';
468 // Splitting:
469 $imgArray = \TYPO3\CMS\Core\Utility\GeneralUtility::trimExplode(',', $images, 1);
470 if (count($imgArray)) {
471 $descrArray = explode(LF, $descr, count($imgArray));
472 foreach ($imgArray as $k => $image) {
473 $descr = $descrArray[$k];
474 $absImagePath = \TYPO3\CMS\Core\Utility\GeneralUtility::getFileAbsFileName($image, 1, 1);
475 if ($absImagePath && @is_file($absImagePath)) {
476 $imgFile = substr($absImagePath, strlen(PATH_site));
477 $imgInfo = @getimagesize($absImagePath);
478 if (is_array($imgInfo)) {
479 $imgFile = '../' . $imgFile;
480 $code .= ((('<br /><img src="' . $imgFile) . '" ') . $imgInfo[3]) . ' class="c-inlineimg" alt="" /><br />
481 ';
482 $code .= ('<p><em>' . htmlspecialchars($descr)) . '</em></p>
483 ';
484 } else {
485 $code .= ('<div style="background-color: red; border: 1px solid black; color: white;">NOT AN IMAGE: ' . $imgFile) . '</div>';
486 }
487 } else {
488 $code .= ('<div style="background-color: red; border: 1px solid black; color: white;">IMAGE FILE NOT FOUND: ' . $image) . '</div>';
489 }
490 }
491 }
492 return $code;
493 }
494
495 /**
496 * Returns header HTML content
497 *
498 * @param string $str Header text
499 * @param string $type Header type (1, 0)
500 * @return string The HTML for the header.
501 * @todo Define visibility
502 */
503 public function headerLine($str, $type = 0) {
504 switch ($type) {
505 case 1:
506 $str = ('<h2 class="t3-row-header">' . htmlspecialchars($str)) . '</h2>
507 ';
508 break;
509 case 0:
510 $str = ('<h3 class="divider">' . htmlspecialchars($str)) . '</h3>
511 ';
512 break;
513 }
514 return $str;
515 }
516
517 /**
518 * Returns prepared content
519 *
520 * @param string $str Content to format.
521 * @return string Formatted content.
522 * @todo Define visibility
523 */
524 public function prepareContent($str) {
525 return ('<p>' . nl2br(trim(strip_tags($str, $this->allowedHTML)))) . '</p>
526 ';
527 }
528
529 /**
530 * Prints a single $table/$field information piece
531 * If $anchors is set, then seeAlso references to the same table will be page-anchors, not links.
532 *
533 * @param string $key CSH key / table name
534 * @param string $field Sub key / field name
535 * @param boolean $anchors If anchors is to be shown.
536 * @return string HTML content
537 * @todo Define visibility
538 */
539 public function printItem($key, $field, $anchors = FALSE) {
540 $out = '';
541 // Load full table definition in $GLOBALS['TCA']
542 \TYPO3\CMS\Core\Utility\GeneralUtility::loadTCA($key);
543 if ($key && (!$field || is_array($GLOBALS['TCA_DESCR'][$key]['columns'][$field]))) {
544 // Make seeAlso references.
545 $seeAlsoRes = $this->make_seeAlso($GLOBALS['TCA_DESCR'][$key]['columns'][$field]['seeAlso'], $anchors ? $key : '');
546 // Making item:
547 $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(($GLOBALS['LANG']->getLL('details') . ':')) . $this->prepareContent($GLOBALS['TCA_DESCR'][$key]['columns'][$field]['details']) : '')) . ($GLOBALS['TCA_DESCR'][$key]['columns'][$field]['syntax'] ? $this->headerLine(($GLOBALS['LANG']->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(($GLOBALS['LANG']->getLL('seeAlso') . ':')) . '<p>') . $seeAlsoRes) . '</p>' : '')) . ($this->back ? ((('<br /><p><a href="' . htmlspecialchars(('mod.php?M=help_cshmanual&tfID=' . rawurlencode($this->back)))) . '" class="typo3-goBack">') . htmlspecialchars($GLOBALS['LANG']->getLL('goBack'))) . '</a></p>' : '')) . '<br />';
548 }
549 return $out;
550 }
551
552 /**
553 * Returns labels for a given field in a given structure
554 *
555 * @param string $key CSH key / table name
556 * @param string $field Sub key / field name
557 * @return array Table and field labels in a numeric array
558 * @todo Define visibility
559 */
560 public function getTableFieldNames($key, $field) {
561 $GLOBALS['LANG']->loadSingleTableDescription($key);
562 // Define the label for the key
563 $keyName = $key;
564 if (is_array($GLOBALS['TCA_DESCR'][$key]['columns']['']) && isset($GLOBALS['TCA_DESCR'][$key]['columns']['']['alttitle'])) {
565 // If there's an alternative title, use it
566 $keyName = $GLOBALS['TCA_DESCR'][$key]['columns']['']['alttitle'];
567 } elseif (isset($GLOBALS['TCA'][$key])) {
568 // Otherwise, if it's a table, use its title
569 $keyName = $GLOBALS['TCA'][$key]['ctrl']['title'];
570 } else {
571 // If no title was found, make sure to remove any "_MOD_"
572 $keyName = preg_replace('/^_MOD_/', '', $key);
573 }
574 // Define the label for the field
575 $fieldName = $field;
576 if (is_array($GLOBALS['TCA_DESCR'][$key]['columns'][$field]) && isset($GLOBALS['TCA_DESCR'][$key]['columns'][$field]['alttitle'])) {
577 // If there's an alternative title, use it
578 $fieldName = $GLOBALS['TCA_DESCR'][$key]['columns'][$field]['alttitle'];
579 } elseif (isset($GLOBALS['TCA'][$key]) && isset($GLOBALS['TCA'][$key]['columns'][$field])) {
580 // Otherwise, if it's a table, use its title
581 $fieldName = $GLOBALS['TCA'][$key]['columns'][$field]['label'];
582 }
583 return array($keyName, $fieldName);
584 }
585
586 /**
587 * Returns composite label for table/field
588 *
589 * @param string $key CSH key / table name
590 * @param string $field Sub key / field name
591 * @param string $mergeToken Token to merge the two strings with
592 * @return string Labels joined with merge token
593 * @see getTableFieldNames()
594 * @todo Define visibility
595 */
596 public function getTableFieldLabel($key, $field = '', $mergeToken = ': ') {
597 $tableName = '';
598 $fieldName = '';
599 // Get table / field parts:
600 list($tableName, $fieldName) = $this->getTableFieldNames($key, $field);
601 // Create label:
602 $labelString = $GLOBALS['LANG']->sL($tableName) . ($field ? $mergeToken . rtrim(trim($GLOBALS['LANG']->sL($fieldName)), ':') : '');
603 return $labelString;
604 }
605
606 /******************************
607 *
608 * Glossary related
609 *
610 ******************************/
611 /**
612 * Creates glossary index in $this->glossaryWords
613 * Glossary is cached in cache_hash cache and so will be updated only when cache is cleared.
614 *
615 * @return void
616 * @todo Define visibility
617 */
618 public function createGlossaryIndex() {
619 // Create hash string and try to retrieve glossary array:
620 $hash = md5('typo3/mod.php?M=help_cshmanual:glossary');
621 list($this->glossaryWords, $this->substWords) = unserialize(\TYPO3\CMS\Backend\Utility\BackendUtility::getHash($hash));
622 // Generate glossary words if not found:
623 if (!is_array($this->glossaryWords)) {
624 // Initialize:
625 $this->glossaryWords = array();
626 $this->substWords = array();
627 $CSHkeys = array_flip(array_keys($GLOBALS['TCA_DESCR']));
628 // Glossary
629 foreach ($CSHkeys as $cshKey => $value) {
630 if (\TYPO3\CMS\Core\Utility\GeneralUtility::isFirstPartOfStr($cshKey, 'xGLOSSARY_') && !isset($GLOBALS['TCA'][$cshKey])) {
631 $GLOBALS['LANG']->loadSingleTableDescription($cshKey);
632 if (is_array($GLOBALS['TCA_DESCR'][$cshKey]['columns'])) {
633 // Traverse table columns as listed in TCA_DESCR
634 foreach ($GLOBALS['TCA_DESCR'][$cshKey]['columns'] as $field => $data) {
635 if ($field) {
636 $this->glossaryWords[($cshKey . '.') . $field] = array(
637 'title' => trim($data['alttitle'] ? $data['alttitle'] : $cshKey),
638 'description' => str_replace('%22', '%23%23%23', rawurlencode($data['description']))
639 );
640 }
641 }
642 }
643 }
644 }
645 // First, create unique list of words:
646 foreach ($this->glossaryWords as $key => $value) {
647 // Making word lowercase in order to filter out same words in different cases.
648 $word = strtolower($value['title']);
649 if ($word !== '') {
650 $this->substWords[$word] = $value;
651 $this->substWords[$word]['key'] = $key;
652 }
653 }
654 krsort($this->substWords);
655 \TYPO3\CMS\Backend\Utility\BackendUtility::storeHash($hash, serialize(array($this->glossaryWords, $this->substWords)), 'Glossary');
656 }
657 }
658
659 /**
660 * Processing of all non-HTML content in the output
661 * Will be done by a call-back to ->substituteGlossaryWords_htmlcleaner_callback()
662 *
663 * @param string $code Input HTML code
664 * @return string Output HTML code
665 * @todo Define visibility
666 */
667 public function substituteGlossaryWords($code) {
668 $htmlParser = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\CMS\Core\Html\HtmlParser');
669 $htmlParser->pObj = $this;
670 $code = $htmlParser->HTMLcleaner($code, array(), 1);
671 return $code;
672 }
673
674 /**
675 * Substituting glossary words in the CSH
676 * (This is a call-back function from "class local_t3lib_parsehtml extends t3lib_parsehtml", see top of this script)
677 *
678 * @param string $code Input HTML string
679 * @return string HTML with substituted words in.
680 * @coauthor Alex Widschwendter, media.res kommunikationsloesungen
681 * @todo Define visibility
682 */
683 public function substituteGlossaryWords_htmlcleaner_callback($code) {
684 if ((is_array($this->substWords) && count($this->substWords)) && strlen(trim($code))) {
685 // Substitute words:
686 foreach ($this->substWords as $wordKey => $wordSet) {
687 // quoteMeta used so special chars (which should not occur though) in words will not break the regex. Seemed to work (- kasper)
688 $parts = preg_split(('/( |[\\(])(' . quoteMeta($wordSet['title'])) . ')([\\.\\!\\)\\?\\:\\,]+| )/i', (' ' . $code) . ' ', 2, PREG_SPLIT_DELIM_CAPTURE);
689 if (count($parts) == 5) {
690 $parts[2] = ((((('<a class="glossary-term" href="' . htmlspecialchars(((('mod.php?M=help_cshmanual&tfID=' . rawurlencode($wordSet['key'])) . '&back=') . $this->tfID))) . '" title="') . rawurlencode(htmlspecialchars(\TYPO3\CMS\Core\Utility\GeneralUtility::fixed_lgd_cs(rawurldecode($wordSet['description']), 80)))) . '">') . htmlspecialchars($parts[2])) . '</a>';
691 $code = substr(implode('', $parts), 1, -1);
692 // Disable entry so it doesn't get used next time:
693 unset($this->substWords[$wordKey]);
694 }
695 }
696 $code = str_replace('###', '&quot;', rawurldecode($code));
697 }
698 return $code;
699 }
700
701 }
702
703
704 ?>