mirror of
https://github.com/sbrl/Pepperminty-Wiki.git
synced 2024-11-26 05:32:59 +00:00
Fix to #242
This commit is contained in:
parent
ed4bda5ebc
commit
00edb4af9b
3 changed files with 187 additions and 45 deletions
|
@ -130,6 +130,31 @@ function glob_recursive($pattern, $flags = 0)
|
||||||
return $files;
|
return $files;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Normalize file name & path.
|
||||||
|
* Used to convert filenames returned by glob_recursive() to a format used in pageindex.
|
||||||
|
*
|
||||||
|
* @package core
|
||||||
|
* @author Alx84
|
||||||
|
* @param string $filename A filename with storage prefix as retuned by glob_recursive()
|
||||||
|
* @return string Normalized filename
|
||||||
|
*/
|
||||||
|
function normalize_filename($filename)
|
||||||
|
{
|
||||||
|
global $env;
|
||||||
|
// glob_recursive() returns values like "./storage_prefix/folder/filename.md"
|
||||||
|
// in the pageindex we save them as "folder/filename.md"
|
||||||
|
$result = mb_substr( // Store the filename, whilst trimming the storage prefix
|
||||||
|
$filename,
|
||||||
|
mb_strlen(preg_replace("/^\.\//iu", "", $env->storage_prefix)) // glob_recursive trim the ./ from returned filenames , so we need to as well
|
||||||
|
);
|
||||||
|
// Remove the `./` from the beginning if it's still hanging around
|
||||||
|
if(mb_substr($result, 0, 2) == "./")
|
||||||
|
$result = mb_substr($result, 2);
|
||||||
|
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resolves a relative path against a given base directory.
|
* Resolves a relative path against a given base directory.
|
||||||
* @since 0.20.0
|
* @since 0.20.0
|
||||||
|
|
|
@ -3,20 +3,35 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
/**
|
||||||
/*
|
* Rebuilds the page index based on what files are found
|
||||||
* Sort out the pageindex. Create it if it doesn't exist, and load + parse it
|
* @param bool $output Whether to send progress information to the user's browser.
|
||||||
* if it does.
|
|
||||||
*/
|
*/
|
||||||
if(!file_exists($paths->pageindex))
|
function pageindex_rebuild(bool $output = true) : void {
|
||||||
{
|
|
||||||
|
global $env, $pageindex;
|
||||||
|
|
||||||
|
if($output && !is_cli()) {
|
||||||
|
header("content-type: text/event-stream");
|
||||||
|
ob_end_flush();
|
||||||
|
}
|
||||||
|
|
||||||
$glob_str = $env->storage_prefix . "*.md";
|
$glob_str = $env->storage_prefix . "*.md";
|
||||||
$existingpages = glob_recursive($glob_str);
|
$existingpages = glob_recursive($glob_str);
|
||||||
$existingpages_count = count($existingpages);
|
$existingpages_count = count($existingpages);
|
||||||
|
|
||||||
// Debug statements. Uncomment when debugging the pageindex regenerator.
|
// Debug statements. Uncomment when debugging the pageindex regenerator.
|
||||||
// var_dump($env->storage_prefix);
|
// var_dump($env->storage_prefix);
|
||||||
// var_dump($glob_str);
|
// var_dump($glob_str);
|
||||||
// var_dump($existingpages);
|
// var_dump($existingpages);
|
||||||
|
|
||||||
|
// save our existing pageindex, if it is available at this point
|
||||||
|
// we will use it to salvage some data out of it, like tags and authors
|
||||||
|
if (is_a($pageindex, 'stdClass')) $old_pageindex = $pageindex;
|
||||||
|
else $old_pageindex = new stdClass();
|
||||||
|
|
||||||
|
|
||||||
|
// compose a new pageindex into a global variable
|
||||||
$pageindex = new stdClass();
|
$pageindex = new stdClass();
|
||||||
// We use a for loop here because foreach doesn't loop over new values inserted
|
// We use a for loop here because foreach doesn't loop over new values inserted
|
||||||
// while we were looping
|
// while we were looping
|
||||||
|
@ -24,19 +39,15 @@ if(!file_exists($paths->pageindex))
|
||||||
{
|
{
|
||||||
$pagefilename = $existingpages[$i];
|
$pagefilename = $existingpages[$i];
|
||||||
|
|
||||||
// Create a new entry
|
// Create a new entry for each md file we found
|
||||||
$newentry = new stdClass();
|
$newentry = new stdClass();
|
||||||
$newentry->filename = mb_substr( // Store the filename, whilst trimming the storage prefix
|
|
||||||
$pagefilename,
|
// glob_recursive() returns values like "./storage_prefix/folder/filename.md"
|
||||||
mb_strlen(preg_replace("/^\.\//iu", "", $env->storage_prefix)) // glob_recursive trim the ./ from returned filenames , so we need to as well
|
// in the pageindex we save them as "folder/filename.md"
|
||||||
);
|
$newentry->filename = normalize_filename($pagefilename);
|
||||||
// Remove the `./` from the beginning if it's still hanging around
|
|
||||||
if(mb_substr($newentry->filename, 0, 2) == "./")
|
|
||||||
$newentry->filename = mb_substr($newentry->filename, 2);
|
|
||||||
$newentry->size = filesize($pagefilename); // Store the page size
|
$newentry->size = filesize($pagefilename); // Store the page size
|
||||||
$newentry->lastmodified = filemtime($pagefilename); // Store the date last modified
|
$newentry->lastmodified = filemtime($pagefilename); // Store the date last modified
|
||||||
// Todo find a way to keep the last editor independent of the page index
|
|
||||||
$newentry->lasteditor = "unknown"; // Set the editor to "unknown"
|
|
||||||
|
|
||||||
// Extract the name of the (sub)page without the ".md"
|
// Extract the name of the (sub)page without the ".md"
|
||||||
$pagekey = filepath_to_pagename($newentry->filename);
|
$pagekey = filepath_to_pagename($newentry->filename);
|
||||||
|
@ -59,12 +70,6 @@ if(!file_exists($paths->pageindex))
|
||||||
$newentry->uploadedfilemime = finfo_file($mimechecker, $env->storage_prefix . $pagekey);
|
$newentry->uploadedfilemime = finfo_file($mimechecker, $env->storage_prefix . $pagekey);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Debug statements. Uncomment when debugging the pageindex regenerator.
|
|
||||||
// echo("pagekey: ");
|
|
||||||
// var_dump($pagekey);
|
|
||||||
// echo("newentry: ");
|
|
||||||
// var_dump($newentry);
|
|
||||||
|
|
||||||
// Subpage parent checker
|
// Subpage parent checker
|
||||||
if(strpos($pagekey, "/") !== false)
|
if(strpos($pagekey, "/") !== false)
|
||||||
{
|
{
|
||||||
|
@ -84,6 +89,14 @@ if(!file_exists($paths->pageindex))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Attempt to salvage tags and lasteditor from the previous pageindex
|
||||||
|
if (@$old_pageindex->$pagekey->tags)
|
||||||
|
$newentry->tags = $old_pageindex->$pagekey->tags;
|
||||||
|
$newentry->lasteditor = "unknown";
|
||||||
|
if (@$old_pageindex->$pagekey->lasteditor)
|
||||||
|
$newentry->lasteditor = $old_pageindex->$pagekey->lasteditor;
|
||||||
|
|
||||||
|
|
||||||
// If the initial revision doesn't exist on disk, create it (if it does, then we handle that later)
|
// If the initial revision doesn't exist on disk, create it (if it does, then we handle that later)
|
||||||
if(function_exists("history_add_revision") && !file_exists("{$pagefilename}.r0")) { // Can't use module_exists - too early
|
if(function_exists("history_add_revision") && !file_exists("{$pagefilename}.r0")) { // Can't use module_exists - too early
|
||||||
copy($pagefilename, "{$pagefilename}.r0");
|
copy($pagefilename, "{$pagefilename}.r0");
|
||||||
|
@ -91,20 +104,31 @@ if(!file_exists($paths->pageindex))
|
||||||
"type" => "edit",
|
"type" => "edit",
|
||||||
"rid" => 0,
|
"rid" => 0,
|
||||||
"timestamp" => $newentry->lastmodified,
|
"timestamp" => $newentry->lastmodified,
|
||||||
"filename" => "{$pagefilename}.r0",
|
"filename" => normalize_filename("{$pagefilename}.r0"),
|
||||||
"newsize" => $newentry->size,
|
"newsize" => $newentry->size,
|
||||||
"sizediff" => $newentry->size,
|
"sizediff" => $newentry->size,
|
||||||
"editor" => "unknown"
|
"editor" => $newentry->lasteditor
|
||||||
] ];
|
] ];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Store the new entry in the new page index
|
// Store the new entry in the new page index
|
||||||
$pageindex->$pagekey = $newentry;
|
$pageindex->$pagekey = $newentry;
|
||||||
|
|
||||||
|
if($output) {
|
||||||
|
$message = "[" . ($i + 1) . " / $existingpages_count] Added $pagefilename to the pageindex.";
|
||||||
|
if(!is_cli()) $message = "data: $message\n\n";
|
||||||
|
else $message = "$message\r";
|
||||||
|
echo($message);
|
||||||
|
flush();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(function_exists("history_add_revision")) {
|
if(function_exists("history_add_revision")) {
|
||||||
$history_revs = glob_recursive($env->storage_prefix . "*.r*");
|
|
||||||
// It's very important that we read the history revisions in the right order and that we don't skip any
|
// collect from the filesystem what revision files we have
|
||||||
|
$history_revs = glob_recursive($env->storage_prefix . "*.md.r*");
|
||||||
|
|
||||||
|
// sort them in the ascending order of their revision numbers - it's very important for further processing
|
||||||
usort($history_revs, function($a, $b) {
|
usort($history_revs, function($a, $b) {
|
||||||
preg_match("/[0-9]+$/", $a, $revid_a);
|
preg_match("/[0-9]+$/", $a, $revid_a);
|
||||||
$revid_a = intval($revid_a[0]);
|
$revid_a = intval($revid_a[0]);
|
||||||
|
@ -112,8 +136,8 @@ if(!file_exists($paths->pageindex))
|
||||||
$revid_b = intval($revid_b[0]);
|
$revid_b = intval($revid_b[0]);
|
||||||
return $revid_a - $revid_b;
|
return $revid_a - $revid_b;
|
||||||
});
|
});
|
||||||
// We can guarantee that the direcotry separator is present on the end - it's added explicitly earlier
|
|
||||||
$strlen_storageprefix = strlen($env->storage_prefix);
|
|
||||||
foreach($history_revs as $filename) {
|
foreach($history_revs as $filename) {
|
||||||
preg_match("/[0-9]+$/", $filename, $revid);
|
preg_match("/[0-9]+$/", $filename, $revid);
|
||||||
error_log("raw revid | ".var_export($revid, true));
|
error_log("raw revid | ".var_export($revid, true));
|
||||||
|
@ -121,7 +145,7 @@ if(!file_exists($paths->pageindex))
|
||||||
$revid = intval($revid[0]);
|
$revid = intval($revid[0]);
|
||||||
|
|
||||||
$pagename = filepath_to_pagename($filename);
|
$pagename = filepath_to_pagename($filename);
|
||||||
$filepath_stripped = substr($filename, $strlen_storageprefix);
|
$filepath_stripped = normalize_filename($filename);
|
||||||
|
|
||||||
if(!isset($pageindex->$pagename->history))
|
if(!isset($pageindex->$pagename->history))
|
||||||
$pageindex->$pagename->history = [];
|
$pageindex->$pagename->history = [];
|
||||||
|
@ -135,6 +159,17 @@ if(!file_exists($paths->pageindex))
|
||||||
if($revid > 0 && isset($pageindex->$pagename->history[$revid - 1])) {
|
if($revid > 0 && isset($pageindex->$pagename->history[$revid - 1])) {
|
||||||
$prevsize = filesize(end($pageindex->$pagename->history)->filename);
|
$prevsize = filesize(end($pageindex->$pagename->history)->filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Let's attempt to salvage the editor for this revision from the old pageindex
|
||||||
|
// For that we walk through history of edits from old pageindex to find what editor was set for this specific file
|
||||||
|
$revision_editor = "unknown";
|
||||||
|
if ($old_pageindex->$pagename->history) {
|
||||||
|
foreach ($old_pageindex->$pagename->history as $revision)
|
||||||
|
if ($revision->filename == $filepath_stripped && isset($revision->editor))
|
||||||
|
$revision_editor = $revision->editor;
|
||||||
|
}
|
||||||
|
|
||||||
|
// save the revision into history
|
||||||
$pageindex->$pagename->history[$revid] = (object) [
|
$pageindex->$pagename->history[$revid] = (object) [
|
||||||
"type" => "edit",
|
"type" => "edit",
|
||||||
"rid" => $revid,
|
"rid" => $revid,
|
||||||
|
@ -142,13 +177,30 @@ if(!file_exists($paths->pageindex))
|
||||||
"filename" => $filepath_stripped,
|
"filename" => $filepath_stripped,
|
||||||
"newsize" => $newsize,
|
"newsize" => $newsize,
|
||||||
"sizediff" => $newsize - $prevsize,
|
"sizediff" => $newsize - $prevsize,
|
||||||
"editor" => "unknown"
|
"editor" => $revision_editor
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
save_pageindex();
|
save_pageindex();
|
||||||
unset($existingpages);
|
unset($existingpages);
|
||||||
|
|
||||||
|
|
||||||
|
if($output && !is_cli()) {
|
||||||
|
echo("data: Done! \n\n");
|
||||||
|
flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Sort out the pageindex. Create it if it doesn't exist, and load + parse it
|
||||||
|
* if it does.
|
||||||
|
*/
|
||||||
|
if(!file_exists($paths->pageindex))
|
||||||
|
{
|
||||||
|
pageindex_rebuild(false);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -47,10 +47,10 @@ register_module([
|
||||||
$content .= "<p>You're currently running Pepperminty Wiki $version+" . substr($commit, 0, 7) . ".</p>\n";
|
$content .= "<p>You're currently running Pepperminty Wiki $version+" . substr($commit, 0, 7) . ".</p>\n";
|
||||||
$content .= "<h2>Actions</h2>";
|
$content .= "<h2>Actions</h2>";
|
||||||
|
|
||||||
|
// rebuild search index button
|
||||||
$content .= "<button class='action-invindex-rebuild' title='Rebuilds the index that is consulted when searching the wiki. Hit this button if some pages are not showing up.'>Rebuild Search Index</button>\n";
|
$content .= "<button class='action-invindex-rebuild' title='Rebuilds the index that is consulted when searching the wiki. Hit this button if some pages are not showing up.'>Rebuild Search Index</button>\n";
|
||||||
$content .= "<progress class='action-invindex-rebuild-progress' min='0' max='100' value='0' style='display: none;'></progress><br />\n";
|
$content .= "<progress class='action-invindex-rebuild-progress' min='0' max='100' value='0' style='display: none;'></progress><br />\n";
|
||||||
$content .= "<output class='action-invindex-rebuild-latestmessage'></output><br />\n";
|
$content .= "<output class='action-invindex-rebuild-latestmessage'></output><br />\n";
|
||||||
|
|
||||||
$invindex_rebuild_script = <<<SCRIPT
|
$invindex_rebuild_script = <<<SCRIPT
|
||||||
window.addEventListener("load", function(event) {
|
window.addEventListener("load", function(event) {
|
||||||
document.querySelector(".action-invindex-rebuild").addEventListener("click", function(event) {
|
document.querySelector(".action-invindex-rebuild").addEventListener("click", function(event) {
|
||||||
|
@ -76,9 +76,39 @@ window.addEventListener("load", function(event) {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
SCRIPT;
|
SCRIPT;
|
||||||
|
|
||||||
page_renderer::add_js_snippet($invindex_rebuild_script);
|
page_renderer::add_js_snippet($invindex_rebuild_script);
|
||||||
|
|
||||||
|
// rebuild page index button
|
||||||
|
$content .= "<button class='action-pageindex-rebuild' title='Rebuilds the page index that contains information (tags, author, dates, filename) about all wiki pages. Hit this button if MD files were changed externally.'>Rebuild Page Index</button>\n";
|
||||||
|
$content .= "<progress class='action-pageindex-rebuild-progress' min='0' max='100' value='0' style='display: none;'></progress><br />\n";
|
||||||
|
$content .= "<output class='action-pageindex-rebuild-latestmessage'></output><br />\n";
|
||||||
|
$pageindex_rebuild_script = <<<SCRIPT
|
||||||
|
window.addEventListener("load", function(event) {
|
||||||
|
document.querySelector(".action-pageindex-rebuild").addEventListener("click", function(event) {
|
||||||
|
var rebuildActionEvents = new EventSource("?action=pageindex-rebuild");
|
||||||
|
var latestMessageElement = document.querySelector(".action-pageindex-rebuild-latestmessage");
|
||||||
|
var progressElement = document.querySelector(".action-pageindex-rebuild-progress");
|
||||||
|
rebuildActionEvents.addEventListener("message", function(event) {
|
||||||
|
console.log(event);
|
||||||
|
let message = event.data;
|
||||||
|
latestMessageElement.value = event.data;
|
||||||
|
let parts = message.match(/^\[\s*(\d+)\s+\/\s+(\d+)\s*\]/);
|
||||||
|
if(parts != null) {
|
||||||
|
progressElement.style.display = "";
|
||||||
|
progressElement.min = 0;
|
||||||
|
progressElement.max = parseInt(parts[2]);
|
||||||
|
progressElement.value = parseInt(parts[1]);
|
||||||
|
}
|
||||||
|
if(message.startsWith("Done!"))
|
||||||
|
rebuildActionEvents.close();
|
||||||
|
});
|
||||||
|
// Close the connection on error & don't try again
|
||||||
|
rebuildActionEvents.addEventListener("error", (_event) => rebuildActionEvents.close());
|
||||||
|
});
|
||||||
|
});
|
||||||
|
SCRIPT;
|
||||||
|
page_renderer::add_js_snippet($pageindex_rebuild_script);
|
||||||
|
|
||||||
$content .= "<h2>Settings</h2>";
|
$content .= "<h2>Settings</h2>";
|
||||||
$content .= "<p>Mouse over the name of each setting to see a description of what it does.</p>\n";
|
$content .= "<p>Mouse over the name of each setting to see a description of what it does.</p>\n";
|
||||||
$content .= "<form action='?action=configure-save' method='post'>\n";
|
$content .= "<form action='?action=configure-save' method='post'>\n";
|
||||||
|
@ -207,6 +237,41 @@ SCRIPT;
|
||||||
exit(page_renderer::render_main("Master Settings Updated - $settings->sitename", $content));
|
exit(page_renderer::render_main("Master Settings Updated - $settings->sitename", $content));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @api {get} ?action=pageindex-rebuild[&format=json] Rebuilds the page index
|
||||||
|
* @apiName UserList
|
||||||
|
* @apiGroup Utility
|
||||||
|
* @apiPermission Anonymous
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/* _ _ _ _ _ _
|
||||||
|
* (_) | | | | (_) | | | |
|
||||||
|
* _ __ __ _ __ _ ___ _ _ __ __| | ___ __ __ ______ _ __ ___ | |__ _ _ _ | | __| |
|
||||||
|
* | '_ \ / _` | / _` | / _ \ | | | '_ \ / _` | / _ \ \ \/ / |______| | '__| / _ \ | '_ \ | | | | | | | | / _` |
|
||||||
|
* | |_) | | (_| | | (_| | | __/ | | | | | | | (_| | | __/ > < | | | __/ | |_) | | |_| | | | | | | (_| |
|
||||||
|
* | .__/ \__,_| \__, | \___| |_| |_| |_| \__,_| \___| /_/\_\ |_| \___| |_.__/ \__,_| |_| |_| \__,_|
|
||||||
|
* | | __/ |
|
||||||
|
* |_| |___/
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
add_action("pageindex-rebuild", function() {
|
||||||
|
global $env, $settings;
|
||||||
|
if($env->is_admin ||
|
||||||
|
(
|
||||||
|
!empty($_POST["secret"]) &&
|
||||||
|
$_POST["secret"] === $settings->secret
|
||||||
|
)
|
||||||
|
)
|
||||||
|
pageindex_rebuild();
|
||||||
|
else
|
||||||
|
{
|
||||||
|
http_response_code(401);
|
||||||
|
exit(page_renderer::render_main("Error - Page index regenerator - $settings->sitename", "<p>Error: You aren't allowed to regenerate the page index. Try logging in as an admin, or setting the <code>secret</code> POST parameter to $settings->sitename's secret - which can be found in $settings->sitename's <code>peppermint.json</code> file.</p>"));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
add_help_section("800-raw-page-content", "Viewing Raw Page Content", "<p>Although you can use the edit page to view a page's source, you can also ask $settings->sitename to send you the raw page source and nothing else. This feature is intented for those who want to automate their interaction with $settings->sitename.</p>
|
add_help_section("800-raw-page-content", "Viewing Raw Page Content", "<p>Although you can use the edit page to view a page's source, you can also ask $settings->sitename to send you the raw page source and nothing else. This feature is intented for those who want to automate their interaction with $settings->sitename.</p>
|
||||||
<p>To use this feature, navigate to the page for which you want to see the source, and then alter the <code>action</code> parameter in the url's query string to be <code>raw</code>. If the <code>action</code> parameter doesn't exist, add it. Note that when used on an file's page this action will return the source of the description and not the file itself.</p>");
|
<p>To use this feature, navigate to the page for which you want to see the source, and then alter the <code>action</code> parameter in the url's query string to be <code>raw</code>. If the <code>action</code> parameter doesn't exist, add it. Note that when used on an file's page this action will return the source of the description and not the file itself.</p>");
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue