[TASK] CGL violations FunctionCallArgumentSpacing in /typo3/sysext/t*/
[Packages/TYPO3.CMS.git] / typo3 / sysext / tsconfig_help / mod1 / index.php
1 <?php
2 /***************************************************************
3 * Copyright notice
4 *
5 * (c) 2007-2011 Stephane Schitter <stephane.schitter@free.fr>
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 *
17 * This script is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * This copyright notice MUST APPEAR in all copies of the script!
23 ***************************************************************/
24
25
26 // DEFAULT initialization of a module [BEGIN]
27 unset($MCONF);
28 require_once('conf.php');
29 require_once($BACK_PATH.'init.php');
30 require_once($BACK_PATH.'template.php');
31
32 $LANG->includeLLFile('EXT:tsconfig_help/mod1/locallang.xml');
33 $BE_USER->modAccess($MCONF, 1); // This checks permissions and exits if the users has no permission for entry.
34 // DEFAULT initialization of a module [END]
35
36
37 /**
38 * Module 'TypoScript Help' for the 'tsconfig_help' extension.
39 *
40 * @author Stephane Schitter <stephane.schitter@free.fr>
41 * @package TYPO3
42 * @subpackage tx_tsconfighelp
43 */
44 class tx_tsconfighelp_module1 extends t3lib_SCbase {
45 var $pageinfo;
46 var $objStringsPerExtension = array(); // This is used to count how many times the same obj_string appears in each extension manual
47 var $allObjStrings = array(); // This is used to count how many times the same obj_string appears across all extensions
48
49 /**
50 * Initializes the Module
51 * @return void
52 */
53 function init() {
54 parent::init();
55 }
56
57 /**
58 * Adds items to the ->MOD_MENU array. Used for the function menu selector.
59 *
60 * @return void
61 */
62 function menuConfig() {
63 $this->MOD_MENU = array(
64 'function' => array(
65 '1' => $GLOBALS['LANG']->getLL('display')
66 )
67 );
68
69 if($GLOBALS['BE_USER']->user['admin']) {
70 $this->MOD_MENU['function']['2'] = $GLOBALS['LANG']->getLL('rebuild');
71 }
72
73 parent::menuConfig();
74 }
75
76 /**
77 * Main function of the module. Write the content to $this->content
78 *
79 * @return void
80 */
81 function main() {
82 // Access check!
83 $access = $GLOBALS['BE_USER']->check('modules', 'help_txtsconfighelpM1');
84
85 // Draw the header.
86 $this->doc = t3lib_div::makeInstance('template');
87 $this->doc->backPath = $GLOBALS['BACK_PATH'];
88 $this->doc->setModuleTemplate('templates/tsconfig_help.html');
89
90 if ($access || $GLOBALS['BE_USER']->user['admin']) {
91
92 $this->doc->form = '<form action="" method="post">';
93
94 // JavaScript
95 $this->doc->JScode = '
96 <script language="javascript" type="text/javascript">
97 script_ended = 0;
98 function jumpToUrl(URL) {
99 document.location = URL;
100 }
101 </script>
102 ';
103 $this->doc->postCode = '
104 <script language="javascript" type="text/javascript">
105 script_ended = 1;
106 if (top.fsMod) top.fsMod.recentIds["web"] = 0;
107 </script>
108 ';
109
110 $this->content .= $this->doc->header($GLOBALS['LANG']->getLL('title'));
111
112 // Render content:
113 $this->moduleContent();
114
115 $this->content .= $this->doc->spacer(10);
116
117 $markers['FUNC_MENU'] = t3lib_BEfunc::getFuncMenu($this->id, 'SET[function]', $this->MOD_SETTINGS['function'], $this->MOD_MENU['function']);
118 } else {
119 $this->content .= $this->doc->header($GLOBALS['LANG']->getLL('title'));
120 $markers['FUNC_MENU'] = '';
121 }
122 // Setting up the buttons and markers for docheader
123 $docHeaderButtons = $this->getButtons();
124 $markers['CSH'] = $docHeaderButtons['csh'];
125 $markers['CONTENT'] = $this->content;
126
127 // Build the <body> for the module
128 $this->content = $this->doc->moduleBody($this->pageinfo, $docHeaderButtons, $markers);
129 // Renders the module page
130 $this->content = $this->doc->render(
131 $GLOBALS['LANG']->getLL('title'),
132 $this->content
133 );
134 }
135
136 /**
137 * Prints out the module HTML
138 *
139 * @return void
140 */
141 function printContent() {
142 echo $this->content;
143 }
144
145 /**
146 * Create the panel of buttons for submitting the form or otherwise perform operations.
147 *
148 * @return array all available buttons as an assoc. array
149 */
150 protected function getButtons() {
151 $buttons = array(
152 'csh' => '',
153 'shortcut' => '',
154 );
155
156 if (($this->id && is_array($this->pageinfo)) || ($GLOBALS['BE_USER']->user['admin'] && !$this->id)) {
157 // Shortcut
158 if ($GLOBALS['BE_USER']->mayMakeShortcut()) {
159 $buttons['shortcut'] = $this->doc->makeShortcutIcon('id', implode(',', array_keys($this->MOD_MENU)), $this->MCONF['name']);
160 }
161 }
162 return $buttons;
163 }
164
165 /**
166 * Generates the module content
167 *
168 * @return void
169 */
170 function moduleContent() {
171 switch ((string)$this->MOD_SETTINGS['function']) {
172 case 1:
173 $content = '<div align="left"><strong>' . $GLOBALS['LANG']->getLL('referenceExplanation') . '</strong></div>';
174 $content .= '<p>' . $GLOBALS['LANG']->getLL('referenceExplanationDetailed') . '</p><br />';
175 $this->content .= $this->doc->section($GLOBALS['LANG']->getLL('displayReferences'), $content, 0, 1);
176 $this->content .= '<a href="#" onclick="vHWin=window.open(\'' . $GLOBALS['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 />';
177 $this->content .= '<a href="#" onclick="vHWin=window.open(\'' . $GLOBALS['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 />';
178 $this->content .= '<a href="#" onclick="vHWin=window.open(\'' . $GLOBALS['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 />';
179 break;
180
181 case 2:
182 if ($GLOBALS['BE_USER']->user['admin']) {
183 if (t3lib_div::_GP('_rebuild')) {
184 // remove all data from the database
185 $this->purgeSQLContents();
186
187 // get all loaded extension keys
188 $extArray = $GLOBALS['TYPO3_LOADED_EXT'];
189
190 $content = '<div align="left"><strong>' . $GLOBALS['LANG']->getLL('loadedTSfrom') . '</strong></div><br />';
191
192 // parse the extension names only (no need for all details from the TYPO3_LOADED_EXT table
193 foreach ($extArray as $extName => $dummy) {
194 // check that the extension is really loaded (which should always be the case)
195 if (t3lib_extMgm::isLoaded($extName)) {
196 // extract the content.xml from the manual.sxw ZIP file
197 $manual = $this->getZIPFileContents(t3lib_extMgm::extPath($extName).'doc/manual.sxw', 'content.xml');
198
199 // check if the manual file actually exists and if the content.xml could be loaded
200 if ($manual != '') {
201 // if the manual file exists, proceed with the load into the SQL database
202 $content .= '<p>Extension '.$extName.'...';
203
204 // run the extraction processing and import the data into SQL. Return the number of TS tables found in the open office document
205 $number = $this->loadExtensionManual($extName, $manual);
206
207 // print a status message with a link to the openoffice manual
208 $content .= $number . ' ' . $GLOBALS['LANG']->getLL('sections') . ' (<a href="' .
209 t3lib_div::getIndpEnv('TYPO3_SITE_URL') . TYPO3_mainDir . t3lib_extMgm::extRelPath($extName) .
210 'doc/manual.sxw">manual</a>)</p>';
211 }
212 } else {
213 // this should never happen!
214 die ("Fatal error : loaded extension not actually loaded? Please file a bug report at http://bugs.typo3.org!");
215 }
216 }
217
218 $this->content .= $this->doc->section($GLOBALS['LANG']->getLL('rebuildTS'), $content . '<br />', 0, 1);
219
220 // Issue warnings about duplicate or empty obj_strings, if any
221 // An obj_string should be unique. It should appear in only one extension manual and then only once
222 // If the sum of all occurrences of a given obj_string is more than one, issue a list of duplicate entries as a warning
223 $duplicateWarnings = '';
224 $emptyWarnings = '';
225 foreach ($this->objStringsPerExtension as $obj_string => $extensions) {
226 if (empty($obj_string)) {
227 $emptyWarnings = '<p class="typo3-red">' . $GLOBALS['LANG']->getLL('warning_manualsWithoutMarkers');
228 foreach ($extensions as $extensionKey => $counter) {
229 $emptyWarnings .= ' '.$extensionKey.' ('.$counter.')<br />';
230 }
231 $emptyWarnings .= '</p><br />';
232 } else {
233 if (array_sum($extensions) > 1) {
234 $duplicateWarnings .= $obj_string.':';
235 foreach ($extensions as $extensionKey => $counter) {
236 $duplicateWarnings .= ' '.$extensionKey.' ('.$counter.')';
237 }
238 $duplicateWarnings .= '<br />';
239 }
240 }
241 }
242 $warnings = $emptyWarnings;
243 if (!empty($duplicateWarnings)) {
244 $warnings .= '<p class="typo3-red">'.$GLOBALS['LANG']->getLL('warning_duplicateMarkers').'<br />'.$duplicateWarnings.'</p>';
245 }
246 if (!empty($warnings)) {
247 $this->content .= $this->doc->section($GLOBALS['LANG']->getLL('updateWarnings'), '<div>'.$warnings.'</div>', 0, 1);
248 }
249 }
250
251 $content = '<p>' . $GLOBALS['LANG']->getLL('rebuildExplanation') . '</p><br />';
252 $content .= $GLOBALS['LANG']->getLL('rebuild') . ' <input type="submit" name="_rebuild" value="Rebuild" /><br />';
253 $this->content .= $this->doc->section($GLOBALS['LANG']->getLL('rebuildTS'), $content, 0, 1);
254 } else {
255 $this->content .= '<p>' . $GLOBALS['LANG']->getLL('adminAccessOnly') . '</p><br />';
256 }
257
258
259 break;
260 }
261 }
262
263 /**
264 * Returns the contents of a specific file within the ZIP
265 *
266 * @return string contents
267 */
268 function getZIPFileContents($ZIPfile, $filename) {
269 if (file_exists($ZIPfile)) {
270 // Unzipping SXW file, getting filelist:
271 $tempPath = PATH_site.'typo3temp/tx_tsconfighelp_ziptemp/';
272 t3lib_div::mkdir($tempPath);
273
274 $this->unzip($ZIPfile, $tempPath);
275 $output = t3lib_div::getUrl($tempPath.$filename);
276
277 $cmd = 'rm -r "'.$tempPath.'"';
278 t3lib_utility_Command::exec($cmd);
279
280 return $output;
281 }
282 }
283
284 /**
285 * Unzips a zip file in the given path.
286 * Uses the Extension Manager unzip functions.
287 *
288 *
289 * @param string $file Full path to zip file
290 * @param string $path Path to change to before extracting
291 * @return boolean TRUE on success, FALSE in failure
292 */
293 function unzip($file, $path) {
294 // we use the unzip class of the Extension Manager here
295 // TODO: move unzip class to core
296 if (!t3lib_extMgm::isLoaded('em')) {
297 //em is not loaded, so include the unzip class
298 t3lib_div::requireOnce(PATH_typo3 . 'sysext/em/classes/tools/class.tx_em_tools_unzip.php');
299 }
300 $unzip = t3lib_div::makeInstance('tx_em_Tools_Unzip', $file);
301 $ret = $unzip->extract(array('add_path'=>$path));
302 return (is_array($ret));
303 }
304
305 /**
306 * Parses the whole XML file in order to understand the Styles structure. This function is mostly looking at the styles
307 * that create bold or italic characters in the document, as these will later on need to be translated to <i> and <strong> tags
308 * This function takes into account the hierarchy of the styles, as created by OpenOffice. This means that if a style has
309 * a parant, this function will make it inherit the styles of the parent. Therefore bold and italic styles are propagated
310 * to children as well.
311 *
312 * This function assumes the STYLE definitions are not nested. If they are then, then "close" type will need to be used
313 * more carefully, and a depth counter will need to be implemented.
314 *
315 * @param array The XML values array. The XML index is not necessary in this function.
316 * @return array Array that contains the different styles with their parent (required to recognise "Table Contents"-type styles), and their style (bold/italic)
317 */
318 function parseStyles($vals) {
319 $currentStyleName = '';
320 $style = array ();
321
322 foreach ($vals as $node) {
323 switch ($node['type']) {
324 case 'open':
325 switch ($node['tag']) {
326 case 'STYLE:STYLE':
327 $currentStyleName = $node['attributes']['STYLE:NAME'];
328
329 if (array_key_exists('STYLE:PARENT-STYLE-NAME', $node['attributes'])) {
330 $parentStyleName = $node['attributes']['STYLE:PARENT-STYLE-NAME'];
331 $style[$currentStyleName]['parents'][] = $parentStyleName; // keep trace of parents in the style array
332 } else {
333 $parentStyleName = ''; // this style has no parent, therefore clean the variable to avoid side effects with next use of that variable
334 }
335
336 if (array_key_exists($parentStyleName, $style)) { // the style parent is already documented in the array
337 $style[$currentStyleName] = $style[$parentStyleName]; // inherit parent style
338 }
339 break;
340 }
341 break;
342
343 case 'complete':
344 switch ($node['tag']) {
345 case 'STYLE:PROPERTIES':
346 if (is_array($node['attributes']) && array_key_exists('FO:FONT-WEIGHT', $node['attributes'])) {
347 $style[$currentStyleName]['font-weight'] = $node['attributes']['FO:FONT-WEIGHT']; // bold for example
348 }
349 if (is_array($node['attributes']) && array_key_exists('FO:FONT-STYLE', $node['attributes'])) {
350 $style[$currentStyleName]['font-style'] = $node['attributes']['FO:FONT-STYLE']; // italic for example
351 }
352 break;
353 }
354 break;
355
356 case 'close':
357 switch ($node['tag']) {
358 case 'STYLE:STYLE':
359 $currentStyleName = '';
360 break;
361 case 'STYLE:PROPERTIES':
362 break;
363 }
364 break;
365 }
366 }
367
368 return $style;
369 }
370
371
372 /**
373 * Checks if the style is a child of a specified parent. This is useful for example to check if a specific style that has
374 * a generic name ("P8" for example) is a child of the "Table Contents" style. It would not only inherit its style (bold/
375 * italic) but also its properties like being part of a Table.
376 *
377 * This function references the global $Styles variables which must have been created previously with parseStyles()
378 *
379 * @param string Name of the child style that we want to get properties for
380 * @param string Name of the parent style that we want to compare the child against
381 * @return boolean TRUE if the child and parent are linked together. FALSE otherwise.
382 */
383 function isStyleChildOf($child, $parent) {
384 global $Styles;
385
386 if (!strcmp($child, $parent)) { // the child is actually the same as the parent. They are obviously linked together
387 return TRUE;
388 }
389
390 if (is_array($Styles[$child]) // the child is a documented style
391 && array_key_exists('parents', $Styles[$child]) // it has some parents
392 && (array_search($parent, $Styles[$child]['parents']) !== FALSE)) { // and the parent appears amongst its ancestors
393 return TRUE;
394 }
395 return FALSE;
396 }
397
398 /**
399 * Find the table description that we want, then find a TABLE:TABLE close, immediately followed by a TEXT:P which has a
400 * style which is a child of a "Table Contents", then look up the index to find where the TABLE begins, and start browsing
401 * from there (returns these start and end indexes).
402 *
403 * This function only finds the next TS definition table. In order to find all TS definition tables from the document, the
404 * function needs to be called several times, starting where it left off last time. The third parameter is the index that
405 * is used to indicate where to start, and which is modified when the function returns to indicate where we left off.
406 *
407 * This function uses the unusual index XML array in addition to the values, this is necessary to find where in the XML
408 * tree a TABLE starts once we found where it ends.
409 *
410 * @param array The XML values array
411 * @param array The XML index array
412 * @param integer This is a reference to the index in the array where we should be starting the search
413 * @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).
414 */
415 function nextTSDefinitionTable($vals, $index, &$id) {
416 // browse the table where we left off last time
417 while ($id < count ($vals)) {
418 $node = $vals[$id];
419 if (!strcmp($node['type'], 'close') && !strcmp($node['tag'], 'TABLE:TABLE')) { // check if next entry is a candidate
420 $nextNode = $vals[$id+1];
421 if (!strcmp($nextNode['tag'], 'TEXT:P') && $this->isStyleChildOf($nextNode['attributes']['TEXT:STYLE-NAME'], 'Table Contents')) {
422 // we found a good entry
423 $closeIndex = array_search($id, $index['TABLE:TABLE']); // find the ID in the list of table items
424
425 $tableStart = $index['TABLE:TABLE'][$closeIndex-1]; // find the matching start of the table in the $vals array
426
427 return array($tableStart, $id++);
428 }
429 }
430 $id = $id+1;
431 }
432 return array(FALSE, 0); // marks the end of the input, no more table to find. WARNING: needs to be tested with === FALSE
433 }
434
435 /**
436 * Converts an Open Office like style (font-weight:bold for example) into an HTML style (b is for bold). This function uses the global
437 * $Styles defined through the parseStyles function
438 *
439 * @param array an array containing the [attributes][style] items in the OO format
440 * @return array an array where the items are all the HTML styles to apply to closely match the input OO-like styles
441 */
442 function styleTags($node) {
443 global $Styles;
444
445 $styleName = $node['attributes']['TEXT:STYLE-NAME'];
446 switch ($Styles[$styleName]['font-weight']) {
447 case 'bold':
448 $styleTags[] = 'b';
449 break;
450 }
451 switch ($Styles[$styleName]['font-style']) {
452 case 'italic':
453 $styleTags[] = 'i';
454 break;
455 }
456 return $styleTags;
457 }
458
459 /**
460 * Converts an array containing style strings (for example ['b','i']) into their HTML equivalents
461 *
462 * @param array an array containing all the style tags
463 * @param string either '' or '/' depending on whether the style definition is to open or close the style
464 * @return string the sequence of tags to open or close the style, for example <strong><i>
465 */
466 function styleHTML($style, $char) {
467 $string = '';
468 if (count ($style) > 0) {
469 foreach ($style as $tag) {
470 $string .= '<'.$char.$tag.'>';
471 }
472 }
473 return $string;
474 }
475
476 /**
477 * This function does a little more than just HSC'ing the text passed to it. It does a general cleaning of the input:
478 * htmlspecialchars() : general cleaning for the HTML display, including single quotes transformation
479 * stripslashes() : otherwise the backslashes will cause an issue with a future unserialize of the data
480 * &nbsp if empty : if the input is empty, we return a &nbsp; string so that in the HTML output something will be displayed
481 * utf8 to entities cleaning : in some SXW docs we can find UTF8 characters that need to be converted to be displayed on screen
482 *
483 * @param string Text that will need to be transformed according to the HSC and other rules
484 * @return string Transformed text that can now be freely serialized or exported to HTML
485 */
486 function HSCtext($text) {
487 global $LANG;
488
489 if (strcmp($text, '')) { // there is some content in the text field
490 $cleantext = stripslashes(htmlspecialchars($text, ENT_QUOTES)); // stripslashes required as it could confuse unserialize
491 return $LANG->csConvObj->utf8_to_entities($cleantext, $LANG->charSet);
492 } else { // there is no text, it's empty
493 return '&nbsp;';
494 }
495 }
496
497 /**
498 * This function parses a Table from an Open Office document, in an XML format, and extracts the information. It will therefore crawl the
499 * XML tree and aggregate all the accepted contents into an array with the table contents.
500 *
501 * This function needs to extract the following information from the TABLE:
502 * property => (column 1)
503 * datatype => (column 2)
504 * description => (column 3)
505 * default => (column 4)
506 * column_count => number of columns found in table. Usually 4, but for spanned columns, it would be less (1 for example)
507 * is_propertyTable => ??? (almost always equal to 1)
508 *
509 * @param array This is the input XML data that is to be parsed
510 * @param integer The starting ID in the XML array to parse the data from
511 * @param integer The ending ID in the XML array to stop parsing data
512 * @return array An array with the contents of the different columns extracted from the input data
513 */
514 function parseTable($vals, $start, $end) {
515 $sectionHeader = 0;
516 $sectionRow = 0;
517 $sectionCell = 0;
518 $sectionP = 0;
519
520 $newLineRequired = ''; // this variable will either be empty (no newline required) or '\n' (newline required)
521 $textStyle = array (); // this will be the list of tag styles to apply to the text
522
523 $currentRow = 0;
524 $currentCell = 0;
525
526 $rowID = 0;
527 $cellID = 0; // also gets reset at every top-level row
528
529 $table = array(); // will contain the results of the function
530
531 $id = $start;
532 while ($id < $end) {
533 $node = $vals[$id];
534
535 // sanity check
536 if ($sectionHeader < 0) die ('Malformed XML (header-rows)'.LF);
537 if ($sectionRow < 0) die ('Malformed XML (row)'.LF);
538 if ($sectionCell < 0) die ('Malformed XML (cell)'.LF);
539 if ($sectionP < 0) die ('Malformed XML (P)'.LF);
540
541 switch ($node['type']) {
542 case 'open':
543 switch ($node['tag']) {
544 case 'TABLE:TABLE-HEADER-ROWS':
545 $sectionHeader++;
546 break;
547
548 case 'TABLE:TABLE-ROW':
549 if (!$sectionHeader) { // skip section header, we only look at the *contents* of the table
550 $sectionRow++;
551 if ($sectionRow == 1) { // make sure we are within a top-level row
552 $rowID++;
553 $cellID = 0;
554 }
555 }
556 break;
557
558 case 'TABLE:TABLE-CELL':
559 if (!$sectionHeader) { // skip section header, we only look at the *contents* of the table
560 $sectionCell++;
561 if ($sectionCell == 1) { // make sure we are within a top-level cell
562 $cellID++;
563 $newLineRequired = ''; // no newline required after this
564 }
565 }
566 break;
567
568 case 'TEXT:P':
569 if ($sectionCell) { // make sure we are in a cell
570 $sectionP++;
571 $table[$rowID-1][$cellID-1] .= $this->styleHTML($this->styleTags($node), '') . $newLineRequired.$this->HSCtext($node['value']);
572 $newLineRequired = ''; // no newline required after this
573 $latestTEXTPopen = $node;
574 }
575 break;
576 }
577 break;
578
579 case 'complete':
580 switch ($node['tag']) {
581 case 'TEXT:P':
582 if ($sectionCell) { // make sure we are in a cell
583 $table[$rowID-1][$cellID-1] .= $this->styleHTML($this->styleTags($node), '') . $newLineRequired.$this->HSCtext($node['value']).$this->styleHTML($this->styleTags($node), '/');
584 $newLineRequired = '<br>'; // after a paragraph, require a new-line
585 }
586 break;
587
588 case 'TEXT:SPAN':
589 if ($sectionCell) { // make sure we are in a cell
590 $table[$rowID-1][$cellID-1] .= $this->styleHTML($this->styleTags($node), '').$newLineRequired.$this->HSCtext($node['value']).$this->styleHTML($this->styleTags($node), '/');
591 $newLineRequired = ''; // no newline required after this
592 }
593 break;
594
595 case 'TEXT:S':
596 if ($sectionCell) { // make sure we are in a cell
597 for ($i=0; $i<$node['attributes']['TEXT:C']; $i++) {
598 $table[$rowID-1][$cellID-1] .= '&nbsp;';
599 }
600 $newLineRequired = ''; // no newline required after this
601 }
602 break;
603 }
604 break;
605
606 case 'cdata':
607 switch ($node['tag']) {
608 case 'TEXT:P':
609 if ($sectionCell) { // make sure we are in a cell
610 $table[$rowID-1][$cellID-1] .= $this->styleHTML($this->styleTags($node), '') . $newLineRequired.$this->HSCtext($node['value']).$this->styleHTML($this->styleTags($node), '/');
611 $newLineRequired = ''; // no newline required after this
612 }
613 break;
614 }
615 break;
616
617 case 'close':
618 switch ($node['tag']) {
619 case 'TABLE:TABLE-HEADER-ROWS':
620 $sectionHeader--;
621 break;
622
623 case 'TABLE:TABLE-ROW':
624 if (!$sectionHeader) { // skip section header, we only look at the *contents* of the table
625 $sectionRow--;
626 }
627 break;
628
629 case 'TABLE:TABLE-CELL':
630 if (!$sectionHeader) { // skip section header, we only look at the *contents* of the table
631 $sectionCell--;
632 }
633 break;
634
635 case 'TEXT:P':
636 $sectionP--;
637 $newLineRequired = '<br>'; // after a paragraph, require a new-line
638 $table[$rowID-1][$cellID-1] .= $this->styleHTML($this->styleTags($latestTEXTPopen), '/');
639 break;
640 }
641 break;
642 }
643 $id = $id+1;
644 }
645 return $table;
646 }
647
648 /**
649 * Load the contents of the table into the SQL database
650 *
651 * @param string Name of the extension to load the documentation for. This is used to make the unique hash in the database
652 * @param array Contents of the documentation table
653 * @param string Name of the table from the source document (name at the bottom of the table in OpenOffice)
654 * @return boolean TRUE on success and FALSE on failure from the INSERT database query
655 */
656 function dumpIntoSQL($extension, $table, $tableName) {
657 global $uid;
658
659 foreach ($table as $row) {
660 $tempArray = array();
661 $tempArray['property'] = $row[0];
662
663 $tempArray['datatype'] = count($row)==2 ? '&nbsp;':$row[1]; // in the case there are only 2 columns, the second one is the description !
664 $tempArray['description'] = count($row)==2 ? $row[1]:$row[2]; // in the case there are only 2 columns, the second one is the description !
665 $tempArray['default'] = $row[3];
666 $tempArray['column_count'] = count($row);
667 $tempArray['is_propertyTable'] = 1;
668 $tsHelpArray['rows'][] = $tempArray;
669 }
670 $appdata = serialize($tsHelpArray);
671 $obj_string = trim($tableName, '[]');
672
673 if (isset($this->objStringsPerExtension[$obj_string])) {
674 if (isset($this->objStringsPerExtension[$obj_string][$extension])) {
675 $this->objStringsPerExtension[$obj_string][$extension]++;
676 } else {
677 $this->objStringsPerExtension[$obj_string][$extension] = 1;
678 }
679 } else {
680 $this->objStringsPerExtension[$obj_string] = array();
681 $this->objStringsPerExtension[$obj_string][$extension] = 1;
682 }
683
684 // If the obj_string was already encountered increase its counter. If not initialise it as 0
685 // The counter (when bigger than 0) is appended to the obj_string to make it unique
686 // This way the tables do not overwrite each other in the online help
687 if (isset($this->allObjStrings[$obj_string])) {
688 $this->allObjStrings[$obj_string]++;
689 $obj_string .= ' ('.$this->allObjStrings[$obj_string].')';
690 } else {
691 $this->allObjStrings[$obj_string] = 0;
692 }
693 $md5hash = md5($obj_string);
694 $description = ''; // unused
695 $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
696 $title = ''; // unused
697
698 $insertFields = array(
699 'guide' => $guide,
700 'md5hash' => $md5hash,
701 'description' => $description,
702 'obj_string' => $obj_string,
703 'appdata' => $appdata,
704 'title' => $title
705 );
706
707 return $GLOBALS['TYPO3_DB']->exec_INSERTquery('static_tsconfig_help', $insertFields);
708 }
709
710 /**
711 * Purges the existing contents for TypoScript help in the database. This ensures that several runs of the import process will not push
712 * duplicate information in the database, but that we clean it first before adding new contents.
713 *
714 * @param string Name of the extension for which to delete all the data in the database. If empty, all database will be cleaned
715 * @return void
716 */
717 function purgeSQLContents($extension='') {
718 $guide = hexdec(substr(md5($extension), 6, 6));
719 if ($extension != '') {
720 $GLOBALS['TYPO3_DB']->exec_DELETEquery('static_tsconfig_help', 'guide='.$guide);
721 } else {
722 $GLOBALS['TYPO3_DB']->exec_TRUNCATEquery('static_tsconfig_help');
723 }
724 }
725
726 /**
727 * 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
728 * the styles associated with the contents so that later on we can distinguish bold and italic characters for example. It then parses the XML
729 * array to find all the TS-like description tables and parses them before loading them into the SQL database.
730 *
731 * @param string Name of the extension to load manual from
732 * @param string Input data from the manual.sxw in a string form. One large string with the whole OO manual document.
733 * @return integer Number of individual tables found in the document and loaded into the SQL database
734 */
735 function loadExtensionManual($extension, $contents) {
736 global $Styles;
737
738 // read the contents into an XML array
739 $parser = xml_parser_create();
740 xml_parse_into_struct($parser, $contents, $vals, $index);
741
742 xml_parser_free($parser);
743
744 // parse styles from the manual for future rendering
745 $Styles = $this->parseStyles($vals);
746
747 $id = 0;
748 $tableNumber = 0;
749 do {
750 list($tableStart, $tableEnd) = $this->nextTSDefinitionTable($vals, $index, $id);
751 if ($tableStart !== FALSE) {
752 // The title of the table can either be self-contained in a single complete entry
753 if (!strcmp($vals[$id]['type'], 'complete')) {
754 $title = $vals[$id]['value'];
755 } else { // or it can be spread across a number of spans or similar
756 $watchTag = $vals[$id]['tag'];
757 $title = '';
758 while (strcmp($vals[$id]['tag'], $watchTag) || strcmp($vals[$id]['type'], 'close')) {
759 $title .= $vals[$id++]['value'];
760 }
761 }
762 $tableContents = $this->parseTable($vals, $tableStart, $tableEnd);
763 $this->dumpIntoSQL($extension, $tableContents, $title);
764 $tableNumber++;
765 }
766 } while ($tableStart !== FALSE);
767 return $tableNumber;
768 }
769 }
770
771 // Make instance:
772 $SOBE = t3lib_div::makeInstance('tx_tsconfighelp_module1');
773 $SOBE->init();
774
775 // Include files?
776 foreach ($SOBE->include_once as $INC_FILE) include_once($INC_FILE);
777
778 $SOBE->main();
779 $SOBE->printContent();
780
781 ?>