mirror of
https://github.com/php/phd.git
synced 2026-03-23 22:52:05 +01:00
320 lines
12 KiB
PHP
320 lines
12 KiB
PHP
#!@php_bin@
|
|
<?php
|
|
/* $Id$ */
|
|
|
|
/* {{{ Find the $ROOT directory of PhD
|
|
@php_dir@ will be replaced by the pear package manager
|
|
If @php_dir@ however hasn't been replaced by anything,
|
|
fallback to the dir containing this file */
|
|
$ROOT = "@php_dir@/phd";
|
|
if ($ROOT == "@php_dir"."@/phd") {
|
|
$ROOT = dirname(__FILE__);
|
|
}
|
|
/* }}} */
|
|
|
|
(include $ROOT."/config.php")
|
|
&& isset($OPTIONS)
|
|
&& is_array($OPTIONS)
|
|
&& isset($OPTIONS["output_format"], $OPTIONS["output_theme"])
|
|
&& is_array($OPTIONS["output_theme"])
|
|
or die("Invalid configuration/file not found.\nThis should never happen, did you edit config.php yourself?\n");
|
|
|
|
require $ROOT. "/include/PhDReader.class.php";
|
|
require $ROOT. "/include/PhDPartialReader.class.php";
|
|
require $ROOT. "/include/PhDHelper.class.php";
|
|
require $ROOT. "/include/PhDFormat.class.php";
|
|
require $ROOT. "/include/PhDTheme.class.php";
|
|
require $ROOT. "/include/PhDThemeXhtml.class.php";
|
|
|
|
/* {{{ Build the .ser file names to allow multiple sources for PHD. */
|
|
$OPTIONS['index_location'] = $OPTIONS['xml_root'] . DIRECTORY_SEPARATOR . '.index_' . basename($OPTIONS['xml_file'], '.xml') . '.ser';
|
|
$OPTIONS['refnames_location'] = $OPTIONS['xml_root'] . DIRECTORY_SEPARATOR . '.refnames_' . basename($OPTIONS['xml_file'], '.xml') . '.ser';
|
|
$OPTIONS['classes_location'] = $OPTIONS['xml_root'] . DIRECTORY_SEPARATOR . '.classes_' . basename($OPTIONS['xml_file'], '.xml') . '.ser';
|
|
$OPTIONS['vars_location'] = $OPTIONS['xml_root'] . DIRECTORY_SEPARATOR . '.vars_' . basename($OPTIONS['xml_file'], '.xml') . '.ser';
|
|
/* }}} */
|
|
|
|
/* {{{ Index the DocBook file or load from .ser cache files
|
|
NOTE: There are two cache files (where * is the basename of the XML source file):
|
|
- index_*.ser (containing the ID infos)
|
|
- refnames_*.ser (containing <refname> => File ID) */
|
|
if (!$OPTIONS["index"] && (file_exists($OPTIONS['index_location']) && file_exists($OPTIONS['refnames_location']) && file_exists($OPTIONS['classes_location']) && file_exists($OPTIONS['vars_location']))) {
|
|
/* FIXME: Load from sqlite db? */
|
|
v("Unserializing cached index files...", VERBOSE_INDEXING);
|
|
|
|
$IDs = unserialize(file_get_contents($OPTIONS['index_location']));
|
|
$REFS = unserialize(file_get_contents($OPTIONS['refnames_location']));
|
|
$CLASSES = unserialize(file_get_contents($OPTIONS['classes_location']));
|
|
$VARS = unserialize(file_get_contents($OPTIONS['vars_location']));
|
|
|
|
v("Unserialization done", VERBOSE_INDEXING);
|
|
} else {
|
|
v("Indexing...", VERBOSE_INDEXING);
|
|
|
|
/* This file will "return" an $IDs, $REFS, $CLASSES, $VARS array */
|
|
require $ROOT. "/mktoc.php";
|
|
|
|
file_put_contents($OPTIONS['index_location'], $ids = serialize($IDs));
|
|
file_put_contents($OPTIONS['refnames_location'], $refs = serialize($REFS));
|
|
file_put_contents($OPTIONS['classes_location'], $classes = serialize($CLASSES));
|
|
file_put_contents($OPTIONS['vars_location'], $vars = serialize($VARS));
|
|
|
|
$IDs2 = unserialize($ids);
|
|
$REFS2 = unserialize($refs);
|
|
$CLASSES2 = unserialize($classes);
|
|
$VARS2 = unserialize($vars);
|
|
if ($IDs !== $IDs2 || $REFS !== $REFS2 || $CLASSES !== $CLASSES2 || $VARS !== $VARS2) {
|
|
trigger_error("Serialized representation does not match", E_USER_WARNING);
|
|
}
|
|
|
|
v("Indexing done", VERBOSE_INDEXING);
|
|
}
|
|
/* }}} */
|
|
|
|
foreach($OPTIONS["output_format"] as $output_format) {
|
|
v("Starting %s rendering", $output_format, VERBOSE_FORMAT_RENDERING);
|
|
|
|
switch($output_format) {
|
|
case "xhtml":
|
|
$classname = "XHTMLPhDFormat";
|
|
break;
|
|
case "manpage":
|
|
$classname = "ManpagePhDFormat";
|
|
break;
|
|
case "pdf":
|
|
$classname = "PDFPhDFormat";
|
|
break;
|
|
}
|
|
|
|
|
|
// {{{ Initialize the output format and fetch the methodmaps
|
|
require $ROOT. "/formats/$output_format.php";
|
|
$format = new $classname(array($IDs, $REFS, $CLASSES, $VARS));
|
|
$formatmap = $format->getElementMap();
|
|
$formattextmap = $format->getTextMap();
|
|
/* }}} */
|
|
|
|
/* {{{ initialize output themes and fetch the methodmaps */
|
|
$themes = $elementmaps = $textmaps = array();
|
|
foreach($OPTIONS["output_theme"][$output_format] as $theme => $array) {
|
|
is_dir($ROOT. "/themes/$theme") or die("Can't find the '$theme' theme");
|
|
v("Using the %s theme (%s)", $theme, join(", ", $array), VERBOSE_THEME_RENDERING);
|
|
|
|
foreach($array as $themename) {
|
|
$themename = basename($themename);
|
|
require_once $ROOT. "/themes/$theme/$themename.php";
|
|
switch($theme) {
|
|
// FIXME: This is stupid and definetly does not belong in here.
|
|
case "php":
|
|
$themes[$themename] = new $themename(array($IDs, $REFS, $CLASSES, $VARS),
|
|
array(
|
|
"version" => $OPTIONS["version_info"],
|
|
"acronym" => $OPTIONS["acronyms_file"],
|
|
)
|
|
);
|
|
break;
|
|
default:
|
|
$themes[$themename] = new $themename(array($IDs, $REFS, $CLASSES, $VARS));
|
|
}
|
|
|
|
$themes[$themename]->postConstruct();
|
|
$themes[$themename]->registerFormat($format);
|
|
|
|
|
|
// If the theme returns empty callback map there is no need to include it
|
|
$tmp = $themes[$themename]->getElementMap();
|
|
if(!empty($tmp)) {
|
|
$elementmaps[$themename] = $tmp;
|
|
}
|
|
|
|
$tmp = $themes[$themename]->getTextMap();
|
|
if (!empty($tmp)) {
|
|
$textmaps[$themename] = $tmp;
|
|
}
|
|
}
|
|
|
|
}
|
|
/* }}} */
|
|
|
|
/* {{{ Initialize the PhD[Partial]Reader */
|
|
if (!empty($OPTIONS["render_ids"]) || !empty($OPTIONS["skip_ids"])) {
|
|
$idlist = $OPTIONS["render_ids"]+$OPTIONS["skip_ids"];
|
|
|
|
v("Running partial build", VERBOSE_RENDER_STYLE);
|
|
if (!is_array($idlist)) {
|
|
$idlist = array($idlist => 1);
|
|
}
|
|
foreach($idlist as $id => $notused) {
|
|
if (!isset($IDs[$id])) {
|
|
trigger_error(sprintf("Unknown ID %s, bailing", $id), E_USER_ERROR);
|
|
}
|
|
}
|
|
|
|
$reader = new PhDPartialReader($OPTIONS);
|
|
} else {
|
|
v("Running full build", VERBOSE_RENDER_STYLE);
|
|
|
|
$reader = new PhDReader($OPTIONS);
|
|
}
|
|
/* }}} */
|
|
|
|
while($reader->read()) {
|
|
$nodetype = $reader->nodeType;
|
|
|
|
switch($nodetype) {
|
|
case XMLReader::ELEMENT:
|
|
case XMLReader::END_ELEMENT: /* {{{ */
|
|
$nodename = $reader->name;
|
|
$open = $nodetype == XMLReader::ELEMENT;
|
|
$isChunk = $reader->isChunk;
|
|
$attrs = $reader->getAttributes();
|
|
$props = array(
|
|
"empty" => $reader->isEmptyElement,
|
|
"isChunk" => $isChunk,
|
|
"lang" => $reader->xmlLang,
|
|
"ns" => $reader->namespaceURI,
|
|
"sibling" => $reader->getPreviousSiblingTagName(),
|
|
);
|
|
|
|
$skip = array();
|
|
foreach($elementmaps as $theme => $map) {
|
|
if (isset($map[$nodename])) {
|
|
$tag = $map[$nodename];
|
|
if (is_array($tag)) {
|
|
$tag = $reader->notXPath($tag);
|
|
}
|
|
if ($tag) {
|
|
if (strncmp($tag, "format_", 7)) {
|
|
$retval = $themes[$theme]->transformFromMap($open, $tag, $nodename, $attrs, $props);
|
|
if ($retval !== false) {
|
|
$themes[$theme]->appendData($retval, $isChunk);
|
|
$skip[] = $theme;
|
|
}
|
|
continue;
|
|
}
|
|
|
|
$funcname = $tag;
|
|
$retval = $themes[$theme]->{$funcname}($open, $nodename, $attrs, $props);
|
|
if ($retval !== false) {
|
|
$themes[$theme]->appendData($retval, $isChunk);
|
|
$skip[] = $theme;
|
|
}
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
|
|
$funcname = "format_$nodename";
|
|
if (count($skip) < count($themes)) {
|
|
if (isset($formatmap[$nodename])) {
|
|
$tag = $formatmap[$nodename];
|
|
if (is_array($tag)) {
|
|
$tag = $reader->notXPath($tag);
|
|
}
|
|
if (strncmp($tag, "format_", 7)) {
|
|
$retval = $format->transformFromMap($open, $tag, $nodename, $attrs, $props);
|
|
foreach($themes as $name => $theme) {
|
|
if (!in_array($name, $skip)) {
|
|
$theme->appendData($retval, $isChunk);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
$funcname = $tag;
|
|
}
|
|
$retval = $format->{$funcname}($open, $nodename, $attrs, $props);
|
|
foreach($themes as $name => $theme) {
|
|
if (!in_array($name, $skip)) {
|
|
$theme->appendData($retval, $isChunk);
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
/* }}} */
|
|
|
|
case XMLReader::TEXT: /* {{{ */
|
|
$skip = array();
|
|
$value = $reader->value;
|
|
$parentname = $reader->getParentTagName();
|
|
foreach($textmaps as $theme => $map) {
|
|
if (isset($map[$parentname])) {
|
|
$tagname = $map[$parentname];
|
|
if (is_array($tagname)) {
|
|
$tagname = $reader->notXPath($tagname, $reader->depth-1);
|
|
}
|
|
|
|
if ($tagname) {
|
|
$retval = $themes[$theme]->{$tagname}($value, $parentname);
|
|
if ($retval !== false) {
|
|
$skip[] = $theme;
|
|
$themes[$theme]->appendData($retval, false);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (count($skip) < count($themes)) {
|
|
$retval = false;
|
|
if (isset($formattextmap[$parentname])) {
|
|
$tagname = $formattextmap[$parentname];
|
|
if (is_array($tagname)) {
|
|
$tagname = $reader->notXPath($tagname, $reader->depth-1);
|
|
}
|
|
if ($tagname) {
|
|
$retval = $format->{$tagname}($value, $parentname);
|
|
}
|
|
}
|
|
if ($retval === false) {
|
|
$retval = $format->TEXT($value);
|
|
}
|
|
foreach ($themes as $name => $theme) {
|
|
if (!in_array($name, $skip)) {
|
|
$theme->appendData($retval, false);
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
/* }}} */
|
|
|
|
case XMLReader::CDATA: /* {{{ */
|
|
$value = $reader->value;
|
|
foreach($themes as $name => $theme) {
|
|
if (method_exists($theme, "CDATA"))
|
|
$retval = $theme->CDATA($value);
|
|
else
|
|
$retval = $format->CDATA($value);
|
|
$theme->appendData($retval, false);
|
|
}
|
|
break;
|
|
/* }}} */
|
|
|
|
case XMLReader::WHITESPACE:
|
|
case XMLReader::SIGNIFICANT_WHITESPACE: /* {{{ */
|
|
$value = $reader->value;
|
|
foreach($themes as $name => $theme) {
|
|
$theme->appendData($value, false);
|
|
}
|
|
break;
|
|
/* }}} */
|
|
|
|
case XMLReader::COMMENT:
|
|
case XMLReader::DOC_TYPE:
|
|
/* swallow it */
|
|
continue 2;
|
|
|
|
default:
|
|
$nodename = $reader->name;
|
|
trigger_error("Don't know how to handle {$nodename} {$nodetype}", E_USER_ERROR);
|
|
return;
|
|
}
|
|
}
|
|
|
|
$reader->close();
|
|
v("Finished rendering", VERBOSE_FORMAT_RENDERING);
|
|
|
|
} // foreach($OPTIONS["output_thtemes"])
|
|
|
|
/*
|
|
* vim600: sw=4 ts=4 syntax=php et
|
|
* vim<600: sw=4 ts=4
|
|
*/
|
|
|