1
0
mirror of https://github.com/php/phd.git synced 2026-03-24 15:12:18 +01:00
Files
archived-phd/phpdotnet/phd/IndexRepository.php

281 lines
9.8 KiB
PHP

<?php
namespace phpdotnet\phd;
class IndexRepository
{
private array $indexes = [];
private array $children = [];
private array $refs = [];
private array $vars = [];
private array $classes = [];
private array $examples = [];
public function __construct(
private \SQLite3 $db
) {}
public function init(): void {
$create = <<<SQL
CREATE TABLE ids (
docbook_id TEXT,
filename TEXT,
parent_id TEXT,
sdesc TEXT,
ldesc TEXT,
element TEXT,
previous TEXT,
next TEXT,
chunk INTEGER
);
CREATE TABLE changelogs (
membership TEXT, -- How the extension in distributed (pecl, core, bundled with/out external dependencies..)
docbook_id TEXT,
parent_id TEXT,
version TEXT,
description TEXT
);
CREATE TABLE indexing (
time INTEGER PRIMARY KEY
);
SQL;
$this->db->exec('DROP TABLE IF EXISTS ids');
$this->db->exec('DROP TABLE IF EXISTS indexing');
$this->db->exec('DROP TABLE IF EXISTS changelogs');
$this->db->exec('PRAGMA default_synchronous=OFF');
$this->db->exec('PRAGMA count_changes=OFF');
$this->db->exec('PRAGMA cache_size=100000');
$this->db->exec($create);
}
public function saveIndexingTime(int $time): void {
$this->db->exec("BEGIN TRANSACTION; INSERT INTO indexing (time) VALUES ('" . $time . "'); COMMIT");
}
public function commit(
array $commitList,
array $postReplacementIndexes,
array $postReplacementValues,
array $changelog,
): bool {
if (!$commitList) {
return false;
}
foreach ($postReplacementValues as $key => $postReplacementValue) {
$postReplacementValues[$key] = $this->db->escapeString($postReplacementValue);
}
foreach ($commitList as $key => $commit) {
$commitList[$key] = sprintf(
"INSERT INTO ids (docbook_id, filename, parent_id, sdesc, ldesc, element, previous, next, chunk) VALUES('%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d);\n",
$this->db->escapeString($commit["docbook_id"]),
$this->db->escapeString($commit["filename"]),
$this->db->escapeString($commit["parent_id"]),
$this->db->escapeString($commit["sdesc"]),
$this->db->escapeString($commit["ldesc"]),
$this->db->escapeString($commit["element"]),
$this->db->escapeString($commit["previous"]),
$this->db->escapeString($commit["next"]),
$this->db->escapeString($commit["chunk"])
);
}
$search = $this->db->escapeString("POST-REPLACEMENT");
$none = $this->db->escapeString("");
foreach($postReplacementIndexes as $a) {
if (isset($postReplacementValues[$a["docbook_id"]])) {
$replacement = $postReplacementValues[$a["docbook_id"]];
$commitList[$a["idx"]] = str_replace($search, $replacement, $commitList[$a["idx"]]);
} else {
// If there are still post replacement, then they don't have
// any 'next' page
$commitList[$a["idx"]] = str_replace($search, $none, $commitList[$a["idx"]]);
}
}
$this->db->exec('BEGIN TRANSACTION; '.implode("", $commitList).' COMMIT');
$this->saveChangelogs($changelog);
return true;
}
private function saveChangelogs(array $changelog): void {
$log = "";
foreach($changelog as $id => $arr) {
foreach($arr as $entry) {
foreach(preg_split('/,\s+/', $entry[2]) as $version) {
$log .= sprintf(
"INSERT INTO changelogs (membership, docbook_id, parent_id, version, description) VALUES('%s', '%s', '%s', '%s', '%s');\n",
$this->db->escapeString($entry[0] ?? ''),
$this->db->escapeString($id),
$this->db->escapeString($entry[1]),
$this->db->escapeString($version),
$this->db->escapeString($entry[3])
);
}
}
}
$this->db->exec('BEGIN TRANSACTION; ' . $log. ' COMMIT');
}
public function lastErrorCode(): int {
return $this->db->lastErrorCode();
}
public function lastErrorMsg(): string {
return $this->db->lastErrorMsg();
}
public function getIndexingTimeCount(): int {
$queryResult = $this->db->query('SELECT COUNT(time) FROM indexing');
if ($queryResult === false) {
return 0;
}
$indexingCount = $queryResult->fetchArray(\SQLITE3_NUM);
return $indexingCount[0];
}
public function getIndexingTime(): int {
$indexing = $this->db->query('SELECT time FROM indexing')
->fetchArray(\SQLITE3_ASSOC);
return $indexing['time'];
}
public function getIndexes(): array {
$this->indexes = [];
$this->db->createAggregate("indexes", [$this, "SQLiteIndex"], [$this, "SQLiteFinal"], 9);
$this->db->query('SELECT indexes(docbook_id, filename, parent_id, sdesc, ldesc, element, previous, next, chunk) FROM ids');
return $this->indexes;
}
protected function SQLiteIndex($context, $index, $id, $filename, $parent, $sdesc, $ldesc, $element, $previous, $next, $chunk): void {
$this->indexes[$id] = [
"docbook_id" => $id,
"filename" => $filename,
"parent_id" => $parent,
"sdesc" => $sdesc,
"ldesc" => $ldesc,
"element" => $element,
"previous" => $previous,
"next" => $next,
"chunk" => $chunk,
];
}
private static function SQLiteFinal($context): mixed {
return $context;
}
public function getChildren(): array {
$this->children = [];
$this->db->createAggregate("children", [$this, "SQLiteChildren"], [$this, "SQLiteFinal"], 2);
$this->db->query('SELECT children(docbook_id, parent_id) FROM ids WHERE chunk != 0');
return $this->children;
}
private function SQLiteChildren($context, $index, $id, $parent): void {
if (!isset($this->children[$parent])
|| !is_array($this->children[$parent])
) {
$this->children[$parent] = [];
}
$this->children[$parent][] = $id;
}
public function getRefNames(): array {
$this->refs = [];
$this->db->createAggregate("refname", [$this, "SQLiteRefname"], [$this, "SQLiteFinal"], 2);
$this->db->query('SELECT refname(docbook_id, sdesc) FROM ids WHERE element=\'refentry\'');
return $this->refs;
}
private function SQLiteRefname($context, $index, $id, $sdesc): void {
$ref = strtolower($sdesc);
$this->refs[$ref] = $id;
}
public function getVarNames(): array {
$this->vars = [];
$this->db->createAggregate("varname", [$this, "SQLiteVarname"], [$this, "SQLiteFinal"], 2);
$this->db->query('SELECT varname(docbook_id, sdesc) FROM ids WHERE element=\'phpdoc:varentry\'');
return $this->vars;
}
private function SQLiteVarname($context, $index, $id, $sdesc): void {
$this->vars[$sdesc] = $id;
}
public function getClassNames(): array {
$this->classes = [];
$this->db->createAggregate("classname", [$this, "SQLiteClassname"], [$this, "SQLiteFinal"], 2);
$this->db->query('SELECT classname(docbook_id, sdesc) FROM ids WHERE element=\'phpdoc:exceptionref\' OR element=\'phpdoc:classref\'');
return $this->classes;
}
private function SQLiteClassname($context, $index, $id, $sdesc): void {
$this->classes[strtolower($sdesc)] = $id;
}
public function getExamples(): array {
$this->examples = [];
$this->db->createAggregate("example", [$this, "SQLiteExample"], [$this, "SQLiteFinal"], 1);
$this->db->query('SELECT example(docbook_id) FROM ids WHERE element=\'example\'');
return $this->examples;
}
private function SQLiteExample($context, $index, $id): void {
$this->examples[] = $id;
}
public function getRootIndex(): array|false {
return $this->db->querySingle('SELECT * FROM ids WHERE parent_id=""', true);
}
public function getChangelogsForChildrenOf($bookids): array {
$ids = [];
foreach((array)$bookids as $bookid) {
$ids[] = "'" . $this->db->escapeString($bookid) . "'";
}
$results = $this->db->query("SELECT * FROM changelogs WHERE parent_id IN (" . join(", ", $ids) . ")");
return $this->_returnChangelog($results);
}
public function getChangelogsForMembershipOf($memberships): array {
$ids = [];
foreach((array)$memberships as $membership) {
$ids[] = "'" . $this->db->escapeString($membership) . "'";
}
$results = $this->db->query("SELECT * FROM changelogs WHERE membership IN (" . join(", ", $ids) . ")");
return $this->_returnChangelog($results);
}
private function _returnChangelog($results): array {
if (!$results) {
return [];
}
$changelogs = [];
while ($row = $results->fetchArray()) {
$changelogs[] = $row;
}
return $changelogs;
}
public function getParents(array $renderIds): array {
$parents = [];
foreach($renderIds as $p => $v) {
do {
$id = $this->db->escapeString($p);
$row = $this->db->query("SELECT parent_id FROM ids WHERE docbook_id = '$id'")->fetchArray(\SQLITE3_ASSOC);
if ($row["parent_id"]) {
$parents[] = $p = $row["parent_id"];
continue;
}
break;
} while(1);
}
return $parents;
}
}