From 4556b3c349910550fcd224c3f7bffa60f7beec36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bruno=20Ryb=C3=A1rsky?= Date: Wed, 1 May 2024 17:23:57 +0200 Subject: [PATCH] Test meme filtering --- endpoints/meme.php | 2 +- lib/config.php | 3 + lib/meme.php | 139 +++++++++++++++++++++++++++++---------------- 3 files changed, 94 insertions(+), 50 deletions(-) diff --git a/endpoints/meme.php b/endpoints/meme.php index ae3d503..8eff44c 100644 --- a/endpoints/meme.php +++ b/endpoints/meme.php @@ -7,7 +7,7 @@ function endpoint($endpoint_data): array return match ($endpoint_data["action"]) { "addMeme" => addMeme($endpoint_data['meme_title'], $endpoint_data['meme_text'], $endpoint_data['meme_image_id']), - "renderGallery" => renderMemeGallery(), + "renderGallery" => renderMemeGallery($endpoint_data['offset'], $endpoint_data['meme_author'], $endpoint_data['meme_id'], $endpoint_data['meme_keyword']), "deleteMeme" => deleteMeme($endpoint_data['meme_id']), "getMemeVotes" => getMemeVotes($endpoint_data['meme_id']), "deleteVoteMeme" => deleteVoteMeme($endpoint_data['meme_id']), diff --git a/lib/config.php b/lib/config.php index 432c31e..bc7b01f 100644 --- a/lib/config.php +++ b/lib/config.php @@ -54,6 +54,9 @@ function loadRouterConfig(): array 'newsarticle' => [ 'default_permissions' => 255, ], + 'meme' => [ + 'per_page' => 10 + ], 'seo' => [ 'author' => 'Tím AdlerkaTop', 'description' => 'Toto je neoficiánla študentská stránka pre Adlerku, kde môžete nájsť plno zaujímavostí.', diff --git a/lib/meme.php b/lib/meme.php index 4d73134..8f2656a 100644 --- a/lib/meme.php +++ b/lib/meme.php @@ -8,8 +8,8 @@ require_once "lib/account.php"; * @param string $title The title of the meme. * @param string $memeText The text content of the meme. * @param int $imageID The ID of the image associated with the meme. - * @global mysqli $mysqli The database connection object. * @return array Returns an associative array with the operation status and a message. + * @global mysqli $mysqli The database connection object. */ function addMeme(string $title, string $memeText, int $imageID): array { @@ -25,6 +25,28 @@ function addMeme(string $title, string $memeText, int $imageID): array } return $output; } + +function executeAndRenderMemes(mysqli_stmt $stmt): string { + global $routerConfig; + $stmt->execute(); + $stmt->bind_result($memeID, $title, $textContent, $createdAt, $authorID, $filePath, $imageWidth, $imageHeight, $userNickname); + + $memes_out = ''; + $meme_template = file_get_contents($routerConfig['template_dir'] . "meme.html"); + $meme_gallery_template = file_get_contents($routerConfig['template_dir'] . 'meme_gallery.html'); + + while ($stmt->fetch()) { + $memes_out .= renderMeme($memeID, $authorID, $title, $textContent, $createdAt, $filePath, $imageWidth, $imageHeight, $userNickname, $meme_template); + } + + $meme_add = isLoggedIn() ? file_get_contents($routerConfig['template_dir'] . 'meme_add.html') : ''; + $meme_gallery_out = str_replace('__TEMPLATE_MEMES_HERE__', $memes_out, $meme_gallery_template); + $meme_gallery_out = str_replace('__TEMPLATE_MEME_ADD__', $meme_add, $meme_gallery_out); + + $stmt->close(); + return $meme_gallery_out; +} + /** * Renders a meme into HTML based on provided data and a template. * @@ -54,21 +76,19 @@ function renderMeme(int $id, int $authorId, string $title, string $textContent, $meme_votes = calculateNetVotes($id); $meme_net_votes = $meme_votes['NetVotes']; - if ($meme_votes['UserVote'] > 0){ + if ($meme_votes['UserVote'] > 0) { $meme_upvote_active = 'fill'; $meme_downvote_active = 'line'; $meme_vote_counter_class = 'positive'; $meme_upvote_button_class = ' visual_hover'; $meme_downvote_button_class = ''; - } - elseif (($meme_votes['UserVote'] < 0)) { + } elseif (($meme_votes['UserVote'] < 0)) { $meme_upvote_active = 'line'; $meme_downvote_active = 'fill'; $meme_vote_counter_class = 'negative'; $meme_upvote_button_class = ''; $meme_downvote_button_class = ' visual_hover'; - } - else { + } else { $meme_downvote_active = 'line'; $meme_upvote_active = 'line'; $meme_vote_counter_class = 'neutral'; @@ -86,60 +106,78 @@ function renderMeme(int $id, int $authorId, string $title, string $textContent, return str_replace('__TEMPLATE_MEME_TEXT__', htmlspecialchars($textContent), $meme_out); } + /** - * Generates an HTML representation of a gallery of memes from the database. - * Renders the memes using renderMeme. + * Renders a gallery of memes, optionally filtered by author ID, meme ID, or a keyword. * - * @global mysqli $mysqli The database connection object. - * @global array $routerConfig Configuration settings including paths to templates. - * @return string Returns the complete HTML content of the meme gallery. + * This function retrieves memes from the database and returns an HTML string representation. + * It supports filtering by author ID, meme ID, or a keyword that is searched in titles and text content. + * It also supports pagination through an offset parameter. + * + * @param int|null $offset Pagination offset, used to calculate the starting point for records to return. + * @param int|null $authorId Optional author ID for filtering memes by a specific author. + * @param int|null $memeId Optional meme ID for rendering a single meme. + * @param string|null $keyword Optional keyword for full-text search in meme titles and content. + * @return string Returns the complete HTML content of the meme gallery, optionally filtered. */ -function renderMemeGallery(): string -{ - global $mysqli; - global $routerConfig; - $stmtlist = $mysqli->prepare('SELECT Memes.ID, Memes.Title, Memes.TextContent, Memes.CreatedAt, Memes.AuthorID, Files.Path, Files.Width, Files.Height, Files.Type, Users.Nickname FROM Memes INNER JOIN Users ON Memes.AuthorID = Users.ID INNER JOIN Files ON Memes.FileID = Files.ID'); +function renderMemeGallery(?int $offset = null, ?int $authorId = null, ?int $memeId = null, ?string $keyword = null): string { + global $mysqli, $routerConfig; - // Execute the prepared statement - $memeID = 0; - $authorID = 0; - $title = ""; - $textContent = ""; - $filePath = ""; - $fileType = ""; - $userNickname = ""; - $createdAt = ""; - $imageWidth = 0; - $imageHeight = 0; - // Bind the result variables - $stmtlist->bind_result($memeID, $title, $textContent, $createdAt, $authorID, $filePath, $imageWidth, $imageHeight, $fileType, $userNickname); - $stmtlist->execute(); + // Start building the SQL query + $query = 'SELECT Memes.ID, Memes.Title, Memes.TextContent, Memes.CreatedAt, Memes.AuthorID, + Files.Path, Files.Width, Files.Height, Users.Nickname + FROM Memes + INNER JOIN Users ON Memes.AuthorID = Users.ID + INNER JOIN Files ON Memes.FileID = Files.ID'; - $meme_gallery_template = file_get_contents($routerConfig['template_dir'] . 'meme_gallery.html'); + $conditions = []; + $params = []; + $types = ''; - // Fetch the results - $memes_out = ''; - $meme_template = file_get_contents($routerConfig['template_dir'] . "meme.html"); - $stmtlist->store_result(); - while ($stmtlist->fetch()) { - if (str_starts_with($fileType, 'image')) { - $memes_out .= renderMeme($memeID, $authorID, $title, $textContent, $createdAt, $filePath, $imageWidth, $imageHeight, $userNickname, $meme_template); - } + // Add conditions based on provided parameters + if ($authorId !== null) { + $conditions[] = 'Memes.AuthorID = ?'; + $params[] = $authorId; + $types .= 'i'; + } + if ($memeId !== null) { + $conditions[] = 'Memes.ID = ?'; + $params[] = $memeId; + $types .= 'i'; + } + if ($keyword !== null) { + $conditions[] = '(Memes.Title LIKE CONCAT("%", ?, "%") OR Memes.TextContent LIKE CONCAT("%", ?, "%"))'; + $params[] = $keyword; + $params[] = $keyword; + $types .= 'ss'; } - $meme_add = isLoggedIn() ? file_get_contents($routerConfig['template_dir'] . 'meme_add.html') : ''; - $meme_gallery_out = str_replace('__TEMPLATE_MEMES_HERE__', $memes_out, $meme_gallery_template); - $meme_gallery_out = str_replace('__TEMPLATE_MEME_ADD__', $meme_add, $meme_gallery_out); -// Close the statement - $stmtlist->close(); - return $meme_gallery_out; + // Append conditions to the query + if (!empty($conditions)) { + $query .= ' WHERE ' . join(' AND ', $conditions); + } + + if($offset == null) { + $offset = 0; + } + // Add pagination and limit + $query .= ' LIMIT ? OFFSET ?'; + $params[] = $routerConfig['meme']['per_page']; + $params[] = $routerConfig['meme']['per_page'] * $offset; + $types .= 'ii'; + + $stmt = $mysqli->prepare($query); + $stmt->bind_param($types, ...$params); + return executeAndRenderMemes($stmt); } + + /** * Deletes a meme from the database if the current user has the right permissions. * * @param int $memeID The ID of the meme to delete. - * @global mysqli $mysqli The database connection object. * @return array Returns an associative array with the status of the operation. + * @global mysqli $mysqli The database connection object. */ function deleteMeme(int $memeID): array { @@ -161,13 +199,14 @@ function deleteMeme(int $memeID): array } return $out; } + /** * Records or updates a vote on a meme by the current user. * * @param int $memeID The ID of the meme to be voted on. * @param int $isUpvote Indicates whether the vote is an upvote (1) or downvote (0). - * @global mysqli $mysqli The database connection object. * @return array Returns an associative array with the status of the vote operation. + * @global mysqli $mysqli The database connection object. */ function voteMeme(int $memeID, int $isUpvote): array { @@ -185,12 +224,13 @@ function voteMeme(int $memeID, int $isUpvote): array $memeVoteConn->close(); return $out; } + /** * Deletes a vote previously made by the current user on a meme. * * @param int $memeID The ID of the meme whose vote is to be deleted. - * @global mysqli $mysqli The database connection object. * @return array Returns an associative array with the status of the deletion. + * @global mysqli $mysqli The database connection object. */ function deleteVoteMeme(int $memeID): array { @@ -205,13 +245,14 @@ function deleteVoteMeme(int $memeID): array $memeVoteConn->close(); return $out; } + /** * Calculates the net votes for a meme and determines if the current user has voted on it. * The array has both the net votes and the user vote(0 when the user hasn't voted) * * @param int $memeID The ID of the meme for which votes are being calculated. - * @global mysqli $mysqli The database connection object. * @return array Returns an array with net votes and the user's vote status. + * @global mysqli $mysqli The database connection object. */ function calculateNetVotes(int $memeID): array {