TYPO3 API  SVNRelease
class.t3lib_syntaxhl.php
Go to the documentation of this file.
00001 <?php
00002 /***************************************************************
00003  *  Copyright notice
00004  *
00005  *  (c) 1999-2011 Kasper Skårhøj (kasperYYYY@typo3.com)
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  *  A copy is found in the textfile GPL.txt and important notices to the license
00017  *  from the author is found in LICENSE.txt distributed with these scripts.
00018  *
00019  *
00020  *  This script is distributed in the hope that it will be useful,
00021  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00022  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00023  *  GNU General Public License for more details.
00024  *
00025  *  This copyright notice MUST APPEAR in all copies of the script!
00026  ***************************************************************/
00027 /**
00028  * Contains a class for various syntax highlighting.
00029  *
00030  * $Id: class.t3lib_syntaxhl.php 10121 2011-01-18 20:15:30Z ohader $
00031  *
00032  * @author  Kasper Skårhøj <kasperYYYY@typo3.com>
00033  */
00034 /**
00035  * [CLASS/FUNCTION INDEX of SCRIPT]
00036  *
00037  *
00038  *
00039  *   84: class t3lib_syntaxhl
00040  *
00041  *            SECTION: Markup of Data Structure, <T3DataStructure>
00042  *  156:     function highLight_DS($str)
00043  *  183:     function highLight_DS_markUpRecursively($struct,$parent='',$app='')
00044  *
00045  *            SECTION: Markup of Data Structure, <T3FlexForms>
00046  *  268:     function highLight_FF($str)
00047  *  295:     function highLight_FF_markUpRecursively($struct,$parent='',$app='')
00048  *
00049  *            SECTION: Various
00050  *  376:     function getAllTags($str)
00051  *  407:     function splitXMLbyTags($tagList,$str)
00052  *
00053  * TOTAL FUNCTIONS: 6
00054  * (This index is automatically created/updated by the extension "extdeveval")
00055  *
00056  */
00057 
00058 
00059 /**
00060  * Syntax Highlighting class.
00061  *
00062  * @author  Kasper Skårhøj <kasperYYYY@typo3.com>
00063  * @package TYPO3
00064  * @subpackage t3lib
00065  */
00066 class t3lib_syntaxhl {
00067 
00068         // Internal, dynamic:
00069     var $htmlParse; // Parse object.
00070 
00071         // External, static:
00072     var $DS_wrapTags = array(
00073         'T3DataStructure' => array('<span style="font-weight: bold;">', '</span>'),
00074         'type' => array('<span style="font-weight: bold; color: #000080;">', '</span>'),
00075         'section' => array('<span style="font-weight: bold; color: #000080;">', '</span>'),
00076         'el' => array('<span style="font-weight: bold; color: #800000;">', '</span>'),
00077         'meta' => array('<span style="font-weight: bold; color: #800080;">', '</span>'),
00078         '_unknown' => array('<span style="font-style: italic; color: #666666;">', '</span>'),
00079 
00080         '_applicationTag' => array('<span style="font-weight: bold; color: #FF6600;">', '</span>'),
00081         '_applicationContents' => array('<span style="font-style: italic; color: #C29336;">', '</span>'),
00082 
00083         'sheets' => array('<span style="font-weight: bold; color: #008000;">', '</span>'),
00084         'parent:sheets' => array('<span style="color: #008000;">', '</span>'),
00085 
00086         'ROOT' => array('<span style="font-weight: bold; color: #008080;">', '</span>'),
00087         'parent:el' => array('<span style="font-weight: bold; color: #008080;">', '</span>'),
00088 
00089         'langDisable' => array('<span style="color: #000080;">', '</span>'),
00090         'langChildren' => array('<span style="color: #000080;">', '</span>'),
00091     );
00092 
00093     var $FF_wrapTags = array(
00094         'T3FlexForms' => array('<span style="font-weight: bold;">', '</span>'),
00095         'meta' => array('<span style="font-weight: bold; color: #800080;">', '</span>'),
00096         'data' => array('<span style="font-weight: bold; color: #800080;">', '</span>'),
00097         'el' => array('<span style="font-weight: bold; color: #80a000;">', '</span>'),
00098         'itemType' => array('<span style="font-weight: bold; color: #804000;">', '</span>'),
00099         'section' => array('<span style="font-weight: bold; color: #604080;">', '</span>'),
00100         'numIndex' => array('<span style="color: #333333;">', '</span>'),
00101         '_unknown' => array('<span style="font-style: italic; color: #666666;">', '</span>'),
00102 
00103 
00104         'sDEF' => array('<span style="font-weight: bold; color: #008000;">', '</span>'),
00105         'level:sheet' => array('<span style="font-weight: bold; color: #008000;">', '</span>'),
00106 
00107         'lDEF' => array('<span style="font-weight: bold; color: #000080;">', '</span>'),
00108         'level:language' => array('<span style="font-weight: bold; color: #000080;">', '</span>'),
00109 
00110         'level:fieldname' => array('<span style="font-weight: bold; color: #666666;">', '</span>'),
00111 
00112         'vDEF' => array('<span style="font-weight: bold; color: #008080;">', '</span>'),
00113         'level:value' => array('<span style="font-weight: bold; color: #008080;">', '</span>'),
00114 
00115         'currentSheetId' => array('<span style="color: #000080;">', '</span>'),
00116         'currentLangId' => array('<span style="color: #000080;">', '</span>'),
00117     );
00118 
00119 
00120     /*************************************
00121      *
00122      * Markup of Data Structure, <T3DataStructure>
00123      *
00124      *************************************/
00125 
00126     /**
00127      * Makes syntax highlighting of a Data Structure, <T3DataStructure>
00128      *
00129      * @param   string      Data Structure XML, must be valid since it's parsed.
00130      * @return  string      HTML code with highlighted content. Must be wrapped in <PRE> tags
00131      */
00132     function highLight_DS($str) {
00133 
00134             // Parse DS to verify that it is valid:
00135         $DS = t3lib_div::xml2array($str);
00136         if (is_array($DS)) {
00137             $completeTagList = array_unique($this->getAllTags($str)); // Complete list of tags in DS
00138 
00139                 // Highlighting source:
00140             $this->htmlParse = t3lib_div::makeInstance('t3lib_parsehtml'); // Init parser object
00141             $struct = $this->splitXMLbyTags(implode(',', $completeTagList), $str); // Split the XML by the found tags, recursively into LARGE array.
00142             $markUp = $this->highLight_DS_markUpRecursively($struct); // Perform color-markup on the parsed content. Markup preserves the LINE formatting of the XML.
00143 
00144                 // Return content:
00145             return $markUp;
00146         } else {
00147             $error = 'ERROR: The input content failed XML parsing: ' . $DS;
00148         }
00149         return $error;
00150     }
00151 
00152     /**
00153      * Making syntax highlighting of the parsed Data Structure XML.
00154      * Called recursively.
00155      *
00156      * @param   array       The structure, see splitXMLbyTags()
00157      * @param   string      Parent tag.
00158      * @param   string      "Application" - used to denote if we are 'inside' a section
00159      * @return  string      HTML
00160      */
00161     function highLight_DS_markUpRecursively($struct, $parent = '', $app = '') {
00162         $output = '';
00163         foreach ($struct as $k => $v) {
00164             if ($k % 2) {
00165                 $nextApp = $app;
00166                 $wrap = array('', '');
00167 
00168                 switch ($app) {
00169                     case 'TCEforms':
00170                     case 'tx_templavoila':
00171                         $wrap = $this->DS_wrapTags['_applicationContents'];
00172                     break;
00173                     case 'el':
00174                     default:
00175                         if ($parent == 'el') {
00176                             $wrap = $this->DS_wrapTags['parent:el'];
00177                             $nextApp = 'el';
00178                         } elseif ($parent == 'sheets') {
00179                             $wrap = $this->DS_wrapTags['parent:sheets'];
00180                         } else {
00181                             $wrap = $this->DS_wrapTags[$v['tagName']];
00182                             $nextApp = '';
00183                         }
00184 
00185                             // If no wrap defined, us "unknown" definition
00186                         if (!is_array($wrap)) {
00187                             $wrap = $this->DS_wrapTags['_unknown'];
00188                         }
00189 
00190                             // Check for application sections in the XML:
00191                         if ($app == 'el' || $parent == 'ROOT') {
00192                             switch ($v['tagName']) {
00193                                 case 'TCEforms':
00194                                 case 'tx_templavoila':
00195                                     $nextApp = $v['tagName'];
00196                                     $wrap = $this->DS_wrapTags['_applicationTag'];
00197                                 break;
00198                             }
00199                         }
00200                     break;
00201                 }
00202 
00203                 $output .= $wrap[0] . htmlspecialchars($v['tag']) . $wrap[1];
00204                 $output .= $this->highLight_DS_markUpRecursively($v['sub'], $v['tagName'], $nextApp);
00205                 $output .= $wrap[0] . htmlspecialchars('</' . $v['tagName'] . '>') . $wrap[1];
00206             } else {
00207                 $output .= htmlspecialchars($v);
00208             }
00209         }
00210 
00211         return $output;
00212     }
00213 
00214 
00215     /*************************************
00216      *
00217      * Markup of Data Structure, <T3FlexForms>
00218      *
00219      *************************************/
00220 
00221     /**
00222      * Makes syntax highlighting of a FlexForm Data, <T3FlexForms>
00223      *
00224      * @param   string      Data Structure XML, must be valid since it's parsed.
00225      * @return  string      HTML code with highlighted content. Must be wrapped in <PRE> tags
00226      */
00227     function highLight_FF($str) {
00228 
00229             // Parse DS to verify that it is valid:
00230         $DS = t3lib_div::xml2array($str);
00231         if (is_array($DS)) {
00232             $completeTagList = array_unique($this->getAllTags($str)); // Complete list of tags in DS
00233 
00234                 // Highlighting source:
00235             $this->htmlParse = t3lib_div::makeInstance('t3lib_parsehtml'); // Init parser object
00236             $struct = $this->splitXMLbyTags(implode(',', $completeTagList), $str); // Split the XML by the found tags, recursively into LARGE array.
00237             $markUp = $this->highLight_FF_markUpRecursively($struct); // Perform color-markup on the parsed content. Markup preserves the LINE formatting of the XML.
00238 
00239                 // Return content:
00240             return $markUp;
00241         } else {
00242             $error = 'ERROR: The input content failed XML parsing: ' . $DS;
00243         }
00244         return $error;
00245     }
00246 
00247     /**
00248      * Making syntax highlighting of the parsed FlexForm XML.
00249      * Called recursively.
00250      *
00251      * @param   array       The structure, see splitXMLbyTags()
00252      * @param   string      Parent tag.
00253      * @param   string      "Application" - used to denote if we are 'inside' a section
00254      * @return  string      HTML
00255      */
00256     function highLight_FF_markUpRecursively($struct, $parent = '', $app = '') {
00257         $output = '';
00258 
00259             // Setting levels:
00260         if ($parent == 'data') {
00261             $app = 'sheet';
00262         } elseif ($app == 'sheet') {
00263             $app = 'language';
00264         } elseif ($app == 'language') {
00265             $app = 'fieldname';
00266         } elseif ($app == 'fieldname') {
00267             $app = 'value';
00268         } elseif ($app == 'el' || $app == 'numIndex') {
00269             $app = 'fieldname';
00270         }
00271 
00272             // Traverse structure:
00273         foreach ($struct as $k => $v) {
00274             if ($k % 2) {
00275                 $wrap = array('', '');
00276 
00277                 if ($v['tagName'] == 'numIndex') {
00278                     $app = 'numIndex';
00279                 }
00280 
00281                     // Default wrap:
00282                 $wrap = $this->FF_wrapTags[$v['tagName']];
00283 
00284                     // If no wrap defined, us "unknown" definition
00285                 if (!is_array($wrap)) {
00286                     switch ($app) {
00287                         case 'sheet':
00288                         case 'language':
00289                         case 'fieldname':
00290                         case 'value':
00291                             $wrap = $this->FF_wrapTags['level:' . $app];
00292                         break;
00293                         default:
00294                             $wrap = $this->FF_wrapTags['_unknown'];
00295                         break;
00296                     }
00297                 }
00298 
00299                 if ($v['tagName'] == 'el') {
00300                     $app = 'el';
00301                 }
00302 
00303                 $output .= $wrap[0] . htmlspecialchars($v['tag']) . $wrap[1];
00304                 $output .= $this->highLight_FF_markUpRecursively($v['sub'], $v['tagName'], $app);
00305                 $output .= $wrap[0] . htmlspecialchars('</' . $v['tagName'] . '>') . $wrap[1];
00306             } else {
00307                 $output .= htmlspecialchars($v);
00308             }
00309         }
00310 
00311         return $output;
00312     }
00313 
00314 
00315     /*************************************
00316      *
00317      * Various
00318      *
00319      *************************************/
00320 
00321     /**
00322      * Returning all tag names found in XML/HTML input string
00323      *
00324      * @param   string      HTML/XML input
00325      * @return  array       Array with all found tags (starttags only)
00326      */
00327     function getAllTags($str) {
00328 
00329             // Init:
00330         $tags = array();
00331         $token = md5(microtime());
00332 
00333             // Markup all tag names with token.
00334         $markUpStr = preg_replace('/<([[:alnum:]_]+)[^>]*>/', $token . '${1}' . $token, $str);
00335 
00336             // Splitting by token:
00337         $parts = explode($token, $markUpStr);
00338 
00339             // Traversing parts:
00340         foreach ($parts as $k => $v) {
00341             if ($k % 2) {
00342                 $tags[] = $v;
00343             }
00344         }
00345 
00346             // Returning tags:
00347         return $tags;
00348     }
00349 
00350     /**
00351      * Splitting the input source by the tags listing in $tagList.
00352      * Called recursively.
00353      *
00354      * @param   string      Commalist of tags to split source by (into blocks, ALL being block-tags!)
00355      * @param   string      Input string.
00356      * @return  array       Array with the content arranged hierarchically.
00357      */
00358     function splitXMLbyTags($tagList, $str) {
00359         $struct = $this->htmlParse->splitIntoBlock($tagList, $str);
00360 
00361             // Traverse level:
00362         foreach ($struct as $k => $v) {
00363             if ($k % 2) {
00364                 $tag = $this->htmlParse->getFirstTag($v);
00365                 $tagName = $this->htmlParse->getFirstTagName($tag, TRUE);
00366                 $struct[$k] = array(
00367                     'tag' => $tag,
00368                     'tagName' => $tagName,
00369                     'sub' => $this->splitXMLbyTags($tagList, $this->htmlParse->removeFirstAndLastTag($struct[$k]))
00370                 );
00371             }
00372         }
00373 
00374         return $struct;
00375     }
00376 }
00377 
00378 
00379 if (defined('TYPO3_MODE') && isset($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['t3lib/class.t3lib_syntaxhl.php'])) {
00380     include_once($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['t3lib/class.t3lib_syntaxhl.php']);
00381 }
00382 
00383 ?>