1
0
mirror of https://github.com/php/phd.git synced 2026-03-24 07:02:07 +01:00
Files
archived-phd/render.php

311 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__);
}
/* }}} */
require_once ($ROOT . "/config.php");
(include $ROOT . "/include/PhDRenderOptions.class.php")
&& is_array(PhDConfig::output_theme())
or trigger_error("Invalid configuration. This should never happen, was config.php edited manually? Please re-run phd-setup.", E_USER_ERROR);
/* If no docbook file was passed, die */
if (!is_dir(PhDConfig::xml_root()) || !is_file(PhDConfig::xml_file())) {
trigger_error("No '.manual.xml' file was given. Specify it on the command line with --docbook.", E_USER_ERROR);
}
/* This needs to be done in *all* cases! */
PhDConfig::set_output_dir(realpath(PhDConfig::output_dir()) . DIRECTORY_SEPARATOR);
// These files really should be moved into phd/
PhDConfig::set_version_info(PhDConfig::xml_root()."/phpbook/phpbook-xsl/version.xml");
PhDConfig::set_acronyms_file(PhDConfig::xml_root()."/entities/acronyms.xml");
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";
/* {{{ Build the .ser file names to allow multiple sources for PHD. */
PhDConfig::set_index_location(PhDConfig::xml_root() . DIRECTORY_SEPARATOR . '.index_' . basename(PhDConfig::xml_file(), '.xml') . '.ser');
PhDConfig::set_refnames_location(PhDConfig::xml_root() . DIRECTORY_SEPARATOR . '.refnames_' . basename(PhDConfig::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 (!PhDConfig::index() && (file_exists(PhDConfig::index_location()) && file_exists(PhDConfig::refnames_location()))) {
/* FIXME: Load from sqlite db? */
v("Unserializing cached index files...", VERBOSE_INDEXING);
$IDs = unserialize(file_get_contents(PhDConfig::index_location()));
$REFS = unserialize(file_get_contents(PhDConfig::refnames_location()));
v("Unserialization done", VERBOSE_INDEXING);
} else {
v("Indexing...", VERBOSE_INDEXING);
/* This file will "return" an $IDs & $REFS array */
require $ROOT. "/mktoc.php";
file_put_contents(PhDConfig::index_location(), $ids = serialize($IDs));
file_put_contents(PhDConfig::refnames_location(), $refs = serialize($REFS));
$IDs2 = unserialize($ids);
$REFS2 = unserialize($refs);
if ($IDs !== $IDs2 || $REFS !== $REFS2) {
trigger_error("Serialized representation does not match", E_USER_WARNING);
}
v("Indexing done", VERBOSE_INDEXING);
}
/* }}} */
foreach(PhDConfig::output_format() as $output_format) {
v("Starting %s rendering", $output_format, VERBOSE_FORMAT_RENDERING);
switch($output_format) {
case "xhtml":
$classname = "XHTMLPhDFormat";
break;
}
// {{{ Initialize the output format and fetch the methodmaps
require $ROOT. "/formats/$output_format.php";
$format = new $classname(array($IDs, $REFS));
$formatmap = $format->getElementMap();
$formattextmap = $format->getTextMap();
/* }}} */
/* {{{ initialize output themes and fetch the methodmaps */
$themes = $elementmaps = $textmaps = array();
foreach(val(PhDConfig::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),
array(
"version" => PhDConfig::version_info(),
"acronym" => PhDConfig::acronyms_file(),
)
);
break;
default:
$themes[$themename] = new $themename(array($IDs, $REFS));
}
// FIXME: this needs to go away when we add support for
// things other than xhtml
$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 */
$idlist = PhDConfig::render_ids()+PhDConfig::skip_ids();
if (!empty($idlist)) {
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();
} else {
v("Running full build", VERBOSE_RENDER_STYLE);
$reader = new PhDReader();
}
/* }}} */
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(PhDConfig::output_themes())
?>