forked from Adleraci/adlerka.top
Test
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
<?php
|
||||
|
||||
use Random\RandomException;
|
||||
|
||||
/**
|
||||
* Checks if the current session represents a logged-in user.
|
||||
*
|
||||
@@ -435,7 +436,7 @@ function addActivationCodes(int $count): array
|
||||
|
||||
$output = ["Status" => "Fail"]; // Default Status is "Fail"
|
||||
|
||||
if (is_numeric($count) && $count > 0 && isUserAdmin() && isLoggedIn()) {
|
||||
if ($count > 0 && isUserAdmin() && isLoggedIn()) {
|
||||
$stmt = $mysqli->prepare("INSERT INTO Users (ActivationToken, CreatedAt, CreatedBy) VALUES (?, NOW(), ?)");
|
||||
|
||||
for ($i = 0; $i < $count; $i++) {
|
||||
|
@@ -29,7 +29,7 @@ function loadRouterConfig(): array
|
||||
return [
|
||||
'inlining' => false,
|
||||
'domain' => 'adlerka',
|
||||
'tld' => 'top',
|
||||
'tld' => 'space',
|
||||
'default_page' => 'index',
|
||||
'default_site' => 'home',
|
||||
'template_dir' => 'templates/',
|
||||
@@ -58,9 +58,9 @@ function loadRouterConfig(): array
|
||||
'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í.',
|
||||
'keywords' => 'adlerka, alderka, studenti, studentska stranka, web, dev, webdev, web dev, skola, zabava',
|
||||
'author' => 'Tím Adlerka space',
|
||||
'description' => 'Toto je oficiálna stránka pre Adlerácky vesmírny program, kde môžete nájsť plno zaujímavostí o ňom.',
|
||||
'keywords' => 'adlerka, alderka, studenti, vesmir, space, project, projekt, web, dev, webdev, web dev, skola, zabava',
|
||||
'generator' => 'TurboRoute',
|
||||
'robots' => 'follow, index, max-snippet:-1, max-video-preview:-1, max-image-preview:large'
|
||||
]
|
||||
|
316
lib/meme.php
316
lib/meme.php
@@ -1,316 +0,0 @@
|
||||
<?php
|
||||
|
||||
require_once "lib/upload.php";
|
||||
require_once "lib/account.php";
|
||||
/**
|
||||
* Adds a meme to the database with associated image and text content.
|
||||
*
|
||||
* @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.
|
||||
* @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
|
||||
{
|
||||
global $mysqli;
|
||||
$output = ["Status" => "Fail"];
|
||||
if (isLoggedIn() && fileExists($imageID, false) && !empty($title) && !empty($memeText) && !empty($imageID) && $imageID > 0) {
|
||||
$stmtMemeAdd = $mysqli->prepare('INSERT INTO Memes (AuthorID, Title, TextContent, FileID) VALUES (?, ?, ?, ?)');
|
||||
$stmtMemeAdd->bind_param('issi', $_SESSION['ID'], htmlspecialchars($title), htmlspecialchars($memeText), $imageID);
|
||||
if ($stmtMemeAdd->execute() && $stmtMemeAdd->affected_rows > 0) {
|
||||
$output["Status"] = "Success";
|
||||
$output["Meme"] = "Funny";
|
||||
}
|
||||
}
|
||||
return $output;
|
||||
}
|
||||
|
||||
function executeAndRenderMemes(mysqli_stmt $stmt): string {
|
||||
global $routerConfig;
|
||||
$stmt->execute();
|
||||
$stmt->store_result();
|
||||
$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.
|
||||
*
|
||||
* @param int $id The ID of the meme.
|
||||
* @param int $authorId The author's user ID.
|
||||
* @param string $title The title of the meme.
|
||||
* @param string $textContent The text content of the meme.
|
||||
* @param string $createdAt The creation timestamp of the meme.
|
||||
* @param string $filePath The file path of the associated image.
|
||||
* @param int $imageWidth The width of the image.
|
||||
* @param int $imageHeight The height of the image.
|
||||
* @param string $userNickname The nickname of the meme's author.
|
||||
* @param string $meme_template The HTML template for a meme. (used to not read the template over and over when rendering more memes)
|
||||
* @return string Returns the rendered HTML of the meme.
|
||||
*/
|
||||
function renderMeme(int $id, int $authorId, string $title, string $textContent, string $createdAt, string $filePath, int $imageWidth, int $imageHeight, string $userNickname, string $meme_template): string
|
||||
{
|
||||
|
||||
$meme_out = str_replace('__TEMPLATE_MEME_TITLE__', htmlspecialchars($title), $meme_template);
|
||||
$meme_out = str_replace('__TEMPLATE_MEME_AUTHOR__', htmlspecialchars($userNickname), $meme_out);
|
||||
$meme_out = str_replace('__TEMPLATE_MEME_DATE__', htmlspecialchars($createdAt), $meme_out);
|
||||
$meme_out = str_replace('__TEMPLATE_MEME_IMAGE__', '/' . htmlspecialchars($filePath), $meme_out);
|
||||
$meme_out = str_replace('__TEMPLATE_MEME_IMAGE_WIDTH__', strval($imageWidth), $meme_out);
|
||||
$meme_out = str_replace('__TEMPLATE_MEME_IMAGE_HEIGHT__', strval($imageHeight), $meme_out);
|
||||
$meme_out = str_replace('__TEMPLATE_MEME_DELETE_BUTTON__', (isModerator() || $_SESSION['ID'] == $authorId) ? "<button onclick=\"deleteMeme($id);\"><i class='ri-delete-bin-line'></i></button>" : '', $meme_out);
|
||||
|
||||
$meme_votes = calculateNetVotes($id);
|
||||
$meme_net_votes = $meme_votes['NetVotes'];
|
||||
|
||||
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)) {
|
||||
$meme_upvote_active = 'line';
|
||||
$meme_downvote_active = 'fill';
|
||||
$meme_vote_counter_class = 'negative';
|
||||
$meme_upvote_button_class = '';
|
||||
$meme_downvote_button_class = ' visual_hover';
|
||||
} else {
|
||||
$meme_downvote_active = 'line';
|
||||
$meme_upvote_active = 'line';
|
||||
$meme_vote_counter_class = 'neutral';
|
||||
$meme_upvote_button_class = '';
|
||||
$meme_downvote_button_class = '';
|
||||
}
|
||||
$meme_upvote = isLoggedIn() ? "<button id='meme_votes_upvote_button_$id' class='meme_upvote$meme_upvote_button_class' onclick=\"voteMeme($id, 1);\"> <i id='meme_votes_upvote_$id' class=\"ri-arrow-up-circle-$meme_upvote_active\"></i></button>" : '';
|
||||
$meme_downvote = isLoggedIn() ? "<button id='meme_votes_downvote_button_$id' class='meme_downvote$meme_downvote_button_class' onclick=\"voteMeme($id, 0);\"> <i id='meme_votes_downvote_$id' class=\"ri-arrow-down-circle-$meme_downvote_active\"></i></button>" : '';
|
||||
|
||||
$meme_out = str_replace('__TEMPLATE_MEME_VOTES_NUMBER__', strval($meme_net_votes), $meme_out);
|
||||
$meme_out = str_replace('__TEMPLATE_MEME_UPVOTE__', $meme_upvote, $meme_out);
|
||||
$meme_out = str_replace('__TEMPLATE_MEME_DOWNVOTE__', $meme_downvote, $meme_out);
|
||||
$meme_out = str_replace('__TEMPLATE_MEME_ID__', strval($id), $meme_out);
|
||||
$meme_out = str_replace('__TEMPLATE_MEME_VOTE_COUNTER_CLASS__', $meme_vote_counter_class, $meme_out);
|
||||
|
||||
return str_replace('__TEMPLATE_MEME_TEXT__', htmlspecialchars($textContent), $meme_out);
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders a gallery of memes, optionally filtered by author ID, meme ID, or a keyword.
|
||||
*
|
||||
* 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 getMemeGallery(?int $offset = null, ?int $authorId = null, ?int $memeId = null, ?string $keyword = null): array {
|
||||
return [
|
||||
"Status" => "Success",
|
||||
"Output" => renderMemeGallery($offset, $authorId, $memeId, $keyword)
|
||||
];
|
||||
}
|
||||
|
||||
function renderMemeGallery(?int $offset = null, ?int $authorId = null, ?int $memeId = null, ?string $keyword = null): string {
|
||||
global $mysqli, $routerConfig;
|
||||
|
||||
// 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';
|
||||
|
||||
$conditions = [];
|
||||
$params = [];
|
||||
$types = '';
|
||||
|
||||
// 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';
|
||||
}
|
||||
|
||||
// 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.
|
||||
* @return array Returns an associative array with the status of the operation.
|
||||
* @global mysqli $mysqli The database connection object.
|
||||
*/
|
||||
function deleteMeme(int $memeID): array
|
||||
{
|
||||
global $mysqli;
|
||||
$out = ["Status" => "Fail"];
|
||||
if (isLoggedIn()) {
|
||||
$query = !isModerator() ? 'DELETE FROM Memes WHERE ID = ? AND AuthorID = ?' : 'DELETE FROM Memes WHERE ID = ?';
|
||||
$stmtDelete = $mysqli->prepare($query);
|
||||
if (!isModerator()) {
|
||||
$stmtDelete->bind_param('ii', $memeID, $_SESSION['ID']);
|
||||
} else {
|
||||
$stmtDelete->bind_param('i', $memeID);
|
||||
}
|
||||
$stmtDelete->execute();
|
||||
if ($stmtDelete->affected_rows > 0) {
|
||||
$out['Status'] = 'Success';
|
||||
}
|
||||
$stmtDelete->close();
|
||||
}
|
||||
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).
|
||||
* @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
|
||||
{
|
||||
global $mysqli;
|
||||
$out = ["Status" => "Fail"];
|
||||
if ($isUpvote != 1) {
|
||||
$isUpvote = 0;
|
||||
}
|
||||
$memeVoteConn = $mysqli->prepare('INSERT INTO MemeVotes (MemeID, UserID, isUpvote) VALUES (?, ?, ?) ON DUPLICATE KEY UPDATE isUpvote = VALUES(isUpvote)');
|
||||
$memeVoteConn->bind_param('iii', $memeID, $_SESSION['ID'], $isUpvote);
|
||||
$memeVoteConn->execute();
|
||||
if ($memeVoteConn->affected_rows > 0) {
|
||||
$out['Status'] = 'Success';
|
||||
}
|
||||
$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.
|
||||
* @return array Returns an associative array with the status of the deletion.
|
||||
* @global mysqli $mysqli The database connection object.
|
||||
*/
|
||||
function deleteVoteMeme(int $memeID): array
|
||||
{
|
||||
global $mysqli;
|
||||
$out = ["Status" => "Fail"];
|
||||
$memeVoteConn = $mysqli->prepare('DELETE FROM MemeVotes WHERE MemeID = ? AND UserID = ?');
|
||||
$memeVoteConn->bind_param('ii', $memeID, $_SESSION['ID']);
|
||||
$memeVoteConn->execute();
|
||||
if ($memeVoteConn->affected_rows > 0) {
|
||||
$out['Status'] = 'Success';
|
||||
}
|
||||
$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.
|
||||
* @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
|
||||
{
|
||||
global $mysqli;
|
||||
|
||||
// Adjusted query to calculate net votes and get the user's vote in one go
|
||||
$query = "
|
||||
SELECT
|
||||
SUM(CASE WHEN isUpvote = 1 THEN 1 ELSE -1 END) AS NetVotes,
|
||||
(
|
||||
SELECT CASE WHEN isUpvote = 1 THEN 1 ELSE -1 END
|
||||
FROM MemeVotes
|
||||
WHERE MemeID = ? AND UserID = ?
|
||||
) AS UserVote
|
||||
FROM MemeVotes
|
||||
WHERE MemeID = ?";
|
||||
|
||||
$stmt = $mysqli->prepare($query);
|
||||
$userID = $_SESSION['ID'];
|
||||
$stmt->bind_param('iii', $memeID, $userID, $memeID);
|
||||
$stmt->execute();
|
||||
$result = $stmt->get_result();
|
||||
|
||||
$data = $result->fetch_assoc();
|
||||
|
||||
$netVotes = $data['NetVotes'] ?? 0; // Null coalescing operator in case no votes are found
|
||||
$userVote = $data['UserVote'] ?? 0; // Default to 0 if the user hasn't voted
|
||||
|
||||
$stmt->close();
|
||||
|
||||
return [
|
||||
"NetVotes" => $netVotes,
|
||||
"UserVote" => $userVote
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches the net votes and user's vote status for a specific meme.
|
||||
* Essentially just a wrapper of getMemeVotes for an API call
|
||||
*
|
||||
* @param int $memeID The ID of the meme to fetch votes for.
|
||||
* @return array Returns an array with the net votes and the user's vote status, along with operation status.
|
||||
*/
|
||||
function getMemeVotes(int $memeID): array
|
||||
{
|
||||
$voteData = calculateNetVotes($memeID);
|
||||
return [
|
||||
"Status" => "Success",
|
||||
"NetVotes" => $voteData['NetVotes'],
|
||||
"UserVote" => $voteData['UserVote']
|
||||
];
|
||||
}
|
@@ -11,7 +11,7 @@
|
||||
*/
|
||||
function generateScriptData(array $phpArray):string {
|
||||
// Check if the array is associative and single-level
|
||||
if (is_array($phpArray) && count($phpArray) > 0 && count(array_filter(array_keys($phpArray), 'is_string')) === count($phpArray)) {
|
||||
if (count($phpArray) > 0 && count(array_filter(array_keys($phpArray), 'is_string')) === count($phpArray)) {
|
||||
// Generate JavaScript code to save each array element to local storage
|
||||
$out = "<script>";
|
||||
foreach ($phpArray as $key => $value) {
|
||||
|
@@ -1,21 +0,0 @@
|
||||
<?php
|
||||
|
||||
require_once "lib/account.php";
|
||||
function submitSurvey(int $satisfaction, int $functionality, int $content, string $comment): array
|
||||
{
|
||||
global $mysqli;
|
||||
$output = ["Status" => "Fail", "Opinion" => "Ignored unsuccessfully!"];
|
||||
if (isLoggedIn()
|
||||
&& $satisfaction >= 1 && $satisfaction <= 5
|
||||
&& $functionality >= 1 && $functionality <= 5
|
||||
&& $content >= 1 && $content <= 5
|
||||
&& !empty($comment)) {
|
||||
$stmtMemeAdd = $mysqli->prepare('INSERT INTO Survey (AuthorID, Satisfaction, Functionality, Content, Comment) VALUES (?, ?, ?, ?, ?)');
|
||||
$stmtMemeAdd->bind_param('iiiis', $_SESSION['ID'], $satisfaction, $functionality, $content, htmlspecialchars($comment));
|
||||
if ($stmtMemeAdd->execute() && $stmtMemeAdd->affected_rows > 0) {
|
||||
$output["Status"] = "Success";
|
||||
$output["Opinion"] = "Ignored successfully!";
|
||||
}
|
||||
}
|
||||
return $output;
|
||||
}
|
Reference in New Issue
Block a user