Added feature #15783: Improve ExtJS skin: Tabs
[Packages/TYPO3.CMS.git] / typo3 / view_help.php
old mode 100755 (executable)
new mode 100644 (file)
index 3a67109..e066649
@@ -2,7 +2,7 @@
 /***************************************************************
 *  Copyright notice
 *
-*  (c) 1999-2005 Kasper Skaarhoj (kasperYYYY@typo3.com)
+*  (c) 1999-2010 Kasper Skårhøj (kasperYYYY@typo3.com)
 *  All rights reserved
 *
 *  This script is part of the TYPO3 project. The TYPO3 project is
  * See Inside TYPO3 for details.
  *
  * $Id$
- * Revised for TYPO3 3.7 5/2004 by Kasper Skaarhoj
+ * Revised for TYPO3 3.7 5/2004 by Kasper Skårhøj
  * XHTML-trans compliant
  *
- * @author     Kasper Skaarhoj <kasperYYYY@typo3.com>
+ * @author     Kasper Skårhøj <kasperYYYY@typo3.com>
  */
 /**
  * [CLASS/FUNCTION INDEX of SCRIPT]
  *
  *
  *
- *   82: class local_t3lib_parsehtml extends t3lib_parsehtml
- *   93:     function processContent($value,$dir,$conf)
+ *   91: class local_t3lib_parsehtml extends t3lib_parsehtml
+ *  102:     function processContent($value,$dir,$conf)
  *
  *
- *  114: class SC_view_help
- *  138:     function init()
- *  159:     function main()
- *  190:     function printContent()
+ *  122: class SC_view_help
+ *  146:     function init()
+ *  167:     function main()
+ *  198:     function printContent()
  *
  *              SECTION: Rendering main modes
- *  213:     function render_TOC()
- *  330:     function render_TOC_el($table, $tocCat, &$outputSections, &$tocArray, &$CSHkeys)
- *  362:     function render_TOC_makeTocList($tocArray)
- *  401:     function render_Table($table)
- *  461:     function render_Single($table,$field)
+ *  221:     function render_TOC()
+ *  338:     function render_TOC_el($table, $tocCat, &$outputSections, &$tocArray, &$CSHkeys)
+ *  370:     function render_TOC_makeTocList($tocArray)
+ *  409:     function render_Table($table)
+ *  469:     function render_Single($table,$field)
  *
  *              SECTION: Rendering CSH items
- *  507:     function make_seeAlso($value,$anchorTable='')
- *  556:     function printImage($images,$descr)
- *  591:     function headerLine($str,$type=0)
- *  612:     function prepareContent($str)
- *  627:     function printItem($table,$field,$anchors=0)
- *  660:     function getTableFieldNames($table,$field)
- *  683:     function getTableFieldLabel($table,$field='',$mergeToken=': ')
- *  702:     function createGlossaryIndex()
- *  738:     function substituteGlossaryWords($code)
- *  776:     function substituteGlossaryWords_nonHTML($code)
+ *  515:     function make_seeAlso($value,$anchorTable='')
+ *  564:     function printImage($images,$descr)
+ *  599:     function headerLine($str,$type=0)
+ *  620:     function prepareContent($str)
+ *  635:     function printItem($table,$field,$anchors=0)
+ *  668:     function getTableFieldNames($table,$field)
+ *  691:     function getTableFieldLabel($table,$field='',$mergeToken=': ')
+ *
+ *              SECTION: Glossary related
+ *  726:     function createGlossaryIndex()
+ *  785:     function substituteGlossaryWords($code)
+ *  801:     function substituteGlossaryWords_htmlcleaner_callback($code)
  *
  * TOTAL FUNCTIONS: 19
  * (This index is automatically created/updated by the extension "extdeveval")
 require('init.php');
 require('template.php');
 $LANG->includeLLFile('EXT:lang/locallang_view_help.xml');
-require_once(PATH_t3lib.'class.t3lib_loadmodules.php');
-require_once(PATH_t3lib.'class.t3lib_parsehtml.php');
 
 
 /**
  * Extension of the parse_html class.
  *
- * @author     Kasper Skaarhoj <kasperYYYY@typo3.com>
+ * @author     Kasper Skårhøj <kasperYYYY@typo3.com>
  * @package TYPO3
  * @subpackage core
  */
@@ -98,11 +98,10 @@ class local_t3lib_parsehtml extends t3lib_parsehtml {
         * @access private
         */
        function processContent($value,$dir,$conf)      {
-               $value = $this->pObj->substituteGlossaryWords($value);
+               $value = $this->pObj->substituteGlossaryWords_htmlcleaner_callback($value);
 
                return $value;
        }
-
 }
 
 
@@ -114,7 +113,7 @@ class local_t3lib_parsehtml extends t3lib_parsehtml {
 /**
  * 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.
  *
- * @author     Kasper Skaarhoj <kasperYYYY@typo3.com>
+ * @author     Kasper Skårhøj <kasperYYYY@typo3.com>
  * @package TYPO3
  * @subpackage core
  */
@@ -128,6 +127,7 @@ class SC_view_help {
 
                // Internal, static: GPvar:
        var $tfID;                      // Table/FIeld id.
+       var $ffID;                      // Flexform file/field information
        var $back;                      // Back (previous tfID)
        var $renderALL;         // If set, then in TOC mode the FULL manual will be printed as well!
 
@@ -147,6 +147,15 @@ class SC_view_help {
 
                        // Setting GPvars:
                $this->tfID = t3lib_div::_GP('tfID');
+                       // Sanitizes the tfID using whitelisting.
+               if (!preg_match('/^[a-zA-Z0-9_\-\.\*]*$/', $this->tfID)) {
+                       $this->tfID = '';
+               }
+               if (!$this->tfID) {
+                       if (($this->ffID = t3lib_div::_GP('ffID'))) {
+                               $this->ffID = unserialize(base64_decode($this->ffID));
+                       }
+               }
                $this->back = t3lib_div::_GP('back');
                $this->renderALL = t3lib_div::_GP('renderALL');
 
@@ -167,7 +176,6 @@ class SC_view_help {
                global $BE_USER,$LANG,$TCA_DESCR,$TCA,$TBE_TEMPLATE;
 
                        // Start HTML output accumulation:
-               $TBE_TEMPLATE->docType = 'xhtml_trans';
                $TBE_TEMPLATE->divClass = 'typo3-view-help';
                $this->content.= $TBE_TEMPLATE->startPage($LANG->getLL('title'));
 
@@ -177,6 +185,9 @@ class SC_view_help {
                } elseif ($this->tfID) { // ... otherwise show only single field:
                        $this->createGlossaryIndex();
                        $this->content.= $this->render_Single($this->table,$this->field);
+               }
+               elseif (is_array($this->ffID)) {
+                       $this->content.= $this->render_SingleFlex();
                } else {        // Render Table Of Contents if nothing else:
                        $this->content.= $this->render_TOC();
                }
@@ -291,21 +302,20 @@ class SC_view_help {
                $output = '';
                $output.= '
 
-                       <h1>'.$LANG->getLL('manual_title',1).'</h1>
-                       <p>'.t3lib_BEfunc::TYPO3_copyRightNotice().'</p>';
+                       <h1>'.$LANG->getLL('manual_title',1).'</h1>';
 
                $output.= '
 
-                       <h1>'.$LANG->getLL('introduction',1).'</h1>
+                       <h2>'.$LANG->getLL('introduction',1).'</h2>
                        <p>'.$LANG->getLL('description',1).'</p>';
 
                $output.= '
 
-                       <h1>'.$LANG->getLL('TOC',1).'</h1>'.
+                       <h2>'.$LANG->getLL('TOC',1).'</h2>'.
                        $this->render_TOC_makeTocList($tocArray);
 
                if (!$this->renderALL)  {
-               $output.= '
+                       $output.= '
                                <br/>
                                <p class="c-nav"><a href="view_help.php?renderALL=1">'.$LANG->getLL('full_manual',1).'</a></p>';
                }
@@ -313,7 +323,7 @@ class SC_view_help {
                if ($this->renderALL)   {
                        $output.= '
 
-                               <h1>'.$LANG->getLL('full_manual_chapters',1).'</h1>'.
+                               <h2>'.$LANG->getLL('full_manual_chapters',1).'</h2>'.
                                implode('
 
 
@@ -321,6 +331,8 @@ class SC_view_help {
                                ',$outputSections);
                }
 
+               $output .= '<hr /><p class="manual-title">'.t3lib_BEfunc::TYPO3_copyRightNotice().'</p>';
+
                return $output;
        }
 
@@ -422,8 +434,7 @@ class SC_view_help {
                        $parts[0] = ''; // Reserved for header of table
 
                                // Traverse table columns as listed in TCA_DESCR
-                       reset($TCA_DESCR[$table]['columns']);
-                       while(list($field) = each($TCA_DESCR[$table]['columns']))       {
+                       foreach ($TCA_DESCR[$table]['columns'] as $field => $value) {
 
                                $fieldValue = isset($TCA[$table]) && strcmp($field,'') ? $TCA[$table]['columns'][$field] : array();
 
@@ -436,12 +447,14 @@ class SC_view_help {
                                }
                        }
 
-                       if (!strcmp($parts,'')) unset($parts[0]);
+                       if (!$parts[0]) {
+                               unset($parts[0]);
+                       }
                        $output.= implode('<br />',$parts);
                }
 
                        // Substitute glossary words:
-               $output = $this->substituteGlossaryWords_nonHTML($output);
+               $output = $this->substituteGlossaryWords($output);
 
                        // TOC link:
                if (!$this->renderALL)  {
@@ -477,7 +490,7 @@ class SC_view_help {
                $output.= $this->printItem($table,$field);
 
                        // Substitute glossary words:
-               $output = $this->substituteGlossaryWords_nonHTML($output);
+               $output = $this->substituteGlossaryWords($output);
 
                        // Link to Full table description and TOC:
                $getLLKey = $this->limitAccess ? 'fullDescription' : 'fullDescription_module';
@@ -489,13 +502,22 @@ class SC_view_help {
        }
 
 
+       /**
+        * Renders CSH for a single field.
+        *
+        * @param       string          CSH key / table name
+        * @param       string          Sub key / field name
+        * @return      string          HTML output
+        */
+       function render_SingleFlex() {
+               $output = '';
 
+                       // Render
+               $output.= $this->printItemFlex();
 
-
-
-
-
-
+                       // Substitute glossary words:
+               return $this->substituteGlossaryWords($output);
+       }
 
 
        /************************************
@@ -514,8 +536,8 @@ class SC_view_help {
        function make_seeAlso($value,$anchorTable='')   {
                global $TCA,$BE_USER,$TCA_DESCR;
 
-                       // Split references by comma, vert.line or linebreak
-               $items = split(',|'.chr(10),$value);
+                       // Split references by comma or linebreak
+               $items = preg_split('/[,' . LF . ']/', $value);
                $lines = array();
 
                foreach($items as $val) {
@@ -565,8 +587,8 @@ class SC_view_help {
                        // Splitting:
                $imgArray = t3lib_div::trimExplode(',', $images, 1);
                if (count($imgArray))   {
-                       $descrArray = explode(chr(10),$descr,count($imgArray));
-#debug($descrArray);
+                       $descrArray = explode(LF,$descr,count($imgArray));
+
                        foreach($imgArray as $k => $image)      {
                                $descr = $descrArray[$k];
 
@@ -598,11 +620,11 @@ class SC_view_help {
        function headerLine($str,$type=0)       {
                switch($type)   {
                        case 1:
-                               $str='<h3>'.htmlspecialchars($str).'</h3>
+                               $str = '<h2 class="t3-row-header">' . htmlspecialchars($str) . '</h2>
                                ';
                        break;
                        case 0:
-                               $str='<h4 class="uppercase">'.htmlspecialchars($str).'</h4>
+                               $str = '<h3 class="divider">' . htmlspecialchars($str) . '</h3>
                                ';
                        break;
                }
@@ -657,6 +679,35 @@ class SC_view_help {
        }
 
        /**
+        * Prints a single $table/$field information piece
+        * If $anchors is set, then seeAlso references to the same table will be page-anchors, not links.
+        *
+        * @param       string          Table name
+        * @param       string          Field name
+        * @param       boolean         If anchors is to be shown.
+        * @return      string          HTML content
+        */
+       function printItemFlex() {
+               // Get all texts
+               foreach (explode(',', 'description,details,syntax,image,image_descr,seeAlso') as $var) {
+                       // Double $ below is not a error!
+                       $$var = $GLOBALS['LANG']->sL($this->ffID['cshFile'] . ':' . $this->ffID['field'] . '.' . $var);
+               }
+               // Make seeAlso references.
+               $seeAlsoRes = $this->make_seeAlso($seeAlso);
+
+                       // Making item:
+               $out= $this->headerLine($this->ffID['title'], 1) .
+                               $this->prepareContent($description) .
+                               ($details ? $this->headerLine($GLOBALS['LANG']->getLL('details').':') . $this->prepareContent($details) : '') .
+                               ($syntax ? $this->headerLine($GLOBALS['LANG']->getLL('syntax').':') . $this->prepareContent($syntax) : '') .
+                               ($image ? $this->printImage($image, $image_descr) : '') .
+                               ($seeAlso && $seeAlsoRes ? $this->headerLine($GLOBALS['LANG']->getLL('seeAlso').':').'<p>'.$seeAlsoRes.'</p>' : '') .
+               '<br />';
+               return $out;
+       }
+
+       /**
         * Returns labels for $table and $field.
         * If $table is "_MOD_" prefixed, the part after "_MOD_" is returned (non-tables, fx. modules)
         *
@@ -671,7 +722,7 @@ class SC_view_help {
 
                        $tableName = is_array($TCA_DESCR[$table]['columns']['']) && $TCA_DESCR[$table]['columns']['']['alttitle'] ?
                                                        $TCA_DESCR[$table]['columns']['']['alttitle'] :
-                                                       (isset($TCA[$table]) ? $TCA[$table]['ctrl']['title'] : ereg_replace('^_MOD_','',$table));
+                                                       (isset($TCA[$table]) ? $TCA[$table]['ctrl']['title'] : preg_replace('/^_MOD_/','',$table));
                        $fieldName = is_array($TCA_DESCR[$table]['columns'][$field]) && $TCA_DESCR[$table]['columns'][$field]['alttitle'] ?
                                                        $TCA_DESCR[$table]['columns'][$field]['alttitle'] :
                                                        (isset($TCA[$table])&&isset($TCA[$table]['columns'][$field]) ? $TCA[$table]['columns'][$field]['label'] : $field);
@@ -695,114 +746,144 @@ class SC_view_help {
 
                        // Create label:
                $labelStr = $LANG->sL($tableName).
-                                       ($field ? $mergeToken.ereg_replace(':$','', trim($LANG->sL($fieldName))):'');
+                                       ($field ? $mergeToken.rtrim(trim($LANG->sL($fieldName)), ':'):'');
 
                return $labelStr;
        }
 
+
+
+
+
+
+
+
+
+
+
+       /******************************
+        *
+        * Glossary related
+        *
+        ******************************/
+
        /**
         * Creates glossary index in $this->glossaryWords
+        * Glossary is cached in cache_hash cache and so will be updated only when cache is cleared.
         *
         * @return      void
-        * @todo: Implement some caching of this array - needed when the glossary grows to a large size!
         */
        function createGlossaryIndex()  {
                global $TCA_DESCR,$TCA,$LANG;
-return;
-                       // Initialize:
-               $CSHkeys = array_flip(array_keys($TCA_DESCR));
 
-                       // Glossary
-               foreach($CSHkeys as $cshKey => $value)  {
-                       if (t3lib_div::isFirstPartOfStr($cshKey, 'xGLOSSARY_') && !isset($TCA[$cshKey]))        {
-                               $LANG->loadSingleTableDescription($cshKey);
-
-                               if (is_array($TCA_DESCR[$cshKey]['columns']))   {
-
-                                               // Traverse table columns as listed in TCA_DESCR
-                                       reset($TCA_DESCR[$cshKey]['columns']);
-                                       while(list($field,$data) = each($TCA_DESCR[$cshKey]['columns']))        {
-                                               if ($field)     {
-                                                       $this->glossaryWords[$cshKey.'.'.$field] = array(
-                                                               'title' => trim($data['alttitle'] ? $data['alttitle'] : $cshKey),
-                                                               'description' => $data['description'],
-                                                       );
+                       // Create hash string and try to retrieve glossary array:
+               $hash = md5('typo3/view_help.php:glossary');
+               list($this->glossaryWords,$this->substWords) = unserialize(t3lib_BEfunc::getHash($hash));
+
+                       // Generate glossary words if not found:
+               if (!is_array($this->glossaryWords)) {
+
+                               // Initialize:
+                       $this->glossaryWords = array();
+                       $this->substWords = array();
+                       $CSHkeys = array_flip(array_keys($TCA_DESCR));
+
+                               // Glossary
+                       foreach($CSHkeys as $cshKey => $value)  {
+                               if (t3lib_div::isFirstPartOfStr($cshKey, 'xGLOSSARY_') && !isset($TCA[$cshKey]))        {
+                                       $LANG->loadSingleTableDescription($cshKey);
+
+                                       if (is_array($TCA_DESCR[$cshKey]['columns']))   {
+
+                                                       // Traverse table columns as listed in TCA_DESCR
+                                               foreach ($TCA_DESCR[$cshKey]['columns'] as $field => $data) {
+                                                       if ($field)     {
+                                                               $this->glossaryWords[$cshKey.'.'.$field] = array(
+                                                                       'title' => trim($data['alttitle'] ? $data['alttitle'] : $cshKey),
+                                                                       'description' =>  str_replace('%22','%23%23%23', rawurlencode($data['description'])),
+                                                               );
+                                                       }
                                                }
                                        }
                                }
                        }
+
+                               // First, create unique list of words:
+                       foreach($this->glossaryWords as $key => $value) {
+                               $word = strtolower($value['title']);    // Making word lowercase in order to filter out same words in different cases.
+
+                               if ($word!=='') {
+                                       $this->substWords[$word] = $value;
+                                       $this->substWords[$word]['key'] = $key;
+                               }
+                       }
+
+                       krsort($this->substWords);
+
+                       t3lib_BEfunc::storeHash($hash,serialize(array($this->glossaryWords,$this->substWords)),'Glossary');
                }
-#debug($this->glossaryWords);
+       }
+
+       /**
+        * Processing of all non-HTML content in the output
+        * Will be done by a call-back to ->substituteGlossaryWords_htmlcleaner_callback()
+        *
+        * @param       string          Input HTML code
+        * @return      string          Output HTML code
+        */
+       function substituteGlossaryWords($code) {
+               $htmlParser = t3lib_div::makeInstance('local_t3lib_parsehtml');
+               $htmlParser->pObj = $this;
+               $code = $htmlParser->HTMLcleaner($code, array(), 1);
+
+               return $code;
        }
 
        /**
         * Substituting glossary words in the CSH
+        * (This is a call-back function from "class local_t3lib_parsehtml extends t3lib_parsehtml", see top of this script)
         *
         * @param       string          Input HTML string
         * @return      string          HTML with substituted words in.
-        * @todo        It is certain that the substitution of words could be improved. This is just a basic implementation. Suggestions are welcome!
+        * @coauthor    alex widschwendter, media.res kommunikationsloesungen
         */
-       function substituteGlossaryWords($code) {
-               if (is_array($this->glossaryWords) && strlen(trim($code)))      {
-#debug(array($code),1);
-                               // First, create unique list of words:
-                       $substWords = array();
-                       foreach($this->glossaryWords as $key => $value) {
-                               $word = strtolower($value['title']);    // Making word lowercase in order to filter out same words in different cases.
-
-                               if ($word!=='') {
-                                       $substWords[$word] = $value;
-                                       $substWords[$word]['key'] = $key;
-                               }
-                       }
+       function substituteGlossaryWords_htmlcleaner_callback($code)    {
+               if (is_array($this->substWords) && count($this->substWords) && strlen(trim($code)))     {
 
                                // Substitute words:
-                       foreach($substWords as $wordSet)        {
-                               $parts = preg_split("/([^[:alnum:]]+)(".$wordSet['title'].")([^[:alnum:]]+)/", ' '.$code.' ', 2, PREG_SPLIT_DELIM_CAPTURE);
+                       foreach($this->substWords as $wordKey => $wordSet)      {
+                                       // quoteMeta used so special chars (which should not occur though) in words will not break the regex. Seemed to work (- kasper)
+                               $parts = preg_split('/( |[\(])('.quoteMeta($wordSet['title']).')([\.\!\)\?\:\,]+| )/i', ' '.$code.' ', 2, PREG_SPLIT_DELIM_CAPTURE);
                                if (count($parts) == 5) {
-                                       $parts[2] = '<a style="background-color: yellow; " href="'.htmlspecialchars('view_help.php?tfID='.rawurlencode($wordSet['key']).'&back='.$this->tfID).'" title="'.htmlspecialchars($wordSet['description']).'">'.$parts[2].'</a>';
-#debug($parts,$word);
-#debug($wordSet['title']);
+                                       $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))).'">'.
+                                                               htmlspecialchars($parts[2]).
+                                                               '</a>';
                                        $code = substr(implode('',$parts),1,-1);
 
                                                // Disable entry so it doesn't get used next time:
-                                       unset($this->glossaryWords[$wordSet['key']]);
+                                       unset($this->substWords[$wordKey]);
                                }
                        }
+                       $code = str_replace('###', '&quot;',rawurldecode($code));
                }
 
                return $code;
        }
 
-       /**
-        * [Describe function...]
-        *
-        * @param       [type]          $code: ...
-        * @return      [type]          ...
-        */
-       function substituteGlossaryWords_nonHTML($code) {
-               $htmlParser = t3lib_div::makeInstance('local_t3lib_parsehtml');
-               $htmlParser->pObj = &$this;
-               $code = $htmlParser->HTMLcleaner($code, array(), 1);
-
-               return $code;
-       }
 }
 
 
-// Include extension?
+
 if (defined('TYPO3_MODE') && $TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['typo3/view_help.php'])    {
        include_once($TYPO3_CONF_VARS[TYPO3_MODE]['XCLASS']['typo3/view_help.php']);
 }
 
 
 
-
-
-
 // Make instance:
 $SOBE = t3lib_div::makeInstance('SC_view_help');
 $SOBE->init();
 $SOBE->main();
 $SOBE->printContent();
+
 ?>
\ No newline at end of file