[BUGFIX] Error when opening TYPO3 manual
[Packages/TYPO3.CMS.git] / typo3 / view_help.php
1 <?php
2 /***************************************************************
3 * Copyright notice
4 *
5 * (c) 1999-2011 Kasper Skårhøj (kasperYYYY@typo3.com)
6 * All rights reserved
7 *
8 * This script is part of the TYPO3 project. The TYPO3 project is
9 * free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * The GNU General Public License can be found at
15 * http://www.gnu.org/copyleft/gpl.html.
16 * A copy is found in the textfile GPL.txt and important notices to the license
17 * from the author is found in LICENSE.txt distributed with these scripts.
18 *
19 *
20 * This script is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
24 *
25 * This copyright notice MUST APPEAR in all copies of the script!
26 ***************************************************************/
27 /**
28 * Document for viewing the online help texts, also known as TCA_DESCR.
29 * See Inside TYPO3 for details.
30 *
31 * Revised for TYPO3 3.7 5/2004 by Kasper Skårhøj
32 * XHTML-trans compliant
33 *
34 * @author Kasper Skårhøj <kasperYYYY@typo3.com>
35 */
36
37 require('init.php');
38 require('template.php');
39 $GLOBALS['LANG']->includeLLFile('EXT:lang/locallang_view_help.xml');
40
41
42 /**
43 * Extension of the parse_html class.
44 *
45 * @author Kasper Skårhøj <kasperYYYY@typo3.com>
46 * @package TYPO3
47 * @subpackage core
48 */
49 class local_t3lib_parsehtml extends t3lib_parsehtml {
50
51 /**
52 * Processing content between tags for HTML_cleaner
53 *
54 * @param string The value
55 * @param integer Direction, either -1 or +1. 0 (zero) means no change to input value.
56 * @param mixed Not used, ignore.
57 * @return string The processed value.
58 * @access private
59 */
60 function processContent($value,$dir,$conf) {
61 $value = $this->pObj->substituteGlossaryWords_htmlcleaner_callback($value);
62
63 return $value;
64 }
65 }
66
67
68
69
70
71
72
73 /**
74 * 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.
75 *
76 * @author Kasper Skårhøj <kasperYYYY@typo3.com>
77 * @package TYPO3
78 * @subpackage core
79 */
80 class SC_view_help {
81 var $allowedHTML = '<strong><em><b><i>';
82
83 // For these vars, see init()
84 var $limitAccess; // If set access to fields and tables is checked. Should be done for TRUE database tables.
85 var $table; // The "table" key
86 var $field; // The "field" key
87 /**
88 * Key used to point to the right CSH resource
89 * In simple cases, is equal to $table
90 *
91 * @var string
92 */
93 protected $mainKey;
94
95 // Internal, static: GPvar:
96 var $tfID; // Table/FIeld id.
97 var $ffID; // Flexform file/field information
98 var $back; // Back (previous tfID)
99 var $renderALL; // If set, then in TOC mode the FULL manual will be printed as well!
100
101 // Internal, dynamic:
102 var $content; // Content accumulation.
103 var $glossaryWords; // Glossary words
104
105
106
107 /**
108 * Initialize the class for various input etc.
109 *
110 * @return void
111 */
112 function init() {
113
114 // Setting GPvars:
115 $this->tfID = t3lib_div::_GP('tfID');
116 // Sanitizes the tfID using whitelisting.
117 if (!preg_match('/^[a-zA-Z0-9_\-\.\*]*$/', $this->tfID)) {
118 $this->tfID = '';
119 }
120 if (!$this->tfID) {
121 if (($this->ffID = t3lib_div::_GP('ffID'))) {
122 $this->ffID = unserialize(base64_decode($this->ffID));
123 }
124 }
125 $this->back = t3lib_div::_GP('back');
126 $this->renderALL = t3lib_div::_GP('renderALL');
127
128 // Set internal table/field to the parts of "tfID" incoming var.
129 $identifierParts = explode('.', $this->tfID);
130 // The table is the first item
131 $this->table = array_shift($identifierParts);
132 $this->mainKey = $this->table;
133 // The field is the second one
134 $this->field = array_shift($identifierParts);
135 // There may be extra parts for FlexForms
136 if (count($identifierParts) > 0) {
137 // There's at least one extra part
138 $extraIdentifierInformation = array();
139 $extraIdentifierInformation[] = array_shift($identifierParts);
140 // Load the TCA details of the table
141 t3lib_div::loadTCA($this->table);
142 // If the ds_pointerField contains a comma, it means the choice of FlexForm DS
143 // is determined by 2 parameters. In this case we have an extra identifier part
144 if (strpos($GLOBALS['TCA'][$this->table]['columns'][$this->field]['config']['ds_pointerField'], ',') !== FALSE) {
145 $extraIdentifierInformation[] = array_shift($identifierParts);
146 }
147 // The remaining parts make up the FlexForm field name itself
148 // (reassembled with dots)
149 $flexFormField = implode('.', $identifierParts);
150 // Assemble a different main key and switch field to use FlexForm field name
151 $this->mainKey .= '.' . $this->field;
152 foreach ($extraIdentifierInformation as $extraKey) {
153 $this->mainKey .= '.' . $extraKey;
154 }
155 $this->field = $flexFormField;
156 }
157
158 // limitAccess is checked if the $this->table really IS a table (and if the user is NOT a translator who should see all!)
159 $showAllToUser = t3lib_BEfunc::isModuleSetInTBE_MODULES('txllxmltranslateM1') && $GLOBALS['BE_USER']->check('modules','txllxmltranslateM1');
160 $this->limitAccess = isset($GLOBALS['TCA'][$this->table]) ? !$showAllToUser : FALSE;
161 }
162
163 /**
164 * Main function, rendering the display
165 *
166 * @return void
167 */
168 function main() {
169
170 // Start HTML output accumulation:
171 $GLOBALS['TBE_TEMPLATE']->divClass = 'typo3-view-help';
172 $this->content .= $GLOBALS['TBE_TEMPLATE']->startPage($GLOBALS['LANG']->getLL('title'));
173
174 if ($this->field == '*') {
175 // If ALL fields is supposed to be shown:
176 $this->createGlossaryIndex();
177 $this->content .= $this->render_Table($this->mainKey);
178
179 } elseif ($this->tfID) {
180 // ... otherwise show only single field:
181 $this->createGlossaryIndex();
182 $this->content .= $this->render_Single($this->mainKey, $this->field);
183
184 } elseif (is_array($this->ffID)) {
185 $this->content .= $this->render_SingleFlex();
186
187 } else {
188 // Render Table Of Contents if nothing else:
189 $this->content.= $this->render_TOC();
190 }
191
192 // Print close-button:
193 # $this->content.='<br /><form action=""><input type="submit" value="'.htmlspecialchars($GLOBALS['LANG']->getLL('close')).'" onclick="self.close(); return false;" /></form><br/>';
194
195 // End page:
196 $this->content.= '<br/>';
197 $this->content .= $GLOBALS['TBE_TEMPLATE']->endPage();
198 }
199
200 /**
201 * Outputting the accumulated content to screen
202 *
203 * @return void
204 */
205 function printContent() {
206 echo $this->content;
207 }
208
209
210
211
212
213
214
215
216
217 /************************************
218 *
219 * Rendering main modes
220 *
221 ************************************/
222
223 /**
224 * Creates Table Of Contents and possibly "Full Manual" mode if selected.
225 *
226 * @return string HTML content
227 */
228 function render_TOC() {
229 // Initialize:
230 $CSHkeys = array_flip(array_keys($GLOBALS['TCA_DESCR']));
231 $TCAkeys = array_keys($GLOBALS['TCA']);
232
233 $outputSections = array();
234 $tocArray = array();
235
236
237 // TYPO3 Core Features:
238 $GLOBALS['LANG']->loadSingleTableDescription('xMOD_csh_corebe');
239 $this->render_TOC_el('xMOD_csh_corebe', 'core', $outputSections, $tocArray, $CSHkeys);
240
241 // Backend Modules:
242 $loadModules = t3lib_div::makeInstance('t3lib_loadModules');
243 $loadModules->load($GLOBALS['TBE_MODULES']);
244 foreach($loadModules->modules as $mainMod => $info) {
245 $cshKey = '_MOD_'.$mainMod;
246 if ($CSHkeys[$cshKey]) {
247 $GLOBALS['LANG']->loadSingleTableDescription($cshKey);
248 $this->render_TOC_el($cshKey, 'modules', $outputSections, $tocArray, $CSHkeys);
249 }
250
251 if (is_array($info['sub'])) {
252 foreach($info['sub'] as $subMod => $subInfo) {
253 $cshKey = '_MOD_'.$mainMod.'_'.$subMod;
254 if ($CSHkeys[$cshKey]) {
255 $GLOBALS['LANG']->loadSingleTableDescription($cshKey);
256 $this->render_TOC_el($cshKey, 'modules', $outputSections, $tocArray, $CSHkeys);
257 }
258 }
259 }
260 }
261
262 // Database Tables:
263 foreach($TCAkeys as $table) {
264 // Load descriptions for table $table
265 $GLOBALS['LANG']->loadSingleTableDescription($table);
266 if (is_array($GLOBALS['TCA_DESCR'][$table]['columns']) && $GLOBALS['BE_USER']->check('tables_select',$table)) {
267 $this->render_TOC_el($table, 'tables', $outputSections, $tocArray, $CSHkeys);
268 }
269 }
270
271 // Extensions
272 foreach($CSHkeys as $cshKey => $value) {
273 if (t3lib_div::isFirstPartOfStr($cshKey, 'xEXT_') && !isset($GLOBALS['TCA'][$cshKey])) {
274 $GLOBALS['LANG']->loadSingleTableDescription($cshKey);
275 $this->render_TOC_el($cshKey, 'extensions', $outputSections, $tocArray, $CSHkeys);
276 }
277 }
278
279 // Glossary
280 foreach($CSHkeys as $cshKey => $value) {
281 if (t3lib_div::isFirstPartOfStr($cshKey, 'xGLOSSARY_') && !isset($GLOBALS['TCA'][$cshKey])) {
282 $GLOBALS['LANG']->loadSingleTableDescription($cshKey);
283 $this->render_TOC_el($cshKey, 'glossary', $outputSections, $tocArray, $CSHkeys);
284 }
285 }
286
287 // Other:
288 foreach($CSHkeys as $cshKey => $value) {
289 if (!t3lib_div::isFirstPartOfStr($cshKey, '_MOD_') && !isset($GLOBALS['TCA'][$cshKey])) {
290 $GLOBALS['LANG']->loadSingleTableDescription($cshKey);
291 $this->render_TOC_el($cshKey, 'other', $outputSections, $tocArray, $CSHkeys);
292 }
293 }
294
295
296 // COMPILE output:
297 $output = '';
298 $output.= '
299
300 <h1>'.$GLOBALS['LANG']->getLL('manual_title',1).'</h1>';
301
302 $output.= '
303
304 <h2>'.$GLOBALS['LANG']->getLL('introduction',1).'</h2>
305 <p>'.$GLOBALS['LANG']->getLL('description',1).'</p>';
306
307 $output.= '
308
309 <h2>'.$GLOBALS['LANG']->getLL('TOC',1).'</h2>'.
310 $this->render_TOC_makeTocList($tocArray);
311
312 if (!$this->renderALL) {
313 $output.= '
314 <br/>
315 <p class="c-nav"><a href="view_help.php?renderALL=1">'.$GLOBALS['LANG']->getLL('full_manual',1).'</a></p>';
316 }
317
318 if ($this->renderALL) {
319 $output.= '
320
321 <h2>'.$GLOBALS['LANG']->getLL('full_manual_chapters',1).'</h2>'.
322 implode('
323
324
325 <!-- NEW SECTION: -->
326 ',$outputSections);
327 }
328
329 $output .= '<hr /><p class="manual-title">'.t3lib_BEfunc::TYPO3_copyRightNotice().'</p>';
330
331 return $output;
332 }
333
334 /**
335 * Creates a TOC list element and renders corresponding HELP content if "renderALL" mode is set.
336 *
337 * @param string CSH key / Table name
338 * @param string TOC category keyword: "core", "modules", "tables", "other"
339 * @param array Array for accumulation of rendered HELP Content (in "renderALL" mode). Passed by reference!
340 * @param array TOC array; Here TOC index elements are created. Passed by reference!
341 * @param array 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!
342 * @return void
343 */
344 function render_TOC_el($table, $tocCat, &$outputSections, &$tocArray, &$CSHkeys) {
345 if ($this->renderALL) { // Render full manual right here!
346 $outputSections[$table] = $this->render_Table($table);
347
348 if ($outputSections[$table]) {
349 $outputSections[$table] = '
350
351 <!-- New CSHkey/Table: '.$table.' -->
352 <p class="c-nav"><a name="ANCHOR_'.$table.'" href="#">'.$GLOBALS['LANG']->getLL('to_top',1).'</a></p>
353 <h2>'.$this->getTableFieldLabel($table).'</h2>
354
355 '.$outputSections[$table];
356 $tocArray[$tocCat][$table] = '<a href="#ANCHOR_'.$table.'">'.$this->getTableFieldLabel($table).'</a>';
357 } else {
358 unset($outputSections[$table]);
359 }
360 } else { // Only TOC:
361 $tocArray[$tocCat][$table] = '<p><a href="view_help.php?tfID='.rawurlencode($table.'.*').'">'.$this->getTableFieldLabel($table).'</a></p>';
362 }
363
364 // Unset CSH key:
365 unset($CSHkeys[$table]);
366 }
367
368 /**
369 * Renders the TOC index as a HTML bullet list from TOC array
370 *
371 * @param array ToC Array.
372 * @return string HTML bullet list for index.
373 */
374 function render_TOC_makeTocList($tocArray) {
375 // The Various manual sections:
376 $keys = explode(',', 'core,modules,tables,extensions,glossary,other');
377
378 // Create TOC bullet list:
379 $output = '';
380 foreach($keys as $tocKey) {
381 if (is_array($tocArray[$tocKey])) {
382 $output.='
383 <li>'.$GLOBALS['LANG']->getLL('TOC_'.$tocKey,1).'
384 <ul>
385 <li>'.implode('</li>
386 <li>',$tocArray[$tocKey]).'</li>
387 </ul>
388 </li>';
389 }
390 }
391
392 // Compile TOC:
393 $output = '
394
395 <!-- TOC: -->
396 <div class="c-toc">
397 <ul>
398 '.$output.'
399 </ul>
400 </div>';
401
402 return $output;
403 }
404
405 /**
406 * Render CSH for a full cshKey/table
407 *
408 * @param string $key Full CSH key (may be different from table name)
409 * @param string $table CSH key / table name
410 * @return string HTML output
411 */
412 function render_Table($key, $table = NULL) {
413 $output = '';
414
415 // take default key if not explicitly specified
416 if ($table === NULL) {
417 $table = $key;
418 }
419
420 // Load table TCA
421 t3lib_div::loadTCA($key);
422
423 // Load descriptions for table $table
424 $GLOBALS['LANG']->loadSingleTableDescription($key);
425
426 if (is_array($GLOBALS['TCA_DESCR'][$key]['columns']) && (!$this->limitAccess || $GLOBALS['BE_USER']->check('tables_select', $table))) {
427 // Initialize variables:
428 $parts = array();
429 $parts[0] = ''; // Reserved for header of table
430
431 // Traverse table columns as listed in TCA_DESCR
432 foreach ($GLOBALS['TCA_DESCR'][$key]['columns'] as $field => $_) {
433
434 $fieldValue = isset($GLOBALS['TCA'][$key]) && strcmp($field, '') ? $GLOBALS['TCA'][$key]['columns'][$field] : array();
435
436 if (is_array($fieldValue) && (!$this->limitAccess || !$fieldValue['exclude'] || $GLOBALS['BE_USER']->check('non_exclude_fields', $table . ':' . $field))) {
437 if (!$field) {
438 $parts[0] = $this->printItem($key, '', 1); // Header
439 } else {
440 $parts[] = $this->printItem($key, $field, 1); // Field
441 }
442 }
443 }
444
445 if (!$parts[0]) {
446 unset($parts[0]);
447 }
448 $output .= implode('<br />', $parts);
449 }
450
451 // Substitute glossary words:
452 $output = $this->substituteGlossaryWords($output);
453
454 // TOC link:
455 if (!$this->renderALL) {
456 $tocLink = '<p class="c-nav"><a href="view_help.php">' . $GLOBALS['LANG']->getLL('goToToc', 1) . '</a></p>';
457
458 $output =
459 $tocLink.'
460 <br/>'.
461 $output.'
462 <br />'.
463 $tocLink;
464 }
465
466 return $output;
467 }
468
469 /**
470 * Renders CSH for a single field.
471 *
472 * @param string $key CSH key / table name
473 * @param string $field Sub key / field name
474 * @return string HTML output
475 */
476 function render_Single($key, $field) {
477 $output = '';
478
479 // Load the description field
480 $GLOBALS['LANG']->loadSingleTableDescription($key);
481
482 // Render single item
483 $output.= $this->printItem($key, $field);
484
485 // Substitute glossary words:
486 $output = $this->substituteGlossaryWords($output);
487
488 // Link to Full table description and TOC:
489 $getLLKey = $this->limitAccess ? 'fullDescription' : 'fullDescription_module';
490 $output.= '<br />
491 <p class="c-nav"><a href="view_help.php?tfID=' . rawurlencode($key . '.*') . '">' . $GLOBALS['LANG']->getLL($getLLKey, 1) . '</a></p>
492 <p class="c-nav"><a href="view_help.php">' . $GLOBALS['LANG']->getLL('goToToc', 1) . '</a></p>';
493
494 return $output;
495 }
496
497
498 /**
499 * Renders CSH for a single field.
500 *
501 * @param string CSH key / table name
502 * @param string Sub key / field name
503 * @return string HTML output
504 * @deprecated since TYPO3 4.5, this function will be removed in TYPO3 4.7. Use render_Single() instead.
505 */
506 function render_SingleFlex() {
507 t3lib_div::logDeprecatedFunction();
508 $output = '';
509
510 // Render
511 $output.= $this->printItemFlex();
512
513 // Substitute glossary words:
514 return $this->substituteGlossaryWords($output);
515 }
516
517
518 /************************************
519 *
520 * Rendering CSH items
521 *
522 ************************************/
523
524 /**
525 * Make seeAlso links from $value
526 *
527 * @param string See-also input codes
528 * @param string If $anchorTable is set to a tablename, then references to this table will be made as anchors, not URLs.
529 * @return string See-also links HTML
530 */
531 function make_seeAlso($value,$anchorTable='') {
532 // Split references by comma or linebreak
533 $items = preg_split('/[,' . LF . ']/', $value);
534 $lines = array();
535
536 foreach($items as $val) {
537 $val = trim($val);
538 if ($val) {
539 $iP = explode(':',$val);
540 $iPUrl = t3lib_div::trimExplode('|',$val);
541 // URL reference:
542 if (substr($iPUrl[1],0,4)=='http') {
543 $lines[] = '<a href="'.htmlspecialchars($iPUrl[1]).'" target="_blank"><em>'.htmlspecialchars($iPUrl[0]).'</em></a>';
544 } elseif (substr($iPUrl[1],0,5)=='FILE:') {
545 $fileName = t3lib_div::getFileAbsFileName(substr($iPUrl[1],5),1,1);
546 if ($fileName && @is_file($fileName)) {
547 $fileName = '../'.substr($fileName,strlen(PATH_site));
548 $lines[] = '<a href="'.htmlspecialchars($fileName).'" target="_blank"><em>'.htmlspecialchars($iPUrl[0]).'</em></a>';
549 }
550 } else {
551 // "table" reference
552 t3lib_div::loadTCA($iP[0]);
553
554 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])))))) { // Checking read access:
555
556 // Load table descriptions:
557 #$GLOBALS['LANG']->loadSingleTableDescription($iP[0]);
558 if (isset($GLOBALS['TCA_DESCR'][$iP[0]])) {
559 // Make see-also link:
560 $href = ($this->renderALL || ($anchorTable && $iP[0]==$anchorTable) ? '#'.implode('.',$iP) : 'view_help.php?tfID='.rawurlencode(implode('.',$iP)).'&back='.$this->tfID);
561 $label = $this->getTableFieldLabel($iP[0],$iP[1],' / ');
562 $lines[] = '<a href="'.htmlspecialchars($href).'">'.htmlspecialchars($label).'</a>';
563 }
564 }
565 }
566 }
567 }
568 return implode('<br />',$lines);
569 }
570
571 /**
572 * Will return an image tag with description in italics.
573 *
574 * @param string Image file reference (list of)
575 * @param string Description string (divided for each image by line break)
576 * @return string Image HTML codes
577 */
578 function printImage($images,$descr) {
579 $code = '';
580 // Splitting:
581 $imgArray = t3lib_div::trimExplode(',', $images, 1);
582 if (count($imgArray)) {
583 $descrArray = explode(LF,$descr,count($imgArray));
584
585 foreach($imgArray as $k => $image) {
586 $descr = $descrArray[$k];
587
588 $absImagePath = t3lib_div::getFileAbsFileName($image,1,1);
589 if ($absImagePath && @is_file($absImagePath)) {
590 $imgFile = substr($absImagePath,strlen(PATH_site));
591 $imgInfo = @getimagesize($absImagePath);
592 if (is_array($imgInfo)) {
593 $imgFile = '../'.$imgFile;
594 $code.= '<br /><img src="'.$imgFile.'" '.$imgInfo[3].' class="c-inlineimg" alt="" /><br />
595 ';
596 $code.= '<p><em>' . htmlspecialchars($descr) . '</em></p>
597 ';
598 } else $code.= '<div style="background-color: red; border: 1px solid black; color: white;">NOT AN IMAGE: '.$imgFile.'</div>';
599 } else $code.= '<div style="background-color: red; border: 1px solid black; color: white;">IMAGE FILE NOT FOUND: '.$image.'</div>';
600 }
601 }
602
603 return $code;
604 }
605
606 /**
607 * Returns header HTML content
608 *
609 * @param string Header text
610 * @param string Header type (1, 0)
611 * @return string The HTML for the header.
612 */
613 function headerLine($str,$type=0) {
614 switch($type) {
615 case 1:
616 $str = '<h2 class="t3-row-header">' . htmlspecialchars($str) . '</h2>
617 ';
618 break;
619 case 0:
620 $str = '<h3 class="divider">' . htmlspecialchars($str) . '</h3>
621 ';
622 break;
623 }
624
625 return $str;
626 }
627
628 /**
629 * Returns prepared content
630 *
631 * @param string Content to format.
632 * @return string Formatted content.
633 */
634 function prepareContent($str) {
635 return '<p>'.nl2br(trim(strip_tags($str,$this->allowedHTML))).'</p>
636 ';
637 }
638
639 /**
640 * Prints a single $table/$field information piece
641 * If $anchors is set, then seeAlso references to the same table will be page-anchors, not links.
642 *
643 * @param string $key CSH key / table name
644 * @param string $field Sub key / field name
645 * @param boolean $anchors If anchors is to be shown.
646 * @return string HTML content
647 */
648 function printItem($key, $field, $anchors = FALSE) {
649 $out = '';
650
651 // Load full table definition in $GLOBALS['TCA']
652 t3lib_div::loadTCA($key);
653
654 if ($key && (!$field || is_array($GLOBALS['TCA_DESCR'][$key]['columns'][$field]))) {
655 // Make seeAlso references.
656 $seeAlsoRes = $this->make_seeAlso($GLOBALS['TCA_DESCR'][$key]['columns'][$field]['seeAlso'], $anchors ? $key : '');
657
658 // Making item:
659 $out = '<a name="' . $key . '.' . $field . '"></a>' .
660 $this->headerLine($this->getTableFieldLabel($key, $field), 1) .
661 $this->prepareContent($GLOBALS['TCA_DESCR'][$key]['columns'][$field]['description']) .
662 ($GLOBALS['TCA_DESCR'][$key]['columns'][$field]['details'] ? $this->headerLine($GLOBALS['LANG']->getLL('details').':').$this->prepareContent($GLOBALS['TCA_DESCR'][$key]['columns'][$field]['details']) : '') .
663 ($GLOBALS['TCA_DESCR'][$key]['columns'][$field]['syntax'] ? $this->headerLine($GLOBALS['LANG']->getLL('syntax').':').$this->prepareContent($GLOBALS['TCA_DESCR'][$key]['columns'][$field]['syntax']) : '') .
664 ($GLOBALS['TCA_DESCR'][$key]['columns'][$field]['image'] ? $this->printImage($GLOBALS['TCA_DESCR'][$key]['columns'][$field]['image'],$GLOBALS['TCA_DESCR'][$key]['columns'][$field]['image_descr']) : '') .
665 ($GLOBALS['TCA_DESCR'][$key]['columns'][$field]['seeAlso'] && $seeAlsoRes ? $this->headerLine($GLOBALS['LANG']->getLL('seeAlso').':').'<p>'.$seeAlsoRes.'</p>' : '') .
666 ($this->back ? '<br /><p><a href="' . htmlspecialchars('view_help.php?tfID=' . rawurlencode($this->back)) . '" class="typo3-goBack">' . htmlspecialchars($GLOBALS['LANG']->getLL('goBack')) . '</a></p>' : '') .
667 '<br />';
668 }
669 return $out;
670 }
671
672 /**
673 * Prints a single $table/$field information piece
674 * If $anchors is set, then seeAlso references to the same table will be page-anchors, not links.
675 *
676 * @param string Table name
677 * @param string Field name
678 * @param boolean If anchors is to be shown.
679 * @return string HTML content
680 * @deprecated since TYPO3 4.5, this function will be removed in TYPO3 4.7. Use printItem() instead.
681 */
682 function printItemFlex() {
683 t3lib_div::logDeprecatedFunction();
684 // Get all texts
685 foreach (explode(',', 'description,details,syntax,image,image_descr,seeAlso') as $var) {
686 // Double $ below is not a error!
687 $$var = $GLOBALS['LANG']->sL($this->ffID['cshFile'] . ':' . $this->ffID['field'] . '.' . $var);
688 }
689 // Make seeAlso references.
690 $seeAlsoRes = $this->make_seeAlso($seeAlso);
691
692 // Making item:
693 $out= $this->headerLine($this->ffID['title'], 1) .
694 $this->prepareContent($description) .
695 ($details ? $this->headerLine($GLOBALS['LANG']->getLL('details').':') . $this->prepareContent($details) : '') .
696 ($syntax ? $this->headerLine($GLOBALS['LANG']->getLL('syntax').':') . $this->prepareContent($syntax) : '') .
697 ($image ? $this->printImage($image, $image_descr) : '') .
698 ($seeAlso && $seeAlsoRes ? $this->headerLine($GLOBALS['LANG']->getLL('seeAlso').':').'<p>'.$seeAlsoRes.'</p>' : '') .
699 '<br />';
700 return $out;
701 }
702
703 /**
704 * Returns labels for a given field in a given structure
705 *
706 * @param string $key CSH key / table name
707 * @param string $field Sub key / field name
708 * @return array Table and field labels in a numeric array
709 */
710 function getTableFieldNames($key, $field) {
711 $GLOBALS['LANG']->loadSingleTableDescription($key);
712
713 // Define the label for the key
714 $keyName = $key;
715 if (is_array($GLOBALS['TCA_DESCR'][$key]['columns']['']) && isset($GLOBALS['TCA_DESCR'][$key]['columns']['']['alttitle'])) {
716 // If there's an alternative title, use it
717 $keyName = $GLOBALS['TCA_DESCR'][$key]['columns']['']['alttitle'];
718 } elseif (isset($GLOBALS['TCA'][$key])) {
719 // Otherwise, if it's a table, use its title
720 $keyName = $GLOBALS['TCA'][$key]['ctrl']['title'];
721 } else {
722 // If no title was found, make sure to remove any "_MOD_"
723 $keyName = preg_replace('/^_MOD_/', '', $key);
724 }
725 // Define the label for the field
726 $fieldName = $field;
727 if (is_array($GLOBALS['TCA_DESCR'][$key]['columns'][$field]) && isset($GLOBALS['TCA_DESCR'][$key]['columns'][$field]['alttitle'])) {
728 // If there's an alternative title, use it
729 $fieldName = $GLOBALS['TCA_DESCR'][$key]['columns'][$field]['alttitle'];
730 } elseif (isset($GLOBALS['TCA'][$key]) && isset($GLOBALS['TCA'][$key]['columns'][$field])) {
731 // Otherwise, if it's a table, use its title
732 $fieldName = $GLOBALS['TCA'][$key]['columns'][$field]['label'];
733 }
734 return array($keyName, $fieldName);
735 }
736
737 /**
738 * Returns composite label for table/field
739 *
740 * @param string $key CSH key / table name
741 * @param string $field Sub key / field name
742 * @param string $mergeToken Token to merge the two strings with
743 * @return string Labels joined with merge token
744 * @see getTableFieldNames()
745 */
746 function getTableFieldLabel($key, $field = '', $mergeToken = ': ') {
747 $tableName = '';
748 $fieldName = '';
749
750 // Get table / field parts:
751 list($tableName, $fieldName) = $this->getTableFieldNames($key, $field);
752
753 // Create label:
754 $labelString = $GLOBALS['LANG']->sL($tableName) .
755 ($field ? $mergeToken . rtrim(trim($GLOBALS['LANG']->sL($fieldName)), ':') : '');
756
757 return $labelString;
758 }
759
760
761
762
763
764
765
766
767
768
769
770 /******************************
771 *
772 * Glossary related
773 *
774 ******************************/
775
776 /**
777 * Creates glossary index in $this->glossaryWords
778 * Glossary is cached in cache_hash cache and so will be updated only when cache is cleared.
779 *
780 * @return void
781 */
782 function createGlossaryIndex() {
783 // Create hash string and try to retrieve glossary array:
784 $hash = md5('typo3/view_help.php:glossary');
785 list($this->glossaryWords,$this->substWords) = unserialize(t3lib_BEfunc::getHash($hash));
786
787 // Generate glossary words if not found:
788 if (!is_array($this->glossaryWords)) {
789
790 // Initialize:
791 $this->glossaryWords = array();
792 $this->substWords = array();
793 $CSHkeys = array_flip(array_keys($GLOBALS['TCA_DESCR']));
794
795 // Glossary
796 foreach($CSHkeys as $cshKey => $value) {
797 if (t3lib_div::isFirstPartOfStr($cshKey, 'xGLOSSARY_') && !isset($GLOBALS['TCA'][$cshKey])) {
798 $GLOBALS['LANG']->loadSingleTableDescription($cshKey);
799
800 if (is_array($GLOBALS['TCA_DESCR'][$cshKey]['columns'])) {
801
802 // Traverse table columns as listed in TCA_DESCR
803 foreach ($GLOBALS['TCA_DESCR'][$cshKey]['columns'] as $field => $data) {
804 if ($field) {
805 $this->glossaryWords[$cshKey.'.'.$field] = array(
806 'title' => trim($data['alttitle'] ? $data['alttitle'] : $cshKey),
807 'description' => str_replace('%22','%23%23%23', rawurlencode($data['description'])),
808 );
809 }
810 }
811 }
812 }
813 }
814
815 // First, create unique list of words:
816 foreach($this->glossaryWords as $key => $value) {
817 $word = strtolower($value['title']); // Making word lowercase in order to filter out same words in different cases.
818
819 if ($word!=='') {
820 $this->substWords[$word] = $value;
821 $this->substWords[$word]['key'] = $key;
822 }
823 }
824
825 krsort($this->substWords);
826
827 t3lib_BEfunc::storeHash($hash,serialize(array($this->glossaryWords,$this->substWords)),'Glossary');
828 }
829 }
830
831 /**
832 * Processing of all non-HTML content in the output
833 * Will be done by a call-back to ->substituteGlossaryWords_htmlcleaner_callback()
834 *
835 * @param string Input HTML code
836 * @return string Output HTML code
837 */
838 function substituteGlossaryWords($code) {
839 $htmlParser = t3lib_div::makeInstance('local_t3lib_parsehtml');
840 $htmlParser->pObj = $this;
841 $code = $htmlParser->HTMLcleaner($code, array(), 1);
842
843 return $code;
844 }
845
846 /**
847 * Substituting glossary words in the CSH
848 * (This is a call-back function from "class local_t3lib_parsehtml extends t3lib_parsehtml", see top of this script)
849 *
850 * @param string Input HTML string
851 * @return string HTML with substituted words in.
852 * @coauthor alex widschwendter, media.res kommunikationsloesungen
853 */
854 function substituteGlossaryWords_htmlcleaner_callback($code) {
855 if (is_array($this->substWords) && count($this->substWords) && strlen(trim($code))) {
856
857 // Substitute words:
858 foreach($this->substWords as $wordKey => $wordSet) {
859 // quoteMeta used so special chars (which should not occur though) in words will not break the regex. Seemed to work (- kasper)
860 $parts = preg_split('/( |[\(])('.quoteMeta($wordSet['title']).')([\.\!\)\?\:\,]+| )/i', ' '.$code.' ', 2, PREG_SPLIT_DELIM_CAPTURE);
861 if (count($parts) == 5) {
862 $parts[2] = '<a class="glossary-term" href="'.htmlspecialchars('view_help.php?tfID='.rawurlencode($wordSet['key']).'&back='.$this->tfID).'" title="'.rawurlencode(htmlspecialchars(t3lib_div::fixed_lgd_cs(rawurldecode($wordSet['description']),80))).'">'.
863 htmlspecialchars($parts[2]).
864 '</a>';
865 $code = substr(implode('',$parts),1,-1);
866
867 // Disable entry so it doesn't get used next time:
868 unset($this->substWords[$wordKey]);
869 }
870 }
871 $code = str_replace('###', '&quot;',rawurldecode($code));
872 }
873
874 return $code;
875 }
876
877 }
878
879
880
881 if (defined('TYPO3_MODE') && isset($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['typo3/view_help.php'])) {
882 include_once($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['typo3/view_help.php']);
883 }
884
885
886
887 // Make instance:
888 $SOBE = t3lib_div::makeInstance('SC_view_help');
889 $SOBE->init();
890 $SOBE->main();
891 $SOBE->printContent();
892
893 ?>