page_filename); // The old revision content - the Pepperminty Wiki core sorts this out for us
+ $oldsource = file_get_contents($current_revision_filepath); // The current revision's content
+
+ // Save the old content over the current content
+ file_put_contents($current_revision_filepath, $newsource);
+
+ // NOTE: We don't run the save preprocessors here because they are run when a page is edited - reversion is special and requires different treatment.
+ // FUTURE: We may want ot refactor the save preprocessor system ot take a single object instead - then we can add as many params as we like and we could execute the save preprocessors as normal :P
+
+ // Add the old content as a new revision
+ $result = history_add_revision(
+ $pageindex->{$env->page},
+ $newsource,
+ $oldsource,
+ true, // Yep, go ahead and save the page index
+ "revert" // It's a revert, not an edit
+ );
+
+ // Update the redirect metadata, if the redirect module is installed
+ if(module_exists("feature-redirect"))
+ update_redirect_metadata($pageindex->{$env->page}, $newsource);
+
+ // Add an entry to the recent changes log, if the module exists
+ if($result !== false && module_exists("feature-recent-changes"))
+ add_recent_change([
+ "type" => "revert",
+ "timestamp" => time(),
+ "page" => $env->page,
+ "user" => $env->user,
+ "newsize" => strlen($newsource),
+ "sizediff" => strlen($newsource) - strlen($oldsource)
+ ]);
+
+ if($result === false) {
+ http_response_code(503);
+ exit(page_renderer::render_main("Server Error - Revert - $settings->sitename", "A server error occurred when $settings->sitename tried to save the reversion of " . htmlentities($env->page) . "
. Please contact $settings->sitename's administrator $settings->admindetails_name, whose email address can be found at the bottom of every page (including this one).
"));
+ }
+
+ http_response_code(201);
+ exit(page_renderer::render_main("Reverting " . htmlentities($env->page) . " - $settings->sitename", "" . htmlentities($env->page) . " has been reverted back to revision {$env->history->revision_number} successfully.
+ Go back to the page, or continue reviewing its history.
"));
+
+ // $env->page_filename
+ //
+ });
register_save_preprocessor("history_add_revision");
}
]);
-function history_add_revision(&$pageinfo, &$newsource, &$oldsource, $save_pageindex = true) {
+/**
+ * Adds a history revision against a page.
+ * Note: Does not updaate the current page content! This function _only_
+ * records a new revision against a page name. Thus it is possible to have a
+ * disparaty between the history revisions and the actual content displayed in
+ * the current revision if you're not careful!
+ * @param object $pageinfo The pageindex object of the page to operate on.
+ * @param string $newsource The page content to save as the new revision.
+ * @param string $oldsource The old page content that is the current revision (before the update).
+ * @param boolean $save_pageindex Whether the page index should be saved to disk.
+ * @param string $change_type The type of change to record this as in the history revision log
+ */
+function history_add_revision(&$pageinfo, &$newsource, &$oldsource, $save_pageindex = true, $change_type = "edit") {
global $pageindex, $paths, $env;
if(!isset($pageinfo->history))
@@ -3294,8 +3397,7 @@ function history_add_revision(&$pageinfo, &$newsource, &$oldsource, $save_pagein
// Save the *new source* as a revision
// This results in 2 copies of the current source, but this is ok
- // since any time someone changes something, it create a new
- // revision
+ // since any time someone changes something, it creates a new revision
// Note that we can't save the old source here because we'd have no
// clue who edited it since $pageinfo has already been updated by
// this point
@@ -3305,7 +3407,7 @@ function history_add_revision(&$pageinfo, &$newsource, &$oldsource, $save_pagein
$ridFilename = "$pageinfo->filename.r$nextRid";
// Insert a new entry into the history
$pageinfo->history[] = [
- "type" => "edit", // We might want to store other types later (e.g. page moves)
+ "type" => $change_type, // We might want to store other types later (e.g. page moves)
"rid" => $nextRid,
"timestamp" => time(),
"filename" => $ridFilename,
@@ -3315,11 +3417,13 @@ function history_add_revision(&$pageinfo, &$newsource, &$oldsource, $save_pagein
];
// Save the new source as a revision
- file_put_contents("$env->storage_prefix$ridFilename", $newsource);
+ $result = file_put_contents("$env->storage_prefix$ridFilename", $newsource);
// Save the edited pageindex
- if($save_pageindex)
- file_put_contents($paths->pageindex, json_encode($pageindex, JSON_PRETTY_PRINT));
+ if($result !== false && $save_pageindex)
+ $result = file_put_contents($paths->pageindex, json_encode($pageindex, JSON_PRETTY_PRINT));
+
+ return $result;
}
@@ -3619,31 +3723,39 @@ register_module([
"code" => function() {
global $settings;
- register_save_preprocessor(function(&$index_entry, &$pagedata) {
- $matches = [];
- if(preg_match("/^# ?REDIRECT ?\[\[([^\]]+)\]\]/i", $pagedata, $matches) === 1)
- {
- //error_log("matches: " . var_export($matches, true));
- // We have found a redirect page!
- // Update the metadata to reflect this.
- $index_entry->redirect = true;
- $index_entry->redirect_target = $matches[1];
- }
- else
- {
- // This page isn't a redirect. Unset the metadata just in case.
- if(isset($index_entry->redirect))
- unset($index_entry->redirect);
- if(isset($index_entry->redirect_target))
- unset($index_entry->redirect_target);
- }
- });
+ register_save_preprocessor("update_redirect_metadata");
// Register a help section
add_help_section("25-redirect", "Redirect Pages", "$settings->sitename supports redirect pages. To create a redirect page, enter something like # REDIRECT [[pagename]]
on the first line of the redirect page's content. This must appear as the first line of the page, with no whitespace before it. You can include content beneath the redirect if you want, too (such as a reason for redirecting the page).
");
}
]);
+/**
+ * Updates the metadata associated with redirects in the pageindex entry
+ * specified utilising the provided page content.
+ * @param object $index_entry The page index entry object to update.
+ * @param string $pagedata The page content to operate on.
+ */
+function update_redirect_metadata(&$index_entry, &$pagedata) {
+ $matches = [];
+ if(preg_match("/^# ?REDIRECT ?\[\[([^\]]+)\]\]/i", $pagedata, $matches) === 1)
+ {
+ //error_log("matches: " . var_export($matches, true));
+ // We have found a redirect page!
+ // Update the metadata to reflect this.
+ $index_entry->redirect = true;
+ $index_entry->redirect_target = $matches[1];
+ }
+ else
+ {
+ // This page isn't a redirect. Unset the metadata just in case.
+ if(isset($index_entry->redirect))
+ unset($index_entry->redirect);
+ if(isset($index_entry->redirect_target))
+ unset($index_entry->redirect_target);
+ }
+}
+
diff --git a/core.php b/core.php
index ca13bbd..de5ca7a 100644
--- a/core.php
+++ b/core.php
@@ -111,15 +111,15 @@ if($env->is_logged_in)
/**
* @apiDefine Admin Only the wiki administrator may use this call.
*/
- /**
- * @apiDefine Moderator Only users loggged with a moderator account may use this call.
- */
/**
-* @apiDefine User Only users loggged in may use this call.
-*/
+ * @apiDefine Moderator Only users loggged with a moderator account may use this call.
+ */
/**
-* @apiDefine Anonymous Anybody may use this call.
-*/
+ * @apiDefine User Only users loggged in may use this call.
+ */
+/**
+ * @apiDefine Anonymous Anybody may use this call.
+ */
/**
* @apiDefine UserNotLoggedInError
* @apiError UserNotLoggedInError You didn't log in before sending this request.
diff --git a/module_index.json b/module_index.json
index f88f3c1..972a7c0 100755
--- a/module_index.json
+++ b/module_index.json
@@ -39,9 +39,9 @@
"name": "API status",
"version": "0.1",
"author": "Starbeamrainbowlabs",
- "description": "Provides a basic JSON status action that provices a few useful bits of information for API consumption.",
+ "description": "Provides a basic JSON status action that provides a few useful bits of information for API consumption.",
"id": "api-status",
- "lastupdate": 1523055259,
+ "lastupdate": 1530565418,
"optional": false
},
{
@@ -77,7 +77,7 @@
"author": "Starbeamrainbowlabs",
"description": "Adds the ability to keep unlimited page history, limited only by your disk space. Note that this doesn't store file history (yet). Currently depends on feature-recent-changes for rendering of the history page.",
"id": "feature-history",
- "lastupdate": 1518645062,
+ "lastupdate": 1530571420,
"optional": false
},
{
@@ -95,7 +95,7 @@
"author": "Starbeamrainbowlabs",
"description": "Adds support for redirect pages. Uses the same syntax that Mediawiki does.",
"id": "feature-redirect",
- "lastupdate": 1498646092,
+ "lastupdate": 1530570852,
"optional": false
},
{
diff --git a/modules/api-status.php b/modules/api-status.php
index c2f73af..21da6a0 100644
--- a/modules/api-status.php
+++ b/modules/api-status.php
@@ -16,7 +16,13 @@ register_module([
* @apiParam {boolean} Whether or not the result should be minified JSON. Default: false
*/
-
+ /*
+ * ███████ ████████ █████ ████████ ██ ██ ███████
+ * ██ ██ ██ ██ ██ ██ ██ ██
+ * ███████ ██ ███████ ██ ██ ██ ███████
+ * ██ ██ ██ ██ ██ ██ ██ ██
+ * ███████ ██ ██ ██ ██ ██████ ███████
+ */
add_action("status", function() {
global $version, $env, $settings, $actions;
diff --git a/modules/feature-history.php b/modules/feature-history.php
index 517a7be..e090b38 100644
--- a/modules/feature-history.php
+++ b/modules/feature-history.php
@@ -12,7 +12,7 @@ register_module([
* @apiGroup Page
* @apiPermission Anonymous
*
- * @apiParam {string} page The page name to return a revision list for.
+ * @apiUse PageParameter
* @apiParam {string} format The format to return the list of pages in. available values: html, json, text. Default: html
*/
@@ -37,8 +37,8 @@ register_module([
$content .= "\t\t\n";
foreach(array_reverse($pageindex->{$env->page}->history) as $revisionData)
{
- // Only display edits for now
- if($revisionData->type != "edit")
+ // Only display edits & reverts for now
+ if($revisionData->type != "edit" || $revisionData->type != "revert")
continue;
// The number (and the sign) of the size difference to display
@@ -48,7 +48,11 @@ register_module([
$size_display_class .= " significant";
$size_title_display = human_filesize($revisionData->newsize - $revisionData->sizediff) . " -> " . human_filesize($revisionData->newsize);
- $content .= "- #$revisionData->rid " . render_editor(page_renderer::render_username($revisionData->editor)) . " " . render_timestamp($revisionData->timestamp) . " ($size_display)";
+ $content .= "
- ";
+ $content .= "#$revisionData->rid " . render_editor(page_renderer::render_username($revisionData->editor)) . " " . render_timestamp($revisionData->timestamp) . " ($size_display)";
+ if($env->is_logged_in || ($settings->history_revert_require_moderator && $env->is_admin && $env->is_logged_in))
+ $content .= " (restore this revision)";
+ $content .= "
";
}
}
else
@@ -83,12 +87,105 @@ register_module([
});
+ /**
+ * @api {get} ?action=history-revert&page={pageName}&revision={rid} Revert a page to a previous version
+ * @apiName HistoryRevert
+ * @apiGroup Editing
+ * @apiPermission User
+ * @apiUse PageParameter
+ * @apiUse UserNotLoggedInError
+ * @apiUse UserNotModeratorError
+ *
+ * @apiParam {string} revision The page revision number to revert to.
+ */
+ /*
+ * ██ ██ ██ ███████ ████████ ██████ ██████ ██ ██
+ * ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
+ * ███████ ██ ███████ ██ ██ ██ ██████ ████ █████
+ * ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
+ * ██ ██ ██ ███████ ██ ██████ ██ ██ ██
+ *
+ * ██████ ███████ ██ ██ ███████ ██████ ████████
+ * ██ ██ ██ ██ ██ ██ ██ ██ ██
+ * ██████ █████ ██ ██ █████ ██████ ██
+ * ██ ██ ██ ██ ██ ██ ██ ██ ██
+ * ██ ██ ███████ ████ ███████ ██ ██ ██
+ */
+ add_action("history-revert", function() {
+ global $env, $settings, $pageindex;
+
+ if((!$env->is_admin && $settings->history_revert_require_moderator) ||
+ $env->is_logged_in) {
+ http_response_code(401);
+ exit(page_renderer::render_main("Unauthorised - $settings->sitename", "You can't revert pages to a previous revision because " . ($settings->history_revert_require_moderator && $env->is_logged_in ? "you aren't logged in as a moderator. You can try logging out and then" : "you aren't logged in. You can try") . " page_filename); // The old revision content - the Pepperminty Wiki core sorts this out for us
+ $oldsource = file_get_contents($current_revision_filepath); // The current revision's content
+
+ // Save the old content over the current content
+ file_put_contents($current_revision_filepath, $newsource);
+
+ // NOTE: We don't run the save preprocessors here because they are run when a page is edited - reversion is special and requires different treatment.
+ // FUTURE: We may want ot refactor the save preprocessor system ot take a single object instead - then we can add as many params as we like and we could execute the save preprocessors as normal :P
+
+ // Add the old content as a new revision
+ $result = history_add_revision(
+ $pageindex->{$env->page},
+ $newsource,
+ $oldsource,
+ true, // Yep, go ahead and save the page index
+ "revert" // It's a revert, not an edit
+ );
+
+ // Update the redirect metadata, if the redirect module is installed
+ if(module_exists("feature-redirect"))
+ update_redirect_metadata($pageindex->{$env->page}, $newsource);
+
+ // Add an entry to the recent changes log, if the module exists
+ if($result !== false && module_exists("feature-recent-changes"))
+ add_recent_change([
+ "type" => "revert",
+ "timestamp" => time(),
+ "page" => $env->page,
+ "user" => $env->user,
+ "newsize" => strlen($newsource),
+ "sizediff" => strlen($newsource) - strlen($oldsource)
+ ]);
+
+ if($result === false) {
+ http_response_code(503);
+ exit(page_renderer::render_main("Server Error - Revert - $settings->sitename", "A server error occurred when $settings->sitename tried to save the reversion of " . htmlentities($env->page) . "
. Please contact $settings->sitename's administrator $settings->admindetails_name, whose email address can be found at the bottom of every page (including this one).
"));
+ }
+
+ http_response_code(201);
+ exit(page_renderer::render_main("Reverting " . htmlentities($env->page) . " - $settings->sitename", "" . htmlentities($env->page) . " has been reverted back to revision {$env->history->revision_number} successfully.
+ Go back to the page, or continue reviewing its history.
"));
+
+ // $env->page_filename
+ //
+ });
register_save_preprocessor("history_add_revision");
}
]);
-function history_add_revision(&$pageinfo, &$newsource, &$oldsource, $save_pageindex = true) {
+/**
+ * Adds a history revision against a page.
+ * Note: Does not updaate the current page content! This function _only_
+ * records a new revision against a page name. Thus it is possible to have a
+ * disparaty between the history revisions and the actual content displayed in
+ * the current revision if you're not careful!
+ * @param object $pageinfo The pageindex object of the page to operate on.
+ * @param string $newsource The page content to save as the new revision.
+ * @param string $oldsource The old page content that is the current revision (before the update).
+ * @param boolean $save_pageindex Whether the page index should be saved to disk.
+ * @param string $change_type The type of change to record this as in the history revision log
+ */
+function history_add_revision(&$pageinfo, &$newsource, &$oldsource, $save_pageindex = true, $change_type = "edit") {
global $pageindex, $paths, $env;
if(!isset($pageinfo->history))
@@ -96,8 +193,7 @@ function history_add_revision(&$pageinfo, &$newsource, &$oldsource, $save_pagein
// Save the *new source* as a revision
// This results in 2 copies of the current source, but this is ok
- // since any time someone changes something, it create a new
- // revision
+ // since any time someone changes something, it creates a new revision
// Note that we can't save the old source here because we'd have no
// clue who edited it since $pageinfo has already been updated by
// this point
@@ -107,7 +203,7 @@ function history_add_revision(&$pageinfo, &$newsource, &$oldsource, $save_pagein
$ridFilename = "$pageinfo->filename.r$nextRid";
// Insert a new entry into the history
$pageinfo->history[] = [
- "type" => "edit", // We might want to store other types later (e.g. page moves)
+ "type" => $change_type, // We might want to store other types later (e.g. page moves)
"rid" => $nextRid,
"timestamp" => time(),
"filename" => $ridFilename,
@@ -117,11 +213,13 @@ function history_add_revision(&$pageinfo, &$newsource, &$oldsource, $save_pagein
];
// Save the new source as a revision
- file_put_contents("$env->storage_prefix$ridFilename", $newsource);
+ $result = file_put_contents("$env->storage_prefix$ridFilename", $newsource);
// Save the edited pageindex
- if($save_pageindex)
- file_put_contents($paths->pageindex, json_encode($pageindex, JSON_PRETTY_PRINT));
+ if($result !== false && $save_pageindex)
+ $result = file_put_contents($paths->pageindex, json_encode($pageindex, JSON_PRETTY_PRINT));
+
+ return $result;
}
?>
diff --git a/modules/feature-redirect.php b/modules/feature-redirect.php
index 66fd0d8..3b8ec98 100644
--- a/modules/feature-redirect.php
+++ b/modules/feature-redirect.php
@@ -8,29 +8,37 @@ register_module([
"code" => function() {
global $settings;
- register_save_preprocessor(function(&$index_entry, &$pagedata) {
- $matches = [];
- if(preg_match("/^# ?REDIRECT ?\[\[([^\]]+)\]\]/i", $pagedata, $matches) === 1)
- {
- //error_log("matches: " . var_export($matches, true));
- // We have found a redirect page!
- // Update the metadata to reflect this.
- $index_entry->redirect = true;
- $index_entry->redirect_target = $matches[1];
- }
- else
- {
- // This page isn't a redirect. Unset the metadata just in case.
- if(isset($index_entry->redirect))
- unset($index_entry->redirect);
- if(isset($index_entry->redirect_target))
- unset($index_entry->redirect_target);
- }
- });
+ register_save_preprocessor("update_redirect_metadata");
// Register a help section
add_help_section("25-redirect", "Redirect Pages", "$settings->sitename supports redirect pages. To create a redirect page, enter something like # REDIRECT [[pagename]]
on the first line of the redirect page's content. This must appear as the first line of the page, with no whitespace before it. You can include content beneath the redirect if you want, too (such as a reason for redirecting the page).
");
}
]);
+/**
+ * Updates the metadata associated with redirects in the pageindex entry
+ * specified utilising the provided page content.
+ * @param object $index_entry The page index entry object to update.
+ * @param string $pagedata The page content to operate on.
+ */
+function update_redirect_metadata(&$index_entry, &$pagedata) {
+ $matches = [];
+ if(preg_match("/^# ?REDIRECT ?\[\[([^\]]+)\]\]/i", $pagedata, $matches) === 1)
+ {
+ //error_log("matches: " . var_export($matches, true));
+ // We have found a redirect page!
+ // Update the metadata to reflect this.
+ $index_entry->redirect = true;
+ $index_entry->redirect_target = $matches[1];
+ }
+ else
+ {
+ // This page isn't a redirect. Unset the metadata just in case.
+ if(isset($index_entry->redirect))
+ unset($index_entry->redirect);
+ if(isset($index_entry->redirect_target))
+ unset($index_entry->redirect_target);
+ }
+}
+
?>