1
0
mirror of https://github.com/php/phd.git synced 2026-03-23 22:52:05 +01:00
Files
archived-phd/phpdotnet/phd/Package/PHP/PDF.php
2024-12-29 19:58:10 +00:00

322 lines
13 KiB
PHP

<?php
namespace phpdotnet\phd;
class Package_PHP_PDF extends Package_Generic_PDF {
protected $elementmap = array(
'article' => 'format_tocnode_newpage',
'appendix' => 'format_tocnode_newpage',
'book' => 'format_book',
'bibliography' => array(
/* DEFAULT */ 'format_suppressed_tags',
'article' => 'format_tocnode_newpage',
'book' => 'format_tocnode_newpage',
'part' => 'format_tocnode_newpage',
),
'callout' => 'format_collect_id',
'chapter' => 'format_tocnode_newpage',
'co' => 'format_collect_id',
'colophon' => 'format_tocnode_newpage',
'footnote' => 'format_collect_id',
'glossary' => array(
/* DEFAULT */ 'format_suppressed_tags',
'article' => 'format_tocnode_newpage',
'book' => 'format_tocnode_newpage',
'part' => 'format_tocnode_newpage',
),
'index' => array(
/* DEFAULT */ 'format_suppressed_tags',
'article' => 'format_tocnode_newpage',
'book' => 'format_tocnode_newpage',
'part' => 'format_tocnode_newpage',
),
'legalnotice' => 'format_tocnode_newpage',
'part' => 'format_tocnode_newpage',
'phpdoc:exceptionref' => 'format_tocnode_exception',
'phpdoc:classref' => 'format_tocnode_class',
'preface' => 'format_tocnode_newpage',
'refentry' => 'format_tocnode_newpage',
'reference' => 'format_tocnode_newpage',
'phpdoc:varentry' => 'format_tocnode_newpage',
'sect1' => 'format_tocnode',
'sect2' => 'format_tocnode',
'sect3' => 'format_tocnode',
'sect4' => 'format_tocnode',
'sect5' => 'format_tocnode',
'section' => 'format_tocnode',
'set' => array(
/* DEFAULT */ 'format_root_set',
'set' => 'format_set',
),
'setindex' => 'format_tocnode_newpage',
);
protected $textmap = array(
'title' => array(
/* DEFAULT */ false,
'book' => 'format_bookname',
'set' => array(
/* DEFAULT */ 'format_setname',
'set' => false,
),
),
'type' => array(
/* DEFAULT */ 'format_type_text',
'classsynopsisinfo' => false,
'fieldsynopsis' => 'format_type_if_object_or_pseudo_text',
'methodparam' => 'format_type_if_object_or_pseudo_text',
'methodsynopsis' => array(
/* DEFAULT */ 'format_type_if_object_or_pseudo_text',
'classsynopsis' => false,
),
),
'titleabbrev' => array(
/* DEFAULT */ 'format_suppressed_tags',
'phpdoc:classref' => 'format_grep_classname_text',
'phpdoc:exceptionref' => 'format_grep_classname_text',
),
);
/* Common properties for all functions pages */
protected $bookName = "";
/* Current Chunk settings */
protected $cchunk = array();
/* Default Chunk settings */
protected $dchunk = array(
"phpdoc:classref" => null,
"bookname" => null,
"setname" => null,
"toc-root" => null,
"id-to-outline" => array(),
"id-to-page" => array(),
"root-outline" => null,
);
public function __construct(
Config $config,
OutputHandler $outputHandler
) {
parent::__construct($config, $outputHandler);
$this->registerFormatName("PHP-PDF");
$this->setTitle("PHP Manual");
}
public function __destruct() {}
public function update($event, $value = null) {
switch($event) {
case Render::STANDALONE:
if ($value) {
$this->registerElementMap($this->getDefaultElementMap());
$this->registerTextMap($this->getDefaultTextMap());
} else {
$this->registerElementMap($this->elementmap);
$this->registerTextMap($this->elementmap);
}
break;
case Render::INIT:
if (!class_exists("HaruDoc")) die ("PDF output needs libharu & haru/pecl extensions... Please install them and start PhD again.\n");
$this->setOutputDir($this->config->outputDir . strtolower($this->getFormatName()) . DIRECTORY_SEPARATOR);
if(!file_exists($this->getOutputDir()) || is_file($this->getOutputDir())) mkdir($this->getOutputDir(), 0777, true) or die("Can't create the cache directory.\n");
break;
case Render::VERBOSE:
$this->outputHandler->v("Starting %s rendering", $this->getFormatName(), VERBOSE_FORMAT_RENDERING);
break;
}
}
public function getDefaultElementMap() {
return array_merge(parent::getDefaultElementMap(), $this->elementmap);
}
public function getDefaultTextMap() {
return array_merge(parent::getDefaultTextMap(), $this->textmap);
}
// Do nothing
public function appendData($data) {}
// To override
public function format_root_set($open, $name, $attrs, $props) {}
public function format_set($open, $name, $attrs, $props) {}
public function format_book($open, $name, $attrs, $props) {
if ($open) {
parent::newChunk();
$this->cchunk = $this->dchunk;
$pdfDoc = new PdfWriter();
try {
$pdfDoc->setCompressionMode(\HaruDoc::COMP_ALL);
} catch (\HaruException $e) {
trigger_error("PDF Compression failed, you need to compile libharu with Zlib...", E_USER_WARNING);
}
parent::setPdfDoc($pdfDoc);
if (isset($attrs[Reader::XMLNS_XML]["base"]) && $base = $attrs[Reader::XMLNS_XML]["base"])
parent::setChunkInfo("xml-base", $base);
$id = $attrs[Reader::XMLNS_XML]["id"];
$this->cchunk["root-outline"] = $this->cchunk["id-to-outline"][$id] =
$pdfDoc->createOutline(Format::getShortDescription($id), null, true);
$this->setIdToPage($id);
} else {
$this->resolveLinks($this->cchunk["bookname"]);
$pdfDoc = parent::getPdfDoc();
$this->outputHandler->v("Writing PDF Manual (%s)", $this->cchunk["bookname"], VERBOSE_TOC_WRITING);
$pdfDoc->saveToFile($this->getOutputDir() . $this->toValidName($this->cchunk["bookname"]) . $this->getExt());
unset($pdfDoc);
}
return false;
}
public function format_bookname($value, $tag) {
$this->cchunk["bookname"] = trim($value);
parent::getPdfDoc()->setCurrentBookName($this->cchunk["bookname"]);
parent::getPdfDoc()->appendText($this->cchunk["bookname"]);
return false;
}
public function format_setname($value, $tag) {
$this->cchunk["setname"] = trim($value);
parent::getPdfDoc()->appendText($this->cchunk["setname"]);
return false;
}
public function format_tocnode($open, $name, $attrs, $props, $newpage = false) {
if ($open) {
if ($newpage) {
parent::getPdfDoc()->add(PdfWriter::PAGE);
} else {
parent::getPdfDoc()->add(PdfWriter::LINE_JUMP);
}
if (isset($attrs[Reader::XMLNS_XML]["base"]) && $base = $attrs[Reader::XMLNS_XML]["base"]) {
parent::setChunkInfo("xml-base", $base);
}
if (isset($attrs[Reader::XMLNS_XML]["id"]) && $id = $attrs[Reader::XMLNS_XML]["id"]) {
$parentId = Format::getParent($id);
if (isset($this->cchunk["id-to-outline"][$parentId])) {
$this->cchunk["id-to-outline"][$id] = parent::getPdfDoc()->createOutline
(Format::getShortDescription($id), $this->cchunk["id-to-outline"][$parentId], false);
} else {
$this->cchunk["id-to-outline"][$id] = parent::getPdfDoc()->createOutline
(Format::getShortDescription($id), $this->cchunk["root-outline"], false);
}
$this->setIdToPage($id);
}
parent::setChunkInfo("examplenumber", 0);
}
return "";
}
public function format_tocnode_newpage($open, $name, $attrs, $props) {
return $this->format_tocnode($open, $name, $attrs, $props, true);
}
public function format_tocnode_exception($open, $name, $attrs, $props) {
return $this->format_tocnode($open, "reference", $attrs, $props, true);
}
public function format_tocnode_class($open, $name, $attrs, $props) {
return $this->format_tocnode($open, "reference", $attrs, $props, true);
}
public function format_grep_classname_text($value, $tag) {
$this->cchunk["phpdoc:classref"] = strtolower($value);
}
// Convert the book name to a Unix valid filename
protected function toValidName($functionName) {
return str_replace(array(":", "::", "->", "/", "\\", " "), array(".", ".", ".", "-", "-", "-"), $functionName);
}
protected function setIdToPage($id) {
if (isset($this->cchunk["id-to-page"]) && is_array($this->cchunk["id-to-page"])) {
$this->cchunk["id-to-page"][$id] = parent::getPdfDoc()->getCurrentPage();
}
}
protected function resolveLinks($name) {
$this->outputHandler->v("Resolving Internal Links... (%s)", $name, VERBOSE_TOC_WRITING);
$linksToResolve = parent::getChunkInfo("links-to-resolve");
foreach ($linksToResolve as $link => $targets) {
if (isset($this->cchunk["id-to-page"][$link]) && $destPage = $this->cchunk["id-to-page"][$link]) {
foreach ($targets as $target) {
$page = $target[0];
$rectangle = array($target[1], $target[2], $target[3], $target[4]);
parent::getPdfDoc()->resolveInternalLink($page, $rectangle, $destPage);
}
}
}
}
public function format_type_text($type) {
$type = trim(preg_replace('/[ \n\t]+/', ' ', $type));
$t = strtolower($type);
switch($t) {
case "bool":
$href = "language.types.boolean";
break;
case "int":
case "long":
$href = "language.types.integer";
break;
case "double":
$href = "language.types.float";
break;
case "void":
case "boolean":
case "integer":
case "float":
case "string":
case "array":
case "object":
case "resource":
case "null":
case "callable":
case "iterable":
$href = "language.types.$t";
break;
case "mixed":
$href = "language.types.declarations";
break;
default:
/* Check if its a classname. */
$t = strtolower(str_replace(array("_", "::", "->"), array("-", "-", "-"), $t));
$href = Format::getFilename("class.$t");
}
parent::getPdfDoc()->setFont(PdfWriter::FONT_NORMAL, 12, array(0, 0, 1)); // blue
$linkAreas = parent::getPdfDoc()->add(PdfWriter::LINK_ANNOTATION, $type);
$linksToResolve = parent::getChunkInfo("links-to-resolve");
if (!isset($linksToResolve[$href]))
$linksToResolve[$href] = array();
foreach ($linkAreas as $area)
$linksToResolve[$href][] = $area;
parent::setChunkInfo("links-to-resolve", $linksToResolve);
parent::getPdfDoc()->revertFont();
return '';
}
public function format_type_if_object_or_pseudo_text($type) {
if (in_array(strtolower($type), array("bool", "int", "double", "boolean", "integer", "float", "string", "array", "object", "resource", "null"))) {
parent::getPdfDoc()->appendText(" " . $type);
return false;
}
return self::format_type_text($type);
}
public function format_collect_id($open, $name, $attrs) {
if ($open && isset($attrs[Reader::XMLNS_XML]["id"]) && $id = $attrs[Reader::XMLNS_XML]["id"]) {
$this->setIdToPage($id);
}
return false;
}
}