dedicated search_link() function for generating links to search results, see #936

This commit is contained in:
Shish 2023-08-18 13:38:55 +01:00 committed by Shish
parent 23e36b4349
commit 43c7be0e89
25 changed files with 54 additions and 43 deletions

View file

@ -197,7 +197,7 @@ function redirect_to_next_image(Image $image): void
$target_image = $image->get_next($search_terms); $target_image = $image->get_next($search_terms);
if ($target_image === null) { if ($target_image === null) {
$redirect_target = referer_or(make_link("post/list"), ['post/view']); $redirect_target = referer_or(search_link(), ['post/view']);
} else { } else {
$redirect_target = make_link("post/view/{$target_image->id}", null, $query); $redirect_target = make_link("post/view/{$target_image->id}", null, $query);
} }

View file

@ -10,6 +10,18 @@ require_once "core/urls.php";
class UrlsTest extends TestCase class UrlsTest extends TestCase
{ {
public function test_search_link()
{
$this->assertEquals(
"/test/post/list/bar+foo/1",
search_link(["foo", "bar"])
);
$this->assertEquals(
"/test/post/list/cat%2A+rating%3D%5Eq/1",
search_link(["rating=?", "cat*"])
);
}
public function test_make_link() public function test_make_link()
{ {
// basic // basic

View file

@ -23,6 +23,20 @@ class Link
} }
} }
/**
* Build a link to a search page for given terms,
* with all the appropriate escaping
*/
function search_link(array $terms = [], int $page = 1): string
{
if($terms) {
$q = urlencode(Tag::caret(Tag::implode($terms)));
return make_link("post/list/$q/$page");
} else {
return make_link("post/list/$page");
}
}
/** /**
* Figure out the correct way to link to a page, taking into account * Figure out the correct way to link to a page, taking into account
* things like the nice URLs setting. * things like the nice URLs setting.

View file

@ -134,7 +134,7 @@ class Approval extends Extension
{ {
global $user; global $user;
if ($user->can(Permissions::APPROVE_IMAGE)) { if ($user->can(Permissions::APPROVE_IMAGE)) {
$event->add_link("Pending Approval", make_link("/post/list/approved%3Ano/1"), 60); $event->add_link("Pending Approval", search_link(["approved:no"]), 60);
} }
} }

View file

@ -353,7 +353,7 @@ class ArtistsTheme extends Themelet
{ {
global $page; global $page;
$artist_link = "<a href='".make_link("post/list/".$artist['name']."/1")."'>".str_replace("_", " ", $artist['name'])."</a>"; $artist_link = "<a href='".search_link([$artist['name']])."'>".str_replace("_", " ", $artist['name'])."</a>";
$html = "<table id='poolsList' class='zebra'> $html = "<table id='poolsList' class='zebra'>
<thead> <thead>

View file

@ -26,7 +26,7 @@ class BrowserSearch extends Extension
if ($event->page_matches("browser_search.xml")) { if ($event->page_matches("browser_search.xml")) {
// First, we need to build all the variables we'll need // First, we need to build all the variables we'll need
$search_title = $config->get_string(SetupConfig::TITLE); $search_title = $config->get_string(SetupConfig::TITLE);
$search_form_url = make_link('post/list/{searchTerms}'); $search_form_url = search_link(['{searchTerms}']);
$suggenton_url = make_link('browser_search/')."{searchTerms}"; $suggenton_url = make_link('browser_search/')."{searchTerms}";
$icon_b64 = base64_encode(file_get_contents("ext/static_files/static/favicon.ico")); $icon_b64 = base64_encode(file_get_contents("ext/static_files/static/favicon.ico"));

View file

@ -75,7 +75,7 @@ class Favorites extends Extension
$i_favorites_count = Image::count_images(["favorited_by={$event->display_user->name}"]); $i_favorites_count = Image::count_images(["favorited_by={$event->display_user->name}"]);
$i_days_old = ((time() - strtotime($event->display_user->join_date)) / 86400) + 1; $i_days_old = ((time() - strtotime($event->display_user->join_date)) / 86400) + 1;
$h_favorites_rate = sprintf("%.1f", ($i_favorites_count / $i_days_old)); $h_favorites_rate = sprintf("%.1f", ($i_favorites_count / $i_days_old));
$favorites_link = make_link("post/list/favorited_by={$event->display_user->name}/1"); $favorites_link = search_link(["favorited_by={$event->display_user->name}"]);
$event->add_stats("<a href='$favorites_link'>Posts favorited</a>: $i_favorites_count, $h_favorites_rate per day"); $event->add_stats("<a href='$favorites_link'>Posts favorited</a>: $i_favorites_count, $h_favorites_rate per day");
} }
@ -115,7 +115,7 @@ class Favorites extends Extension
global $user; global $user;
$username = url_escape($user->name); $username = url_escape($user->name);
$event->add_link("My Favorites", make_link("post/list/favorited_by=$username/1"), 20); $event->add_link("My Favorites", search_link(["favorited_by=$username"]), 20);
} }
public function onSearchTermParse(SearchTermParseEvent $event) public function onSearchTermParse(SearchTermParseEvent $event)

View file

@ -37,7 +37,7 @@ EOD
$contact_link = empty($contact_link) ? "" : "<br><a href='$contact_link'>Contact</a> &ndash;"; $contact_link = empty($contact_link) ? "" : "<br><a href='$contact_link'>Contact</a> &ndash;";
$search_html = " $search_html = "
<div class='space' id='search'> <div class='space' id='search'>
<form action='".make_link("post/list")."' method='GET'> <form action='".search_link()."' method='GET'>
<input name='search' size='30' type='search' value='' class='autocomplete_tags' autofocus='autofocus' autocomplete='off' /> <input name='search' size='30' type='search' value='' class='autocomplete_tags' autofocus='autofocus' autocomplete='off' />
<input type='hidden' name='q' value='/post/list'> <input type='hidden' name='q' value='/post/list'>
<input type='submit' value='Search'/> <input type='submit' value='Search'/>

View file

@ -266,7 +266,7 @@ class ImageIO extends Extension
$i_image_count = Image::count_images(["user={$event->display_user->name}"]); $i_image_count = Image::count_images(["user={$event->display_user->name}"]);
$i_days_old = ((time() - strtotime($event->display_user->join_date)) / 86400) + 1; $i_days_old = ((time() - strtotime($event->display_user->join_date)) / 86400) + 1;
$h_image_rate = sprintf("%.1f", ($i_image_count / $i_days_old)); $h_image_rate = sprintf("%.1f", ($i_image_count / $i_days_old));
$images_link = make_link("post/list/user=$u_name/1"); $images_link = search_link(["user=$u_name"]);
$event->add_stats("<a href='$images_link'>Posts uploaded</a>: $i_image_count, $h_image_rate per day"); $event->add_stats("<a href='$images_link'>Posts uploaded</a>: $i_image_count, $h_image_rate per day");
} }

View file

@ -25,15 +25,8 @@ class Index extends Extension
global $cache, $page, $user; global $cache, $page, $user;
if ($event->page_matches("post/list")) { if ($event->page_matches("post/list")) {
if (isset($_GET['search'])) { if (isset($_GET['search'])) {
// implode(explode()) to resolve aliases and sanitise $page->set_mode(PageMode::REDIRECT);
$search = url_escape(Tag::caret(Tag::implode(Tag::explode($_GET['search'], false)))); $page->set_redirect(search_link(Tag::explode($_GET['search'], false)));
if (empty($search)) {
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("post/list/1"));
} else {
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link('post/list/'.$search.'/1'));
}
return; return;
} }

View file

@ -79,15 +79,13 @@ and of course start organising your images :-)
$next = $page_number + 1; $next = $page_number + 1;
$u_tags = url_escape(Tag::implode($search_terms)); $u_tags = url_escape(Tag::implode($search_terms));
$query = empty($u_tags) ? "" : '/'.$u_tags;
$h_prev = ($page_number <= 1) ? "Prev" : '<a href="'.search_link($search_terms, $prev).'">Prev</a>';
$h_prev = ($page_number <= 1) ? "Prev" : '<a href="'.make_link('post/list'.$query.'/'.$prev).'">Prev</a>';
$h_index = "<a href='".make_link()."'>Index</a>"; $h_index = "<a href='".make_link()."'>Index</a>";
$h_next = ($page_number >= $total_pages) ? "Next" : '<a href="'.make_link('post/list'.$query.'/'.$next).'">Next</a>'; $h_next = ($page_number >= $total_pages) ? "Next" : '<a href="'.search_link($search_terms, $next).'">Next</a>';
$h_search_string = html_escape(Tag::implode($search_terms)); $h_search_string = html_escape(Tag::implode($search_terms));
$h_search_link = make_link("post/list"); $h_search_link = search_link();
$h_search = " $h_search = "
<p><form action='$h_search_link' method='GET'> <p><form action='$h_search_link' method='GET'>
<input type='search' name='search' value='$h_search_string' placeholder='Search' class='autocomplete_tags' autocomplete='off' /> <input type='search' name='search' value='$h_search_string' placeholder='Search' class='autocomplete_tags' autocomplete='off' />

View file

@ -43,7 +43,7 @@ class NotesTheme extends Themelet
public function search_notes_page(Page $page): void public function search_notes_page(Page $page): void
{ //IN DEVELOPMENT, NOT FULLY WORKING { //IN DEVELOPMENT, NOT FULLY WORKING
$html = '<form method="GET" action="'.make_link("post/list/note=").'"> $html = '<form method="GET" action="'.search_link(["note="]).'">
<input placeholder="Search Notes" type="text" name="search"/> <input placeholder="Search Notes" type="text" name="search"/>
<input type="submit" style="display: none;" value="Find"/> <input type="submit" style="display: none;" value="Find"/>
</form>'; </form>';

View file

@ -119,11 +119,10 @@ class NumericScore extends Extension
$this->theme->get_nuller($event->display_user); $this->theme->get_nuller($event->display_user);
} }
$u_name = url_escape($event->display_user->name);
$n_up = Image::count_images(["upvoted_by={$event->display_user->name}"]); $n_up = Image::count_images(["upvoted_by={$event->display_user->name}"]);
$link_up = make_link("post/list/upvoted_by=$u_name/1"); $link_up = search_link(["upvoted_by={$event->display_user->name}"]);
$n_down = Image::count_images(["downvoted_by={$event->display_user->name}"]); $n_down = Image::count_images(["downvoted_by={$event->display_user->name}"]);
$link_down = make_link("post/list/downvoted_by=$u_name/1"); $link_down = search_link(["downvoted_by={$event->display_user->name}]"]);
$event->add_stats("<a href='$link_up'>$n_up Upvotes</a> / <a href='$link_down'>$n_down Downvotes</a>"); $event->add_stats("<a href='$link_up'>$n_up Upvotes</a> / <a href='$link_down'>$n_down Downvotes</a>");
} }

View file

@ -18,11 +18,10 @@ class RatingsTheme extends Themelet
public function get_rater_html(int $image_id, string $rating, bool $can_rate): HTMLElement public function get_rater_html(int $image_id, string $rating, bool $can_rate): HTMLElement
{ {
$u_rating = url_escape(Tag::caret($rating));
return SHM_POST_INFO( return SHM_POST_INFO(
"Rating", "Rating",
$can_rate, $can_rate,
A(["href"=>make_link("post/list/rating=$u_rating/1")], Ratings::rating_to_human($rating)), A(["href"=>search_link(["rating=$rating"])], Ratings::rating_to_human($rating)),
$this->get_selection_rater_html("rating", selected_options: [$rating]) $this->get_selection_rater_html("rating", selected_options: [$rating])
); );
} }

View file

@ -22,7 +22,7 @@ class RelationshipsTheme extends Themelet
if (bool_escape($image->has_children)) { if (bool_escape($image->has_children)) {
$ids = $database->get_col("SELECT id FROM images WHERE parent_id = :iid", ["iid"=>$image->id]); $ids = $database->get_col("SELECT id FROM images WHERE parent_id = :iid", ["iid"=>$image->id]);
$html = "This post has <a href='".make_link('post/list/parent='.$image->id.'/1')."'>".(count($ids) > 1 ? "child posts" : "a child post")."</a>"; $html = "This post has <a href='".search_link(['parent='.$image->id])."'>".(count($ids) > 1 ? "child posts" : "a child post")."</a>";
$html .= " (post "; $html .= " (post ";
foreach ($ids as $id) { foreach ($ids as $id) {
$html .= "#<a href='".make_link('post/view/'.$id)."'>{$id}</a>, "; $html .= "#<a href='".make_link('post/view/'.$id)."'>{$id}</a>, ";

View file

@ -152,7 +152,7 @@ class TagEdit extends Extension
if ($user->can(Permissions::MASS_TAG_EDIT) && isset($_POST['tags']) && isset($_POST['source'])) { if ($user->can(Permissions::MASS_TAG_EDIT) && isset($_POST['tags']) && isset($_POST['source'])) {
$this->mass_source_edit($_POST['tags'], $_POST['source']); $this->mass_source_edit($_POST['tags'], $_POST['source']);
$page->set_mode(PageMode::REDIRECT); $page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("post/list")); $page->set_redirect(search_link());
} }
} }
} }

View file

@ -47,9 +47,8 @@ class TagEditTheme extends Themelet
$tag_links = []; $tag_links = [];
foreach ($image->get_tag_array() as $tag) { foreach ($image->get_tag_array() as $tag) {
$u_tag = url_escape($tag);
$tag_links[] = A([ $tag_links[] = A([
"href" => make_link("post/list/$u_tag/1"), "href" => search_link([$tag]),
"class" => "tag", "class" => "tag",
"title" => "View all posts tagged $tag" "title" => "View all posts tagged $tag"
], $tag); ], $tag);

View file

@ -119,7 +119,7 @@ class TagHistoryTheme extends Themelet
$current_tags = Tag::explode($current_tags); $current_tags = Tag::explode($current_tags);
$taglinks = SPAN(); $taglinks = SPAN();
foreach ($current_tags as $tag) { foreach ($current_tags as $tag) {
$taglinks->appendChild(A(["href"=>make_link("post/list/$tag/1")], $tag)); $taglinks->appendChild(A(["href"=>search_link([$tag])], $tag));
$taglinks->appendChild(" "); $taglinks->appendChild(" ");
} }

View file

@ -298,7 +298,6 @@ class TagListTheme extends Themelet
public function tag_link(string $tag): string public function tag_link(string $tag): string
{ {
$u_tag = url_escape(Tag::caret($tag)); return search_link([$tag]);
return make_link("post/list/$u_tag/1");
} }
} }

View file

@ -97,7 +97,7 @@ class Trash extends Extension
{ {
global $user; global $user;
if ($user->can(Permissions::VIEW_TRASH)) { if ($user->can(Permissions::VIEW_TRASH)) {
$event->add_link("Trash", make_link("/post/list/in%3Atrash/1"), 60); $event->add_link("Trash", search_link(["in:trash"]), 60);
} }
} }

View file

@ -45,7 +45,7 @@ class UploadTest extends ShimmiePHPUnitTestCase
]; ];
$page = $this->post_page("upload", ["tags0"=>"foo bar"]); $page = $this->post_page("upload", ["tags0"=>"foo bar"]);
$this->assert_response(302); $this->assert_response(302);
$this->assertStringStartsWith("/test/post/list/poster=test/1", $page->redirect); $this->assertStringStartsWith("/test/post/list/poster%3Dtest/1", $page->redirect);
$this->assertEquals(4, $database->get_one("SELECT COUNT(*) FROM images")); $this->assertEquals(4, $database->get_one("SELECT COUNT(*) FROM images"));
} }

View file

@ -300,7 +300,7 @@ class UploadTheme extends Themelet
$page->set_redirect(make_link("post/view/{$image_ids[0]}")); $page->set_redirect(make_link("post/view/{$image_ids[0]}"));
} else { } else {
$page->set_mode(PageMode::REDIRECT); $page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("post/list/poster={$user->name}/1")); $page->set_redirect(search_link(["poster={$user->name}"]));
} }
} }
} }

View file

@ -38,7 +38,7 @@ class UserActionColumn extends ActionColumn
public function display(array $row): HTMLElement public function display(array $row): HTMLElement
{ {
return A(["href"=>make_link("post/list/user={$row['name']}/1")], "Posts"); return A(["href"=>search_link(["user={$row['name']}"])], "Posts");
} }
} }

View file

@ -45,8 +45,7 @@ class CustomCommentListTheme extends CommentListTheme
$un = $image->get_owner()->name; $un = $image->get_owner()->name;
$t = ""; $t = "";
foreach ($image->get_tag_array() as $tag) { foreach ($image->get_tag_array() as $tag) {
$u_tag = url_escape($tag); $t .= "<a href='".search_link([$tag])."'>".html_escape($tag)."</a> ";
$t .= "<a href='".make_link("post/list/$u_tag/1")."'>".html_escape($tag)."</a> ";
} }
$p = autodate($image->posted); $p = autodate($image->posted);

View file

@ -45,8 +45,7 @@ class CustomCommentListTheme extends CommentListTheme
$un = $image->get_owner()->name; $un = $image->get_owner()->name;
$t = ""; $t = "";
foreach ($image->get_tag_array() as $tag) { foreach ($image->get_tag_array() as $tag) {
$u_tag = url_escape($tag); $t .= "<a href='".search_link([$tag])."'>".html_escape($tag)."</a> ";
$t .= "<a href='".make_link("post/list/$u_tag/1")."'>".html_escape($tag)."</a> ";
} }
$p = autodate($image->posted); $p = autodate($image->posted);