Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/main'
Browse files Browse the repository at this point in the history
  • Loading branch information
Giraffaman committed Feb 24, 2024
2 parents e8290f5 + 2f4d857 commit ea7404a
Show file tree
Hide file tree
Showing 10 changed files with 141 additions and 46 deletions.
43 changes: 40 additions & 3 deletions core/imageboard/search.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,21 @@

use GQLA\Query;

/**
* A small chunk of SQL code + parameters, to be used in a larger query
*
* eg
*
* $q = new Querylet("SELECT * FROM images");
* $q->append(new Querylet(" WHERE id = :id", ["id" => 123]));
* $q->append(new Querylet(" AND rating = :rating", ["rating" => "safe"]));
* $q->append(new Querylet(" ORDER BY id DESC"));
*
* becomes
*
* SELECT * FROM images WHERE id = :id AND rating = :rating ORDER BY id DESC
* ["id" => 123, "rating" => "safe"]
*/
class Querylet
{
/**
Expand All @@ -25,6 +40,9 @@ public function append(Querylet $querylet): void
}
}

/**
* When somebody has searched for a tag, "cat", "cute", "-angry", etc
*/
class TagCondition
{
public function __construct(
Expand All @@ -34,6 +52,10 @@ public function __construct(
}
}

/**
* When somebody has searched for a specific image property, like "rating:safe",
* "id:123", "width:100", etc
*/
class ImgCondition
{
public function __construct(
Expand All @@ -45,10 +67,19 @@ public function __construct(

class Search
{
/** @var list<string> */
/**
* The search code is dark and full of horrors, and it's not always clear
* what's going on. This is a list of the steps that the search code took
* to find the images that it returned.
*
* @var list<string>
*/
public static array $_search_path = [];

/**
* Build a search query for a given set of tags and return
* the results as a PDOStatement (raw SQL rows)
*
* @param list<string> $tags
*/
private static function find_images_internal(int $start = 0, ?int $limit = null, array $tags = []): \FFSPHP\PDOStatement
Expand Down Expand Up @@ -203,10 +234,13 @@ private static function tag_or_wildcard_to_ids(string $tag): array
/**
* Turn a human input string into a an abstract search query
*
* (This is only public for testing purposes, nobody should be calling this
* directly from outside this class)
*
* @param string[] $terms
* @return array{0: TagCondition[], 1: ImgCondition[], 2: string}
*/
private static function terms_to_conditions(array $terms): array
public static function terms_to_conditions(array $terms): array
{
global $config;

Expand Down Expand Up @@ -234,10 +268,13 @@ private static function terms_to_conditions(array $terms): array
/**
* Turn an abstract search query into an SQL Querylet
*
* (This is only public for testing purposes, nobody should be calling this
* directly from outside this class)
*
* @param TagCondition[] $tag_conditions
* @param ImgCondition[] $img_conditions
*/
private static function build_search_querylet(
public static function build_search_querylet(
array $tag_conditions,
array $img_conditions,
?string $order = null,
Expand Down
3 changes: 0 additions & 3 deletions core/imageboard/tag.php
Original file line number Diff line number Diff line change
Expand Up @@ -210,9 +210,6 @@ public static function sanitize(string $tag): string
$tag = "";
} // hard-code one bad case...

if (mb_strlen($tag, 'UTF-8') > 255) {
throw new InvalidInput("The tag below is longer than 255 characters, please use a shorter tag.\n$tag\n");
}
return $tag;
}

Expand Down
4 changes: 2 additions & 2 deletions ext/image_hash_ban/main.php
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ public function onPageSubNavBuilding(PageSubNavBuildingEvent $event): void
global $user;
if ($event->parent === "system") {
if ($user->can(Permissions::BAN_IMAGE)) {
$event->add_nav_link("image_bans", new Link('image_hash_ban/list/1'), "Post Bans", NavLink::is_active(["image_hash_ban"]));
$event->add_nav_link("image_bans", new Link('image_hash_ban/list'), "Post Bans", NavLink::is_active(["image_hash_ban"]));
}
}
}
Expand All @@ -137,7 +137,7 @@ public function onUserBlockBuilding(UserBlockBuildingEvent $event): void
{
global $user;
if ($user->can(Permissions::BAN_IMAGE)) {
$event->add_link("Post Bans", make_link("image_hash_ban/list/1"));
$event->add_link("Post Bans", make_link("image_hash_ban/list"));
}
}

Expand Down
41 changes: 41 additions & 0 deletions ext/index/main.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\{InputInterface,InputArgument};
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;

require_once "config.php";
Expand Down Expand Up @@ -149,6 +150,46 @@ public function onCliGen(CliGenEvent $event): void
foreach ($items as $item) {
$output->writeln($item->hash);
}
return Command::SUCCESS;
});
$event->app->register('debug:search')
->addArgument('query', InputArgument::REQUIRED)
->addOption('count', null, InputOption::VALUE_NONE, 'Generate a count-only query')
->addOption('page', null, InputOption::VALUE_REQUIRED, 'Page number', default: 1)
->addOption('limit', null, InputOption::VALUE_REQUIRED, 'Number of results per page', default: 25)
->setDescription('Show the SQL generated for a given search query')
->setCode(function (InputInterface $input, OutputInterface $output): int {
$search = Tag::explode($input->getArgument('query'), false);
$page = $input->getOption('page');
$limit = $input->getOption('limit');
$count = $input->getOption('count');

[$tag_conditions, $img_conditions, $order] = Search::terms_to_conditions($search);
if($count) {
$order = null;
$page = null;
$limit = null;
}

$q = Search::build_search_querylet(
$tag_conditions,
$img_conditions,
$order,
$limit,
(int)(($page - 1) * $limit),
);

$sql_str = $q->sql;
$sql_str = preg_replace("/\s+/", " ", $sql_str);
foreach($q->variables as $key => $val) {
if(is_string($val)) {
$sql_str = str_replace(":$key", "'$val'", $sql_str);
} else {
$sql_str = str_replace(":$key", (string)$val, $sql_str);
}
}
$output->writeln(trim($sql_str));

return Command::SUCCESS;
});
}
Expand Down
54 changes: 26 additions & 28 deletions ext/not_a_tag/main.php
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ public function onPageSubNavBuilding(PageSubNavBuildingEvent $event): void
global $user;
if ($event->parent === "tags") {
if ($user->can(Permissions::BAN_IMAGE)) {
$event->add_nav_link("untags", new Link('untag/list/1'), "UnTags");
$event->add_nav_link("untags", new Link('untag/list'), "UnTags");
}
}
}
Expand All @@ -118,40 +118,38 @@ public function onUserBlockBuilding(UserBlockBuildingEvent $event): void
{
global $user;
if ($user->can(Permissions::BAN_IMAGE)) {
$event->add_link("UnTags", make_link("untag/list/1"));
$event->add_link("UnTags", make_link("untag/list"));
}
}

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

if ($event->page_matches("untag", permission: Permissions::BAN_IMAGE)) {
if ($event->page_matches("untag/add", method: "POST")) {
$input = validate_input(["c_tag" => "string", "c_redirect" => "string"]);
$database->execute(
"INSERT INTO untags(tag, redirect) VALUES (:tag, :redirect)",
["tag" => $input['c_tag'], "redirect" => $input['c_redirect']]
);
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(referer_or(make_link()));
}
if ($event->page_matches("untag/remove", method: "POST")) {
$input = validate_input(["d_tag" => "string"]);
$database->execute(
"DELETE FROM untags WHERE LOWER(tag) = LOWER(:tag)",
["tag" => $input['d_tag']]
);
$page->flash("Post ban removed");
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(referer_or(make_link()));
}
if ($event->page_matches("untag/list")) {
$t = new NotATagTable($database->raw_db());
$t->token = $user->get_auth_token();
$t->inputs = $event->GET;
$this->theme->display_crud("UnTags", $t->table($t->query()), $t->paginator());
}
if ($event->page_matches("untag/add", method: "POST", permission: Permissions::BAN_IMAGE)) {
$input = validate_input(["c_tag" => "string", "c_redirect" => "string"]);
$database->execute(
"INSERT INTO untags(tag, redirect) VALUES (:tag, :redirect)",
["tag" => $input['c_tag'], "redirect" => $input['c_redirect']]
);
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(referer_or(make_link()));
}
if ($event->page_matches("untag/remove", method: "POST", permission: Permissions::BAN_IMAGE)) {
$input = validate_input(["d_tag" => "string"]);
$database->execute(
"DELETE FROM untags WHERE LOWER(tag) = LOWER(:tag)",
["tag" => $input['d_tag']]
);
$page->flash("Post ban removed");
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(referer_or(make_link()));
}
if ($event->page_matches("untag/list")) {
$t = new NotATagTable($database->raw_db());
$t->token = $user->get_auth_token();
$t->inputs = $event->GET;
$this->theme->display_crud("UnTags", $t->table($t->query()), $t->paginator());
}
}
}
1 change: 1 addition & 0 deletions ext/post_tags/main.php
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ public function onImageInfoSet(ImageInfoSetEvent $event): void
} else {
$page->flash($e->getMessage());
}
throw $e;
}
}
}
Expand Down
6 changes: 3 additions & 3 deletions ext/post_tags/test.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@ public function testInvalidChange(): void
public function testTagEdit_tooLong(): void
{
$this->log_in_as_user();
$image_id = $this->post_image("tests/pbx_screenshot.jpg", str_repeat("a", 500));
$this->get_page("post/view/$image_id");
$this->assert_title("Post $image_id: tagme");
$this->assertException(TagSetException::class, function () {
$this->post_image("tests/pbx_screenshot.jpg", str_repeat("a", 500));
});
}
}
5 changes: 3 additions & 2 deletions themes/default/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,9 @@ TD {

TABLE.zebra {border-spacing: 0; border: 2px solid var(--zebra-border);}
TABLE.zebra TD, TABLE.zebra TH {vertical-align: middle; padding: 4px;}
TABLE.zebra THEAD TD, TABLE.zebra THEAD TH {border-bottom: 2px solid var(--zebra-border);}
TABLE.zebra TFOOT TD, TABLE.zebra TFOOT TH {border-top: 2px solid var(--zebra-border);}
TABLE.zebra THEAD {position: sticky;top: 0;}
TABLE.zebra THEAD TR:last-child TD, TABLE.zebra TR:last-child THEAD TH {border-bottom: 2px solid var(--zebra-border);}
TABLE.zebra TFOOT TR:first-child TD, TABLE.zebra TFOOT TR:first-child TH {border-top: 2px solid var(--zebra-border);}
TABLE.zebra TR TD {border-bottom: 1px solid var(--zebra-header);}
TABLE.zebra TR:nth-child(odd) {background: var(--zebra-odd);}
TABLE.zebra TR:nth-child(even) {background: var(--zebra-even);}
Expand Down
27 changes: 22 additions & 5 deletions themes/futaba/comment.theme.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
class CustomCommentListTheme extends CommentListTheme
{
public int $inner_id = 0;
public bool $post_page = true;

/**
* @param array<array{0: Image, 1: Comment[]}> $images
Expand All @@ -25,6 +26,7 @@ public function display_comment_list(array $images, int $page_number, int $total
$page->add_block(new Block(null, $this->build_upload_box(), "main", 0));
$page->add_block(new Block(null, "<hr>", "main", 80));
$this->display_paginator($page, "comment/list", null, $page_number, $total_pages);
$this->post_page = false;

// parts for each image
$position = 10;
Expand Down Expand Up @@ -58,7 +60,8 @@ public function display_comment_list(array $images, int $page_number, int $total

public function display_recent_comments(array $comments): void
{
// sidebar fails in this theme
$this->post_page = false;
parent::display_recent_comments($comments);
}

public function build_upload_box(): string
Expand All @@ -69,7 +72,9 @@ public function build_upload_box(): string

protected function comment_to_html(Comment $comment, bool $trim = false): string
{
$inner_id = $this->inner_id; // because custom themes can't add params, because PHP
// because custom themes can't add params, because PHP
$post_page = $this->post_page;
$inner_id = $this->inner_id;
global $user;

$tfe = send_event(new TextFormattingEvent($comment->comment));
Expand All @@ -82,22 +87,34 @@ protected function comment_to_html(Comment $comment, bool $trim = false): string
} else {
$h_comment = $tfe->formatted;
}
$h_comment = preg_replace("/(^|>)(&gt;[^<\n]*)(<|\n|$)/", '${1}<span class=\'greentext\'>${2}</span>${3}', $h_comment);
// handles discrepency in comment page and homepage
$h_comment = str_replace("<br>", "", $h_comment);
$h_comment = str_replace("\n", "<br>", $h_comment);
$i_comment_id = $comment->comment_id;
$i_image_id = $comment->image_id;

$h_userlink = "<a href='".make_link("user/$h_name")."'>$h_name</a>";
$h_date = $comment->posted;
$h_del = "";
if ($user->can(Permissions::DELETE_COMMENT)) {
$h_del = " - " . $this->delete_link($i_comment_id, $i_image_id, $comment->owner_name, $tfe->stripped);
$comment_preview = substr(html_unescape($tfe->stripped), 0, 50);
$j_delete_confirm_message = json_encode("Delete comment by {$comment->owner_name}:\n$comment_preview");
$h_delete_script = html_escape("return confirm($j_delete_confirm_message);");
$h_delete_link = make_link("comment/delete/$i_comment_id/$i_image_id");
$h_del = " - [<a onclick='$h_delete_script' href='$h_delete_link'>Delete</a>]";
}
if ($this->post_page) {
$h_reply = "[<a href='javascript: replyTo($i_image_id, $i_comment_id, \"$h_name\")'>Reply</a>]";
} else {
$h_reply = "[<a href='".make_link("post/view/$i_image_id")."'>Reply</a>]";
}
$h_reply = "[<a href='".make_link("post/view/$i_image_id")."'>Reply</a>]";

if ($inner_id == 0) {
return "<div class='comment' style='margin-top: 8px;'>$h_userlink$h_del $h_date No.$i_comment_id $h_reply<p>$h_comment</p></div>";
} else {
return "<table><tr><td nowrap class='doubledash'>&gt;&gt;</td><td>".
"<div class='reply'>$h_userlink$h_del $h_date No.$i_comment_id $h_reply<p>$h_comment</p></div>" .
"<div class='reply'>$h_userlink$h_del $h_date No.$i_comment_id<p>$h_comment</p></div>" .
"</td></tr></table>";
}
}
Expand Down
3 changes: 3 additions & 0 deletions themes/futaba/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -160,3 +160,6 @@ TABLE.tag_list>TBODY>TR>TD:after {
.thumb {
margin: 16px;
}
.greentext {
color: green;
}

0 comments on commit ea7404a

Please sign in to comment.