';
return sprintf(
$xmlFormat,
(string)$data['id'],
escapeTextValue($data['title_to_index']),
escapeTextValue($data['body']),
escapeTextValue($data['namespace']),
escapeTextValue($data['pagename']),
(int)$data['level'],
(int)$data['modified']
);
}
/**
* Clean text for CDATA inclusion
*
* @param string $value
* @return string
*/
function escapeTextValue($value)
{
if ($value === "" || $value === null) return "";
$value = str_replace("]]>", "]]>", $value);
return stripInvalidXml($value);
}
/**
* Remove characters that are invalid in XML 1.0
*
* @param string $value
* @return string
*/
function stripInvalidXml(string $value): string
{
if (empty($value)) return "";
$value = preg_replace('/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]/u', '', $value);
$value = mb_convert_encoding($value, 'UTF-8', 'UTF-8');
return preg_replace(
'/[^\x{0009}\x{000a}\x{000d}\x{0020}-\x{D7FF}\x{E000}-\x{FFFD}\x{10000}-\x{10FFFF}]/u',
' ',
$value
);
}
/**
* Extract sections based on Heading metadata
*/
function getDocumentsByHeadings($id, $metadata)
{
if (empty($metadata) || empty($metadata['description']['tableofcontents'])) {
return false;
}
$sections = [];
$level = 1;
$previous_title = '';
foreach ($metadata['description']['tableofcontents'] as $row) {
$sections[$row['hid']] = [
'section' => getSectionByTitleLevel($id, $row['title']),
'level' => $row['level'],
'title' => $row['title']
];
if ($row['level'] > $level && !empty($previous_title)) {
$sections[$row['hid']]['title_text'] = $previous_title . " ยป " . $row['title'];
} else {
$sections[$row['hid']]['title_text'] = $row['title'];
$previous_title = $row['title'];
}
$sections[$row['hid']]['title_to_index'] = $row['title'];
}
return $sections;
}
/**
* Regex based section extraction
*/
function getSectionByTitleLevel($id, $header, $extended = false)
{
$headerReg = preg_quote($header, '/');
$file = wikiFN($id);
if (!file_exists($file)) return '';
$doc = io_readFile($file);
$regex = "(={1,6})\s*({$headerReg})\s*(={1,6})";
$section = '';
if (preg_match("/$regex/i", $doc, $matches)) {
$startHeader = $matches[0];
$startHeaderPos = strpos($doc, $startHeader) + strlen($startHeader);
$endDoc = substr($doc, $startHeaderPos);
$endRegex = '(={4,6})(.*?)(={4,6})';
if (preg_match("/$endRegex/i", $endDoc, $matches)) {
$endHeader = $matches[0];
$endHeaderPos = strpos($doc, $endHeader);
} else {
$endHeaderPos = 0;
}
if ($endHeaderPos) {
$section = substr($doc, $startHeaderPos, $endHeaderPos - $startHeaderPos);
} else {
$section = substr($doc, $startHeaderPos);
}
}
$section = trim($section);
if ($extended && empty($section) && isset($endHeader)) {
$startHeaderPos = $endHeaderPos + strlen($endHeader);
$endDoc = substr($doc, $startHeaderPos);
if (preg_match("/$endRegex/i", $endDoc, $matches)) {
$nextEndHeaderPos = strpos($doc, $matches[0], $startHeaderPos);
$section = substr($doc, $startHeaderPos, $nextEndHeaderPos - $startHeaderPos);
} else {
$section = substr($doc, $startHeaderPos);
}
}
return trim($section);
}
/**
* Modernized section extractor using DokuWiki internal parser helpers
*/
function getSection($id, $header)
{
static $cacheInstructions = [];
static $cacheDoc = [];
if (empty($cacheDoc[$id])) {
$file = wikiFN($id);
if (!file_exists($file)) return '';
$doc = io_readFile($file);
$instructions = p_get_instructions($doc);
$cacheInstructions[$id] = $instructions;
$cacheDoc[$id] = $doc;
} else {
$instructions = $cacheInstructions[$id];
$doc = $cacheDoc[$id];
}
$inSection = false;
$startPos = 0;
$endPos = 0;
foreach ($instructions as $instruction) {
if (!$inSection) {
if ($instruction[0] == 'header' && trim($instruction[1][0]) == $header) {
$startPos = $instruction[2];
$inSection = true;
}
} else {
if ($instruction[0] == 'section_close' || $instruction[0] == 'header') {
$endPos = $instruction[2];
break;
}
}
}
$doc = "\n" . str_replace("\r\n", "\n", $doc) . "\n";
return substr($doc, $startPos, ($endPos - $startPos));
}
/**
* Robust way to get searchable plain text by using XHTML and stripping noise
*/
function get_clean_text($wikitext) {
$info = [];
$html = @p_render('xhtml', p_get_instructions($wikitext), $info);
$html = preg_replace('/.*?<\/span>/', '', $html);
$html = preg_replace('/