From 4ede43b192575011071c50b035c7cd261100d0aa Mon Sep 17 00:00:00 2001 From: Zankaria Date: Wed, 18 Dec 2024 19:51:41 +0100 Subject: [PATCH] UserPostQueries.php: refactor implementation --- inc/Data/UserPostQueries.php | 80 +++++++++++++++++++----------------- 1 file changed, 43 insertions(+), 37 deletions(-) diff --git a/inc/Data/UserPostQueries.php b/inc/Data/UserPostQueries.php index e702dd89..bebbd365 100644 --- a/inc/Data/UserPostQueries.php +++ b/inc/Data/UserPostQueries.php @@ -17,16 +17,7 @@ class UserPostQueries { $this->pdo = $pdo; } - /** - * Fetch a page of user posts. - * - * @param array $board_uris The uris of the boards that should be included. - * @param string $ip The IP of the target user. - * @param integer $page_size The Number of posts that should be fetched. - * @param string|null $cursor The directional cursor to fetch the next or previous page. Null to start from the beginning. - * @return PageFetchResult - */ - public function fetchPaginatedByIp(array $board_uris, string $ip, int $page_size, ?string $cursor = null): PageFetchResult { + private function paginate(array $board_uris, int $page_size, ?string $cursor, callable $callback): PageFetchResult { // Decode the cursor. if ($cursor !== null) { list($cursor_type, $uri_id_cursor_map) = Net\decode_cursor($cursor); @@ -41,37 +32,15 @@ class UserPostQueries { foreach ($board_uris as $uri) { // Extract the cursor relative to the board. - $id_cursor = false; - if (isset($uri_id_cursor_map[$uri])) { + $start_id = null; + if ($cursor_type !== null && isset($uri_id_cursor_map[$uri])) { $value = $uri_id_cursor_map[$uri]; if (\is_numeric($value)) { - $id_cursor = (int)$value; + $start_id = (int)$value; } } - if ($id_cursor === false) { - $query = $this->pdo->prepare(sprintf('SELECT * FROM `posts_%s` WHERE `ip` = :ip ORDER BY `sticky` DESC, `id` DESC LIMIT :limit', $uri)); - $query->bindValue(':ip', $ip); - $query->bindValue(':limit', $page_size + 1, \PDO::PARAM_INT); // Always fetch more. - $query->execute(); - $posts = $query->fetchAll(\PDO::FETCH_ASSOC); - } elseif ($cursor_type === self::CURSOR_TYPE_NEXT) { - $query = $this->pdo->prepare(sprintf('SELECT * FROM `posts_%s` WHERE `ip` = :ip AND `id` <= :start_id ORDER BY `sticky` DESC, `id` DESC LIMIT :limit', $uri)); - $query->bindValue(':ip', $ip); - $query->bindValue(':start_id', $id_cursor, \PDO::PARAM_INT); - $query->bindValue(':limit', $page_size + 2, \PDO::PARAM_INT); // Always fetch more. - $query->execute(); - $posts = $query->fetchAll(\PDO::FETCH_ASSOC); - } elseif ($cursor_type === self::CURSOR_TYPE_PREV) { - $query = $this->pdo->prepare(sprintf('SELECT * FROM `posts_%s` WHERE `ip` = :ip AND `id` >= :start_id ORDER BY `sticky` ASC, `id` ASC LIMIT :limit', $uri)); - $query->bindValue(':ip', $ip); - $query->bindValue(':start_id', $id_cursor, \PDO::PARAM_INT); - $query->bindValue(':limit', $page_size + 2, \PDO::PARAM_INT); // Always fetch more. - $query->execute(); - $posts = \array_reverse($query->fetchAll(\PDO::FETCH_ASSOC)); - } else { - throw new \RuntimeException("Unknown cursor type '$cursor_type'"); - } + $posts = $callback($uri, $cursor_type, $start_id, $page_size); $posts_count = \count($posts); @@ -79,7 +48,7 @@ class UserPostQueries { $has_extra_prev_post = true; $has_extra_end_post = true; } elseif ($posts_count === $page_size + 1) { - $has_extra_prev_post = $id_cursor !== false && $id_cursor === (int)$posts[0]['id']; + $has_extra_prev_post = $start_id !== null && $start_id === (int)$posts[0]['id']; $has_extra_end_post = !$has_extra_prev_post; } else { $has_extra_prev_post = false; @@ -112,4 +81,41 @@ class UserPostQueries { return $res; } + + /** + * Fetch a page of user posts. + * + * @param array $board_uris The uris of the boards that should be included. + * @param string $ip The IP of the target user. + * @param integer $page_size The Number of posts that should be fetched. + * @param string|null $cursor The directional cursor to fetch the next or previous page. Null to start from the beginning. + * @return PageFetchResult + */ + public function fetchPaginatedByIp(array $board_uris, string $ip, int $page_size, ?string $cursor = null): PageFetchResult { + return $this->paginate($board_uris, $page_size, $cursor, function($uri, $cursor_type, $start_id, $page_size) use ($ip) { + if ($cursor_type === null) { + $query = $this->pdo->prepare(sprintf('SELECT * FROM `posts_%s` WHERE `ip` = :ip ORDER BY `sticky` DESC, `id` DESC LIMIT :limit', $uri)); + $query->bindValue(':ip', $ip); + $query->bindValue(':limit', $page_size + 1, \PDO::PARAM_INT); // Always fetch more. + $query->execute(); + return $query->fetchAll(\PDO::FETCH_ASSOC); + } elseif ($cursor_type === self::CURSOR_TYPE_NEXT) { + $query = $this->pdo->prepare(sprintf('SELECT * FROM `posts_%s` WHERE `ip` = :ip AND `id` <= :start_id ORDER BY `sticky` DESC, `id` DESC LIMIT :limit', $uri)); + $query->bindValue(':ip', $ip); + $query->bindValue(':start_id', $start_id, \PDO::PARAM_INT); + $query->bindValue(':limit', $page_size + 2, \PDO::PARAM_INT); // Always fetch more. + $query->execute(); + return $query->fetchAll(\PDO::FETCH_ASSOC); + } elseif ($cursor_type === self::CURSOR_TYPE_PREV) { + $query = $this->pdo->prepare(sprintf('SELECT * FROM `posts_%s` WHERE `ip` = :ip AND `id` >= :start_id ORDER BY `sticky` ASC, `id` ASC LIMIT :limit', $uri)); + $query->bindValue(':ip', $ip); + $query->bindValue(':start_id', $start_id, \PDO::PARAM_INT); + $query->bindValue(':limit', $page_size + 2, \PDO::PARAM_INT); // Always fetch more. + $query->execute(); + return \array_reverse($query->fetchAll(\PDO::FETCH_ASSOC)); + } else { + throw new \RuntimeException("Unknown cursor type '$cursor_type'"); + } + }); + } } \ No newline at end of file