diff --git a/core/event.php b/core/event.php index 57f9c2dc..84804e99 100644 --- a/core/event.php +++ b/core/event.php @@ -108,21 +108,26 @@ class PageRequestEvent extends Event if ($offset >= 0 && $offset < $this->arg_count) { return $this->args[$offset]; } else { - throw new SCoreException("Requested an invalid argument #$n"); + $nm1 = $this->arg_count - 1; + throw new SCoreException("Requested an invalid page argument {$offset} / {$nm1}"); } } - public function try_page_num(int $n): int + /** + * If page arg $n is set, then treat that as a 1-indexed page number + * and return a 0-indexed page number less than $max; else return 0 + */ + public function try_page_num(int $n, ?int $max=null): int { if ($this->count_args() > $n) { $i = $this->get_arg($n); if (is_numeric($i) && int_escape($i) > 0) { - return int_escape($i); + return page_number($i, $max); } else { - return 1; + return 0; } } else { - return 1; + return 0; } } diff --git a/ext/comment/main.php b/ext/comment/main.php index a442e4e4..76f8c01e 100644 --- a/ext/comment/main.php +++ b/ext/comment/main.php @@ -264,8 +264,51 @@ class CommentList extends Extension private function onPageRequest_list(PageRequestEvent $event) { - $page_num = $event->try_page_num(1); - $this->build_page($page_num); + global $cache, $database, $user; + + $where = SPEED_HAX ? "WHERE posted > now() - interval '24 hours'" : ""; + + $total_pages = $cache->get("comment_pages"); + if (empty($total_pages)) { + $total_pages = (int)($database->get_one(" + SELECT COUNT(c1) + FROM (SELECT COUNT(image_id) AS c1 FROM comments $where GROUP BY image_id) AS s1 + ") / 10); + $cache->set("comment_pages", $total_pages, 600); + } + $total_pages = max($total_pages, 1); + + $current_page = $event->try_page_num(1, $total_pages); + $threads_per_page = 10; + $start = $threads_per_page * $current_page; + + $result = $database->Execute(" + SELECT image_id,MAX(posted) AS latest + FROM comments + $where + GROUP BY image_id + ORDER BY latest DESC + LIMIT :limit OFFSET :offset + ", ["limit"=>$threads_per_page, "offset"=>$start]); + + $user_ratings = Extension::is_enabled(RatingsInfo::KEY) ? Ratings::get_user_class_privs($user) : ""; + + $images = []; + while ($row = $result->fetch()) { + $image = Image::by_id((int)$row["image_id"]); + if ( + Extension::is_enabled(RatingsInfo::KEY) && !is_null($image) && + !in_array($image->rating, $user_ratings) + ) { + $image = null; // this is "clever", I may live to regret it + } + if (!is_null($image)) { + $comments = $this->get_comments($image->id); + $images[] = [$image, $comments]; + } + } + + $this->theme->display_comment_list($images, $current_page+1, $total_pages, $user->can(Permissions::CREATE_COMMENT)); } private function onPageRequest_beta_search(PageRequestEvent $event) @@ -276,9 +319,8 @@ class CommentList extends Extension $i_comment_count = Comment::count_comments_by_user($duser); $com_per_page = 50; $total_pages = (int)ceil($i_comment_count / $com_per_page); - $page_num = clamp($page_num, 1, $total_pages); - $comments = $this->get_user_comments($duser->id, $com_per_page, ($page_num - 1) * $com_per_page); - $this->theme->display_all_user_comments($comments, $page_num, $total_pages, $duser); + $comments = $this->get_user_comments($duser->id, $com_per_page, $page_num * $com_per_page); + $this->theme->display_all_user_comments($comments, $page_num+1, $total_pages, $duser); } public function onAdminBuilding(AdminBuildingEvent $event) @@ -389,56 +431,6 @@ class CommentList extends Extension } } - private function build_page(int $current_page) - { - global $cache, $database, $user; - - $where = SPEED_HAX ? "WHERE posted > now() - interval '24 hours'" : ""; - - $total_pages = $cache->get("comment_pages"); - if (empty($total_pages)) { - $total_pages = (int)($database->get_one(" - SELECT COUNT(c1) - FROM (SELECT COUNT(image_id) AS c1 FROM comments $where GROUP BY image_id) AS s1 - ") / 10); - $cache->set("comment_pages", $total_pages, 600); - } - $total_pages = max($total_pages, 1); - - $current_page = clamp($current_page, 1, $total_pages); - - $threads_per_page = 10; - $start = $threads_per_page * ($current_page - 1); - - $result = $database->Execute(" - SELECT image_id,MAX(posted) AS latest - FROM comments - $where - GROUP BY image_id - ORDER BY latest DESC - LIMIT :limit OFFSET :offset - ", ["limit"=>$threads_per_page, "offset"=>$start]); - - $user_ratings = Extension::is_enabled(RatingsInfo::KEY) ? Ratings::get_user_class_privs($user) : ""; - - $images = []; - while ($row = $result->fetch()) { - $image = Image::by_id((int)$row["image_id"]); - if ( - Extension::is_enabled(RatingsInfo::KEY) && !is_null($image) && - !in_array($image->rating, $user_ratings) - ) { - $image = null; // this is "clever", I may live to regret it - } - if (!is_null($image)) { - $comments = $this->get_comments($image->id); - $images[] = [$image, $comments]; - } - } - - $this->theme->display_comment_list($images, $current_page, $total_pages, $user->can(Permissions::CREATE_COMMENT)); - } - /** * #return Comment[] */ diff --git a/ext/notes/main.php b/ext/notes/main.php index b29e8232..e5c93c0c 100644 --- a/ext/notes/main.php +++ b/ext/notes/main.php @@ -355,7 +355,7 @@ class Notes extends Extension { global $database, $config; - $pageNumber = $event->try_page_num(1) - 1; + $pageNumber = $event->try_page_num(1); $notesPerPage = $config->get_int('notesNotesPerPage'); @@ -383,7 +383,7 @@ class Notes extends Extension { global $config, $database; - $pageNumber = $event->try_page_num(1) - 1; + $pageNumber = $event->try_page_num(1); $requestsPerPage = $config->get_int('notesRequestsPerPage'); @@ -430,7 +430,7 @@ class Notes extends Extension { global $config, $database; - $pageNumber = $event->try_page_num(1) - 1; + $pageNumber = $event->try_page_num(1); $historiesPerPage = $config->get_int('notesHistoriesPerPage'); diff --git a/ext/pools/main.php b/ext/pools/main.php index 447d19a4..6fe0edb7 100644 --- a/ext/pools/main.php +++ b/ext/pools/main.php @@ -86,6 +86,11 @@ class Pool { } } +function _image_to_id(Image $image): int +{ + return $image->id; +} + class Pools extends Extension { /** @var PoolsTheme */ @@ -237,7 +242,7 @@ class Pools extends Extension break; case "updated": - $this->get_history(page_number($event->get_arg(1))); + $this->get_history($event->try_page_num(1)); break; case "revert": @@ -322,11 +327,8 @@ class Pools extends Extension case "add_posts": if ($this->have_permission($user, $pool)) { - $images = []; - foreach ($_POST['check'] as $imageID) { - $images[] = $imageID; - } - send_event(new PoolAddPostsEvent($pool_id, $images)); + $image_ids = array_map('intval', $_POST['check']); + send_event(new PoolAddPostsEvent($pool_id, $image_ids)); $page->set_mode(PageMode::REDIRECT); $page->set_redirect(make_link("pool/view/" . $pool_id)); } else { @@ -361,7 +363,7 @@ class Pools extends Extension if ($this->have_permission($user, $pool)) { $database->execute( "UPDATE pools SET description=:dsc WHERE id=:pid", - ["dsc" => $_POST['description'], "pid" => int_escape($_POST['pool_id'])] + ["dsc" => $_POST['description'], "pid" => $pool_id] ); $page->set_mode(PageMode::REDIRECT); $page->set_redirect(make_link("pool/view/" . $pool_id)); @@ -374,7 +376,7 @@ class Pools extends Extension case "nuke": // Completely remove the given pool. // -> Only admins and owners may do this - if ($user->can(Permissions::POOLS_ADMIN) || $user->id == $pool['user_id']) { + if ($user->can(Permissions::POOLS_ADMIN) || $user->id == $pool->user_id) { $this->nuke_pool($pool_id); $page->set_mode(PageMode::REDIRECT); $page->set_redirect(make_link("pool/list")); @@ -469,7 +471,7 @@ class Pools extends Extension $pool = $this->get_single_pool_from_title($poolTitle); $poolID = 0; if ($pool) { - $poolID = $pool['id']; + $poolID = $pool->id; } $event->add_querylet(new Querylet("images.id IN (SELECT DISTINCT image_id FROM pool_images WHERE pool_id = $poolID)")); } @@ -500,7 +502,7 @@ class Pools extends Extension if ($pool && $this->have_permission($user, $pool)) { $image_order = ($matches[2] ?: 0); - $this->add_post($pool['id'], $event->image_id, true, $image_order); + $this->add_post($pool->id, $event->image_id, true, $image_order); } } } @@ -532,7 +534,7 @@ class Pools extends Extension if ($this->have_permission($user, $pool)) { send_event( - new PoolAddPostsEvent($pool_id, iterator_map_to_array("image_to_id", $event->items)) + new PoolAddPostsEvent($pool_id, iterator_map_to_array("_image_to_id", $event->items)) ); } break; @@ -543,7 +545,7 @@ class Pools extends Extension $new_pool_title = $_POST['bulk_pool_new']; $pce = new PoolCreationEvent($new_pool_title); send_event($pce); - send_event(new PoolAddPostsEvent($pce->new_id, iterator_map_to_array("image_to_id", $event->items))); + send_event(new PoolAddPostsEvent($pce->new_id, iterator_map_to_array("_image_to_id", $event->items))); break; } } @@ -573,8 +575,6 @@ class Pools extends Extension { global $config, $database; - $pageNumber = clamp($pageNumber, 1, null) - 1; - $poolsPerPage = $config->get_int(PoolsConfig::LISTS_PER_PAGE); $order_by = ""; @@ -752,7 +752,7 @@ class Pools extends Extension { global $config, $user, $database; - $pageNumber = $event->try_page_num(2) - 1; + $pageNumber = $event->try_page_num(2); $pool = $this->get_single_pool($poolID); $imagesPerPage = $config->get_int(PoolsConfig::IMAGES_PER_PAGE); @@ -862,7 +862,7 @@ class Pools extends Extension foreach ($status as $entry) { $images = trim($entry['images']); $images = explode(" ", $images); - $poolID = $entry['pool_id']; + $poolID = (int)$entry['pool_id']; $imageArray = ""; $newAction = -1; diff --git a/ext/pools/test.php b/ext/pools/test.php index fc9d78ff..c6e91432 100644 --- a/ext/pools/test.php +++ b/ext/pools/test.php @@ -12,8 +12,6 @@ class PoolsTest extends ShimmiePHPUnitTestCase public function testCreate() { - global $user; - $this->log_in_as_user(); $image_id_1 = $this->post_image("tests/pbx_screenshot.jpg", "pbx"); $image_id_2 = $this->post_image("tests/bedroom_workshop.jpg", "pbx"); @@ -22,10 +20,12 @@ class PoolsTest extends ShimmiePHPUnitTestCase $this->get_page("pool/new"); - $event = new PoolCreationEvent("foo", $user, true, "My pool description"); - send_event($event); - $pool_id = $event->new_id; - + $page = $this->post_page("pool/create", [ + "title" => "foo", + "public" => "Y", + "description" => "My pool description", + ]); + $pool_id = (int)(explode("/", $page->redirect)[4]); send_event(new PoolAddPostsEvent($pool_id, [$image_id_1, $image_id_2])); return [$pool_id, [$image_id_1, $image_id_2]]; @@ -83,4 +83,80 @@ class PoolsTest extends ShimmiePHPUnitTestCase $this->get_page("pool/updated/$pool_id"); $this->assert_text("Pool"); } + + /** @depends testCreate */ + public function testImport($args) + { + [$pool_id, $image_ids] = $args; + + $this->post_page("pool/import", [ + "pool_id" => $pool_id, + "pool_tag" => "test" + ]); + $this->assert_text("Pool"); + } + + /** @depends testCreate */ + public function testRemovePosts($args) + { + [$pool_id, $image_ids] = $args; + + $page = $this->post_page("pool/remove_posts", [ + "pool_id" => $pool_id, + "check" => [(string)($image_ids[0]), (string)($image_ids[1])] + ]); + $this->assertEquals("redirect", $page->mode); + + return $args; + } + + /** @depends testRemovePosts */ + public function testAddPosts($args) + { + [$pool_id, $image_ids] = $args; + + $page = $this->post_page("pool/add_posts", [ + "pool_id" => $pool_id, + "check" => [(string)($image_ids[0]), (string)($image_ids[1])] + ]); + $this->assertEquals("redirect", $page->mode); + } + + /** @depends testCreate */ + public function testEditDescription($args) + { + [$pool_id, $image_ids] = $args; + + $page = $this->post_page("pool/edit_description", [ + "pool_id" => $pool_id, + "description" => "Updated description" + ]); + $this->assertEquals("redirect", $page->mode); + + return $args; + } + + public function testNuke() + { + $this->log_in_as_user(); + $image_id_1 = $this->post_image("tests/pbx_screenshot.jpg", "pbx"); + $image_id_2 = $this->post_image("tests/bedroom_workshop.jpg", "pbx"); + $this->assertNotNull($image_id_1); + $this->assertNotNull($image_id_2); + + $this->get_page("pool/new"); + + $page = $this->post_page("pool/create", [ + "title" => "foo2", + "public" => "Y", + "description" => "My pool description", + ]); + $pool_id = (int)(explode("/", $page->redirect)[4]); + send_event(new PoolAddPostsEvent($pool_id, [$image_id_1, $image_id_2])); + + $page = $this->post_page("pool/nuke", [ + "pool_id" => "$pool_id", + ]); + $this->assertEquals("redirect", $page->mode); + } } diff --git a/ext/pools/theme.php b/ext/pools/theme.php index 8988674f..63940d16 100644 --- a/ext/pools/theme.php +++ b/ext/pools/theme.php @@ -225,7 +225,6 @@ class PoolsTheme extends Themelet $page->add_block(new Block("Manage Pool", $editor, "left", 15)); } - /** * HERE WE DISPLAY THE RESULT OF THE SEARCH ON IMPORT. */ @@ -234,11 +233,9 @@ class PoolsTheme extends Themelet $this->display_top($pool, "Importing Posts", true); $pool_images = " "; diff --git a/tests/bootstrap.php b/tests/bootstrap.php index b3abff03..9d8dc0ce 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -105,7 +105,7 @@ abstract class ShimmiePHPUnitTestCase extends TestCase } } - protected static function get_page($page_name, $args=null) + protected static function get_page($page_name, $args=null): Page { // use a fresh page global $page; @@ -122,7 +122,7 @@ abstract class ShimmiePHPUnitTestCase extends TestCase return $page; } - protected static function post_page($page_name, $args=null) + protected static function post_page($page_name, $args=null): Page { // use a fresh page global $page; @@ -130,7 +130,12 @@ abstract class ShimmiePHPUnitTestCase extends TestCase $args = []; } foreach ($args as $k=>$v) { - $args[$k] = (string)$v; + if(is_array($v)) { + $args[$k] = $v; + } + else { + $args[$k] = (string)$v; + } } $_GET = []; $_POST = $args; @@ -139,6 +144,7 @@ abstract class ShimmiePHPUnitTestCase extends TestCase if ($page->mode == PageMode::REDIRECT) { $page->code = 302; } + return $page; } // page things