Skip to content

Commit

Permalink
[tag_list] split into tag_list/tag_map
Browse files Browse the repository at this point in the history
  • Loading branch information
shish committed Dec 14, 2024
1 parent 7587338 commit 20d1060
Show file tree
Hide file tree
Showing 14 changed files with 382 additions and 317 deletions.
4 changes: 2 additions & 2 deletions ext/ouroboros_api/main.php
Original file line number Diff line number Diff line change
Expand Up @@ -442,7 +442,7 @@ protected function tagIndex(int $limit, int $page, string $order, string $name,
WHERE count >= :tags_min
ORDER BY LOWER(substr(tag, 1, 1)) LIMIT :start, :max_items
",
['tags_min' => $config->get_int(TagListConfig::TAGS_MIN), 'start' => $start, 'max_items' => $limit]
['tags_min' => $config->get_int(TagMapConfig::TAGS_MIN), 'start' => $start, 'max_items' => $limit]
);
break;
case 'count':
Expand All @@ -454,7 +454,7 @@ protected function tagIndex(int $limit, int $page, string $order, string $name,
WHERE count >= :tags_min
ORDER BY count DESC, tag ASC LIMIT :start, :max_items
",
['tags_min' => $config->get_int(TagListConfig::TAGS_MIN), 'start' => $start, 'max_items' => $limit]
['tags_min' => $config->get_int(TagMapConfig::TAGS_MIN), 'start' => $start, 'max_items' => $limit]
);
break;
}
Expand Down
2 changes: 0 additions & 2 deletions ext/tag_list/config.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,11 @@ class TagListConfig
{
public const LENGTH = "tag_list_length";
public const POPULAR_TAG_LIST_LENGTH = "popular_tag_list_length";
public const TAGS_MIN = "tags_min";
public const INFO_LINK = "info_link";
public const SHOW_NUMBERS = "tag_list_numbers";
public const IMAGE_TYPE = "tag_list_image_type";
public const RELATED_SORT = "tag_list_related_sort";
public const POPULAR_SORT = "tag_list_popular_sort";
public const PAGES = "tag_list_pages";
public const OMIT_TAGS = "tag_list_omit_tags";

public const TYPE_RELATED = "related";
Expand Down
214 changes: 0 additions & 214 deletions ext/tag_list/main.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,6 @@

namespace Shimmie2;

use MicroHTML\HTMLElement;

use function MicroHTML\{emptyHTML, BR, SPAN, A, P, HR};
use function MicroHTML\rawHTML;

require_once "config.php";

class TagList extends Extension
Expand All @@ -21,60 +16,11 @@ public function onInitExt(InitExtEvent $event): void
global $config;
$config->set_default_int(TagListConfig::LENGTH, 15);
$config->set_default_int(TagListConfig::POPULAR_TAG_LIST_LENGTH, 15);
$config->set_default_int(TagListConfig::TAGS_MIN, 3);
$config->set_default_string(TagListConfig::INFO_LINK, 'https://en.wikipedia.org/wiki/$tag');
$config->set_default_string(TagListConfig::OMIT_TAGS, 'tagme*');
$config->set_default_string(TagListConfig::IMAGE_TYPE, TagListConfig::TYPE_RELATED);
$config->set_default_string(TagListConfig::RELATED_SORT, TagListConfig::SORT_ALPHABETICAL);
$config->set_default_string(TagListConfig::POPULAR_SORT, TagListConfig::SORT_TAG_COUNT);
$config->set_default_bool(TagListConfig::PAGES, false);
}

public function onPageRequest(PageRequestEvent $event): void
{
global $config, $page;

if ($event->page_matches("tags/{sub}", method: "GET")) {
$sub = $event->get_arg('sub');

if ($event->get_GET('starts_with')) {
$starts_with = $event->get_GET('starts_with') . "%";
} else {
if ($config->get_bool(TagListConfig::PAGES)) {
$starts_with = "a%";
} else {
$starts_with = "%";
}
}

if ($event->get_GET('mincount')) {
$tags_min = int_escape($event->get_GET('mincount'));
} else {
global $config;
$tags_min = $config->get_int(TagListConfig::TAGS_MIN); // get the default.
}

switch ($sub) {
case 'map':
$this->theme->set_heading("Tag Map");
$this->theme->display_page($this->build_tag_map($starts_with, $tags_min));
break;
case 'alphabetic':
$this->theme->set_heading("Alphabetic Tag List");
$this->theme->display_page($this->build_tag_alphabetic($starts_with, $tags_min));
break;
case 'popularity':
$this->theme->set_heading("Tag List by Popularity");
$this->theme->display_page($this->build_tag_popularity($tags_min));
break;
default:
// don't display anything
break;
}
} elseif ($event->page_matches("tags")) {
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("tags/map"));
}
}

public function onPostListBuilding(PostListBuildingEvent $event): void
Expand All @@ -89,20 +35,6 @@ public function onPostListBuilding(PostListBuildingEvent $event): void
}
}

public function onPageNavBuilding(PageNavBuildingEvent $event): void
{
$event->add_nav_link("tags", new Link('tags/map'), "Tags");
}

public function onPageSubNavBuilding(PageSubNavBuildingEvent $event): void
{
if ($event->parent == "tags") {
$event->add_nav_link("tags_map", new Link('tags/map'), "Map");
$event->add_nav_link("tags_alphabetic", new Link('tags/alphabetic'), "Alphabetic");
$event->add_nav_link("tags_popularity", new Link('tags/popularity'), "Popularity");
}
}

public function onDisplayingImage(DisplayingImageEvent $event): void
{
global $config, $page;
Expand All @@ -123,11 +55,6 @@ public function onDisplayingImage(DisplayingImageEvent $event): void

public function onSetupBuilding(SetupBuildingEvent $event): void
{
$sb = $event->panel->create_new_block("Tag Map Options");
$sb->add_int_option(TagListConfig::TAGS_MIN, "Only show tags used at least ");
$sb->add_label(" times");
$sb->add_bool_option(TagListConfig::PAGES, "<br>Paged tag lists: ");

$sb = $event->panel->create_new_block("Popular / Related Tag List");
$sb->add_int_option(TagListConfig::LENGTH, "Show top ");
$sb->add_label(" related tags");
Expand Down Expand Up @@ -197,147 +124,6 @@ private static function get_omitted_tags(): array
return $results;
}

private function build_az(int $tags_min): HTMLElement
{
global $database;

$tag_data = $database->get_col("
SELECT DISTINCT
LOWER(substr(tag, 1, 1))
FROM tags
WHERE count >= :tags_min
ORDER BY LOWER(substr(tag, 1, 1))
", ["tags_min" => $tags_min]);

$html = SPAN(["class" => "atoz"]);
foreach ($tag_data as $a) {
$html->appendChild(A(["href" => modify_current_url(["starts_with" => $a])], $a));
}
return emptyHTML($html, P(), HR());
}

private function build_tag_map(string $starts_with, int $tags_min): HTMLElement
{
global $config, $database;

$tag_data = $database->get_all("
SELECT
tag,
FLOOR(LN(LN(count - :tags_min + 1)+1)*1.5*100)/100 AS scaled
FROM tags
WHERE count >= :tags_min
AND LOWER(tag) LIKE LOWER(:starts_with)
ORDER BY LOWER(tag)
", ["tags_min" => $tags_min, "starts_with" => $starts_with]);

$html = emptyHTML();
if ($config->get_bool(TagListConfig::PAGES)) {
$html->appendChild($this->build_az($tags_min));
}
foreach ($tag_data as $row) {
$tag = $row['tag'];
$scale = (float)$row['scaled'];
$size = sprintf("%.2f", $scale < 0.5 ? 0.5 : $scale);
$html->appendChild(rawHTML("&nbsp;"));
$html->appendChild($this->theme->build_tag($tag, style: "font-size: {$size}em"));
$html->appendChild(rawHTML("&nbsp;"));
}

return $html;
}

private function build_tag_alphabetic(string $starts_with, int $tags_min): HTMLElement
{
global $config, $database;

$tag_data = $database->get_pairs("
SELECT tag, count
FROM tags
WHERE count >= :tags_min
AND LOWER(tag) LIKE LOWER(:starts_with)
ORDER BY LOWER(tag)
", ["tags_min" => $tags_min, "starts_with" => $starts_with]);

$html = emptyHTML();
if ($config->get_bool(TagListConfig::PAGES)) {
$html->appendChild($this->build_az($tags_min));
}

/*
strtolower() vs. mb_strtolower()
( See https://www.php.net/manual/en/function.mb-strtolower.php for more info )
PHP5's strtolower function does not support Unicode (UTF-8) properly, so
you have to use another function, mb_strtolower, to handle UTF-8 strings.
What's worse is that mb_strtolower is horribly SLOW.
It would probably be better to have a config option for the Tag List that
would allow you to specify if there are UTF-8 tags.
*/
mb_internal_encoding('UTF-8');

$lastLetter = "";
# postres utf8 string sort ignores punctuation, so we get "aza, a-zb, azc"
# which breaks down into "az, a-, az" :(
ksort($tag_data, SORT_STRING | SORT_FLAG_CASE);
$n = 0;
foreach ($tag_data as $tag => $count) {
// In PHP, $array["10"] sets the array key as int(10), not string("10")...
$tag = (string)$tag;
if ($lastLetter != mb_strtolower(substr($tag, 0, strlen($starts_with) + 1))) {
$lastLetter = mb_strtolower(substr($tag, 0, strlen($starts_with) + 1));
if ($n++ > 0) {
$html->appendChild(BR());
$html->appendChild(BR());
}
$html->appendChild($lastLetter);
$html->appendChild(BR());
}
$html->appendChild($this->theme->build_tag($tag));
}

return $html;
}

private function build_tag_popularity(int $tags_min): HTMLElement
{
global $config, $database;

// Make sure that the value of $tags_min is at least 1.
// Otherwise the database will complain if you try to do: LOG(0)
if ($tags_min < 1) {
$tags_min = 1;
}

$tag_data = $database->get_all("
SELECT tag, count, FLOOR(LOG(10, count)) AS scaled
FROM tags
WHERE count >= :tags_min
ORDER BY count DESC, tag ASC
", ["tags_min" => $tags_min]);

$html = emptyHTML(rawHTML("Results grouped by log<sub>10</sub>(n)"));
$lastLog = "";
foreach ($tag_data as $row) {
$tag = $row['tag'];
$count = $row['count'];
$scaled = $row['scaled'];
if ($lastLog != $scaled) {
$lastLog = $scaled;
$html->appendChild(BR());
$html->appendChild(BR());
$html->appendChild("$lastLog");
$html->appendChild(BR());
}
$html->appendChild($this->theme->build_tag($tag));
$html->appendChild(rawHTML("&nbsp;($count)&nbsp;&nbsp;"));
}

return $html;
}

private function add_related_block(Page $page, Image $image): void
{
global $database, $config;
Expand Down
37 changes: 6 additions & 31 deletions ext/tag_list/test.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,37 +6,12 @@

class TagListTest extends ShimmiePHPUnitTestCase
{
/** @var string[] */
private array $pages = ["map", "alphabetic", "popularity"];

public function testTagList(): void
{
$this->get_page('tags/map');
$this->assert_title('Tag List');

$this->get_page('tags/alphabetic');
$this->assert_title('Tag List');

$this->get_page('tags/popularity');
$this->assert_title('Tag List');

# FIXME: test that these show the right stuff
}

public function testMinCount(): void
public function testIndex(): void
{
foreach ($this->pages as $page) {
$this->get_page("tags/$page", ["mincount" => 999999]);
$this->assert_title("Tag List");

$this->get_page("tags/$page", ["mincount" => 1]);
$this->assert_title("Tag List");

$this->get_page("tags/$page", ["mincount" => 0]);
$this->assert_title("Tag List");

$this->get_page("tags/$page", ["mincount" => -1]);
$this->assert_title("Tag List");
}
$this->log_in_as_user();
$image_id = $this->post_image("tests/pbx_screenshot.jpg", "pbx");
$page = $this->get_page("post/view/$image_id");
$this->assert_title("Post $image_id: pbx");
$this->assert_text("pbx");
}
}
35 changes: 1 addition & 34 deletions ext/tag_list/theme.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,43 +6,10 @@

use MicroHTML\HTMLElement;

use function MicroHTML\{A, BR, rawHTML, emptyHTML, joinHTML, TABLE, COLGROUP, COL, THEAD, TH, TR, TD, SPAN};
use function MicroHTML\{A, BR, rawHTML, emptyHTML, TABLE, COLGROUP, COL, THEAD, TH, TR, TD, SPAN};

class TagListTheme extends Themelet
{
public string $heading = "";

public function set_heading(string $text): void
{
$this->heading = $text;
}

public function display_page(HTMLElement $list): void
{
global $page;

$page->set_title("Tag List");
$page->set_heading($this->heading);
$page->add_block(new Block("Tags", $list));

$nav = joinHTML(
BR(),
[
A(["href" => make_link()], "Index"),
rawHTML("&nbsp;"),
A(["href" => make_link("tags/map")], "Map"),
A(["href" => make_link("tags/alphabetic")], "Alphabetic"),
A(["href" => make_link("tags/popularity")], "Popularity"),
rawHTML("&nbsp;"),
A(["href" => modify_current_url(["mincount" => 1])], "Show All"),
]
);

$page->add_block(new Block("Navigation", $nav, "left", 0));
}

// =======================================================================

protected function get_tag_list_preamble(): HTMLElement
{
global $config;
Expand Down
11 changes: 11 additions & 0 deletions ext/tag_map/config.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?php

declare(strict_types=1);

namespace Shimmie2;

class TagMapConfig
{
public const TAGS_MIN = "tags_min";
public const PAGES = "tag_list_pages";
}
Loading

0 comments on commit 20d1060

Please sign in to comment.