TYPO3 API  SVNRelease
index.php
Go to the documentation of this file.
00001 <?php
00002 /***************************************************************
00003 *  Copyright notice
00004 *
00005 *  (c) 2007-2011 Stephane Schitter <stephane.schitter@free.fr>
00006 *  All rights reserved
00007 *
00008 *  This script is part of the TYPO3 project. The TYPO3 project is
00009 *  free software; you can redistribute it and/or modify
00010 *  it under the terms of the GNU General Public License as published by
00011 *  the Free Software Foundation; either version 2 of the License, or
00012 *  (at your option) any later version.
00013 *
00014 *  The GNU General Public License can be found at
00015 *  http://www.gnu.org/copyleft/gpl.html.
00016 *
00017 *  This script is distributed in the hope that it will be useful,
00018 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00019 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00020 *  GNU General Public License for more details.
00021 *
00022 *  This copyright notice MUST APPEAR in all copies of the script!
00023 ***************************************************************/
00024 
00025 
00026 // DEFAULT initialization of a module [BEGIN]
00027 unset($MCONF);
00028 require_once('conf.php');
00029 require_once($BACK_PATH.'init.php');
00030 require_once($BACK_PATH.'template.php');
00031 
00032 $LANG->includeLLFile('EXT:tsconfig_help/mod1/locallang.xml');
00033 $BE_USER->modAccess($MCONF,1);  // This checks permissions and exits if the users has no permission for entry.
00034 // DEFAULT initialization of a module [END]
00035 
00036 
00037 /**
00038  * Module 'TypoScript Help' for the 'tsconfig_help' extension.
00039  *
00040  * @author  Stephane Schitter <stephane.schitter@free.fr>
00041  * @package TYPO3
00042  * @subpackage  tx_tsconfighelp
00043  */
00044 class tx_tsconfighelp_module1 extends t3lib_SCbase {
00045     var $pageinfo;
00046     var $objStringsPerExtension = array(); // This is used to count how many times the same obj_string appears in each extension manual
00047     var $allObjStrings = array(); // This is used to count how many times the same obj_string appears across all extensions
00048 
00049     /**
00050      * Initializes the Module
00051      * @return  void
00052      */
00053     function init() {
00054         global $BE_USER,$LANG,$BACK_PATH,$TCA_DESCR,$TCA,$CLIENT,$TYPO3_CONF_VARS;
00055         parent::init();
00056     }
00057 
00058     /**
00059      * Adds items to the ->MOD_MENU array. Used for the function menu selector.
00060      *
00061      * @return  void
00062      */
00063     function menuConfig()   {
00064         global $LANG;
00065         $this->MOD_MENU = array(
00066             'function' => array(
00067                 '1' => $LANG->getLL('display')
00068             )
00069         );
00070 
00071         if($GLOBALS['BE_USER']->user['admin'])  {
00072             $this->MOD_MENU['function']['2'] = $LANG->getLL('rebuild');
00073         }
00074 
00075         parent::menuConfig();
00076     }
00077 
00078     /**
00079      * Main function of the module. Write the content to $this->content
00080      *
00081      * @return  void
00082      */
00083     function main() {
00084         global $BE_USER,$LANG,$BACK_PATH,$TCA_DESCR,$TCA,$CLIENT,$TYPO3_CONF_VARS;
00085 
00086         // Access check!
00087         $access = $BE_USER->check('modules', 'help_txtsconfighelpM1');
00088 
00089             // Draw the header.
00090         $this->doc = t3lib_div::makeInstance('template');
00091         $this->doc->backPath = $BACK_PATH;
00092         $this->doc->setModuleTemplate('templates/tsconfig_help.html');
00093 
00094         if ($access || $BE_USER->user['admin']) {
00095 
00096             $this->doc->form = '<form action="" method="post">';
00097 
00098                 // JavaScript
00099             $this->doc->JScode = '
00100                 <script language="javascript" type="text/javascript">
00101                     script_ended = 0;
00102                     function jumpToUrl(URL) {
00103                         document.location = URL;
00104                     }
00105                 </script>
00106             ';
00107             $this->doc->postCode = '
00108                 <script language="javascript" type="text/javascript">
00109                     script_ended = 1;
00110                     if (top.fsMod) top.fsMod.recentIds["web"] = 0;
00111                 </script>
00112             ';
00113 
00114             $headerSection = $this->doc->getHeader('pages',$this->pageinfo,$this->pageinfo['_thePath']).'<br />'.$LANG->sL('LLL:EXT:lang/locallang_core.xml:labels.path').': '.t3lib_div::fixed_lgd_cs($this->pageinfo['_thePath'],-50);
00115 
00116             $this->content .= $this->doc->header($LANG->getLL('title'));
00117             $this->content .= $this->doc->spacer(5);
00118 
00119             // Render content:
00120             $this->moduleContent();
00121 
00122             $this->content .= $this->doc->spacer(10);
00123 
00124             $markers['FUNC_MENU'] = t3lib_BEfunc::getFuncMenu($this->id,'SET[function]',$this->MOD_SETTINGS['function'],$this->MOD_MENU['function']);
00125         } else {
00126             $this->content .= $this->doc->header($LANG->getLL('title'));
00127             $markers['FUNC_MENU'] = '';
00128         }
00129             // Setting up the buttons and markers for docheader
00130         $docHeaderButtons = $this->getButtons();
00131         $markers['CSH'] = $docHeaderButtons['csh'];
00132         $markers['CONTENT'] = $this->content;
00133 
00134             // Build the <body> for the module
00135         $this->content = $this->doc->moduleBody($this->pageinfo, $docHeaderButtons, $markers);
00136             // Renders the module page
00137         $this->content = $this->doc->render(
00138             $LANG->getLL('title'),
00139             $this->content
00140         );
00141     }
00142 
00143     /**
00144      * Prints out the module HTML
00145      *
00146      * @return  void
00147      */
00148     function printContent() {
00149         echo $this->content;
00150     }
00151 
00152     /**
00153      * Create the panel of buttons for submitting the form or otherwise perform operations.
00154      *
00155      * @return  array   all available buttons as an assoc. array
00156      */
00157     protected function getButtons() {
00158         global $TCA, $LANG, $BACK_PATH, $BE_USER;
00159 
00160         $buttons = array(
00161             'csh' => '',
00162             'shortcut' => '',
00163         );
00164             // CSH
00165         //$buttons['csh'] = t3lib_BEfunc::cshItem('_MOD_web_func', '', $GLOBALS['BACK_PATH']);
00166 
00167         if (($this->id && is_array($this->pageinfo)) || ($BE_USER->user['admin'] && !$this->id)) {
00168                 // Shortcut
00169             if ($BE_USER->mayMakeShortcut()) {
00170                 $buttons['shortcut'] = $this->doc->makeShortcutIcon('id', implode(',', array_keys($this->MOD_MENU)), $this->MCONF['name']);
00171             }
00172         }
00173         return $buttons;
00174     }
00175 
00176     /**
00177      * Generates the module content
00178      *
00179      * @return  void
00180      */
00181     function moduleContent()    {
00182         global $BACK_PATH, $TYPO3_LOADED_EXT, $LANG;
00183 
00184         switch ((string)$this->MOD_SETTINGS['function'])    {
00185             case 1:
00186                 $content = '<div align="left"><strong>'.$LANG->getLL('referenceExplanation').'</strong></div>';
00187                 $content .= '<p>'.$LANG->getLL('referenceExplanationDetailed').'</p><br />';
00188                 $this->content .= $this->doc->section($LANG->getLL('displayReferences'),$content,0,1);
00189                 $this->content .= '<a href="#" onclick="vHWin=window.open(\''.$BACK_PATH.'wizard_tsconfig.php?mode=tsref&amp;P[formName]=editForm\',\'popUp\',\'height=500,width=780,status=0,menubar=0,scrollbars=1\');vHWin.focus();return false;" title="TSref reference">'.t3lib_iconWorks::getSpriteIcon('actions-system-typoscript-documentation-open').'TSREF</a><br />';
00190                 $this->content .= '<a href="#" onclick="vHWin=window.open(\''.$BACK_PATH.'wizard_tsconfig.php?mode=beuser&amp;P[formName]=editForm\',\'popUp\',\'height=500,width=780,status=0,menubar=0,scrollbars=1\');vHWin.focus();return false;" title="TSref reference">'.t3lib_iconWorks::getSpriteIcon('actions-system-typoscript-documentation-open').'USER TSCONFIG</a><br />';
00191                 $this->content .= '<a href="#" onclick="vHWin=window.open(\''.$BACK_PATH.'wizard_tsconfig.php?mode=page&amp;P[formName]=editForm\',\'popUp\',\'height=500,width=780,status=0,menubar=0,scrollbars=1\');vHWin.focus();return false;" title="TSref reference">'.t3lib_iconWorks::getSpriteIcon('actions-system-typoscript-documentation-open').'PAGE TSCONFIG</a><br />';
00192             break;
00193 
00194             case 2:
00195                 if ($GLOBALS['BE_USER']->user['admin']) {
00196                     if (t3lib_div::_GP('_rebuild')) {
00197                             // remove all data from the database
00198                         $this->purgeSQLContents();
00199 
00200                             // get all loaded extension keys
00201                         $extArray = $TYPO3_LOADED_EXT;
00202 
00203                         $content = '<div align="left"><strong>'.$LANG->getLL('loadedTSfrom').'</strong></div><br />';
00204 
00205                             // parse the extension names only (no need for all details from the TYPO3_LOADED_EXT table
00206                         foreach ($extArray as $extName => $dummy)   {
00207                                 // check that the extension is really loaded (which should always be the case)
00208                             if (t3lib_extMgm::isLoaded($extName))   {
00209                                     // extract the content.xml from the manual.sxw ZIP file
00210                                 $manual = $this->getZIPFileContents(t3lib_extMgm::extPath($extName).'doc/manual.sxw', 'content.xml');
00211 
00212                                     // check if the manual file actually exists and if the content.xml could be loaded
00213                                 if ($manual != '')  {
00214                                         // if the manual file exists, proceed with the load into the SQL database
00215                                     $content .= '<p>Extension '.$extName.'...';
00216 
00217                                         // run the extraction processing and import the data into SQL. Return the number of TS tables found in the open office document
00218                                     $number = $this->loadExtensionManual($extName, $manual);
00219 
00220                                         // print a status message with a link to the openoffice manual
00221                                     $content .= $number.' '.$LANG->getLL('sections').' (<a href="'.t3lib_div::getIndpEnv('TYPO3_SITE_URL').TYPO3_mainDir.t3lib_extMgm::extRelPath($extName).'doc/manual.sxw">manual</a>)</p>';
00222                                 }
00223                             } else  {
00224                                     // this should never happen!
00225                                 die ("Fatal error : loaded extension not actually loaded? Please file a bug report at http://bugs.typo3.org!");
00226                             }
00227                         }
00228 
00229                         $this->content .= $this->doc->section($LANG->getLL('rebuildTS'),$content.'<br />',0,1);
00230 
00231                             // Issue warnings about duplicate or empty obj_strings, if any
00232                             // An obj_string should be unique. It should appear in only one extension manual and then only once
00233                             // If the sum of all occurrences of a given obj_string is more than one, issue a list of duplicate entries as a warning
00234                         $duplicateWarnings = '';
00235                         $emptyWarnings = '';
00236                         foreach ($this->objStringsPerExtension as $obj_string => $extensions)   {
00237                             if (empty($obj_string)) {
00238                                 $emptyWarnings = '<p class="typo3-red">'.$LANG->getLL('warning_manualsWithoutMarkers');
00239                                 foreach ($extensions as $extensionKey => $counter)  {
00240                                     $emptyWarnings .= ' '.$extensionKey.' ('.$counter.')<br />';
00241                                 }
00242                                 $emptyWarnings .= '</p><br />';
00243                             } else {
00244                                 if (array_sum($extensions) > 1) {
00245                                     $duplicateWarnings .= $obj_string.':';
00246                                     foreach ($extensions as $extensionKey => $counter)  {
00247                                         $duplicateWarnings .= ' '.$extensionKey.' ('.$counter.')';
00248                                     }
00249                                     $duplicateWarnings .= '<br />';
00250                                 }
00251                             }
00252                         }
00253                         $warnings = $emptyWarnings;
00254                         if (!empty($duplicateWarnings)) {
00255                             $warnings .= '<p class="typo3-red">'.$LANG->getLL('warning_duplicateMarkers').'<br />'.$duplicateWarnings.'</p>';
00256                         }
00257                         if (!empty($warnings))  {
00258                             $this->content .= $this->doc->section($LANG->getLL('updateWarnings'),'<div>'.$warnings.'</div>',0,1);
00259                         }
00260                     }
00261 
00262                     $content = '<p>'.$LANG->getLL('rebuildExplanation').'</p><br />';
00263                     $content .= $LANG->getLL('rebuild').' <input type="submit" name="_rebuild" value="Rebuild" /><br />';
00264                     $this->content .= $this->doc->section($LANG->getLL('rebuildTS'),$content,0,1);
00265                 } else {
00266                     $this->content .= '<p>'.$LANG->getLL('adminAccessOnly').'</p><br />';
00267                 }
00268 
00269 
00270             break;
00271         }
00272     }
00273 
00274     /**
00275      * Returns the contents of a specific file within the ZIP
00276      *
00277      * @return  string  contents
00278      */
00279     function getZIPFileContents($ZIPfile, $filename)    {
00280         if (file_exists($ZIPfile))  {
00281                 // Unzipping SXW file, getting filelist:
00282             $tempPath = PATH_site.'typo3temp/tx_tsconfighelp_ziptemp/';
00283             t3lib_div::mkdir($tempPath);
00284 
00285             $this->unzip($ZIPfile, $tempPath);
00286             $output = t3lib_div::getURL($tempPath.$filename);
00287 
00288             $cmd = 'rm -r "'.$tempPath.'"';
00289             t3lib_utility_Command::exec($cmd);
00290 
00291             return $output;
00292         }
00293     }
00294 
00295     /**
00296      * Unzips a zip file in the given path.
00297      * Uses the Extension Manager unzip functions.
00298      *
00299      *
00300      * @param string $file      Full path to zip file
00301      * @param string $path      Path to change to before extracting
00302      * @return boolean  True on success, false in failure
00303      */
00304     function unzip($file, $path)    {
00305             // we use the unzip class of the Extension Manager here
00306             // TODO: move unzip class to core
00307         if (!t3lib_extMgm::isLoaded('em')) {
00308                 //em is not loaded, so include the unzip class
00309             t3lib_div::requireOnce(PATH_typo3 . 'sysext/em/classes/tools/class.tx_em_tools_unzip.php');
00310         }
00311         $unzip = t3lib_div::makeInstance('tx_em_Tools_Unzip', $file);
00312         $ret = $unzip->extract(array('add_path'=>$path));
00313         return (is_array($ret));
00314     }
00315 
00316     /**
00317      * Parses the whole XML file in order to understand the Styles structure. This function is mostly looking at the styles
00318      * that create bold or italic characters in the document, as these will later on need to be translated to <i> and <strong> tags
00319      * This function takes into account the hierarchy of the styles, as created by OpenOffice. This means that if a style has
00320      * a parant, this function will make it inherit the styles of the parent. Therefore bold and italic styles are propagated
00321      * to children as well.
00322      *
00323      * This function assumes the STYLE definitions are not nested. If they are then, then "close" type will need to be used
00324      * more carefully, and a depth counter will need to be implemented.
00325      *
00326      * @param   array       The XML values array. The XML index is not necessary in this function.
00327      * @return  array       Array that contains the different styles with their parent (required to recognise "Table Contents"-type styles), and their style (bold/italic)
00328      */
00329     function parseStyles($vals) {
00330         $currentStyleName = '';
00331         $style = array ();
00332 
00333         foreach ($vals as $node)    {
00334             switch ($node['type'])  {
00335                 case 'open':
00336                     switch ($node['tag'])   {
00337                         case 'STYLE:STYLE':
00338                             $currentStyleName = $node['attributes']['STYLE:NAME'];
00339 
00340                             if (array_key_exists('STYLE:PARENT-STYLE-NAME',$node['attributes']))    {
00341                                 $parentStyleName = $node['attributes']['STYLE:PARENT-STYLE-NAME'];
00342                                 $style[$currentStyleName]['parents'][] = $parentStyleName; // keep trace of parents in the style array
00343                             } else {
00344                                 $parentStyleName = ''; // this style has no parent, therefore clean the variable to avoid side effects with next use of that variable
00345                             }
00346 
00347                             if (array_key_exists($parentStyleName, $style)) { // the style parent is already documented in the array
00348                                 $style[$currentStyleName] = $style[$parentStyleName]; // inherit parent style
00349                             }
00350                         break;
00351                     }
00352                 break;
00353 
00354                 case 'complete':
00355                     switch ($node['tag'])   {
00356                         case 'STYLE:PROPERTIES':
00357                             if (is_array($node['attributes']) && array_key_exists('FO:FONT-WEIGHT',$node['attributes']))    {
00358                                 $style[$currentStyleName]['font-weight'] = $node['attributes']['FO:FONT-WEIGHT'];   // bold for example
00359                             }
00360                             if (is_array($node['attributes']) && array_key_exists('FO:FONT-STYLE',$node['attributes'])) {
00361                                 $style[$currentStyleName]['font-style'] = $node['attributes']['FO:FONT-STYLE']; // italic for example
00362                             }
00363                         break;
00364                     }
00365                 break;
00366 
00367                 case 'close':
00368                     switch ($node['tag'])   {
00369                         case 'STYLE:STYLE':
00370                             $currentStyleName = '';
00371                         break;
00372                         case 'STYLE:PROPERTIES':
00373                         break;
00374                     }
00375                 break;
00376             }
00377         }
00378 
00379         return $style;
00380     }
00381 
00382 
00383     /**
00384      * Checks if the style is a child of a specified parent. This is useful for example to check if a specific style that has
00385      * a generic name ("P8" for example) is a child of the "Table Contents" style. It would not only inherit its style (bold/
00386      * italic) but also its properties like being part of a Table.
00387      *
00388      * This function references the global $Styles variables which must have been created previously with parseStyles()
00389      *
00390      * @param   string      Name of the child style that we want to get properties for
00391      * @param   string      Name of the parent style that we want to compare the child against
00392      * @return  boolean     true if the child and parent are linked together. false otherwise.
00393      */
00394     function isStyleChildOf($child, $parent) {
00395         global $Styles;
00396 
00397         if (!strcmp($child, $parent))   { // the child is actually the same as the parent. They are obviously linked together
00398             return TRUE;
00399         }
00400 
00401         if (is_array($Styles[$child])  // the child is a documented style
00402          && array_key_exists('parents',$Styles[$child])  // it has some parents
00403          && (array_search($parent, $Styles[$child]['parents']) !== FALSE))  { // and the parent appears amongst its ancestors
00404             return TRUE;
00405         }
00406         return FALSE;
00407     }
00408 
00409     /**
00410      * Find the table description that we want, then find a TABLE:TABLE close, immediately followed by a TEXT:P which has a
00411      * style which is a child of a "Table Contents", then look up the index to find where the TABLE begins, and start browsing
00412      * from there (returns these start and end indexes).
00413      *
00414      * This function only finds the next TS definition table. In order to find all TS definition tables from the document, the
00415      * function needs to be called several times, starting where it left off last time. The third parameter is the index that
00416      * is used to indicate where to start, and which is modified when the function returns to indicate where we left off.
00417      *
00418      * This function uses the unusual index XML array in addition to the values, this is necessary to find where in the XML
00419      * tree a TABLE starts once we found where it ends.
00420      *
00421      * @param   array       The XML values array
00422      * @param   array       The XML index array
00423      * @param   integer     This is a reference to the index in the array where we should be starting the search
00424      * @return  array       Array of the table start index and table end index where TS is defined. table start is FALSE if there are no more TS entries in the document (consider it similar to an EOF reached status).
00425      */
00426     function nextTSDefinitionTable($vals, $index, &$id) {
00427             // browse the table where we left off last time
00428         while ($id < count ($vals)) {
00429             $node = $vals[$id];
00430             if (!strcmp($node['type'], 'close') && !strcmp($node['tag'], 'TABLE:TABLE'))    { // check if next entry is a candidate
00431                 $nextNode = $vals[$id+1];
00432                 if (!strcmp($nextNode['tag'], 'TEXT:P') && $this->isStyleChildOf($nextNode['attributes']['TEXT:STYLE-NAME'], 'Table Contents')) {
00433                         // we found a good entry
00434                     $closeIndex = array_search($id, $index['TABLE:TABLE']); // find the ID in the list of table items
00435 
00436                     $tableStart = $index['TABLE:TABLE'][$closeIndex-1]; // find the matching start of the table in the $vals array
00437 
00438                     return array($tableStart, $id++);
00439                 }
00440             }
00441             $id = $id+1;
00442         }
00443         return array(FALSE, 0); // marks the end of the input, no more table to find. WARNING: needs to be tested with === FALSE
00444     }
00445 
00446     /**
00447      * Converts an Open Office like style (font-weight:bold for example) into an HTML style (b is for bold). This function uses the global
00448      * $Styles defined through the parseStyles function
00449      *
00450      * @param   array       an array containing the [attributes][style] items in the OO format
00451      * @return  array       an array where the items are all the HTML styles to apply to closely match the input OO-like styles
00452      */
00453     function styleTags($node)   {
00454         global $Styles;
00455 
00456         $styleName = $node['attributes']['TEXT:STYLE-NAME'];
00457         switch ($Styles[$styleName]['font-weight']) {
00458             case 'bold':
00459                 $styleTags[] = 'b';
00460             break;
00461         }
00462         switch ($Styles[$styleName]['font-style'])  {
00463             case 'italic':
00464                 $styleTags[] = 'i';
00465             break;
00466         }
00467         if (!strcmp($styleName,'Table Contents/PRE'))   {
00468             //$styleTags[]='pre'; // unused yet, but could be <pre> in the future - this is for inline code in the manuals
00469         }
00470         return $styleTags;
00471     }
00472 
00473     /**
00474      * Converts an array containing style strings (for example ['b','i']) into their HTML equivalents
00475      *
00476      * @param   array       an array containing all the style tags
00477      * @param   string      either '' or '/' depending on whether the style definition is to open or close the style
00478      * @return  string      the sequence of tags to open or close the style, for example <strong><i>
00479      */
00480     function styleHTML($style, $char)   {
00481         $string = '';
00482         if (count ($style) > 0) {
00483             foreach ($style as $tag)    {
00484                 $string .= '<'.$char.$tag.'>';
00485             }
00486         }
00487         return $string;
00488     }
00489 
00490     /**
00491      * This function does a little more than just HSC'ing the text passed to it. It does a general cleaning of the input:
00492      * htmlspecialchars() : general cleaning for the HTML display, including single quotes transformation
00493      * stripslashes() : otherwise the backslashes will cause an issue with a future unserialize of the data
00494      * &nbsp if empty : if the input is empty, we return a &nbsp; string so that in the HTML output something will be   displayed
00495      * utf8 to entities cleaning : in some SXW docs we can find UTF8 characters that need to be converted to be displayed on screen
00496      *
00497      * @param   string      Text that will need to be transformed according to the HSC and other rules
00498      * @return  string      Transformed text that can now be freely serialized or exported to HTML
00499      */
00500     function HSCtext($text) {
00501         global $LANG;
00502 
00503         if (strcmp($text,''))   { // there is some content in the text field
00504             $cleantext = stripslashes(htmlspecialchars($text, ENT_QUOTES)); // stripslashes required as it could confuse unserialize
00505             return $LANG->csConvObj->utf8_to_entities($cleantext, $LANG->charSet);
00506         } else { // there is no text, it's empty
00507             return '&nbsp;';
00508         }
00509     }
00510 
00511     /**
00512      * This function parses a Table from an Open Office document, in an XML format, and extracts the information. It will therefore crawl the
00513      * XML tree and aggregate all the accepted contents into an array with the table contents.
00514      *
00515      * This function needs to extract the following information from the TABLE:
00516      *   property => (column 1)
00517      *   datatype => (column 2)
00518      *   description => (column 3)
00519      *   default => (column 4)
00520      *   column_count => number of columns found in table. Usually 4, but for spanned columns, it would be less (1 for example)
00521      *   is_propertyTable => ??? (almost always equal to 1)
00522      *
00523      * @param   array       This is the input XML data that is to be parsed
00524      * @param   integer     The starting ID in the XML array to parse the data from
00525      * @param   integer     The ending ID in the XML array to stop parsing data
00526      * @return  array       An array with the contents of the different columns extracted from the input data
00527      */
00528     function parseTable($vals, $start, $end) {
00529         $sectionHeader = 0;
00530         $sectionRow = 0;
00531         $sectionCell = 0;
00532         $sectionP = 0;
00533 
00534         $newLineRequired = ''; // this variable will either be empty (no newline required) or '\n' (newline required)
00535         $textStyle = array (); // this will be the list of tag styles to apply to the text
00536 
00537         $currentRow = 0;
00538         $currentCell = 0;
00539 
00540         $rowID = 0;
00541         $cellID = 0;  // also gets reset at every top-level row
00542 
00543         $table = array(); // will contain the results of the function
00544 
00545         $id = $start;
00546         while ($id < $end)  {
00547             $node = $vals[$id];
00548 
00549             // sanity check
00550             if ($sectionHeader < 0) die ('Malformed XML (header-rows)'.LF);
00551             if ($sectionRow < 0)    die ('Malformed XML (row)'.LF);
00552             if ($sectionCell < 0)   die ('Malformed XML (cell)'.LF);
00553             if ($sectionP < 0)      die ('Malformed XML (P)'.LF);
00554 
00555             switch ($node['type'])  {
00556                 case 'open':
00557                     switch ($node['tag'])   {
00558                         case 'TABLE:TABLE-HEADER-ROWS':
00559                             $sectionHeader++;
00560                         break;
00561 
00562                         case 'TABLE:TABLE-ROW':
00563                             if (!$sectionHeader)    { // skip section header, we only look at the *contents* of the table
00564                                 $sectionRow++;
00565                                 if ($sectionRow == 1)   { // make sure we are within a top-level row
00566                                     $rowID++;
00567                                     $cellID = 0;
00568                                 }
00569                             }
00570                         break;
00571 
00572                         case 'TABLE:TABLE-CELL':
00573                             if (!$sectionHeader)    { // skip section header, we only look at the *contents* of the table
00574                                 $sectionCell++;
00575                                 if ($sectionCell == 1)  { // make sure we are within a top-level cell
00576                                     $cellID++;
00577                                     $newLineRequired = ''; // no newline required after this
00578                                 }
00579                             }
00580                         break;
00581 
00582                         case 'TEXT:P':
00583                             if ($sectionCell)   { // make sure we are in a cell
00584                                 $sectionP++;
00585                                 $table[$rowID-1][$cellID-1] .= $this->styleHTML($this->styleTags($node),'') . $newLineRequired.$this->HSCtext($node['value']);
00586                                 $newLineRequired = ''; // no newline required after this
00587                                 $latestTEXTPopen = $node;
00588                             }
00589                         break;
00590                     }
00591                 break;
00592 
00593                 case 'complete':
00594                     switch ($node['tag'])   {
00595                         case 'TEXT:P':
00596                             if ($sectionCell)   { // make sure we are in a cell
00597                                 $table[$rowID-1][$cellID-1] .= $this->styleHTML($this->styleTags($node),'') . $newLineRequired.$this->HSCtext($node['value']).$this->styleHTML($this->styleTags($node),'/');
00598                                 $newLineRequired = '<br>'; // after a paragraph, require a new-line
00599                             }
00600                         break;
00601 
00602                         case 'TEXT:SPAN':
00603                             if ($sectionCell)   { // make sure we are in a cell
00604                                 $table[$rowID-1][$cellID-1] .= $this->styleHTML($this->styleTags($node),'').$newLineRequired.$this->HSCtext($node['value']).$this->styleHTML($this->styleTags($node),'/');
00605                                 $newLineRequired = ''; // no newline required after this
00606                             }
00607                         break;
00608 
00609                         case 'TEXT:S':
00610                             if ($sectionCell)   { // make sure we are in a cell
00611                                 for ($i=0; $i<$node['attributes']['TEXT:C']; $i++)  {
00612                                     $table[$rowID-1][$cellID-1] .= '&nbsp;';
00613                                 }
00614                                 $newLineRequired = ''; // no newline required after this
00615                             }
00616                         break;
00617                     }
00618                 break;
00619 
00620                 case 'cdata':
00621                     switch ($node['tag'])   {
00622                         case 'TEXT:P':
00623                             if ($sectionCell)   { // make sure we are in a cell
00624                                 $table[$rowID-1][$cellID-1] .= $this->styleHTML($this->styleTags($node),'') . $newLineRequired.$this->HSCtext($node['value']).$this->styleHTML($this->styleTags($node),'/');
00625                                 $newLineRequired = ''; // no newline required after this
00626                             }
00627                         break;
00628                     }
00629                 break;
00630 
00631                 case 'close':
00632                     switch ($node['tag'])   {
00633                         case 'TABLE:TABLE-HEADER-ROWS':
00634                             $sectionHeader--;
00635                         break;
00636 
00637                         case 'TABLE:TABLE-ROW':
00638                             if (!$sectionHeader)    { // skip section header, we only look at the *contents* of the table
00639                                 $sectionRow--;
00640                             }
00641                         break;
00642 
00643                         case 'TABLE:TABLE-CELL':
00644                             if (!$sectionHeader)    { // skip section header, we only look at the *contents* of the table
00645                                 $sectionCell--;
00646                             }
00647                         break;
00648 
00649                         case 'TEXT:P':
00650                             $sectionP--;
00651                             $newLineRequired = '<br>'; // after a paragraph, require a new-line
00652                             $table[$rowID-1][$cellID-1] .= $this->styleHTML($this->styleTags($latestTEXTPopen),'/');
00653                         break;
00654                     }
00655                 break;
00656             }
00657             $id = $id+1;
00658         }
00659         return $table;
00660     }
00661 
00662     /**
00663      * Load the contents of the table into the SQL database
00664      *
00665      * @param   string      Name of the extension to load the documentation for. This is used to make the unique hash in the database
00666      * @param   array       Contents of the documentation table
00667      * @param   string      Name of the table from the source document (name at the bottom of the table in OpenOffice)
00668      * @return  boolean     TRUE on success and FALSE on failure from the INSERT database query
00669      */
00670     function dumpIntoSQL($extension, $table, $tableName)    {
00671         global $uid;
00672 
00673         foreach ($table as $row)    {
00674             $tempArray = array();
00675             $tempArray['property'] = $row[0];
00676 
00677             $tempArray['datatype'] = count($row)==2 ? '&nbsp;':$row[1]; // in the case there are only 2 columns, the second one is the description !
00678             $tempArray['description'] = count($row)==2 ? $row[1]:$row[2];  // in the case there are only 2 columns, the second one is the description !
00679             $tempArray['default'] = $row[3];
00680             $tempArray['column_count'] = count($row);
00681             $tempArray['is_propertyTable'] = 1;
00682             $tsHelpArray['rows'][] = $tempArray;
00683         }
00684         $appdata = serialize($tsHelpArray);
00685         $obj_string = trim($tableName, '[]');
00686 
00687         if (isset($this->objStringsPerExtension[$obj_string]))  {
00688             if (isset($this->objStringsPerExtension[$obj_string][$extension]))  {
00689                 $this->objStringsPerExtension[$obj_string][$extension]++;
00690             } else {
00691                 $this->objStringsPerExtension[$obj_string][$extension] = 1;
00692             }
00693         } else {
00694             $this->objStringsPerExtension[$obj_string] = array();
00695             $this->objStringsPerExtension[$obj_string][$extension] = 1;
00696         }
00697 
00698             // If the obj_string was already encountered increase its counter. If not initialise it as 0
00699             // The counter (when bigger than 0) is appended to the obj_string to make it unique
00700             // This way the tables do not overwrite each other in the online help
00701         if (isset($this->allObjStrings[$obj_string]))   {
00702             $this->allObjStrings[$obj_string]++;
00703             $obj_string .= ' ('.$this->allObjStrings[$obj_string].')';
00704         } else {
00705             $this->allObjStrings[$obj_string] = 0;
00706         }
00707         $md5hash = md5($obj_string);
00708         $description = ''; // unused
00709         $guide = hexdec(substr(md5($extension),6,6));  // try to find a way to uniquely identify the source extension and place the identified into the "guide" column
00710         $title = ''; // unused
00711 
00712         $insertFields = array(
00713             'guide' => $guide,
00714             'md5hash' => $md5hash,
00715             'description' => $description,
00716             'obj_string' => $obj_string,
00717             'appdata' => $appdata,
00718             'title' => $title
00719         );
00720 
00721         return $GLOBALS['TYPO3_DB']->exec_INSERTquery('static_tsconfig_help', $insertFields);
00722     }
00723 
00724     /**
00725      * Purges the existing contents for TypoScript help in the database. This ensures that several runs of the import process will not push
00726      * duplicate information in the database, but that we clean it first before adding new contents.
00727      *
00728      * @param   string      Name of the extension for which to delete all the data in the database. If empty, all database will be cleaned
00729      * @return  void
00730      */
00731     function purgeSQLContents($extension='')    {
00732         $guide = hexdec(substr(md5($extension), 6, 6));
00733         if ($extension != '')   {
00734             $GLOBALS['TYPO3_DB']->exec_DELETEquery('static_tsconfig_help', 'guide='.$guide);
00735         } else {
00736             $GLOBALS['TYPO3_DB']->exec_TRUNCATEquery('static_tsconfig_help');
00737         }
00738     }
00739 
00740     /**
00741      * This is the main function of the loading process. It will first parse the input data and load it into an XML array. It will then find all
00742      * the styles associated with the contents so that later on we can distinguish bold and italic characters for example. It then parses the XML
00743      * array to find all the TS-like description tables and parses them before loading them into the SQL database.
00744      *
00745      * @param   string      Name of the extension to load manual from
00746      * @param   string      Input data from the manual.sxw in a string form. One large string with the whole OO manual document.
00747      * @return  integer     Number of individual tables found in the document and loaded into the SQL database
00748      */
00749     function loadExtensionManual($extension, $contents) {
00750         global $Styles;
00751 
00752             // read the contents into an XML array
00753         $parser = xml_parser_create();
00754         xml_parse_into_struct($parser, $contents, $vals, $index);
00755 
00756         xml_parser_free($parser);
00757 
00758             // parse styles from the manual for future rendering
00759         $Styles = $this->parseStyles($vals);
00760 
00761         $id = 0;
00762         $tableNumber = 0;
00763         do {
00764             list($tableStart, $tableEnd) = $this->nextTSDefinitionTable($vals, $index, $id);
00765             if ($tableStart !== FALSE)  {
00766                     // The title of the table can either be self-contained in a single complete entry
00767                 if (!strcmp($vals[$id]['type'], 'complete'))    {
00768                     $title = $vals[$id]['value'];
00769                 } else { // or it can be spread across a number of spans or similar
00770                     $watchTag = $vals[$id]['tag'];
00771                     $title = '';
00772                     while (strcmp($vals[$id]['tag'], $watchTag) || strcmp($vals[$id]['type'], 'close')) {
00773                         $title .= $vals[$id++]['value'];
00774                     }
00775                 }
00776                 $tableContents = $this->parseTable($vals, $tableStart, $tableEnd);
00777                 $this->dumpIntoSQL($extension, $tableContents, $title);
00778                 $tableNumber++;
00779             }
00780         } while ($tableStart !== FALSE);
00781         return $tableNumber;
00782     }
00783 }
00784 
00785 
00786 if (defined('TYPO3_MODE') && isset($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['ext/tsconfig_help/mod1/index.php'])) {
00787     include_once($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['ext/tsconfig_help/mod1/index.php']);
00788 }
00789 
00790 
00791 
00792 
00793 // Make instance:
00794 $SOBE = t3lib_div::makeInstance('tx_tsconfighelp_module1');
00795 $SOBE->init();
00796 
00797 // Include files?
00798 foreach ($SOBE->include_once as $INC_FILE) include_once($INC_FILE);
00799 
00800 $SOBE->main();
00801 $SOBE->printContent();
00802 
00803 ?>