mirror of
https://github.com/php/phd.git
synced 2026-03-24 07:02:07 +01:00
Preface elements are now rendered inline in the parent page instead of being chunked into separate pages. Explicit annotations like chunk:true or phd:chunk="true" can still force chunking.
465 lines
17 KiB
PHP
465 lines
17 KiB
PHP
<?php
|
|
namespace phpdotnet\phd;
|
|
|
|
class Index extends Format
|
|
{
|
|
private $myelementmap = array(
|
|
'article' => 'format_container_chunk',
|
|
'appendix' => 'format_container_chunk',
|
|
'bibliography' => array(
|
|
/* DEFAULT */ false,
|
|
'article' => 'format_chunk',
|
|
'book' => 'format_chunk',
|
|
'part' => 'format_chunk',
|
|
),
|
|
'book' => 'format_container_chunk',
|
|
'chapter' => 'format_container_chunk',
|
|
'colophon' => 'format_chunk',
|
|
'glossary' => array(
|
|
/* DEFAULT */ false,
|
|
'article' => 'format_chunk',
|
|
'book' => 'format_chunk',
|
|
'part' => 'format_chunk',
|
|
),
|
|
'index' => array(
|
|
/* DEFAULT */ false,
|
|
'article' => 'format_chunk',
|
|
'book' => 'format_chunk',
|
|
'part' => 'format_chunk',
|
|
),
|
|
'legalnotice' => 'format_chunk',
|
|
'part' => 'format_container_chunk',
|
|
'phpdoc:exception' => 'format_container_chunk',
|
|
'phpdoc:exceptionref' => 'format_container_chunk',
|
|
'phpdoc:classref' => 'format_container_chunk',
|
|
'phpdoc:varentry' => 'format_chunk',
|
|
'preface' => 'format_chunk',
|
|
'refentry' => 'format_refentry',
|
|
'reference' => 'format_reference',
|
|
'sect1' => 'format_chunk',
|
|
'section' => array(
|
|
/* DEFAULT */ false,
|
|
'sect1' => 'format_section_chunk',
|
|
'chapter' => 'format_section_chunk',
|
|
'appendix' => 'format_section_chunk',
|
|
'article' => 'format_section_chunk',
|
|
'part' => 'format_section_chunk',
|
|
'reference' => 'format_section_chunk',
|
|
'refentry' => 'format_section_chunk',
|
|
'index' => 'format_section_chunk',
|
|
'bibliography' => 'format_section_chunk',
|
|
'glossary' => 'format_section_chunk',
|
|
'colopone' => 'format_section_chunk',
|
|
'book' => 'format_section_chunk',
|
|
'set' => 'format_section_chunk',
|
|
'setindex' => 'format_section_chunk',
|
|
'legalnotice' => 'format_section_chunk',
|
|
),
|
|
'set' => 'format_container_chunk',
|
|
'setindex' => 'format_chunk',
|
|
'title' => 'format_long_desc',
|
|
'refpurpose' => 'format_long_desc',
|
|
'refname' => 'format_short_desc',
|
|
'titleabbrev' => 'format_short_desc',
|
|
'example' => 'format_example',
|
|
'refsect1' => 'format_refsect1',
|
|
'row' => array(
|
|
/* DEFAULT */ null,
|
|
'tbody' => 'format_row',
|
|
),
|
|
'entry' => array(
|
|
/* DEFAULT */ null,
|
|
"row" => array(
|
|
/* DEFAULT */ null,
|
|
"tbody" => 'format_entry',
|
|
),
|
|
),
|
|
);
|
|
|
|
private $mytextmap = array(
|
|
);
|
|
private $pihandlers = array(
|
|
'dbhtml' => 'PI_DBHTMLHandler',
|
|
'phpdoc' => 'PI_PHPDOCHandler',
|
|
);
|
|
|
|
private bool $inLongDesc = false;
|
|
private bool $inShortDesc = false;
|
|
private string $currentLongDesc = "";
|
|
private string $currentShortDesc = "";
|
|
private $currentchunk;
|
|
private $ids = array();
|
|
private $currentid;
|
|
private $chunks = array();
|
|
private $isChunk = array();
|
|
protected $nfo = array();
|
|
private $isSectionChunk = array();
|
|
private $previousId = "";
|
|
private $inChangelog = false;
|
|
private $currentChangelog = array();
|
|
private string $currentChangeLogString = "";
|
|
protected $changelog = array();
|
|
private $currentMembership = null;
|
|
private $commit = array();
|
|
private $POST_REPLACEMENT_INDEXES = array();
|
|
private $POST_REPLACEMENT_VALUES = array();
|
|
private int $exampleCounter = 0;
|
|
|
|
public function __construct(
|
|
IndexRepository $indexRepository,
|
|
Config $config,
|
|
OutputHandler $outputHandler
|
|
) {
|
|
$this->indexRepository = $indexRepository;
|
|
parent::__construct($config, $outputHandler);
|
|
}
|
|
|
|
public function transformFromMap($open, $tag, $name, $attrs, $props) {
|
|
}
|
|
public function TEXT($value) {
|
|
if ($this->inLongDesc) {
|
|
$this->currentLongDesc .= $value;
|
|
}
|
|
if ($this->inShortDesc) {
|
|
$this->currentShortDesc .= $value;
|
|
}
|
|
if ($this->inChangelog) {
|
|
$this->currentChangeLogString .= $value;
|
|
}
|
|
}
|
|
public function CDATA($value) {
|
|
}
|
|
public function createLink($for, &$desc = null, $type = Format::SDESC) {
|
|
}
|
|
public function appendData($data) {
|
|
if ($this->inLongDesc && is_string($data) && trim($data) === "") {
|
|
$this->currentLongDesc .= $data;
|
|
}
|
|
if ($this->inShortDesc && is_string($data) && trim($data) === "") {
|
|
$this->currentShortDesc .= $data;
|
|
}
|
|
if ($this->inChangelog && is_string($data) && trim($data) === "") {
|
|
$this->currentChangeLogString .= $data;
|
|
}
|
|
}
|
|
|
|
public function update($event, $value = null)
|
|
{
|
|
switch($event) {
|
|
case Render::CHUNK:
|
|
$this->flags = $value;
|
|
break;
|
|
|
|
case Render::STANDALONE:
|
|
if ($value) {
|
|
$this->registerElementMap(static::getDefaultElementMap());
|
|
$this->registerTextMap(static::getDefaultTextMap());
|
|
$this->registerPIHandlers($this->pihandlers);
|
|
}
|
|
break;
|
|
case Render::INIT:
|
|
if ($value) {
|
|
$this->indexRepository->init();
|
|
$this->chunks = array();
|
|
} else {
|
|
print_r($this->chunks);
|
|
}
|
|
break;
|
|
case Render::FINALIZE:
|
|
$this->indexRepository->saveIndexingTime(time());
|
|
if ($this->indexRepository->commit(
|
|
$this->commit,
|
|
$this->POST_REPLACEMENT_INDEXES,
|
|
$this->POST_REPLACEMENT_VALUES,
|
|
$this->changelog,
|
|
)) {
|
|
$this->commit = [];
|
|
}
|
|
if ($this->indexRepository->lastErrorCode()) {
|
|
trigger_error($this->indexRepository->lastErrorMsg(), E_USER_WARNING);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
public function getDefaultElementMap() {
|
|
return $this->myelementmap;
|
|
}
|
|
public function getDefaultTextMap() {
|
|
return $this->mytextmap;
|
|
}
|
|
public function UNDEF($open, $name, $attrs, $props) {
|
|
if ($open) {
|
|
if(isset($attrs[Reader::XMLNS_XML]["id"])) {
|
|
$id = $attrs[Reader::XMLNS_XML]["id"];
|
|
$this->storeInfo($name, $id, $this->currentchunk, false);
|
|
if ($props["empty"]) {
|
|
$this->appendID();
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
if(isset($attrs[Reader::XMLNS_XML]["id"])) {
|
|
$this->appendID();
|
|
}
|
|
return false;
|
|
}
|
|
protected function storeInfo($elm, $id, $filename, $isChunk = true) {
|
|
$this->ids[] = $id;
|
|
$this->currentid = $id;
|
|
$this->nfo[$id] = array(
|
|
"parent" => "",
|
|
"filename" => $filename,
|
|
"sdesc" => "",
|
|
"ldesc" => "",
|
|
"element" => $elm,
|
|
"children" => array(),
|
|
"previous" => $isChunk ? $this->previousId : "",
|
|
"chunk" => $isChunk,
|
|
);
|
|
// Append "next" to the previously inserted row
|
|
if ($isChunk) {
|
|
$this->POST_REPLACEMENT_VALUES[$this->previousId] = $id;
|
|
$this->previousId = $id;
|
|
}
|
|
}
|
|
public function appendID() {
|
|
static $idx = -1;
|
|
$lastChunkId = array_pop($this->ids);
|
|
$parentid = end($this->ids);
|
|
$this->currentid = $parentid;
|
|
|
|
$lastChunk = $this->nfo[$lastChunkId];
|
|
if (is_array($lastChunk["sdesc"])) {
|
|
$array = true;
|
|
$sdesc = array_shift($lastChunk["sdesc"]);
|
|
} else {
|
|
$array = false;
|
|
$sdesc = $lastChunk["sdesc"];
|
|
}
|
|
|
|
$this->commit[++$idx] = [
|
|
"docbook_id" => $lastChunkId,
|
|
"filename" => $lastChunk["filename"],
|
|
"parent_id" => $this->currentchunk,
|
|
"sdesc" => $sdesc,
|
|
"ldesc" => $lastChunk["ldesc"],
|
|
"element" => $lastChunk["element"],
|
|
"previous" => $lastChunk["previous"],
|
|
"next" => ($lastChunk["chunk"] ? "POST-REPLACEMENT" : ""),
|
|
"chunk" => $lastChunk["chunk"],
|
|
];
|
|
if ($lastChunk["chunk"]) {
|
|
$this->POST_REPLACEMENT_INDEXES[] = array("docbook_id" => $lastChunkId, "idx" => $idx);
|
|
}
|
|
if ($array === true) {
|
|
foreach($lastChunk["sdesc"] as $sdesc) {
|
|
$this->commit[++$idx] = [
|
|
"docbook_id" => $lastChunkId,
|
|
"filename" => $lastChunk["filename"],
|
|
"parent_id" => $this->currentchunk,
|
|
"sdesc" => $sdesc,
|
|
"ldesc" => $lastChunk["ldesc"],
|
|
"element" => $lastChunk["element"],
|
|
"previous" => $lastChunk["previous"],
|
|
"next" => ($lastChunk["chunk"] ? "POST-REPLACEMENT" : ""),
|
|
"chunk" => 0,
|
|
];
|
|
$this->POST_REPLACEMENT_INDEXES[] = array("docbook_id" => $lastChunkId, "idx" => $idx);
|
|
}
|
|
}
|
|
|
|
}
|
|
public function format_section_chunk($open, $name, $attrs, $props) {
|
|
if ($open) {
|
|
if (!isset($attrs[Reader::XMLNS_XML]["id"])) {
|
|
$this->isSectionChunk[] = false;
|
|
return $this->UNDEF($open, $name, $attrs, $props);
|
|
}
|
|
$this->isSectionChunk[] = true;
|
|
return $this->format_chunk($open, $name, $attrs, $props);
|
|
}
|
|
if (array_pop($this->isSectionChunk)) {
|
|
return $this->format_chunk($open, $name, $attrs, $props);
|
|
}
|
|
return $this->UNDEF($open, $name, $attrs, $props);
|
|
}
|
|
public function format_container_chunk($open, $name, $attrs, $props) {
|
|
if ($open) {
|
|
if ($name == "book") {
|
|
$this->currentMembership = null;
|
|
}
|
|
return $this->format_chunk($open, $name, $attrs, $props);
|
|
}
|
|
return $this->format_chunk($open, $name, $attrs, $props);
|
|
}
|
|
|
|
public function format_refentry($open, $name, $attrs, $props) {
|
|
/* Note role attribute also has usage with "noversion" to not check version availability */
|
|
/* We overwrite the tag name to continue working with the usual indexing */
|
|
if (isset($attrs[Reader::XMLNS_DOCBOOK]['role'])) {
|
|
return match ($attrs[Reader::XMLNS_DOCBOOK]['role']) {
|
|
'class', 'enum' => $this->format_container_chunk($open, 'phpdoc:classref', $attrs, $props),
|
|
'exception' => $this->format_container_chunk($open, 'phpdoc:exceptionref', $attrs, $props),
|
|
'variable' => $this->format_chunk($open, 'phpdoc:varentry', $attrs, $props),
|
|
'stream_wrapper' => $this->format_chunk($open, 'stream_wrapper', $attrs, $props),
|
|
'stream_context_option' => $this->format_chunk($open, 'stream_context_option', $attrs, $props),
|
|
default => $this->format_chunk($open, $name, $attrs, $props),
|
|
};
|
|
}
|
|
return $this->format_chunk($open, $name, $attrs, $props);
|
|
}
|
|
|
|
public function format_chunk($open, $name, $attrs, $props) {
|
|
if ($props["empty"]) {
|
|
return false;
|
|
}
|
|
|
|
$this->processFilename();
|
|
if ($open) {
|
|
if(isset($attrs[Reader::XMLNS_XML]["id"])) {
|
|
$id = $attrs[Reader::XMLNS_XML]["id"];
|
|
} else {
|
|
$this->isChunk[] = false;
|
|
return false;
|
|
}
|
|
|
|
/* Legacy way to mark chunks */
|
|
if (isset($attrs[Reader::XMLNS_PHD]['chunk'])) {
|
|
$this->isChunk[] = $attrs[Reader::XMLNS_PHD]['chunk'] == "true";
|
|
} elseif (isset($attrs[Reader::XMLNS_DOCBOOK]['annotations'])) {
|
|
$this->isChunk[] = !str_contains($attrs[Reader::XMLNS_DOCBOOK]['annotations'], 'chunk:false');
|
|
} else {
|
|
$this->isChunk[] = ($name !== 'preface');
|
|
}
|
|
|
|
if (end($this->isChunk)) {
|
|
$this->chunks[] = $id;
|
|
$this->currentchunk = $id;
|
|
$this->storeInfo($name, $id, $id);
|
|
} else {
|
|
$this->storeInfo($name, $id, $this->currentchunk, false);
|
|
$this->appendID();
|
|
}
|
|
return false;
|
|
}
|
|
if (array_pop($this->isChunk)) {
|
|
array_pop($this->chunks);
|
|
$this->currentchunk = end($this->chunks);
|
|
$this->appendID();
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public function format_long_desc($open, $name, $attrs, $props) {
|
|
if ($open) {
|
|
$this->inLongDesc = true;
|
|
$this->currentLongDesc = "";
|
|
return;
|
|
}
|
|
$this->inLongDesc = false;
|
|
if ($this->nfo[$this->currentid]["ldesc"] === "") {
|
|
$this->nfo[$this->currentid]["ldesc"] = htmlentities(trim($this->currentLongDesc), ENT_COMPAT, "UTF-8");
|
|
}
|
|
}
|
|
public function format_short_desc($open, $name, $attrs, $props) {
|
|
if ($open) {
|
|
$this->inShortDesc = true;
|
|
$this->currentShortDesc = "";
|
|
return;
|
|
}
|
|
$this->inShortDesc = false;
|
|
$s = htmlentities(trim($this->currentShortDesc), ENT_COMPAT, "UTF-8");
|
|
if ($this->nfo[$this->currentid]["sdesc"] === "") {
|
|
$this->nfo[$this->currentid]["sdesc"] = $s;
|
|
} else {
|
|
if (!is_array($this->nfo[$this->currentid]["sdesc"])) {
|
|
$this->nfo[$this->currentid]["sdesc"] = (array)$this->nfo[$this->currentid]["sdesc"];
|
|
}
|
|
//In the beginning of the array to stay compatible with 0.4
|
|
array_unshift($this->nfo[$this->currentid]["sdesc"], $s);
|
|
}
|
|
}
|
|
|
|
public function format_example($open, $name, $attrs, $props) {
|
|
if ($open) {
|
|
++$this->exampleCounter;
|
|
|
|
if(isset($attrs[Reader::XMLNS_XML]["id"])) {
|
|
$id = $attrs[Reader::XMLNS_XML]["id"];
|
|
}
|
|
else {
|
|
$id = "example-" . $this->exampleCounter;
|
|
}
|
|
|
|
$this->storeInfo($name, $id, $this->currentchunk, false);
|
|
return false;
|
|
}
|
|
|
|
$this->appendID();
|
|
return false;
|
|
}
|
|
public function format_refsect1($open, $name, $attrs, $props) {
|
|
if ($open) {
|
|
if (isset($attrs[Reader::XMLNS_DOCBOOK]['role'])) {
|
|
if ($attrs[Reader::XMLNS_DOCBOOK]['role'] == "changelog") {
|
|
$this->inChangelog = true;
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
$this->inChangelog = false;
|
|
}
|
|
|
|
public function format_entry($open, $name, $attrs, $props) {
|
|
if ($open) {
|
|
$this->currentChangeLogString = "";
|
|
return;
|
|
}
|
|
if ($this->inChangelog) {
|
|
$this->currentChangelog[] = htmlentities(trim($this->currentChangeLogString), ENT_COMPAT, "UTF-8");
|
|
}
|
|
}
|
|
|
|
public function format_row($open, $name, $attrs, $props) {
|
|
if ($this->inChangelog) {
|
|
if ($open) {
|
|
$parent_id = $this->ids[count($this->ids) - 2];
|
|
$this->currentChangelog = array($this->currentMembership, $parent_id);
|
|
} else {
|
|
$this->changelog[$this->currentid][] = $this->currentChangelog;
|
|
}
|
|
}
|
|
|
|
/* Fall back to regular handling so contents get processed */
|
|
return $this->UNDEF($open, $name, $attrs, $props);
|
|
}
|
|
|
|
public function processFilename() {
|
|
static $dbhtml = null;
|
|
if ($dbhtml == null) {
|
|
$dbhtml = $this->getPIHandler("dbhtml");
|
|
}
|
|
$filename = $dbhtml->getAttribute("filename");
|
|
if ($filename) {
|
|
$this->nfo[end($this->chunks)]["filename"] = $filename;
|
|
$dbhtml->setAttribute("filename", false);
|
|
}
|
|
}
|
|
|
|
public function setMembership($membership) {
|
|
$this->currentMembership = $membership;
|
|
}
|
|
|
|
public function format_reference($open, $name, $attrs, $props) {
|
|
if (isset($attrs[Reader::XMLNS_DOCBOOK]['role'])) {
|
|
$name = match ($attrs[Reader::XMLNS_DOCBOOK]['role']) {
|
|
"class", "enum" => "phpdoc:classref",
|
|
"exception" => "phpdoc:exceptionref",
|
|
default => $name,
|
|
};
|
|
}
|
|
return $this->format_container_chunk($open, $name, $attrs, $props);
|
|
}
|
|
}
|