wez             Tue May 25 07:33:48 2004 EDT

  Added files:                 
    /livedocs   livedoc_funcs.php pregenerate.php xml_classes5.php 

  Modified files:              
    /livedocs   configure.in livedoc.php mkindex.php 
    /livedocs/themes/default    html_format.php 
  Log:
  Big commit; will be a little unclear what has changed.
  
  - Split the functions out from livedoc.php and into livedoc_funcs.php
  - Added PHP 5 version of xml_classes5.php; assignment using the reference
    operator leaks massive amounts of memory and will not be fixed.
  - Added pregenerate.php which should be run using PHP 5 (see above!) only to
    generate the entire manual as individual html pages.
  - Some minor corrections to Ilia's perf tweaks
  - Smarter entity handling
  
  Discovery:
  
  do_nav() is way too slow; don't attempt to pregenerate anything until it is
  tuned, unless you are a gentoo user with CPU to burn.
  
  
  
http://cvs.php.net/diff.php/livedocs/configure.in?r1=1.25&r2=1.26&ty=u
Index: livedocs/configure.in
diff -u livedocs/configure.in:1.25 livedocs/configure.in:1.26
--- livedocs/configure.in:1.25  Tue May  4 21:37:04 2004
+++ livedocs/configure.in       Tue May 25 07:33:48 2004
@@ -1,5 +1,5 @@
 ## A configure script
-## $Id: configure.in,v 1.25 2004/05/05 01:37:04 wez Exp $
+## $Id: configure.in,v 1.26 2004/05/25 11:33:48 wez Exp $
 
 AC_PREREQ(2.13)
 AC_INIT(livedoc.php)
@@ -138,6 +138,7 @@
   cp common.php config.php .htaccess $OUTPUTDIR
   rm -f .htaccess
   $lncmd $LIVEDOCS/livedoc.php $OUTPUTDIR/index.php
+  $lncmd $LIVEDOCS/livedoc_funcs.php $OUTPUTDIR/livedoc_funcs.php
   $lncmd $LIVEDOCS/error.php $OUTPUTDIR/error.php
   $lncmd $LIVEDOCS/style_mapping.php $OUTPUTDIR/style_mapping.php
   $lncmd $LIVEDOCS/xml_classes.php $OUTPUTDIR/xml_classes.php
@@ -148,13 +149,12 @@
   echo ""
   echo "You have configured livedocs so that links are relative to 
http://yourserver$WEBBASE";
   echo "$OUTPUTDIR is assumed to be the dir that is displayed by your webserver for 
that URL"
-fi
-
-dnl Generate config.nice (primitive, but saves some brain power)
 
-echo "#!/bin/sh" > config.nice
-echo "./configure $*" >> config.nice
-chmod +x config.nice
+  dnl Generate config.nice (primitive, but saves some brain power)
 
+  echo "#!/bin/sh" > config.nice
+  echo "./configure $*" >> config.nice
+  chmod +x config.nice
 
+fi
 dnl vim:et:sw=2:ts=2
http://cvs.php.net/diff.php/livedocs/livedoc.php?r1=1.106&r2=1.107&ty=u
Index: livedocs/livedoc.php
diff -u livedocs/livedoc.php:1.106 livedocs/livedoc.php:1.107
--- livedocs/livedoc.php:1.106  Mon May 24 16:59:28 2004
+++ livedocs/livedoc.php        Tue May 25 07:33:48 2004
@@ -18,15 +18,10 @@
 // | Generate an HTML version of a phpdoc/docbook page on the fly         |
 // +----------------------------------------------------------------------+
 //
-// $Id: livedoc.php,v 1.106 2004/05/24 20:59:28 iliaa Exp $
+// $Id: livedoc.php,v 1.107 2004/05/25 11:33:48 wez Exp $
 
 define('LIVEDOC_SOURCE', dirname(__FILE__));
-include LIVEDOC_SOURCE . '/common.php';
-include LIVEDOC_SOURCE . '/xml_classes.php';
-include LIVEDOC_SOURCE . '/style_mapping.php';
-include LIVEDOC_SOURCE . '/handlers.php';
-include LIVEDOC_SOURCE . '/themes/' . THEME_NAME . '/html_format.php';
-
+include LIVEDOC_SOURCE . '/livedoc_funcs.php';
 $date = gmdate('Y-m-d H:i:s') . ' GMT';
 
 if (isset($_GET['i'])) {
@@ -56,27 +51,35 @@
  * Aliases and XML -> style mapping
  * Please keep the arrays sorted by keys
  */
-$aliases = array(
-       // For Smarty
-       'smarty.for.programmers' => 'smarty.constants',
-       'smarty.for.designers' => 'language.basic.syntax',
-       'api.functions' => 'handle_appendixes_funcref',
-       'language.custom.functions' => 'handle_appendixes_funcref',
-       'language.basic.syntax' => 'handle_appendixes_funcref',
-       'language.variables' => 'handle_appendixes_funcref',
-       // For PHPdoc
-       'api'             => 'streams',
-       'appendixes'      => 'handle_appendixes_funcref',
-       'faq'             => 'faq.general',
-       'features'        => 'features.http-auth',
-       'funcref'         => 'handle_appendixes_funcref',
-       'getting-started' => 'introduction',
-       'installation'    => 'install.general',
-       'langref'         => 'language.basic-syntax',
-       'manual'          => 'handle_contents',
-       'security'        => 'security.index',
-       'indexes'         => 'handle_index'
-);
+
+if (BUILD_TYPE == 'smarty') {
+       $aliases = array(
+                       // For Smarty
+                       'smarty.for.programmers' => 'smarty.constants',
+                       'smarty.for.designers' => 'language.basic.syntax',
+                       'api.functions' => 'handle_appendixes_funcref',
+                       'language.custom.functions' => 'handle_appendixes_funcref',
+                       'language.basic.syntax' => 'handle_appendixes_funcref',
+                       'language.variables' => 'handle_appendixes_funcref',
+                       );
+} elseif (BUILD_TYPE == 'phpdoc') {
+       $aliases = array(
+                       // For PHPdoc
+                       'api'             => 'streams',
+                       'appendixes'      => 'handle_appendixes_funcref',
+                       'faq'             => 'faq.general',
+                       'features'        => 'features.http-auth',
+                       'funcref'         => 'handle_appendixes_funcref',
+                       'getting-started' => 'introduction',
+                       'installation'    => 'install.general',
+                       'langref'         => 'language.basic-syntax',
+                       'manual'          => 'handle_contents',
+                       'security'        => 'security.index',
+                       'indexes'         => 'handle_index'
+                       );
+} else {
+       $aliases = array();
+}
 
 /*****************************************************************************
  * Handle some special pages in a special way with special code
@@ -158,393 +161,6 @@
        fwrite($f, $contents);
        fclose($f);
        echo $contents;
-}
-
-return;
-
-/*****************************************************************************
- * Helper functions for navigation
- */
-function do_nav($idx, $fb_idx, $lang, $current_page, &$nav, &$children) 
-{
-
-       $nav = "<table class='nav' border='0' cellpadding='0' cellspacing='0' 
width='150'>";
-
-       /* Get the fileinfo for the reference */
-       $tr = sqlite_array_query($idx, "SELECT title, filename, idents.fileid, 
files.dirid from idents, files where id='$current_page' and 
idents.fileid=files.fileid", SQLITE_NUM);
-       if (!$tr) {
-               $tr = sqlite_array_query($fb_idx, "SELECT title, filename, 
idents.fileid, files.dirid from idents, files where id='$current_page' and 
idents.fileid=files.fileid", SQLITE_NUM); 
-       }
-       list($title, $filename, $fileid, $dirid) = $tr;
-
-       /* Get parent ID and child IDs */
-       /* - first we get the first three parts of the path */
-       if (($r = sqlite_single_query($idx, "SELECT path FROM toc WHERE docbook_id = 
'$current_page' LIMIT 1", SQLITE_NUM))) {
-               $path = explode(",", $r);
-               foreach ($path as $item) {
-                       $nav .= do_nav_line($item, 'up', $current_page, $lang, $dummy);
-               }
-               $last_item = $item;
-       } else {
-               $nav .= do_nav_line('manual', 'up', $current_page, $lang, $dummy);
-               $last_item = 'manual';
-       }
-
-       /* With $last_item we're going to show all brothers */
-       $r = (array) sqlite_single_query($idx, "SELECT docbook_id FROM toc WHERE 
parent_docbook_id = '$last_item' ORDER BY id");
-       foreach ($r as $val) {
-               $nav .= do_nav_line($val, 'down', $current_page, $lang, $dummy);
-       }
-
-       $children = array();
-       /* And finally all children, but only if $current_page != $last_item
-        * because showing the same thing twice makes no sense */
-       $r = (array) sqlite_single_query($idx, "SELECT docbook_id FROM toc WHERE 
parent_docbook_id = '$current_page' AND parent_docbook_id <> 'manual' ORDER BY id");
-       foreach ($r as $val) {
-               $nav .= do_nav_line($val, 'downdown', $current_page, $lang, $title);
-               $children[$val] = $title;
-       }
-
-       $nav .= "</table>\n";
-       return $tr;
-}
-
-
-function generate_url_for_id($lang, $ref) 
-{
-       static $cache = array();
-
-       if (isset($cache[$lang][$ref])) {
-               return $cache[$lang][$ref];
-       }
-       
-       /* first determine the file in which the node can be found */
-       $fileid = null;
-       $firstid = $ref;
-
-       $saferef = sqlite_escape_string($ref);
-       
-       if (($fileid = sqlite_single_query($GLOBALS['idx'], "SELECT fileid from idents 
where id='$saferef'"))) {
-               $idx = $GLOBALS['idx'];
-       } else if (isset($GLOBALS['fb_idx']) && ($fileid = 
sqlite_single_query($GLOBALS['fb_idx'], "SELECT fileid from idents where 
id='$saferef'"))) {
-               $idx = $GLOBALS['fb_idx'];
-       }
-
-       if (!$fileid) { /* determine the first node within that file */
-               $firstid = sqlite_single_query($idx, "SELECT id from idents where 
fileid='$fileid' LIMIT 1");
-       }
-
-       if ($firstid != $ref) {
-               $hash = "#$ref";
-       } else {
-               $hash = "";
-       }
-
-       if ($firstid == 'manual') {
-               $firstid = $ref;
-               $hash = '';
-       }
-
-       if (FORCE_DYNAMIC) {
-               $url = "{$_SERVER['PHP_SELF']}?l=$lang&amp;q=$firstid$hash";
-       } else {
-               $url = WEBBASE . "$lang/$firstid.html$hash";
-       }
-
-       $cache[$lang][$ref] = $url;
-       return $url;
-}
-
-function do_nav_line($item, $class, $current_page, $lang, &$fulltitle) {
-       global $current_page_title;
-
-       $nolink = FALSE;
-
-       $title = lookup_title($item);
-       $fulltitle = $title;
-       if (strlen($title) > 25) {
-               $ftitle = " title='$title'";
-               $title = substr($title, 0, 22). '...';
-       } else {
-               $ftitle = "";
-               if (!$title) {
-                       $title = $item . ' [?]';
-                       $nolink = TRUE;
-               }
-       }
-       
-       if ($item == $current_page) {
-               $current_page_title = $title;
-               $title = "<b>$title</b>";
-       }
-       $title = str_replace(' ', '&nbsp;', $title);
-
-       if ($nolink) {
-               return "<tr><td class='$class'>$title</td></tr>\n";
-       } else {
-               $url = generate_url_for_id($lang, $item);
-               return "<tr><td class='$class'><a $ftitle class='$class' 
href='$url'>$title</a></td></tr>\n";
-       }
-}
-
-/*****************************************************************************
- * Search & Replace entities
- */
-function bind_entities($data) {
-
-       global $idx;
-       $sanity = 0;
-
-       while (($ent_count = preg_match_all('/&([a-zA-Z0-9.-]+);/sm', $data, 
$matches)) && $sanity++ < 5) {
-               /* now collect their values */
-               $ents = implode("','", array_unique($matches[1]));
-               $r = sqlite_array_query($idx, "SELECT entid, value from ents where 
entid in ('" . $ents . "')", SQLITE_NUM);
-               if ($r) {
-                       $src = $dst = array();
-                       foreach ($r as $v) {
-                               $src[] = '&' . $v[0] . ';';
-                               $dst[] = $v[1];
-                       }
-                       /* substitute */
-                       $data = str_replace($src, $dst, $data);
-               } else {
-                       /* no matching entities, no point in looping further */
-                       break;
-               }
-       }
-
-       return $data;
-}
-
-
-/*****************************************************************************
- * Helper functions for transformation
- */
-function &load_xml_doc($filename, $included = false, $fallback_filename = '', 
$return_rev = 0) 
-{
-       global $file_revision, $idx, $lang;
-
-       $replace = array();
-       $search = array('&aelig;', '&copy;', '&eacute;', '&egrave;', '&agrave;', 
'&iuml;', '&ouml;', '&auml;', '&Auml;',
-               '&ocirc;', '&ecirc;', '&ucirc;', '&icirc;', '&acirc;', '&euml;', 
'&ccedil;', '&ugrave;');
-       foreach ($search as $item) {
-               $replace[] = html_entity_decode($item);
-       }
-
-       $lang_rev = 0;
-
-       $data = @file_get_contents($filename);
-       if (strlen($data) == 0 && strlen($fallback_filename)) {
-               $data = @file_get_contents($fallback_filename);
-
-               if (strlen($data) == 0) {
-                       $data = "<warning>permissions problem for 
$filename?</warning>";
-               }
-
-       } elseif ($lang != 'en' && preg_match('/<!-- EN-Revision: \d+\.(\d+)/', $data, 
$matches)) {
-               $lang_rev = $matches[1];
-       }
-
-       /* get file revision */
-       if (empty($file_revision) && preg_match('/\$' . 'Revision: [^$]+ \$/', $data, 
$matches)) {
-               $file_revision .= $matches[0];
-       }
-
-       /* strip comments */
-       $data = preg_replace('@<!--\s+.*\s-->@Usm', '', $data);
-
-       /* Replace entities */
-       $data = bind_entities($data);
-
-       /* catch any undefined entities */
-       if ($included) {
-               if (basename($filename) == 'functions.xml') {
-                       $data = 
preg_replace('/&([a-zA-Z0-9-]+)\.([a-zA-Z0-9.-]+);/sme', 
'make_function_link("\\1.\\2");', $data);
-               } else {
-                       $data = 
preg_replace('/&([a-zA-Z0-9-]+)\.([a-zA-Z0-9.-]+);/sme', 'make_xref("\\1.\\2");', 
$data);
-               }
-               if (!$data || $data{1} != '?') {
-                       $data = '<div>' . $data . '</div>';
-               } else {
-                       $data = preg_replace('@(<\\?xml.*\\?>)@U', '\\1<div>', $data) 
. '</div>';
-               }
-       } else {
-               $data = preg_replace('/&([a-zA-Z0-9-]+)\.([a-zA-Z0-9.-]+);/sm', 
'<phpdoc_include ref="\\1.\\2"/>', $data);
-       }
-
-       $data = str_replace($search, $replace, $data);
-
-       $page = new DocBookToHTML($data);
-
-
-       if ($return_rev) {
-               return array($page, $lang_rev);
-       } else {
-               return $page;
-       }
-}
-
-function format_user_notes($id)
-{
-       $notes = sqlite_array_query($GLOBALS['NOTESDB'], "SELECT id, xwhen, who, note 
from notes where sect='$id' order by xwhen desc");
-       if (count($notes) == 0)
-               return '';
-
-       $inner = <<<HTML
-<div class="usernotes">
-       <span class="title">User Contributed Notes</span>
-HTML;
-
-       foreach ($notes as $note) {
-               $date = date("d-M-Y h:i", $note['xwhen']);
-
-               $node = new stdClass;
-               $node->content = $note['note'];
-               $node->attributes['role'] = 'php';
-               $the_note = format_listing($node);
-               
-               $inner .= <<<HTML
-<div class="usernote">
-       <div class="noteheader">
-               <span class="user">$note[who]</span><br />
-               <span class="when">$date</span>
-       </div>
-       $the_note
-</div>
-HTML;
-       }
-               
-       return $inner . "</div>";
-}
-
-function lookup_title($nodeid) 
-{
-       static $ids = array();
-
-       /* Define your own title mappings here: */
-       static $special = array ('indexes' => 'FunctionIndex'); 
-
-       /* we're going to do some tricky stuff here for languages,
-        * by using entities as much as possible */
-       if (isset($special[$nodeid])) {
-               /* Check for the entity value */
-               if (($r = sqlite_single_query($GLOBALS['idx'], "SELECT entid FROM ents 
WHERE entid = '$special[$nodeid]'"))) {
-                       return $r;
-               } else { /* It's not an entity, let's just return it then */
-                       return $special[$nodeid];
-               }
-       }
-
-       /* See if the title lookup is in the cache already */
-       if (isset($ids[$nodeid])) {
-               return $ids[$nodeid];
-       }
-
-       /* It's not, so we try to resolve it from the DB */
-       $safeid = sqlite_escape_string($nodeid);
-       if (($ids[$nodeid] = sqlite_single_query($GLOBALS['idx'], "SELECT title from 
idents where id='$safeid'"))) {
-               return $ids[$nodeid];
-       } else if (isset($GLOBALS['fb_idx']) && ($ids[$nodeid] = 
sqlite_single_query($GLOBALS['fb_idx'], "SELECT title from idents where 
id='$safeid'"))) {
-               return $ids[$nodeid];
-       }
-       return null;
-}
-
-/* transform an entity name of the form "reference.XXXX.functions.ID"
- * and generate a link to its node using its title */
-function make_function_link($ref) 
-{
-       $parts = explode('.', $ref);
-
-       $stag = 'function';
-       $etag = 'function';
-
-       switch (count($parts)) {
-               case 4:
-                       $id = 'function.' . $parts[3];
-                       $func_name = lookup_title($id);
-                       break;
-
-               case 5:
-                       if ($parts[3] == 'class') {
-                               $id = 'class.' . $parts[4];
-                               $func_name = str_replace('-', '_', $parts[4]);
-                               $stag = "xref linkend=\"$id\"";
-                               $etag = "xref";
-                               break;
-                       }
-                       /* fall through */
-
-               default:
-                       /* some weird node type we don't understand */
-                       $id = $ref;
-                       $func_name = 'Unknown ??';                      
-       }
-
-       if ($parts[3] == 'class') {
-               $title = ' - ' . lookup_title($id) . ' class';
-       } else {
-               $title = ' - ' . bind_entities(sqlite_single_query($GLOBALS['idx'], 
"SELECT descr from toc where docbook_id='$id'"));
-       }
-
-       return "<div class=\"function_link\"><$stag>$func_name</$etag>$title</div>";
-}
-
-function make_xref($ref) 
-{
-       $parts = explode('.', $ref);
-       if ($parts[0] == 'reference' && $parts[2] == 'functions') {
-               $id = 'function.'. $parts[3];
-       }
-       $title = lookup_title($id);
-       if (!$title) {
-               $title = $id. ' [?]';
-       }
-       return "<xref linkend=\"$id\">$title</xref>";
-}
-
-function do_contents($id, $level) 
-{
-       global $lang;
-
-       if (($r = sqlite_array_query($GLOBALS['idx'], "SELECT id, docbook_id FROM toc 
WHERE parent_id = ".$id, SQLITE_NUM))) {
-               foreach($r as $row) {
-                       $ret .= "<li>";
-
-                       if (!($title = lookup_title($row[1]))) {
-                               $ret .= $row[1]. ' [?]';
-                       } else {
-                               $ret .= "<a href='".generate_url_for_id($lang, 
$row[1])."'>".$title."</a>";
-                       }
-
-                       if (($level < 2 && strcmp($row[1], 'ref')) ||  $level < 1) {
-                               $ret .= do_contents($row[0], $level + 1);
-                       }
-                       $ret .= "</li>\n";
-               }
-
-               return "<ul>" . $ret . "</ul>\n";
-       }
-
-       return '';
-}
-
-function handle_include($node) 
-{
-       $filename = BASE . strtr($node->attributes['ref'], '.', '/') . '.xml';
-       $fallback_filename = FALLBACK_BASE . strtr($node->attributes['ref'], '.', '/') 
. '.xml';
-
-       $doc = load_xml_doc($filename, true, $fallback_filename);
-       return $doc->transform($GLOBALS['map']);
-}
-
-// Handle the case where a requested node id was not found
-function handle_missing_index() 
-{
-       global $current_page, $lang;
-
-       header('Location: ' . WEBBASE . 'search.php?q=' . urlencode($current_page) . 
'&l=' . $lang);
-       exit;
 }
 
 ?>
http://cvs.php.net/diff.php/livedocs/mkindex.php?r1=1.34&r2=1.35&ty=u
Index: livedocs/mkindex.php
diff -u livedocs/mkindex.php:1.34 livedocs/mkindex.php:1.35
--- livedocs/mkindex.php:1.34   Mon May 24 08:18:48 2004
+++ livedocs/mkindex.php        Tue May 25 07:33:48 2004
@@ -19,7 +19,7 @@
 // | construct an index                                                   |
 // +----------------------------------------------------------------------+
 //
-// $Id: mkindex.php,v 1.34 2004/05/24 12:18:48 wez Exp $
+// $Id: mkindex.php,v 1.35 2004/05/25 11:33:48 wez Exp $
 
 
 /* just to be on the safe side */
@@ -212,7 +212,7 @@
                                if (!isset($replacements[$matches[1][$i]])) {
                                        $id = sqlite_escape_string($matches[1][$i]);
                                        $value = sqlite_escape_string($matches[2][$i]);
-                                       $strsql = "INSERT INTO ents VALUES ('$id', 
'$value')";
+                                       $strsql = "INSERT INTO ents VALUES ('$id', 
'$value', 0)";
                                        @sqlite_query($idx, $strsql);
                                        // echo $strsql . "\n"; // for debuging
 
@@ -220,6 +220,34 @@
                                }
                        }
                }
+
+               $x = 
preg_match_all('/<!ENTITY\s+([a-zA-Z0-9.-]+)\s+SYSTEM\s+\'([^\']+)\'>/Usm', $d, 
$matches);
+               $docs = $GLOBALS['DOCS'] . DIRECTORY_SEPARATOR;
+               $docslen = strlen($docs);
+               $realdocs = realpath($docs) . DIRECTORY_SEPARATOR;
+               $reallen = strlen($realdocs);
+               $lang = $GLOBALS['LANG'] . DIRECTORY_SEPARATOR;
+               $langlen = strlen($lang);
+               for ($i = 0; $i < $x; $i++) {
+                       $id = sqlite_escape_string($matches[1][$i]);
+                       $value = sqlite_escape_string($matches[2][$i]);
+                       echo "value: $value\ndocs: $docs\nreal: $realdocs\nlang: 
$lang\n";
+                       if (strncmp($value, $docs, $docslen) == 0) {
+                               $value = substr($value, $docslen);
+                               $check_lang = true;
+                       } else if (strncmp($value, $realdocs, $reallen) == 0) {
+                               $value = substr($value, $reallen);
+                               $check_lang = true;
+                       } else {
+                               $check_lang = true;
+                       }
+
+                       if ($check_lang && strncmp($value, $lang, $langlen) == 0) {
+                               $value = substr($value, $langlen);
+                       }
+                       echo "   ---> $value\n";
+                       @sqlite_query($idx, "INSERT INTO ents VALUES ('$id', '$value', 
1)");
+               }
        }
        return $replacements;
 }
@@ -306,7 +334,8 @@
 
 CREATE TABLE ents (
        entid TEXT PRIMARY KEY,
-       value TEXT
+       value TEXT,
+       is_file INTEGER default 0
 );
 
 CREATE TABLE funcs (
@@ -324,6 +353,9 @@
        title TEXT,
        descr TEXT
 );
+CREATE INDEX toc_parent_idx on toc(parent_id);
+CREATE INDEX toc_docbook_id_idx on toc(docbook_id);
+CREATE INDEX toc_parent_docbook_id_idx on toc(parent_docbook_id);
 
 CREATE TABLE searchi (
        skey VARCHAR(230),
http://cvs.php.net/diff.php/livedocs/themes/default/html_format.php?r1=1.10&r2=1.11&ty=u
Index: livedocs/themes/default/html_format.php
diff -u livedocs/themes/default/html_format.php:1.10 
livedocs/themes/default/html_format.php:1.11
--- livedocs/themes/default/html_format.php:1.10        Mon May 24 08:43:25 2004
+++ livedocs/themes/default/html_format.php     Tue May 25 07:33:48 2004
@@ -18,7 +18,7 @@
 // | headers and footers for the HTML rendering                           |
 // +----------------------------------------------------------------------+
 //  
-// $Id: html_format.php,v 1.10 2004/05/24 12:43:25 wez Exp $
+// $Id: html_format.php,v 1.11 2004/05/25 11:33:48 wez Exp $
 
 // in livedoc.php
 
@@ -32,7 +32,7 @@
        "http://www.w3.org/TR/html4/loose.dtd";>
 <html lang="$lang">
 <head>
-<meta http-equiv="Content-Type" content="text/html; charset="$charset"/>
+<meta http-equiv="Content-Type" content="text/html; charset=$charset"/>
 <title>$title</title>
 <link rel="stylesheet" href="$css_url" />
 </head>

http://cvs.php.net/co.php/livedocs/livedoc_funcs.php?r=1.1&p=1
Index: livedocs/livedoc_funcs.php
+++ livedocs/livedoc_funcs.php
<?php
include LIVEDOC_SOURCE . '/common.php';
if (version_compare(phpversion(), "5", "ge")) {
        include LIVEDOC_SOURCE . '/xml_classes5.php';
} else {
        include LIVEDOC_SOURCE . '/xml_classes.php';
}
include LIVEDOC_SOURCE . '/style_mapping.php';
include LIVEDOC_SOURCE . '/handlers.php';
include LIVEDOC_SOURCE . '/themes/' . THEME_NAME . '/html_format.php';

/*****************************************************************************
 * Helper functions for navigation
 */
function do_nav($idx, $fb_idx, $lang, $current_page, &$nav, &$children) 
{
        $children = array();
        $nav = "<table class='nav' border='0' cellpadding='0' cellspacing='0' 
width='150'>";

        /* Get the fileinfo for the reference */
        list($tr) = sqlite_array_query($idx, "SELECT title, filename, idents.fileid, 
files.dirid from idents left join files where id='$current_page' and 
idents.fileid=files.fileid", SQLITE_NUM);
        if (!$tr) {
                list($tr) = sqlite_array_query($fb_idx, "SELECT title, filename, 
idents.fileid, files.dirid from idents left join files where id='$current_page' and 
idents.fileid=files.fileid", SQLITE_NUM);  
        }
        if ($tr) {
                list($title, $filename, $fileid, $dirid) = $tr;
        }
        
        /* Get parent ID and child IDs */
        /* - first we get the first three parts of the path */
        $last_item = 'manual';
        if (($r = sqlite_single_query($idx, "SELECT path FROM toc WHERE docbook_id = 
'$current_page' LIMIT 1", SQLITE_NUM))) {
                $path = explode(",", $r);
                foreach ($path as $item) {
                        $nav .= do_nav_line($item, 'up', $current_page, $lang, $dummy);
                        $last_item = $item;
                }
        } else {
                $nav .= do_nav_line('manual', 'up', $current_page, $lang, $dummy);
        }

        /* With $last_item we're going to show all brothers */
        $r = (array) sqlite_single_query($idx, "SELECT docbook_id FROM toc WHERE 
parent_docbook_id = '$last_item' ORDER BY id");
        foreach ($r as $val) {
                $nav .= do_nav_line($val, 'down', $current_page, $lang, $dummy);
        }

        /* And finally all children, but only if $current_page != $last_item
         * because showing the same thing twice makes no sense */
        if ($current_page != $last_item && $current_page != 'manual') {
                $r = (array) sqlite_single_query($idx, "SELECT docbook_id FROM toc 
WHERE parent_docbook_id = '$current_page' ORDER BY id");
                foreach ($r as $val) {
                        $nav .= do_nav_line($val, 'downdown', $current_page, $lang, 
$title);
                        $children[$val] = $title;
                }
        }

        $nav .= "</table>\n";
        return $tr;

}


function generate_url_for_id($lang, $ref) 
{
        static $cache = array();

        if (isset($cache[$lang][$ref])) {
                return $cache[$lang][$ref];
        }
        
        /* first determine the file in which the node can be found */
        $fileid = null;
        $firstid = $ref;

        $saferef = sqlite_escape_string($ref);

        $fileid = sqlite_single_query($GLOBALS['idx'], "SELECT fileid from idents 
where id='$saferef'");
        if ($fileid) {
                $index = $GLOBALS['idx'];
        } else {
                $fileid = sqlite_single_query($GLOBALS['fb_idx'], "SELECT fileid from 
idents where id='$saferef'");
                if ($fileid) {
                        $index = $GLOBALS['fb_idx'];
                } else {
                        $index = null;
                }
        }
        
        if ($fileid !== null && $index !== null) {
                /* determine the first node within that file */
                $firstid = sqlite_single_query($index, "SELECT id from idents where 
fileid='$fileid' LIMIT 1");
        }

        if ($firstid != $ref) {
                $hash = "#$ref";
        } else {
                $hash = "";
        }

        if ($firstid == 'manual') {
                $firstid = $ref;
                $hash = '';
        }

        if (FORCE_DYNAMIC) {
                $url = "{$_SERVER['PHP_SELF']}?l=$lang&amp;q=$firstid$hash";
        } else {
                $url = WEBBASE . "$lang/$firstid.html$hash";
        }

        $cache[$lang][$ref] = $url;
        return $url;
}

function do_nav_line($item, $class, $current_page, $lang, &$fulltitle) {
        global $current_page_title;

        $nolink = FALSE;

        $title = lookup_title($item);
        $fulltitle = $title;
        if (strlen($title) > 25) {
                $ftitle = " title='$title'";
                $title = substr($title, 0, 22). '...';
        } else {
                $ftitle = "";
                if (!$title) {
                        $title = $item . ' [?]';
                        $nolink = TRUE;
                }
        }
        
        if ($item == $current_page) {
                $current_page_title = $title;
                $title = "<b>$title</b>";
        }
        $title = str_replace(' ', '&nbsp;', $title);

        if ($nolink) {
                return "<tr><td class='$class'>$title</td></tr>\n";
        } else {
                $url = generate_url_for_id($lang, $item);
                return "<tr><td class='$class'><a $ftitle class='$class' 
href='$url'>$title</a></td></tr>\n";
        }
}

/*****************************************************************************
 * Search & Replace entities
 */
function bind_entities($data) {

        global $idx;
        
        static $entity_cache = array();
        
        $entities = array();
        $sanity = 0;

        while (($ent_count = preg_match_all('/&([a-zA-Z0-9.-]+);/sm', $data, 
$matches)) && $sanity++ < 5) {
                /* now collect their values */
                $entities_to_find = array_unique($matches[1]);
                foreach ($entities_to_find as $ent) {
                        if (isset($entity_cache[$ent])) {
                                $entities['&' . $ent . ';'] = $entity_cache[$ent];
                                unset($entities_to_find[$ent]);
                        }
                }
                
                if (count($entities_to_find)) {
                        $ents = implode("','", $entities_to_find);
                        $q = sqlite_query($idx, "SELECT entid, value from ents where 
is_file=0 and entid in ('" . $ents . "')");
                        if ($q) {
                                while ($r = sqlite_fetch_array($q, SQLITE_NUM)) {
                                        $entities['&' . $r[0] . ';'] = $r[1];
                                        $entities_cache[$r[0]] = $r[1];
                                }
                        }
                }

                if (!count($entities))
                        break;

                /* substitute */
                $data = strtr($data, $entities);

        } while ($sanity++ < 5);

        return $data;
}


/*****************************************************************************
 * Helper functions for transformation
 */
function load_xml_doc($filename, $included = false, $fallback_filename = '', 
$return_rev = 0) 
{
        global $file_revision, $idx, $lang;

        $replace = array();
        $search = array('&aelig;', '&copy;', '&eacute;', '&egrave;', '&agrave;', 
'&iuml;', '&ouml;', '&auml;', '&Auml;',
                '&ocirc;', '&ecirc;', '&ucirc;', '&icirc;', '&acirc;', '&euml;', 
'&ccedil;', '&ugrave;');
        foreach ($search as $item) {
                $replace[] = html_entity_decode($item);
        }

        $lang_rev = 0;

        $data = @file_get_contents($filename);
        if (strlen($data) == 0 && strlen($fallback_filename)) {
                $data = @file_get_contents($fallback_filename);

                if (strlen($data) == 0) {
                        $data = "<warning>permissions problem for 
$filename?</warning>";
                }

        } elseif ($lang != 'en' && preg_match('/<!-- EN-Revision: \d+\.(\d+)/', $data, 
$matches)) {
                $lang_rev = $matches[1];
        }

        /* get file revision */
        if (empty($file_revision) && preg_match('/\$' . 'Revision: [^$]+ \$/', $data, 
$matches)) {
                $file_revision .= $matches[0];
        }

        /* strip comments */
        $data = preg_replace('@<!--\s+.*\s-->@Usm', '', $data);

        /* Replace entities */
        $data = bind_entities($data);

        /* catch any undefined entities */
        if ($included) {
                if (basename($filename) == 'functions.xml') {
                        $data = 
preg_replace('/&([a-zA-Z0-9-]+)\.([a-zA-Z0-9.-]+);/sme', 
'make_function_link("\\1.\\2");', $data);
                } else {
                        $data = 
preg_replace('/&([a-zA-Z0-9-]+)\.([a-zA-Z0-9.-]+);/sme', 'make_xref("\\1.\\2");', 
$data);
                }
                if (!$data || $data{1} != '?') {
                        $data = '<div>' . $data . '</div>';
                } else {
                        $data = preg_replace('@(<\\?xml.*\\?>)@U', '\\1<div>', $data) 
. '</div>';
                }
        } else {
                $data = preg_replace('/&([a-zA-Z0-9-]+)\.([a-zA-Z0-9.-]+);/sm', 
'<phpdoc_include ref="\\1.\\2"/>', $data);
        }

        $data = str_replace($search, $replace, $data);

        $page = new DocBookToHTML($data);


        if ($return_rev) {
                return array($page, $lang_rev);
        } else {
                return $page;
        }
}

function format_user_notes($id)
{
        $notes = sqlite_array_query($GLOBALS['NOTESDB'], "SELECT id, xwhen, who, note 
from notes where sect='$id' order by xwhen desc");
        if (count($notes) == 0)
                return '';

        $inner = <<<HTML
<div class="usernotes">
        <span class="title">User Contributed Notes</span>
HTML;

        foreach ($notes as $note) {
                $date = date("d-M-Y h:i", $note['xwhen']);

                $node = new stdClass;
                $node->content = $note['note'];
                $node->attributes['role'] = 'php';
                $the_note = format_listing($node);
                
                $inner .= <<<HTML
<div class="usernote">
        <div class="noteheader">
                <span class="user">$note[who]</span><br />
                <span class="when">$date</span>
        </div>
        $the_note
</div>
HTML;
        }
                
        return $inner . "</div>";
}

function lookup_title($nodeid) 
{
        static $ids = array();

        /* Define your own title mappings here: */
        static $special = array ('indexes' => 'FunctionIndex'); 

        /* we're going to do some tricky stuff here for languages,
         * by using entities as much as possible */
        if (isset($special[$nodeid])) {
                /* Check for the entity value */
                if (($r = sqlite_single_query($GLOBALS['idx'], "SELECT entid FROM ents 
WHERE entid = '$special[$nodeid]'"))) {
                        return $r;
                } else { /* It's not an entity, let's just return it then */
                        return $special[$nodeid];
                }
        }

        /* See if the title lookup is in the cache already */
        if (isset($ids[$nodeid])) {
                return $ids[$nodeid];
        }

        /* It's not, so we try to resolve it from the DB */
        $safeid = sqlite_escape_string($nodeid);
        if (($ids[$nodeid] = sqlite_single_query($GLOBALS['idx'], "SELECT title from 
idents where id='$safeid'"))) {
                return $ids[$nodeid];
        } else if (isset($GLOBALS['fb_idx']) && ($ids[$nodeid] = 
sqlite_single_query($GLOBALS['fb_idx'], "SELECT title from idents where 
id='$safeid'"))) {
                return $ids[$nodeid];
        }
        return null;
}

/* transform an entity name of the form "reference.XXXX.functions.ID"
 * and generate a link to its node using its title */
function make_function_link($ref) 
{
        $parts = explode('.', $ref);

        $stag = 'function';
        $etag = 'function';

        switch (count($parts)) {
                case 4:
                        $id = 'function.' . $parts[3];
                        $func_name = lookup_title($id);
                        break;

                case 5:
                        if ($parts[3] == 'class') {
                                $id = 'class.' . $parts[4];
                                $func_name = str_replace('-', '_', $parts[4]);
                                $stag = "xref linkend=\"$id\"";
                                $etag = "xref";
                                break;
                        }
                        /* fall through */

                default:
                        /* some weird node type we don't understand */
                        $id = $ref;
                        $func_name = 'Unknown ??';                      
        }

        if ($parts[3] == 'class') {
                $title = ' - ' . lookup_title($id) . ' class';
        } else {
                $title = ' - ' . bind_entities(sqlite_single_query($GLOBALS['idx'], 
"SELECT descr from toc where docbook_id='$id'"));
        }

        return "<div class=\"function_link\"><$stag>$func_name</$etag>$title</div>";
}

function make_xref($ref) 
{
        $parts = explode('.', $ref);
        if ($parts[0] == 'reference' && $parts[2] == 'functions') {
                $id = 'function.'. $parts[3];
        } else {
                $id = $ref;
        }
        $title = lookup_title($id);
        if (!$title) {
                $title = $id. ' [?]';
        }
        return "<xref linkend=\"$id\">$title</xref>";
}

function do_contents($id, $level) 
{
        global $lang;

        $ret = '';
        if (($r = sqlite_array_query($GLOBALS['idx'], "SELECT id, docbook_id FROM toc 
WHERE parent_id = ".$id, SQLITE_NUM))) {
                foreach($r as $row) {
                        $ret .= "<li>";

                        if (!($title = lookup_title($row[1]))) {
                                $ret .= $row[1]. ' [?]';
                        } else {
                                $ret .= "<a href='".generate_url_for_id($lang, 
$row[1])."'>".$title."</a>";
                        }

                        if (($level < 2 && strncmp($row[1], 'ref', 3)) ||  $level < 1) 
{
                                $ret .= do_contents($row[0], $level + 1);
                        }
                        $ret .= "</li>\n";
                }

                return "<ul>" . $ret . "</ul>\n";
        }

        return '';
}

function handle_include($node) 
{
        global $current_page;

        $ref = $node->attributes['ref'];
        
        $curr_lvl = sqlite_single_query($GLOBALS['idx'], "SELECT lvl from toc where 
docbook_id='$current_page'");
                
        list($row) = sqlite_array_query($GLOBALS['idx'], "SELECT idents.id, lvl from 
ents left join files on ents.value = files.filename left join idents on files.fileid = 
idents.fileid left join toc on ents.entid=toc.docbook_id where is_file=1 and 
ents.entid='$ref' limit 1");
        list($id, $lvl) = $row;

        $filename = sqlite_single_query($GLOBALS['idx'], "SELECT value from ents where 
entid='$ref' and is_file=1");

        $path = PHPDOC . DIRECTORY_SEPARATOR . $filename;

        if (!file_exists($path)) {
                $path = PHPDOC . DIRECTORY_SEPARATOR . $GLOBALS['lang'] . 
DIRECTORY_SEPARATOR . $filename;
        }

        if ($lvl > $curr_lvl) {

                $fake->content = null;
                $fake->attributes['linkend'] = $id;
                $fake->tagname = 'xref';

                return format_link($fake) . " [$ref, $id, $lvl vs $curr_lvl]<br />";
        }

        $doc = load_xml_doc($path, true, null);
        return "<!-- $ref : $filename -->" . $doc->transform($GLOBALS['map']);
}

// Handle the case where a requested node id was not found
function handle_missing_index() 
{
        global $current_page, $lang;

        header('Location: ' . WEBBASE . 'search.php?q=' . urlencode($current_page) . 
'&l=' . $lang);
        exit;
}

?>

http://cvs.php.net/co.php/livedocs/pregenerate.php?r=1.1&p=1
Index: livedocs/pregenerate.php
+++ livedocs/pregenerate.php
<?php
/* walk the index and spit out an html page for each item.
 * Could be modified to spit out .chm bits too.
 * Unfortunately, PHP 4 and reference assignments leak MASSIVE
 * amounts of memory if we run the whole thing in a single process.
 * So, only run this with PHP 5 if you value your RAM!
 */

define('LIVEDOC_SOURCE', dirname(__FILE__));
include LIVEDOC_SOURCE . '/livedoc_funcs.php';

$ids_and_pages = sqlite_query($idx, "select id, filename from idents left join files 
on idents.fileid=files.fileid");

$last_file_name = null;

chdir(OUTPUTDIR);
ob_start();

$start_time = microtime(true);
$gen_time = 0;
$clean_time = 0;
$number_processed = 0;
$note_time = 0;
$nav_time = 0;
$load_time = 0;

while ($page_row = sqlite_fetch_array($ids_and_pages)) {
        if ($last_file_name == $page_row[1])
                continue;

        $number_processed++;

        $last_file_name = $page_row[1];
        $current_page = $page_row[0];

        fwrite(STDERR, "Generating $current_page\t"); fflush(STDERR);
        
        $ts = microtime(true);
        list($title, $filename, $fileid, $dirid) = do_nav($idx, $fb_idx, $lang, 
$current_page, $nav, $children);
        $tnav = microtime(true) - $ts;

        $ts = microtime(true);
        list($page, $lang_rev) = load_xml_doc(BASE . $filename, false, FALLBACK_BASE . 
$filename, 1);
        $tload = microtime(true) - $ts;

        $load_time += $tload;
        $nav_time += $tnav;

        ob_clean();
        echo manual_page_header();

        $ts = microtime(true);
        echo $page->transform($map, $current_page);
        $tgen = microtime(true) - $ts;
        $gen_time += $tgen;

        if ($NOTESDB) {
                $tn = microtime(true);
                fwrite(STDERR, "[notes]\t"); fflush(STDERR);
                echo format_user_notes($current_page);
                $gen_note = microtime(true) - $tn;
                $note_time += $gen_note;
        } else {
                $gen_note = 0;
        }
        if (empty($file_revision)) {
                $file_revision = 'unknown revision';
        }
        echo manual_page_footer();
        $contents = ob_get_contents();
        ob_clean();
        
        
        $save_file = $lang . "/" . $current_page . ".html";
        fwrite(STDERR, "\t$save_file "); fflush(STDERR);
        $f = fopen($save_file, 'w');
        fwrite($f, $contents);
        fclose($f);

        fwrite(STDERR, "\n"); fflush(STDERR);

        $ts = microtime(true);
        $nodes = $__node_count;

        /* try to release as much memory as possible */
        $page = null;
        unset($page);
        unset($nav);
        unset($children);
        unset($current_page_title);
        unset($dirid);
        unset($fileid);
        unset($filename);
        unset($title);
        unset($file_revision);
        unset($contents);
        unset($f);
        unset($save_file);

        $tclean = microtime(true) - $ts;
        $clean_time += $tclean;

        fprintf(STDERR, "nav %.2fs, load %.2fs, gen %.2fs [note %.2fs], clean(%d) in 
%.2fs\n\n",
                $tnav, $tload,
                $tgen, $gen_note, $nodes, $tclean);

        if ($__node_count > 0) {
                fwrite(STDERR, "nodes: $__node_count\n"); fflush(STDERR);
        }
}

$elapsed = microtime(true) - $start_time;

fprintf(STDERR, "\nProcessed %d pages.\n\nOverall:    %.2fs   (%.2fs 
each)\nGeneration: %.2fs    (%.2fs each)\nCleaning:    %.2fs   (%.2fs each)\nNotes:  
%.2fs   (%.2fs each)\nNav: %.2fs   (%.2fs each)\nLoad:  %.2fs   (%.2fs each)\n\n",
        $number_processed,
        $elapsed, $elapsed / $number_processed,
        $gen_time, $gen_time / $number_processed,
        $clean_time, $clean_time / $number_processed,
        $nav_time, $nav_time / $number_processed,
        $load_time, $load_time / $number_processed,
        $note_time, $note_time / $number_processed
);



?>

http://cvs.php.net/co.php/livedocs/xml_classes5.php?r=1.1&p=1
Index: livedocs/xml_classes5.php
+++ livedocs/xml_classes5.php
<?php
/* vim: set tabstop=4 shiftwidth=4: */
// +----------------------------------------------------------------------+
// | PHP version 4                                                        |
// +----------------------------------------------------------------------+
// | Copyright (c) 1997-2004 The PHP Group                                |
// +----------------------------------------------------------------------+
// | This source file is subject to version 3.0 of the PHP license,       |
// | that is bundled with this package in the file LICENSE, and is        |
// | available through the world-wide-web at the following url:           |
// | http://www.php.net/license/3_0.txt.                                  |
// | If you did not receive a copy of the PHP license and are unable to   |
// | obtain it through the world-wide-web, please send a note to          |
// | [EMAIL PROTECTED] so we can mail you a copy immediately.               |
// +----------------------------------------------------------------------+
// | Authors: Wez Furlong, Derick Rethans, Ilia Alshanetsky               |
// +----------------------------------------------------------------------+
// | Two XML handling classes for the docbook to html transformation,     |
// | PHP 5 style                                                          |
// +----------------------------------------------------------------------+
//
// $Id: xml_classes5.php,v 1.1 2004/05/25 11:33:48 wez Exp $

class Node { /* {{{ */

        var $tagname = "";
        var $attributes = array();
        var $children = array();
        var $parent = null;
        var $index = 0;
        var $content = "";
        var $nodeid = 0;

        function transform($map) 
        {
                if (strlen($this->tagname) == 0) {
                        return htmlspecialchars($this->content, ENT_NOQUOTES);
                }

                $tagname = 'div';
                $attributes = $this->attributes;
                $attributes['class'] = $this->tagname;

                /* do we match any of the patterns in the map ? */
                foreach ($map as $mapent) {
                        if ($mapent[0][0] == $this->tagname) {
                                $n = $this->parent;
                                $match = true;
                                for ($i = 1; $i < count($mapent[0]); $i++) {
                                        if ($n->tagname != $mapent[0][$i]) {
                                                $match = false;
                                                break;
                                        }
                                        $n = $n->parent;
                                }
                                if ($match) {
                                        if (is_callable($mapent[1])) {
                                                return call_user_func($mapent[1], 
$this);
                                        } else {
                                                $tagname = $mapent[1];
                                        }
                                }
                        }
                }

                if (isset($this->attributes['id'])) {
                        $anchor = sprintf('<a name="%s"></a>', 
$this->attributes['id']);
                } else {
                        $anchor = '';
                }

                if (strlen($tagname)) {
                        $xml = '<' . $tagname;
                        foreach ($attributes as $name => $value) {
                                $xml .= ' ' . $name . '="' . htmlspecialchars($value) 
. '"';
                        }
                } else {
                        $xml = '';
                }
        
                $content = "";
        
                if (count($this->children) == 0) {
                        
                        if (strlen($tagname) == 0) {
                                return '';
                        }
                        
                        if (strlen($this->content)) {
                                $content = htmlspecialchars($this->content, 
ENT_NOQUOTES);
                        }
                } else {
                        for ($i = 0; $i < count($this->children); $i++) {
                                $child = $this->children[$i];
                                $content .= $child->transform($map);
                        }
                }

                if (strlen($tagname)) {
                        $xml .= '>';
                }

                if ($tagname == 'th' && strlen($content) == 0) {
                        $content = '&nbsp;';
                }
                
                $xml .= $anchor;
                $xml .= $content;
                if (strlen($tagname)) {
                        $xml .= '</' . $tagname . '>';
                }
                
                return $xml;
        }

        function select_node($id) 
        {
                if (isset($this->attributes['id']) && $this->attributes['id'] == $id) {
                        return $node;
                }
                // look for children that match
                for ($i = 0; $i < count($this->children); $i++) {
                        $x = $this->select_node($this->children[$i], $id);
                        if (is_object($x)) {
                                return $x;
                        }
                }
                return null;
        }
        
        function Node($tagname, $attributes) 
        {
                static $nodeid = 0;

                $this->nodeid = $nodeid++;
                $this->tagname = $tagname;
                $this->attributes = $attributes;

                $GLOBALS['__node_count']++;
        }

        function set_parent($parent) 
        {
                $this->parent = $parent;
                $this->index = count($parent->children);
                $parent->children[$this->index] = $this;
        }

        function compress() 
        {
                if (count($this->children) == 1 && $this->children[0]->tagname == '') {
                        $this->content = $this->children[0]->content;
                        $this->children = array();
                }
        }

        function as_xml() 
        {
                if (strlen($this->tagname) == 0) {
                        return htmlspecialchars($this->content, ENT_NOQUOTES);
                }

                $xml = '<' . $this->tagname;
                foreach ($this->attributes as $name => $value) {
                        $xml .= ' ' . $name . '="' . htmlspecialchars($value) . '"';
                }
                if (count($this->children) == 0) {
                        if (strlen($this->content) == 0) {
                                $xml .= '/>';
                        } else {
                                $xml .= '>' . htmlspecialchars($this->content, 
ENT_NOQUOTES) . '</' . $this->tagname . '>';
                        }
                } else {
                        $xml .= '>';
                        for ($i = 0; $i < count($this->children); $i++) {
                                $xml .= $this->children[$i]->as_xml();
                        }
                        $xml .= '</' . $this->tagname . '>';
                }
                return $xml;
        }

        function add_child($child) 
        {
                if (count($this->children) == 0 && strlen($this->content)) {
                        if (strlen(trim($this->content)) > 0) {
                                // promote content to an anonymous cdata node
                                $node = new Node("", array());
                                $node->content = $this->content;
                                $node->set_parent($this);
                        }
                        $this->content = "";
                }
                $child->set_parent($this);
        }

        function add_cdata($data) 
        {
                if (count($this->children) == 0) {
                        $this->content .= $data;
                } else {
                        $node = new Node("", array());
                        $node->content = $data;
                        $this->add_child($node);
                }
        }

        function __destruct() {
                $GLOBALS['__node_count']--;
        }

        function release()
        {
                for ($i = 0; $i < count($this->children); $i++) {
                        if (is_object($this->children[$i])) {
                                $this->children[$i]->release();
                        }
                }

                for ($i = 0; $i < count($this->children); $i++) {
                        $this->children[$i] = null;
                }

                $this->parent = null;
        }

}
/* }}} */



class DocBookToHTML { /* {{{ */

        var $html = "";
        var $top = null;
        var $current = null;

        function __destruct() {
                if (is_object($this->top)) {
                        $this->top->release();
                }
                if (is_object($this->current)) {
                        $this->current->release();
                }
                $this->top = null;
                unset($this->top);
                $this->current = null;
                unset($this->current);
        }
        
        function DocBookToHTML($xml, $id = null) 
        {
                if (strlen($xml) == 0) {
                        return;
                }

                $p = xml_parser_create();
                xml_set_object($p, $this);
                xml_parser_set_option($p, XML_OPTION_CASE_FOLDING, 0);
                xml_set_element_handler($p, 'start_elem', 'end_elem');
                xml_set_character_data_handler($p, 'cdata');

                if (!xml_parse($p, $xml, true)) {
                        printf("XML: %d:%d %s\n",
                                        xml_get_current_line_number($p),
                                        xml_get_current_column_number($p),
                                        xml_error_string(xml_get_error_code($p))
                                        );
                        $lines = explode("\n", $xml);
                        $l = xml_get_current_line_number($p);
                        echo "\nLine: $l is <b>" . htmlentities($lines[$l-1]) . 
"</b><br />\n";
                        echo '<pre>';
                        echo htmlentities($xml);
                        echo '</pre>';
                }
                xml_parser_free($p);

                if ($id !== null) {
                        $newtop = $this->top->select_node($id);
                        if (is_object($newtop)) {
                                $this->top = $newtop;
                                $this->top->parent = null;
                        }
                }
        }

        /* apply a transformation map to content */
        function transform($map)
        {
                /* pre-parse the map */

                if (!is_object($this->top)) {
                        return "<div class=\"warning\">XML document contained no 
data</div>";
                }

                $pmap = array();
                foreach ($map as $pat => $rep) {
                        $h = array_reverse(explode('/', $pat));
                        $pmap[] = array($h, $rep);
                }
                return $this->top->transform($pmap);
        }

        /* returns structure as XML */
        function as_xml() 
        {
                return $this->_as_xml($this->top);
        }

        function _as_xml($node) 
        {
                if (strlen($node->tagname) == 0) {
                        return htmlspecialchars($node->content, ENT_NOQUOTES);
                }

                $xml = '<' . $node->tagname;
                foreach ($node->attributes as $name => $value) {
                        $xml .= ' ' . $name . '="' . htmlspecialchars($value) . '"';
                }
                if (count($node->children) == 0) {
                        if (strlen($node->content) == 0) {
                                $xml .= '/>';
                        } else {
                                $xml .= '>' . htmlspecialchars($node->content, 
ENT_NOQUOTES) . '</' . $node->tagname . '>';
                        }
                } else {
                        $xml .= '>';
                        for ($i = 0; $i < count($node->children); $i++) {
                                $xml .= $this->_as_xml($node->children[$i]);
                        }
                        $xml .= '</' . $node->tagname . '>';
                }
                return $xml . "<!-- {$node->nodeid} -->";
        }

        function start_elem($parser, $tagname, $attributes) 
        {
                /* create a new node as a child of the current node */
                $node = new Node($tagname, $attributes);

                if ($this->top === null) {
                        /* set the top node */
                        $this->top = $node;
                        $this->current = $node;
                } else {
                        /* child of current */
                        $this->current->add_child($node);
                        $this->current = $node;
                }
        }

        function end_elem($parser, $tagname) 
        {
                /* pop up to parent of the current node */
                if ($this->current === null) {
                        return;
                }
                /* optimize the node; if it only contains a single cdata (anonymous) 
node,
                 * compress that node into the content */
                $this->current->compress();

                $this->current = $this->current->parent;
        }

        function cdata($parser, $data) 
        {
                $this->current->add_cdata($data);
        }
}
/* }}} */
?>

Reply via email to