function backtotop_postparsefilter(&$pData, &$pFilterHash) { global $gBitSmarty; if (preg_match("/\\{(backtotop[^\\}]*)\\}/i", $pData, $backtotop)) { // remove {backtotop} from page $pData = preg_replace('#(<p>)?' . preg_quote($backtotop[0], '#') . '(</p>)?(\\s*<[Bb][Rr]\\s*/?>)?#', '', $pData); // default values $params['min'] = 1; $params['max'] = 6; $params = array_merge($params, parse_xml_attributes($backtotop[1])); $gBitSmarty->loadPlugin('smarty_function_biticon'); $biticon = array('ipackage' => 'icons', 'iname' => 'go-top', 'iexplain' => 'Back to top'); // get all headers into an array preg_match_all("/<h(\\d[^>]*)>.*?<\\/h\\d>/i", $pData, $headers); $link = '<a class="backtotop" href="#content">' . smarty_function_biticon($biticon, $gBitSmarty) . '</a>'; foreach ($headers[0] as $key => $header) { if ($headers[1][$key] >= $params['min'] && $headers[1][$key] <= $params['max']) { $pData = str_replace($header, $link . $header, $pData); } } $pData .= $link; } }
/** * This crazy function will parse all the data plugin stuff found within any * parsed text section * * @param array $pData Data to be parsed * @access public * @return void */ function parse_data_plugins(&$pData, &$pReplace, &$pCommonObject, $pParseHash) { global $gLibertySystem, $gBitSystem; // note: $curlyTags[0] is the complete match, $curlyTags[1] is plugin name, $curlyTags[2] is plugin arguments preg_match_all("/\\{\\/?([A-Za-z0-9]+)([^\\}]*)\\}/", $pData, $curlyTags, PREG_OFFSET_CAPTURE); if (count($curlyTags[0])) { // if TRUE, replace only CODE plugin, if false, replace all other plugins $code_first = TRUE; // Process plugins in reverse order, so that nested plugins are handled from the inside out. $i = count($curlyTags[0]) - 1; while ($i >= 0) { $plugin_start = $curlyTags[0][$i][0]; $plugin = $curlyTags[1][$i][0]; // Work out where the plugin starts. This can not be done using the // positional data from $curlyTags since the position might have // changed since the last cycle. We therefore need to determine the // position direclty. - xing - Thursday Nov 01, 2007 22:55:10 CET //$pos = $curlyTags[0][$i][1]; $pos = strpos($pData, $plugin_start); $dataTag = strtolower($plugin); // hush up the return of this in case someone uses curly braces to enclose text $pluginInfo = $gLibertySystem->getPluginInfo(@$gLibertySystem->mDataTags[$dataTag]); // only process a standalone unpaired tag or the start tag for a paired tag if (empty($paired_close_tag_seen[$dataTag]) || $paired_close_tag_seen[$dataTag] == 0) { $paired_close_tag_seen[$dataTag] = 1; } else { $paired_close_tag_seen[$dataTag] = 0; } $is_opening_tag = FALSE; if (empty($pluginInfo['requires_pair']) && strtolower($plugin_start) != '{/' . $dataTag . '}' || strpos($plugin_start, ' ') > 0 || strtolower($plugin_start) == '{' . $dataTag . '}' && !$paired_close_tag_seen[$dataTag]) { $is_opening_tag = TRUE; } if (($code_first && $dataTag == 'code' || !$code_first && $dataTag != 'code') && !empty($gLibertySystem->mDataTags[$dataTag]) && !empty($pluginInfo) && ($loadFunc = $gLibertySystem->getPluginFunction($gLibertySystem->mDataTags[$dataTag], 'load_function')) && $is_opening_tag) { if ($pluginInfo['requires_pair']) { $plugin_end = '{/' . $plugin . '}'; $pos_end = strpos(strtolower($pData), strtolower($plugin_end), $pos); // where plugin data ends $plugin_end2 = '{' . $plugin . '}'; $pos_end2 = strpos(strtolower($pData), strtolower($plugin_end2), $pos + 1); // where plugin data ends if ($pos_end2 > 0 && $pos_end2 > 0 && $pos_end2 < $pos_end || $pos_end === FALSE) { $pos_end = $pos_end2; $plugin_end = $plugin_end2; } } else { $pos_end = $pos + strlen($curlyTags[0][$i][0]); $plugin_end = ''; } // Extract the plugin data $plugin_data_len = $pos_end - $pos - strlen($curlyTags[0][$i][0]); $plugin_data = substr($pData, $pos + strlen($plugin_start), $plugin_data_len); $arguments = array(); // Construct argument list array $paramString = str_replace('>', '>', trim($curlyTags[2][$i][0])); if (preg_match('/^\\(.*=>.*\\)$/', $paramString)) { $paramString = preg_replace('/[\\(\\)]/', '', $paramString); //we have the old style parms like {CODE (in=>1)} $params = explode(',', trim($paramString)); foreach ($params as $param) { // the following str_replace line is to decode the > char when html is turned off // perhaps the plugin syntax should be changed in 1.8 not to use any html special chars $parts = preg_split('/=>?/', $param); if (isset($parts[0]) && isset($parts[1])) { $name = trim($parts[0]); $arguments[$name] = trim($parts[1]); } } } else { $paramString = trim($curlyTags[2][$i][0], " \t()"); $paramString = str_replace(""", '"', $paramString); $arguments = parse_xml_attributes($paramString); } if ($ret = $loadFunc($plugin_data, $arguments, $pCommonObject, $pParseHash)) { $key = "parseprotect" . md5(mt_rand()); $pReplace[] = array('key' => $key, 'data' => $ret); // don't modify data if $pos is FALSE if ($pos !== FALSE) { $pData = substr_replace($pData, $key, $pos, $pos_end - $pos + strlen($plugin_end)); } } } $i--; // if we are in CODE parsing mode and list is done, switch to 'parse other plugins' mode and start all over if ($code_first && $i < 0) { $i = count($curlyTags[0]) - 1; $code_first = FALSE; } } // while } }
function maketoc_postparsefilter(&$pData, &$pFilterHash) { preg_match_all("/\\{maketoc(.*?)\\}/i", $pData, $maketocs); if (!empty($maketocs[1])) { // extract the parameters for maketoc foreach ($maketocs[1] as $string) { $params[] = parse_xml_attributes($string); } // get all headers into an array preg_match_all("/<h(\\d)[^>]*>(.*?)<\\/h\\d>/i", $pData, $headers); // clumsy way of finding out if index is set. since we can't allow // duplicate settings of index in one page, we either index everything // or nothing. foreach ($params as $p) { if (empty($index)) { $index = in_array('index', array_keys($p)); } } if ($index) { $counter = array(); foreach (array_keys($headers[2]) as $key) { $level = $headers[1][$key]; if (empty($counter[$level])) { $counter[$level] = 1; } elseif ($level == $headers[1][$key - 1]) { $counter[$level]++; } elseif ($level < $headers[1][$key - 1]) { $counter[$level] = $counter[$level] + 1; } else { $counter[$level] = 1; } $index = ''; foreach ($counter as $k => $c) { if ($k <= $level) { $index .= "{$c}."; } } $headers[2][$key] = $index . ' ' . $headers[2][$key]; } } // remove any html tags from the output text and generate link ids foreach ($headers[2] as $output) { $outputs[] = $id = preg_replace("/<[^>]*>/", "", $output); $id = preg_replace("@parseprotect[[a-zA-Z0-9]{32}@", "", $id); $id = substr(preg_replace("/[^\\w|\\d]*/", "", $id), 0, 40); $ids[] = !empty($id) ? $id : 'id' . microtime() * 1000000; } // insert the <a name> tags in the right places foreach ($headers[0] as $k => $header) { $reconstructed = "<h{$headers[1][$k]} id=\"{$ids[$k]}\">{$headers[2][$k]}</h{$headers[1][$k]}>"; $pData = str_replace($header, $reconstructed, $pData); } if (!empty($outputs)) { $tocHash = array('outputs' => $outputs, 'ids' => $ids, 'levels' => $headers[1]); // (<br[ |\/]*>){0,1} removes up to one occurance of <br> | <br > | <br /> | <br/> or similar variants $sections = preg_split("/\\{maketoc.*?\\}(<br[ |\\/]*>){0,1}/i", $pData); // first section is before any {maketoc} entry, so we can ignore it $ret = ''; foreach ($sections as $k => $section) { // count headers in each section that we know where to begin and where to stop preg_match_all("!<h(\\d)[^>]*>.*?</h\\d>!i", $section, $hs); $tocHash['header_count'][] = count($hs[0]); $ret .= $section; // the last section will create an error if we don't check for available params if (isset($params[$k])) { $ret .= maketoc_create_list($tocHash, $params[$k]); } } } } $pData = isset($ret) ? $ret : preg_replace("/\\{maketoc[^\\}]*\\}\\s*(<br[^>]*>)*/i", "", $pData); }
/** * parse URL-like parameter string * * @param array $pParseString * @access public * @return array or parameters */ function parseString($pParseString) { $ret = array(); if (!empty($pParseString)) { // only call crazy regex when params are too complex for parse_str() if (strpos(trim($pParseString), ' ')) { $ret = parse_xml_attributes($pParseString); } else { parse_str($pParseString, $ret); } } return $ret; }