liberty
[ class tree: liberty ] [ index: liberty ] [ all elements ]

Source for file format.tikiwiki.php

Documentation is available at format.tikiwiki.php

  1. <?php
  2. /**
  3.  * @version  $Revision$
  4.  * @package  liberty
  5.  * @subpackage plugins_format
  6.  */
  7. global $gLibertySystem;
  8.  
  9. /**
  10.  * definitions
  11.  */
  12. define( 'PLUGIN_GUID_TIKIWIKI', 'tikiwiki' );
  13.  
  14. $pluginParams = array (
  15.     'auto_activate'    => TRUE,
  16.     'store_function'   => 'tikiwiki_save_data',
  17.     'load_function'    => 'tikiwiki_parse_data',
  18.     'verify_function'  => 'tikiwiki_verify_data',
  19.     'description'      => 'TikiWiki Syntax Format Parser',
  20.     'edit_label'       => 'Tiki Wiki Syntax',
  21.     'edit_field'       => PLUGIN_GUID_TIKIWIKI,
  22.     'help_page'        => 'TikiWikiSyntax',
  23.     'plugin_type'      => FORMAT_PLUGIN,
  24.     'linebreak'        => "\r\n"
  25. );
  26.  
  27. $gLibertySystem->registerPlugin( PLUGIN_GUID_TIKIWIKI, $pluginParams );
  28.  
  29. /**
  30.  * tikiwiki_save_data
  31.  */
  32. function tikiwiki_save_data( &$pParamHash ) {
  33.     static $parser;
  34.     if( empty( $parser ) ) {
  35.         $parser = new TikiWikiParser();
  36.     }
  37. }
  38.  
  39. function tikiwiki_verify_data( &$pParamHash ) {
  40.     $errorMsg = NULL;
  41.     $pParamHash['content_store']['data'] = $pParamHash['edit'];
  42.     return( $errorMsg );
  43. }
  44.  
  45. function tikiwiki_parse_data( &$pParseHash, &$pCommonObject ) {
  46.     global $gBitSystem;
  47.     $ret = '';
  48.  
  49.     static $parser;
  50.     if( empty( $parser ) ) {
  51.         $parser = new TikiWikiParser();
  52.     }
  53.     $ret = $parser->parseData( $pParseHash, $pCommonObject );
  54.  
  55.     return $ret;
  56. }
  57.  
  58. /**
  59.  * TikiWikiParser
  60.  *
  61.  * @package kernel
  62.  */
  63. class TikiWikiParser extends BitBase {
  64.     function TikiWikiParser() {
  65.         parent::__construct();
  66.     }
  67.  
  68.     // This function handles wiki codes for those special HTML characters
  69.     // that textarea won't leave alone.
  70.     function parseHtmlchar( &$pData ) {
  71.         // cleaning some user input
  72.         $pData = preg_replace( "/&(?!([a-z]{1,7};))/", "&amp;", $pData );
  73.  
  74.         // oft-used characters (case insensitive)
  75.         $patterns = array(
  76.             "~bull~" => "&bull;",
  77.             "~bs~"   => "&#92;",
  78.             "~hs~"   => "&nbsp;",
  79.             "~amp~"  => "&amp;",
  80.             "~ldq~"  => "&ldquo;",
  81.             "~rdq~"  => "&rdquo;",
  82.             "~lsq~"  => "&lsquo;",
  83.             "~rsq~"  => "&rsquo;",
  84.             "~copy~" => "&copy;",
  85.             "~c~"    => "&copy;",
  86.             "~--~"   => "&mdash;",
  87.             " -- "   => " &mdash; ",
  88.             "~lt~"   => "&lt;",
  89.             "~gt~"   => "&gt;",
  90.             "~euro~" => "&euro;",
  91.         );
  92.  
  93.         include_once( UTIL_PKG_PATH."PHP_Compat/Compat/Function/str_ireplace.php" );
  94.         foreach( $patterns as $pattern => $replace ) {
  95.             $pData = str_ireplace( $pattern, $replace, $pData );
  96.         }
  97.  
  98.         // add an easy method to clear floats
  99.         $pData = preg_replace( "/(\r|\n)?~clear~/i", '<br style="clear:both;" />', $pData );
  100.  
  101.         // HTML numeric character entities
  102.         $pData = preg_replace( "/~([0-9]+)~/", "&#$1;", $pData );
  103.     }
  104.  
  105.     function getLinks( $pData ) {
  106.         $links = array();
  107.  
  108.         // Match things like [...], but ignore things like [[foo].
  109.         // -Robin
  110.         if( preg_match_all( "/(?<!\[)\[([^\[\|\]]+)(\||\])/", $pData, $r1 )) {
  111.             $links = array_unique( $r1[1] );
  112.         }
  113.  
  114.         return $links;
  115.     }
  116.  
  117.     function howManyAtStart($str, $car) {
  118.         $cant = 0;
  119.         $i = 0;
  120.         while (($i < strlen($str)) && (isset($str{$i})) && ($str{$i}== $car)) {
  121.             $i++;
  122.             $cant++;
  123.         }
  124.         return $cant;
  125.     }
  126.  
  127.     function parseMediawikiTables( $pData ) {
  128.         // Find all matches to {|...|} with no {| inside.
  129.         while( preg_match( '/\n?\{\|(.*?)\n\|\}/sm', $pData, $matches )) {
  130.             $table_data = str_replace( "\r", "", $matches[1] );
  131.             $table_data = str_replace( '||', "\n|", $table_data );
  132.  
  133.             // get all instances where put in info like: background=blue and convert it to background="blue"
  134.             $xhtmlfix['pattern'] = "!=([^'\"][^\s]*)!";
  135.             $xhtmlfix['replace'] = '="$1"';
  136.  
  137.             while( preg_match('/^![^!]+!!/m', $table_data )) {
  138.                 /* Replace !! with \n! but ONLY in !-defined header rows. */
  139.                 $table_data = preg_replace( '/^!([^!]+)!!/m', "!$1\n!", $table_data );
  140.             }
  141.  
  142.             if( substr( $table_data, 0, 1 ) != "\n" ) {
  143.                 // We have table parameters.
  144.                 list( $table_params, $table_data ) = explode( "\n", $table_data, 2 );
  145.                 $table_params = preg_replace( $xhtmlfix['pattern'], $xhtmlfix['replace'], trim( $table_params ));
  146.                 /* TODO: This attempt to support foo:bar table params needs help!
  147.                 if (strlen($table_params)) {
  148.                     $table_params = preg_replace("/\b(\w+):/", '$1=', $table_params);
  149.                 }
  150.                 */
  151.             } else {
  152.                 $table_params = '';
  153.             }
  154.  
  155.             // apply default class if no other class has been set
  156.             if( !empty( $table_params ) && strpos( 'class=', $table_params ) !== FALSE ) {
  157.                 $table_params .= ' class="table"';
  158.             }
  159.             $content = "<table $table_params>";
  160.  
  161.             $lines = explode( "\n", str_replace( "\\n", "<br />", $table_data ));
  162.             $row = 0;
  163.             foreach( $lines as $line ) {
  164.                 if(( substr( $line, 0, 1 ) == '|' ) || ( substr( $line, 0, 1 ) == '!' )) {
  165.                     if( preg_match( '/^\|\+\s*(.+)$/', $line, $row_matches )) {
  166.                         $content .= "<caption>$row_matches[1]</caption>";
  167.                     } elseif( preg_match( '/^\|-\s*(.+)?$/', $line, $row_matches )) {
  168.                         if( $row ) {
  169.                             $content .= '</tr>';
  170.                             $row++;
  171.                         } else {
  172.                             $row = 1;
  173.                         }
  174.  
  175.                         if( !empty( $row_matches[1] )) {
  176.                             $row_matches[1] = preg_replace( $xhtmlfix['pattern'], $xhtmlfix['replace'], trim( $row_matches[1] ));
  177.                             $content .= "<tr {$row_matches[1]}>";
  178.                         } else {
  179.                             $content .= '<tr>';
  180.                         }
  181.                     } elseif( preg_match( '/^([\|!])\s*([^\|]+\s*\|)?\s*(.*)$/', $line, $row_matches )) {
  182.                         if( !$row ) {
  183.                             $content .= '<tr>';
  184.                             $row = 1;
  185.                         }
  186.  
  187.                         if( !empty( $row_matches[2] )) {
  188.                             $row_matches[2] = preg_replace( $xhtmlfix['pattern'], $xhtmlfix['replace'], trim( $row_matches[2] ));
  189.                         }
  190.  
  191.                         $td       = 't'.(( $row_matches[1] == '!' ) ? 'h' : 'd' );
  192.                         $content .= "<$td".(( !empty( $row_matches[2] )) ? ' '.trim( substr( $row_matches[2], 0, -1 )) : '' ).'>'.$row_matches[3]."</$td>";
  193.                     } else {
  194.                         $content .= "<!-- ERROR:  Ignoring invalid line \"$line\" -->";
  195.                     }
  196.                 } else {
  197.                     $content .= "<!-- ERROR:  Ignoring invalid line \"$line\" -->";
  198.                 }
  199.             }
  200.             $content .= '</tr></table>';
  201.             $pData = str_replace( $matches[0], $content, $pData );
  202.         }
  203.         return $pData;
  204.     }
  205.  
  206.     function parseData( $pParseHash, &$pCommonObject ) {
  207.         global $gBitSystem, $gLibertySystem, $gBitUser, $page;
  208.  
  209.         $data      = $pParseHash['data'];
  210.         $contentId = $pParseHash['content_id'];
  211.  
  212.         // this is used for setting the links when section editing is enabled
  213.         $section_count = 1;
  214.  
  215.         if( $gBitSystem->isPackageActive( 'wiki' ) ) {
  216.             require_once( WIKI_PKG_PATH.'BitPage.php' );
  217.         }
  218.  
  219.         // if the object isn't loaded, we'll try and get the content prefs manually
  220.         if( !empty( $pCommonObject->mPrefs ) ) {
  221.             $contentPrefs = $pCommonObject->mPrefs;
  222.         } elseif( empty( $pCommonObject->mContentId ) && !empty( $contentId ) ) {
  223.             $contentPrefs = $pCommonObject->loadPreferences( $contentId );
  224.         }
  225.  
  226.         // only strip out html if needed
  227.         if( $gBitSystem->isFeatureActive( 'content_allow_html' ) || $gBitSystem->isFeatureActive( 'content_force_allow_html' )) {
  228.             // we allow html unconditionally with this parser
  229.         } elseif( !empty( $contentPrefs['content_enter_html'] )) {
  230.             // we allow html on a per page basis
  231.         } else {
  232.             // we are parsing this page and we either have no way of checking permissions or we have no need for html
  233.             $data = htmlspecialchars( $data, ENT_NOQUOTES, 'UTF-8' );
  234.         }
  235.  
  236.         // Extract [link] sections (to be re-inserted later)
  237.         $noparsedlinks = array();
  238.  
  239.         // This section matches [...].
  240.         // Added handling for [[foo] sections.  -rlpowell
  241.         preg_match_all("/(?<!\[)\[([^\[][^\]]+)\]/", $data, $noparseurl);
  242.  
  243.         foreach (array_unique($noparseurl[1])as $np) {
  244.             $key = md5(BitSystem::genPass());
  245.  
  246.             $aux["key"] = $key;
  247.             $aux["data"] = $np;
  248.             $noparsedlinks[] = $aux;
  249.             $data = str_replace("$np", $key, $data);
  250.         }
  251.  
  252.         // Replace special characters
  253.         //done after url catching because otherwise urls of dyn. sites will be modified
  254.         $this->parseHtmlchar( $data );
  255.  
  256.         //$data = strip_tags($data);
  257.         // BiDi markers
  258.         $bidiCount = 0;
  259.         $bidiCount = preg_match_all("/(\{l2r\})/", $data, $pages);
  260.         $bidiCount += preg_match_all("/(\{r2l\})/", $data, $pages);
  261.  
  262.         $data = preg_replace("/\{l2r\}/", "<div dir='ltr'>", $data);
  263.         $data = preg_replace("/\{r2l\}/", "<div dir='rtl'>", $data);
  264.         $data = preg_replace("/\{lm\}/", "&lrm;", $data);
  265.         $data = preg_replace("/\{rm\}/", "&rlm;", $data);
  266.  
  267.         // Parse MediaWiki-style pipe syntax tables.
  268.         if(( strpos( $data, "{|" ) === 0 || strpos( $data, "\n{|" ) !== FALSE ) && strpos( $data, "\n|}" ) !== FALSE ) {
  269.             $data = $this->parseMediawikiTables($data);
  270.         }
  271.  
  272.         // ============================================= this should go - xing
  273.         // Replace dynamic variables
  274.         // Dynamic variables are similar to dynamic content but they are editable
  275.         // from the page directly, intended for short data, not long text but text
  276.         // will work too
  277.         //     Now won't match HTML-style '%nn' letter codes.
  278. /*
  279.         if (preg_match_all("/%([^% 0-9][^% 0-9][^% ]*)%/",$data,$dvars)) {
  280.             // remove repeated elements
  281.             $dvars = array_unique($dvars[1]);
  282.             // Now replace each dynamic variable by a pair composed of the
  283.             // variable value and a text field to edit the variable. Each
  284.             foreach($dvars as $dvar) {
  285.                 $query = "select `data` from `".BIT_DB_PREFIX."liberty_dynamic_variables` where `name`=?";
  286.                 $result = $this->mDb->query($query,Array($dvar));
  287.                 if($result->numRows()) {
  288.                     $value = $result->fetchRow();
  289.                     $value = $value["data"];
  290.                 } else {
  291.                     //Default value is NULL
  292.                     $value = "NaV";
  293.                 }
  294.                 // Now build 2 divs
  295.                 $id = 'dyn_'.$dvar;
  296.  
  297.                 if( $gBitUser->hasPermission( 'p_wiki_edit_dynvar' ) ) {
  298.                     $span1 = "<span  style='display:inline;' id='dyn_".$dvar."_display'><a class='dynavar' onclick='javascript:toggle_dynamic_var(\"$dvar\");' title='".tra('Click to edit dynamic variable').": $dvar'>$value</a></span>";
  299.                     $span2 = "<span style='display:none;' id='dyn_".$dvar."_edit'><input type='text' name='dyn_".$dvar."' value='".$value."' /></span>";
  300.                 } else {
  301.                     $span1 = "<span class='dynavar' style='display:inline;' id='dyn_".$dvar."_display'>$value</span>";
  302.                     $span2 = '';
  303.                 }
  304.                 $html = $span1.$span2;
  305.                 //It's important to replace only once
  306.                 $dvar_preg = preg_quote( $dvar );
  307.                 $data = preg_replace("+%$dvar_preg%+",$html,$data,1);
  308.                 //Further replacements only with the value
  309.                 $data = str_replace("%$dvar%",$value,$data);
  310.  
  311.             }
  312.             //At the end put an update button
  313.             //<br /><div style="text-align:center"><input type="submit" name="dyn_update" value="'.tra('Update variables').'"/></div>
  314.             $data='<form method="post" name="dyn_vars">'.$data.'<div style="display:none;"><input type="submit" name="_dyn_update" value="'.tra('Update variables').'"/></div></form>';
  315.         }
  316. */
  317.  
  318.         // Replace boxes - add a new line that we can have something like: ^!heading^ without the need for a \n after the initial ^ - \n will be removed below
  319.         $data = preg_replace("/\^([^\^]+)\^/", "<div class=\"alert alert-info bitbox\"><!-- bitremovebr -->\n$1</div>", $data);
  320.         // Replace colors ~~color:text~~
  321.         $data = preg_replace("/\~\~([^\:]+):([^\~]+)\~\~/", "<span style=\"color:$1;\">$2</span>", $data);
  322.         // Replace background colors ++color:text++
  323.         $data = preg_replace("/\+\+([^\s][^\: ]+):([^\+]+)\+\+/", "<span style=\"background:$1;\">$2</span>", $data);
  324.         // Underlined text
  325.         $data = preg_replace("/===([^\=]+)===/", "<span style=\"text-decoration:underline;\">$1</span>", $data);
  326.         // Center text
  327.         $data = preg_replace("/::(.+?)::/", "<div style=\"text-align:center;\">$1</div>", $data);
  328.         // Line breaks
  329.         $data = preg_replace('/%%%/', '<br />', $data);
  330.  
  331.         // reinsert hash-replaced links into page
  332.         foreach ($noparsedlinks as $np) {
  333.             $data = str_replace($np["key"], $np["data"], $data);
  334.         }
  335.  
  336.         $links = $this->getLinks( $data );
  337.  
  338.         // Note that there're links that are replaced
  339.         foreach( $links as $link ) {
  340.             if(( strstr( $link, $_SERVER["SERVER_NAME"] )) || ( !strstr( $link, '//' ))) {
  341.                 $attributes = '';
  342.             } else {
  343.                 $attributes = 'class="external"';
  344.             }
  345.  
  346.             // comments and anonymously created pages get nofollow
  347.             if( $pCommonObject && ( get_class( $pCommonObject ) == 'comments' || ( isset( $pCommonObject->mInfo['user_id'] ) &&  $pCommonObject->mInfo['user_id'] == ANONYMOUS_USER_ID ))) {
  348.                 $attributes .= ' rel="nofollow" ';
  349.             }
  350.  
  351.             // The (?<!\[) stuff below is to give users an easy way to
  352.             // enter square brackets in their output; things like [[foo]
  353.             // get rendered as [foo]. -rlpowell
  354.  
  355.             // prepare link for pattern usage
  356.             $link2 = str_replace( "/", "\/", preg_quote( $link ));
  357.             $pattern = "/(?<!\[)\[$link2\|([^\]\|]+)([^\]])*\]/";
  358.             $data = preg_replace( $pattern, "<a $attributes href='$link'>$1</a>", $data );
  359.             $pattern = "/(?<!\[)\[$link2\]/";
  360.             $data = preg_replace( $pattern, "<a $attributes href='$link'>$link</a>", $data );
  361.         }
  362.  
  363.         // Handle double square brackets.  -rlpowell
  364.         $data = str_replace( "[[", "[", $data );
  365.  
  366.         // now that all links have been taken care of, we can replace all email addresses with the encoded form
  367.         // this will also encode email addressed that have not been linked using []
  368.         $data = encode_email_addresses( $data );
  369.  
  370.         if ($gBitSystem->getConfig('wiki_tables') != 'new') {
  371.             // New syntax for tables
  372.             if (preg_match_all("/\|\|(.*)\|\|/", $data, $tables)) {
  373.                 $maxcols = 1;
  374.  
  375.                 $cols = array();
  376.  
  377.                 for ($i = 0; $i < count($tables[0]); $i++) {
  378.                     $rows = explode('||', $tables[0][$i]);
  379.  
  380.                     $col[$i] = array();
  381.  
  382.                     for ($j = 0; $j < count($rows); $j++) {
  383.                         $cols[$i][$j] = explode('|', $rows[$j]);
  384.  
  385.                         if (count($cols[$i][$j]) > $maxcols)
  386.                             $maxcols = count($cols[$i][$j]);
  387.                     }
  388.                 }
  389.  
  390.                 for ($i = 0; $i < count($tables[0]); $i++) {
  391.                     $repl = '<table class="table">';
  392.  
  393.                     for ($j = 0; $j < count($cols[$i]); $j++) {
  394.                         $ncols = count($cols[$i][$j]);
  395.  
  396.                         if ($ncols == 1 && !$cols[$i][$j][0])
  397.                             continue;
  398.  
  399.                         $repl .= '<tr class="'.( ( $j % 2 ) ? 'even' : 'odd' ).'">';
  400.  
  401.                         for ($k = 0; $k < $ncols; $k++) {
  402.                             $repl .= '<td ';
  403.  
  404.                             if ($k == $ncols - 1 && $ncols < $maxcols)
  405.                                 $repl .= ' colspan="' . ($maxcols - $k).'"';
  406.  
  407.                             $repl .= '>' . $cols[$i][$j][$k] . '</td>';
  408.                         }
  409.  
  410.                         $repl .= '</tr>';
  411.                     }
  412.  
  413.                     $repl .= '</table>';
  414.                     $data = str_replace($tables[0][$i], $repl, $data);
  415.                 }
  416.             }
  417.         } else {
  418.             // New syntax for tables
  419.             // REWRITE THIS CODE
  420.             if( preg_match_all( "/\|\|(.*?)\|\|/s", $data, $tables ) ) {
  421.                 $maxcols = 1;
  422.  
  423.                 $cols = array();
  424.  
  425.                 for( $i = 0; $i < count( $tables[0] ); $i++ ) {
  426.                     $rows = preg_split( "/(\n|\<br\/\>)/", $tables[0][$i] );
  427.                     $col[$i] = array();
  428.  
  429.                     for( $j = 0; $j < count( $rows ); $j++ ) {
  430.                         $rows[$j]     = str_replace( '||', '', $rows[$j] );
  431.                         $cols[$i][$j] = explode( '|', $rows[$j] );
  432.                         if( count( $cols[$i][$j] ) > $maxcols ) {
  433.                             $maxcols = count( $cols[$i][$j] );
  434.                         }
  435.                     }
  436.                 }
  437.  
  438.                 for( $i = 0; $i < count( $tables[0] ); $i++ ) {
  439.                     $repl = '<table class="table table-striped">';
  440.  
  441.                     if( preg_match( "#^~#", $cols[$i][0][0] ) && $cols[$i][0][0] = preg_replace( "#^~#", "", $cols[$i][0][0] ) ) {
  442.                         $th = TRUE;
  443.                     } else {
  444.                         $th = FALSE;
  445.                     }
  446.  
  447.                     for( $j = 0; $j < count( $cols[$i] ); $j++ ) {
  448.                         $ncols = count( $cols[$i][$j] );
  449.  
  450.                         if( $ncols == 1 && !$cols[$i][$j][0] ) {
  451.                             continue;
  452.                         }
  453.  
  454.                         if( $j == 0 && $th ) {
  455.                             $repl .= '<tr>';
  456.                         } else {
  457.                             $repl .= '<tr class="'.( ( $j % 2 ) ? 'odd' : 'even' ).'">';
  458.                         }
  459.  
  460.                         for( $k = 0; $k < $ncols; $k++ ) {
  461.                             $thd = ( ( $j == 0 && $th ) ? 'th' : 'td' );
  462.                             $repl .= "<$thd";
  463.  
  464.                             if( $k == $ncols - 1 && $ncols < $maxcols ) {
  465.                                 $repl .= ' colspan="'.( $maxcols - $k ).'"';
  466.                             }
  467.  
  468.                             $repl .= ">".( str_replace( "\\n", "<br />", $cols[$i][$j][$k] ) )."</$thd>";
  469.                         }
  470.  
  471.                         $repl .= '</tr>';
  472.                     }
  473.  
  474.                     $repl .= '</table>';
  475.                     $data = str_replace($tables[0][$i], $repl, $data);
  476.                 }
  477.             }
  478.         }
  479.  
  480.         // Now tokenize the expression and process the tokens
  481.         // Use tab and newline as tokenizing characters as well  ////
  482.         $lines = explode("\n", $data);
  483.         $data = '';
  484.         $listbeg = array();
  485.         $divdepth = array();
  486.         $inTable = 0;
  487.  
  488.         // loop: process all lines
  489.         foreach ($lines as $line) {
  490.  
  491.             // bitweaver now ignores leading space because it is *VERY* disturbing to unaware users - spiderr
  492.             // unless 'feature_wiki_preserve_leading_blanks is set'.  This is used for sites that have
  493.             // migrated from TikiWiki and have lots of pages whose formatting depends on the presevation of leading spaces
  494.             if (!$gBitSystem->isFeatureActive('wiki_preserve_leading_blanks')) {
  495.                 $line = trim( $line );
  496.             }
  497.  
  498.             // check if we are inside a table, if so, ignore monospaced and do
  499.             // not insert <br/>
  500.             $inTable += substr_count($line, "<table");
  501.             $inTable -= substr_count($line, "</table");
  502.  
  503.             // If the first character is ' ' and we are not in pre then we are in pre
  504.             // bitweaver now ignores leading space because it is *VERY* disturbing to unaware users - spiderr
  505.             if (substr($line, 0, 1) == ' ' && $gBitSystem->isFeatureActive('wiki_monosp') && $inTable == 0) {
  506.                 // This is not list item -- must close lists currently opened
  507.                 while (count($listbeg))
  508.                 $data .= array_shift($listbeg);
  509.  
  510.                 // If the first character is space then
  511.                 // change spaces for &nbsp;
  512.                 $line = '<span style="font-family:monospace;">' . str_replace(' ', '&nbsp;', substr($line, 1)). '</span>';
  513.             }
  514.  
  515.             // Title bars
  516.             $line = preg_replace( "/\-\=([^=]+)\=\-/", "<div class='bitbar'>$1</div><!-- bitremovebr -->", $line );
  517.             // Monospaced text
  518.             $line = preg_replace( "/-\+(.*?)\+-/", "<code>$1</code>", $line );
  519.             // Bold text
  520.             $line = preg_replace( "/__(.*?)__/", "<strong>$1</strong>", $line );
  521.             // Italics
  522.             $line = preg_replace( "/''(.*?)''/", "<em>$1</em>", $line );
  523.             // Definition lists
  524.             $line = preg_replace( "/^;([^:]+):(.+)/", "<dl><dt>$1</dt><dd>$2</dd></dl><!-- bitremovebr -->", $line );
  525.  
  526.             // This line is parseable then we have to see what we have
  527.             if (substr($line, 0, 3) == '---') {
  528.                 // This is not list item -- must close lists currently opened
  529.                 while (count($listbeg))
  530.                     $data .= array_shift($listbeg);
  531.  
  532.                 $line = '<hr/>';
  533.             } else {
  534.                 $litype = substr($line, 0, 1);
  535.  
  536.                 if ($litype == '*' || $litype == '#') {
  537.                     $listlevel = $this->howManyAtStart($line, $litype);
  538.  
  539.                     $liclose = '</li>';
  540.                     $addremove = 0;
  541.  
  542.                     if ($listlevel < count($listbeg)) {
  543.                         while ($listlevel != count($listbeg))
  544.                             $data .= array_shift($listbeg);
  545.  
  546.                         if (substr(current($listbeg), 0, 5) != '</li>')
  547.                             $liclose = '';
  548.                     } elseif ($listlevel > count($listbeg)) {
  549.                         $listyle = '';
  550.  
  551.                         while ($listlevel != count($listbeg)) {
  552.                             array_unshift($listbeg, ($litype == '*' ? '</ul>' : '</ol>'));
  553.  
  554.                             if ($listlevel == count($listbeg)) {
  555.                                 $listate = substr($line, $listlevel, 1);
  556.  
  557.                                 if (($listate == '+' || $listate == '-') && !($litype == '*' && !strstr(current($listbeg), '</ul>') || $litype == '#' && !strstr(current($listbeg), '</ol>'))) {
  558.                                     $thisid = 'id' . microtime() * 1000000;
  559.  
  560.                                     $data .= '<br /><a id="flipper' . $thisid . '" href="javascript:flipWithSign(\'' . $thisid . '\',1)">[' . ($listate == '-' ? '+' : '-') . ']</a>';
  561.                                     $listyle = ' id="' . $thisid . '" style="display:' . ($listate == '+' ? 'block' : 'none') . ';"';
  562.                                     $addremove = 1;
  563.                                 }
  564.                             }
  565.  
  566.                             $data .= ($litype == '*' ? "<ul$listyle>" : "<ol$listyle>");
  567.                         }
  568.  
  569.                         $liclose = '';
  570.                     }
  571.  
  572.                     if ($litype == '*' && !strstr(current($listbeg), '</ul>') || $litype == '#' && !strstr(current($listbeg), '</ol>')) {
  573.                         $data .= array_shift($listbeg);
  574.  
  575.                         $listyle = '';
  576.                         $listate = substr($line, $listlevel, 1);
  577.  
  578.                         if (($listate == '+' || $listate == '-')) {
  579.                             $thisid = 'id' . microtime() * 1000000;
  580.  
  581.                             $data .= '<br /><a id="flipper' . $thisid . '" href="javascript:flipWithSign(\'' . $thisid . '\',1)">[' . ($listate == '-' ? '+' : '-') . ']</a>';
  582.                             $listyle = ' id="' . $thisid . '" style="display:' . ($listate == '+' ? 'block' : 'none') . ';"';
  583.                             $addremove = 1;
  584.                         }
  585.  
  586.                         $data .= ($litype == '*' ? "<ul$listyle>" : "<ol$listyle>");
  587.                         $liclose = '';
  588.                         array_unshift($listbeg, ($litype == '*' ? '</li></ul>' : '</li></ol>'));
  589.                     }
  590.  
  591.                     $line = $liclose . '<li>' . substr($line, $listlevel + $addremove);
  592.  
  593.                     if (substr(current($listbeg), 0, 5) != '</li>')
  594.                         array_unshift($listbeg, '</li>' . array_shift($listbeg));
  595.                 } elseif ($litype == '+') {
  596.                     // Must append paragraph for list item of given depth...
  597.                     $listlevel = $this->howManyAtStart($line, $litype);
  598.  
  599.                     // Close lists down to requested level
  600.                     while ($listlevel < count($listbeg))
  601.                         $data .= array_shift($listbeg);
  602.  
  603.                     if (count($listbeg)) {
  604.                         if (substr(current($listbeg), 0, 5) != '</li>') {
  605.                             array_unshift($listbeg, '</li>' . array_shift($listbeg));
  606.  
  607.                             $liclose = '<li>';
  608.                         } else
  609.                             $liclose = '<br />';
  610.                     } else
  611.                         $liclose = '';
  612.  
  613.                     $line = $liclose . substr($line, count($listbeg));
  614.                 } else {
  615.                     // This is not list item -- must close lists currently opened
  616.                     while (count($listbeg))
  617.                         $data .= array_shift($listbeg);
  618.  
  619.                     // Get count of (possible) header signs at start
  620.                     $hdrlevel = $this->howManyAtStart($line, '!');
  621.  
  622.                     // If 1st char on line is '!' and its count less than 6 (max in HTML)
  623.                     if ($litype == '!' && $hdrlevel > 0 && $hdrlevel <= 6) {
  624.                         // OK. Parse headers here...
  625.                         $aclose = '';
  626.                         $edit_link = '';
  627.                         $addremove = 0;
  628.  
  629.                         // Close lower level divs if opened
  630.                         for (;current($divdepth) >= $hdrlevel; array_shift($divdepth)) {
  631.                             $data .= '</div>';
  632.                         }
  633.  
  634.                         // May be spesial signs present after '!'s?
  635.                         $divstate = substr($line, $hdrlevel, 1);
  636.  
  637.                         if ($divstate == '+' || $divstate == '-') {
  638.                             // OK. Must insert flipper after HEADER, and then open new div...
  639.                             $thisid = 'id' . microtime() * 1000000;
  640.  
  641.                             $aclose = '<a id="flipper' . $thisid . '" href="javascript:flipWithSign(\'' . $thisid . '\',1)">[' . ($divstate == '-' ? '+' : '-') . ']</a>';
  642.                             $aclose .= '<div id="' . $thisid . '" style="display:' . ($divstate == '+' ? 'block' : 'none') . ';">';
  643.                             array_unshift($divdepth, $hdrlevel);
  644.                             $addremove = 1;
  645.                         }
  646.  
  647.                         if( $gBitSystem->isFeatureActive( 'wiki_section_edit' ) && $gBitUser->hasPermission( 'p_wiki_update_page' ) ) {
  648.                             if( $hdrlevel == $gBitSystem->getConfig( 'wiki_section_edit' ) ) {
  649.                                 $edit_url = WIKI_PKG_URL."edit.php?content_id=".$contentId."&amp;section=".$section_count++;
  650.                                 $edit_link = '<span class="editsection" style="float:right;margin-left:5px;">[<a href="'.$edit_url.'">'.tra( "edit" ).'</a>]</span>';
  651.                             }
  652.                         }
  653.                         $hTagLevel = $hdrlevel + 1; // there should only be 1 <h1> per html document
  654.                         $line = $edit_link
  655.                             . "<h$hTagLevel>"
  656.                             . substr($line, $hdrlevel + $addremove)
  657.                             . "</h$hTagLevel>"
  658.                             . $aclose
  659.                             ;
  660.                     } elseif (!strcmp($line, "...page...")) {
  661.                         // Close lists and divs currently opened
  662.                         while (count($listbeg)) {
  663.                             $data .= array_shift($listbeg);
  664.                         }
  665.  
  666.                         while (count($divdepth)) {
  667.                             $data .= '</div>';
  668.                             array_shift ($divdepth);
  669.                         }
  670.  
  671.                         // Leave line unchanged... index.php will split wiki here
  672.                         $line = "...page...";
  673.                     } else {
  674.                         // Usual paragraph.
  675.                         if ($inTable == 0) {
  676.                             $line .= '<br />';
  677.                         }
  678.                     }
  679.                 }
  680.             }
  681.  
  682.             $data .= $line;
  683.         }
  684.  
  685.         // Close lists may remains opened
  686.         while (count($listbeg)) {
  687.             $data .= array_shift($listbeg);
  688.         }
  689.  
  690.         // Close header divs may remains opened
  691.         for ($i = 1; $i <= count($divdepth); $i++) {
  692.             $data .= '</div>';
  693.         }
  694.  
  695.         // Close BiDi DIVs if any
  696.         for ($i = 0; $i < $bidiCount; $i++) {
  697.             $data .= "</div>";
  698.         }
  699.  
  700.         $data = str_replace( "<!-- bitremovebr --><br />", "", $data );
  701.  
  702.         return $data;
  703.     }
  704. }
  705.  
  706. ?>

Documentation generated on Wed, 29 Jul 2015 13:56:36 +0000 by phpDocumentor 1.5.0-lsces