<?php
register_module([
	"name" => "Page History",
	"version" => "0.3",
	"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",
	"code" => function() {
		/**
		 * @api {get} ?action=history&page={pageName} Get a list of revisions for a page
		 * @apiName History
		 * @apiGroup Page
		 * @apiPermission Anonymous
		 * 
		 * @apiParam {string}	page	The page name to return a revision list for.
		 * @apiParam {string}	format	The format to return the list of pages in. available values: html, json, text. Default: html
		 */
		
		/*
		 * ██   ██ ██ ███████ ████████  ██████  ██████  ██    ██
		 * ██   ██ ██ ██         ██    ██    ██ ██   ██  ██  ██
		 * ███████ ██ ███████    ██    ██    ██ ██████    ████
		 * ██   ██ ██      ██    ██    ██    ██ ██   ██    ██
		 * ██   ██ ██ ███████    ██     ██████  ██   ██    ██
		 */
		add_action("history", function() {
			global $settings, $env, $pageindex;
			
			$supported_formats = [ "html", "json", "text" ];
			$format = $_GET["format"] ?? "html";
			
			switch($format) {
				case "html":
					$content = "<h1>History for $env->page</h1>\n";
					if(!empty($pageindex->{$env->page}->history))
					{
						$content .= "\t\t<ul class='page-list'>\n";
						foreach(array_reverse($pageindex->{$env->page}->history) as $revisionData)
						{
							// Only display edits for now
							if($revisionData->type != "edit")
							continue;
							
							// The number (and the sign) of the size difference to display
							$size_display = ($revisionData->sizediff > 0 ? "+" : "") . $revisionData->sizediff;
							$size_display_class = $revisionData->sizediff > 0 ? "larger" : ($revisionData->sizediff < 0 ? "smaller" : "nochange");
							if($revisionData->sizediff > 500 or $revisionData->sizediff < -500)
							$size_display_class .= " significant";
							$size_title_display = human_filesize($revisionData->newsize - $revisionData->sizediff) . " -> " .  human_filesize($revisionData->newsize);
							
							$content .= "<li><a href='?page=" . rawurlencode($env->page) . "&revision=$revisionData->rid'>#$revisionData->rid</a> " . render_editor(page_renderer::render_username($revisionData->editor)) . " " . render_timestamp($revisionData->timestamp) . " <span class='cursor-query $size_display_class' title='$size_title_display'>($size_display)</span>";
						}
					}
					else
					{
						$content .= "<p style='text-align: center;'><em>(None yet! Try editing this page and then coming back here.)</em></p>\n";
					}
					exit(page_renderer::render_main("$env->page - History - $settings->sitename", $content));
				
				case "json":
					$page_history = $pageindex->{$env->page}->history ?? [];
					
					foreach($page_history as &$history_entry) {
						unset($history_entry->filename);
					}
					header("content-type: application/json");
					exit(json_encode($page_history, JSON_PRETTY_PRINT));
				
				case "csv":
					$page_history = $pageindex->{$env->page}->history ?? [];
					
					header("content-type: text/csv");
					echo("revision_id,timestamp,type,editor,newsize,sizediff\n");
					foreach($page_history as $hentry) {
						echo("$hentry->rid,$hentry->timestamp,$hentry->type,$hentry->editor,$hentry->newsize,$hentry->sizediff\n");
					}
					exit();
				
				default:
					http_response_code(400);
					exit(page_renderer::render_main("Format Error - $env->page - History - $settings->sitename", "<p>The format <code>" . htmlentities($format) . "</code> isn't currently supported. Supported formats: html, json, csv"));
			}
			
		});
		
		
		register_save_preprocessor("history_add_revision");
	}
]);

function history_add_revision(&$pageinfo, &$newsource, &$oldsource, $save_pageindex = true) {
	global $pageindex, $paths, $env;
	
	if(!isset($pageinfo->history))
		$pageinfo->history = [];
	
	// 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
	// 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
	
	// TODO Store tag changes here
	$nextRid = count($pageinfo->history); // The next revision id
	$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)
		"rid" => $nextRid,
		"timestamp" => time(),
		"filename" => $ridFilename,
		"newsize" => strlen($newsource),
		"sizediff" => strlen($newsource) - strlen($oldsource),
		"editor" => $pageinfo->lasteditor
	];
	
	// Save the new source as a revision
	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));
}

?>

