Pepperminty-Wiki/modules/page-list.php

308 lines
11 KiB
PHP

<?php
/* This Source Code Form is subject to the terms of the Mozilla Public
* 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/. */
register_module([
"name" => "Page list",
"version" => "0.11.5",
"author" => "Starbeamrainbowlabs",
"description" => "Adds a page that lists all the pages in the index along with their metadata.",
"id" => "page-list",
"code" => function() {
global $settings;
/**
* @api {get} ?action=list[&format={format}] List all pages
* @apiDescription Gets a list of all the pages currently stored on the wiki.
* @apiName ListPages
* @apiGroup Page
* @apiPermission Anonymous
*
* @apiParam {string} format The format to return the page list in. Default: html. Other foramts available: json, text
*/
/*
* ██ ██ ███████ ████████
* ██ ██ ██ ██
* ██ ██ ███████ ██
* ██ ██ ██ ██
* ███████ ██ ███████ ██
*/
add_action("list", function() {
global $pageindex, $settings;
$supported_formats = [ "html", "json", "text" ];
$format = $_GET["format"] ?? "html";
$sorted_pageindex = get_object_vars($pageindex);
$sorter = new Collator("");
uksort($sorted_pageindex, function($a, $b) use($sorter) : int {
return $sorter->compare($a, $b);
});
switch($format) {
case "html":
$title = "All Pages";
$content = " <h1>$title on $settings->sitename</h1>";
$content .= generate_page_list(array_keys($sorted_pageindex));
exit(page_renderer::render_main("$title - $settings->sitename", $content));
break;
case "json":
header("content-type: application/json");
exit(json_encode(array_keys($sorted_pageindex), JSON_PRETTY_PRINT));
case "text":
header("content-type: text/plain");
exit(implode("\n", array_keys($sorted_pageindex)));
default:
http_response_code(400);
exit(page_renderer::render_main("Format error - $settings->sitename", "<p>Error: The format '".htmlentities($format)."' is not currently supported by this action on $settings->sitename. Supported formats: " . htmlentities(implode(", ", $supported_formats)) . "."));
}
});
/**
* @api {get} ?action=list-tags[&tag=] Get a list of tags or pages with a certain tag
* @apiDescription Gets a list of all tags on the wiki. Adding the `tag` parameter causes a list of pages with the given tag to be returned instead.
* @apiName ListTags
* @apiGroup Utility
* @apiPermission Anonymous
*
* @apiParam {string} tag Optional. If provided a list of all the pages with that tag is returned instead.
* @apiParam {string} format Optional. If specified sets the format of the returned result. Supported values: html, json. Default: html
*/
/*
* ██ ██ ███████ ████████ ████████ █████ ██████ ███████
* ██ ██ ██ ██ ██ ██ ██ ██ ██
* ██ ██ ███████ ██ █████ ██ ███████ ██ ███ ███████
* ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
* ███████ ██ ███████ ██ ██ ██ ██ ██████ ███████
*/
add_action("list-tags", function() {
global $pageindex, $settings;
$supported_formats = [ "html", "json", "text" ];
$format = $_GET["format"] ?? "html";
if(!in_array($format, $supported_formats)) {
http_response_code(400);
exit(page_renderer::render_main("Format error - $settings->sitename", "<p>Error: The format '".htmlentities($format)."' is not currently supported by this action on $settings->sitename. Supported formats: " . htmlentities(implode(", ", $supported_formats)) . "."));
}
if(!isset($_GET["tag"]))
{
// Render a list of all tags
$all_tags = get_all_tags();
$sorter = new Collator("");
$sorter->sort($all_tags, Collator::SORT_STRING);
switch($format) {
case "html":
$content = "<h1>All tags</h1>
<ul class='tag-list'>\n";
foreach($all_tags as $tag) {
$content .= " <li><a href='?action=list-tags&amp;tag=" . rawurlencode($tag) . "' class='mini-tag'>".htmlentities($tag)."</a></li>\n";
}
$content .= "</ul>\n";
exit(page_renderer::render("All tags - $settings->sitename", $content));
break;
case "json":
header("content-type: application/json");
exit(json_encode($all_tags, JSON_PRETTY_PRINT));
case "text":
header("content-type: text/plain");
exit(implode("\n", $all_tags));
}
}
$tag = $_GET["tag"];
$pagelist = [];
foreach($pageindex as $pagename => $pagedetails)
{
if(empty($pagedetails->tags)) continue;
if(in_array($tag, $pagedetails->tags))
$pagelist[] = $pagename;
}
$sorter = new Collator("");
$sorter->sort($pagelist, Collator::SORT_STRING);
switch($format)
{
case "html":
$content = "<h1>Tag List: ".htmlentities($tag)."</h1>\n";
$content .= generate_page_list($pagelist);
$content .= "<p>(<a href='?action=list-tags'>All tags</a>)</p>\n";
exit(page_renderer::render("$tag - Tag List - $settings->sitename", $content));
case "json":
header("content-type: application/json");
exit(json_encode($pagelist, JSON_PRETTY_PRINT));
case "text":
header("content-type: text/plain");
exit(implode("\n", $pagelist));
}
});
statistic_add([
"id" => "tag-count",
"name" => "Number of Tags",
"type" => "scalar",
"update" => function($old_data) {
global $pageindex;
$result = new stdClass(); // value, state, completed
$result->value = count(get_all_tags());
$result->completed = true;
return $result;
}
]);
statistic_add([
"id" => "tags-per-page",
"name" => "Average Number of Tags per Page",
"type" => "scalar",
"update" => function($old_data) {
global $pageindex;
$tag_counts = [];
foreach($pageindex as $page_entry)
$tag_counts[] = count($page_entry->tags ?? []);
$result = new stdClass(); // value, state, completed
$result->value = empty($tag_counts) ? -1 : round(array_sum($tag_counts) / count($tag_counts), 3);
$result->completed = true;
return $result;
}
]);
statistic_add([
"id" => "most-tags",
"name" => "Most tags on a single page",
"type" => "scalar",
"update" => function($old_data) {
global $pageindex;
$highest_tag_count = 0;
$highest_tag_page = "";
foreach($pageindex as $pagename => $page_entry) {
if(count($page_entry->tags ?? []) > $highest_tag_count) {
$highest_tag_count = count($page_entry->tags ?? []);
$highest_tag_page = $pagename;
}
}
$result = new stdClass(); // value, state, completed
$result->value = "$highest_tag_count (<a href='?page=" . rawurlencode($highest_tag_page) . "'>" . htmlentities($highest_tag_page) . "</a>)";
$result->completed = true;
return $result;
}
]);
statistic_add([
"id" => "untagged-pages",
"name" => "Untagged Pages",
"type" => "page-list",
"update" => function($old_data) {
global $pageindex;
$untagged_pages = [];
foreach($pageindex as $pagename => $page_entry) {
if(empty($page_entry->tags) || count($page_entry->tags ?? []) == 0)
$untagged_pages[] = $pagename;
}
sort($untagged_pages, SORT_STRING | SORT_FLAG_CASE);
$result = new stdClass(); // value, state, completed
$result->value = $untagged_pages;
$result->completed = true;
return $result;
}
]);
add_help_section("30-all-pages-tags", "Listing pages and tags", "<p>All the pages and tags on $settings->sitename are listed on a pair of pages to aid navigation. The list of all pages on $settings->sitename can be found by clicking &quot;All Pages&quot; on the top bar. The list of all the tags currently in use can be found by clicking &quot;All Tags&quot; in the &quot;More...&quot; menu in the top right.</p>
<p>Each tag on either page can be clicked, and leads to a list of all pages that possess that particular tag.</p>
<p>Redirect pages are shown in italics. A page's last known editor is also shown next to each entry on a list of pages, along with the last known size (which should correct, unless it was changed outside of $settings->sitename) and the time since the last modification (hovering over this will show the exact time that the last modification was made in a tooltip).</p>");
}
]);
/**
* Gets a list of all the tags currently used across the wiki.
* @package page-list
* @since 0.15.0
* @return string[] A list of all unique tags present on all pages across the wiki.
*/
function get_all_tags()
{
global $pageindex;
$all_tags = [];
foreach($pageindex as $page_entry) {
if(empty($page_entry->tags))
continue;
foreach($page_entry->tags as $tag) {
if(!in_array($tag, $all_tags))
$all_tags[] = $tag;
}
}
return $all_tags;
}
/**
* Renders a list of pages as HTML.
* @package page-list
* @param string[] $pagelist A list of page names to include in the list.
* @return string The specified list of pages as HTML.
*/
function generate_page_list($pagelist)
{
global $pageindex;
// ✎ &#9998; 🕒 &#128338;
$result = "<ul class='page-list'>\n";
foreach($pagelist as $pagename)
{
// Construct a list of tags that are attached to this page ready for display
$tags = "";
// Make sure that this page does actually have some tags first
if(isset($pageindex->$pagename->tags))
{
foreach($pageindex->$pagename->tags as $tag)
{
$tags .= "<a href='?action=list-tags&amp;tag=" . rawurlencode($tag) . "' class='mini-tag'>".htmlentities($tag)."</a>, ";
}
$tags = substr($tags, 0, -2); // Remove the last ", " from the tag list
}
$pageDisplayName = htmlentities($pagename);
if(isset($pageindex->$pagename) and
!empty($pageindex->$pagename->redirect))
$pageDisplayName = "<em>$pageDisplayName</em>";
$url = "index.php?page=" . rawurlencode($pagename);
if(isset($pageindex->$pagename->redirect) && $pageindex->$pagename->redirect == true)
$url .= "&amp;redirect=no";
$result .= "<li><a href='$url'>$pageDisplayName</a>
<em class='size'>(" . human_filesize($pageindex->$pagename->size) . ")</em>
<span class='editor'><span class='texticon cursor-query' title='Last editor'>&#9998;</span> " . htmlentities($pageindex->$pagename->lasteditor) . "</span>
<time class='cursor-query' title='" . date("l jS \of F Y \a\\t h:ia T", $pageindex->$pagename->lastmodified) . "'>" . human_time_since($pageindex->$pagename->lastmodified) . "</time>
<span class='tags'>$tags</span></li>";
}
$result .= " </ul>\n";
return $result;
}
?>