diff --git a/assets/script.js b/assets/script.js
index 1420898..21775ee 100644
--- a/assets/script.js
+++ b/assets/script.js
@@ -9,7 +9,7 @@ let config =
function isLoggedIn() {
"use strict";
- return UserInfo.Email && 0 < UserInfo.Email.length;
+ return UserInfo.Email && UserInfo.Email.length > 0;
}
async function handleResponse(data, successMessage, failureMessage) {
@@ -19,7 +19,7 @@ async function handleResponse(data, successMessage, failureMessage) {
const statusMessage = document.createElement("div");
statusMessage.classList.add("status-message");
- if ('Success' === data.Status) {
+ if (data.Status === 'Success') {
statusMessage.innerText = successMessage;
statusMessage.classList.add("success");
} else {
@@ -104,10 +104,10 @@ async function displayList(data, elementId, deleteFunction) {
headerRow.appendChild(th);
}
- if ("function" === typeof deleteFunction) {
+ if (typeof deleteFunction === "function") {
const th = document.createElement("th");
let deleteBtn = document.createElement('i');
- deleteBtn.classList = ["ri-delete-bin-line"];
+ deleteBtn.classList.add("ri-delete-bin-line");
th.appendChild(deleteBtn);
headerRow.appendChild(th);
}
@@ -119,7 +119,7 @@ async function displayList(data, elementId, deleteFunction) {
td.appendChild(document.createTextNode(line[key]));
dataRow.appendChild(td);
}
- if ("function" === typeof deleteFunction) {
+ if (typeof deleteFunction === "function") {
const td = document.createElement("td");
const deleteButton = document.createElement('button');
deleteButton.innerHTML = "";
@@ -234,13 +234,13 @@ async function articleInit() {
let articleContainerElement = document.getElementById("articlecreatecontainer");
let articleCreateOpenElement = document.getElementById("articlecreateopen");
articleContainerElement.addEventListener("keyup", function (ev) {
- if ("Escape" === ev.key) {
+ if (ev.key === "Escape") {
togglearticlecreate();
}
});
PageIntervals.push(setInterval(renderarticles, config.articleRefresh));
document.getElementById("articleprivilegeinput").setAttribute("max", UserInfo.Privileges);
- if (2 > UserInfo.Privileges) {
+ if (UserInfo.Privileges < 2) {
articleContainerElement.style.display = "none";
articleCreateOpenElement.style.display = "none";
} else {
@@ -258,7 +258,7 @@ async function onPageLoad() {
clearInterval(interval);
}
- if ("home" === currentSite && "settings" === currentPage) {
+ if (currentSite === "home" && currentPage === "settings") {
if (document.getElementById("user-settings")) {
await populateUserInfoFields(UserInfo);
}
@@ -267,16 +267,16 @@ async function onPageLoad() {
await listUsers(true);
}
}
- if ("account" === currentSite && "index" === currentPage && isLoggedIn()) {
+ if (currentSite === "account" && currentPage === "index" && isLoggedIn()) {
await showDashboardGreeting();
}
- if ("news" === currentSite && "index" === currentPage) {
+ if (currentSite === "news" && currentPage === "index") {
await articleInit();
}
- if ("account" === currentSite && "files" === currentPage) {
+ if (currentSite === "account" && currentPage === "files") {
await listFiles();
}
- if ("memes" === currentSite && "index" === currentPage) {
+ if (currentSite === "memes" && currentPage === "index") {
await getMemeImages();
}
}
@@ -461,7 +461,7 @@ async function getUserInfo() {
};
const result = await doAction('/account', data, "User info retrieved Successfully!", "User info retrieval failed.", true);
- if (result && "Success" === result.Status) {
+ if (result && result.Status === "Success") {
Object.keys(result.UserInfo).forEach(index => {
let value = result.UserInfo[index];
localStorage.setItem("UserInfo_" + index, value);
@@ -498,7 +498,7 @@ async function listUsers(silent) {
doAction('/account', data, "User list retrieved Successfully!", "User list retrieval failed.", silent).then((result) => {
- if (result && "Success" === result.Status) {
+ if (result && result.Status === "Success") {
displayList(result.Users, "userListTable", deleteUser);
}
});
@@ -541,7 +541,7 @@ async function deleteActivationCode(activationCode) {
//Admin settings end
-if ("loading" === document.readyState) {
+if (document.readyState === "loading") {
document.addEventListener("DOMContentLoaded", initAjax);
} else {
setTimeout(initAjax, 0);
@@ -574,7 +574,7 @@ async function getFileList() {
action: "getAllFiles"
}, "Zoznam súborov bol úspešne stiahnutý", "Nastala chyba pri sťahovaní zoznamu súborov", true);
- if ("Success" === resp.Status) {
+ if (resp.Status === "Success") {
return resp.Files;
} else {
return false;
@@ -642,10 +642,10 @@ async function reloadMemeVotes(memeID) {
memeVoteCounterElement.innerText = memeVotes;
memeVoteCounterElement.classList.remove("positive", "negative", "neutral");
- if (memeVotes > 0) {
+ if (0 < memeVotes) {
memeVoteCounterElement.classList.add("positive");
}
- else if (memeVotes < 0) {
+ else if (0 > memeVotes) {
memeVoteCounterElement.classList.add("negative");
}
else {
@@ -654,20 +654,15 @@ async function reloadMemeVotes(memeID) {
memeVoteUpvoteButtonElement.classList.remove('visual_hover');
memeVoteDownvoteButtonElement.classList.remove('visual_hover');
- if (userVote > 0) {
+ let memeUpvoteVariant = "line";
+ let memeDownvoteVariant = "line";
+ if (0 < userVote) {
memeUpvoteVariant = "fill";
- memeDownvoteVariant = "line";
memeVoteUpvoteButtonElement.classList.add('visual_hover');
- }
- else if (userVote < 0) {
- memeUpvoteVariant = "line";
+ } else if (0 > userVote) {
memeDownvoteVariant = "fill";
memeVoteDownvoteButtonElement.classList.add('visual_hover');
}
- else {
- memeUpvoteVariant = "line";
- memeDownvoteVariant = "line";
- }
memeVoteUpvoteElement.classList = [`ri-arrow-up-circle-${memeUpvoteVariant}`];
memeVoteDownvoteElement.classList = [`ri-arrow-down-circle-${memeDownvoteVariant}`];
@@ -680,13 +675,13 @@ async function voteMeme(memeID, isUpvote){
let memeVoteDelete = false;
if(isUpvote) {
if(memeVoteUpvoteElement.classList.contains("ri-arrow-up-circle-fill")){
- deleteVoteMeme(memeID);
+ await deleteVoteMeme(memeID);
memeVoteDelete = true;
}
}
else {
if(memeVoteDownvoteElement.classList.contains("ri-arrow-down-circle-fill")){
- deleteVoteMeme(memeID);
+ await deleteVoteMeme(memeID);
memeVoteDelete = true;
}
}
diff --git a/assets/style.css b/assets/style.css
index 49bf616..701d142 100644
--- a/assets/style.css
+++ b/assets/style.css
@@ -371,11 +371,11 @@ div#articleslist>article{
}
.positive {
- color: green;
+ color: #008000;
}
.negative {
- color: red;
+ color: #ff0000;
}
.neutral {
@@ -390,12 +390,12 @@ div#articleslist>article{
}
.visual_hover.meme_upvote {
- --pico-background-color: green;
+ --pico-background-color: #008000;
--pico-border-color: unset;
}
.visual_hover.meme_downvote {
- --pico-background-color: red;
+ --pico-background-color: #ff0000;
--pico-border-color: unset;
}
diff --git a/endpoints/newsarticle.php b/endpoints/newsarticle.php
index 099094b..856cb3b 100644
--- a/endpoints/newsarticle.php
+++ b/endpoints/newsarticle.php
@@ -11,6 +11,12 @@ function endpoint($endpoint_data): array
$endpoint_data["title"],
$endpoint_data["body"]
),
+ "addNewsComment" => addNewsComment(
+ $endpoint_data["user_id"],
+ $endpoint_data['news_article_id'],
+ $endpoint_data["comment_text"],
+ $endpoint_data["parent_id"]
+ ),
default => ["Status" => "Fail", "message" => "Invalid action"],
};
}
\ No newline at end of file
diff --git a/index.php b/index.php
index 0196cd2..d683e30 100644
--- a/index.php
+++ b/index.php
@@ -1,32 +1,40 @@
0 && !empty($_SESSION["email"]) && $_SESSION["privilege_level"] >= $routerConfig["permissions"]["logged_in_default"];
}
+/**
+ * Checks if the logged-in user is verified.
+ *
+ * @global array $routerConfig Global configuration array containing permission thresholds.
+ * @return bool Returns true if the user is logged in and verified; otherwise, false.
+ */
function isVerified(): bool
{
global $routerConfig;
return isLoggedIn() && $_SESSION["privilege_level"] >= $routerConfig["permissions"]["verified"];
}
+/**
+ * Checks if the logged-in user is trustworthy.
+ *
+ * @global array $routerConfig Global configuration array containing permission thresholds.
+ * @return bool Returns true if the user is logged in and considered trustworthy; otherwise, false.
+ */
function isTrustWorthy(): bool
{
global $routerConfig;
return isLoggedIn() && $_SESSION["privilege_level"] >= $routerConfig["permissions"]["trustworthy"];
}
-
+/**
+ * Checks if the logged-in user is a moderator.
+ *
+ * @global array $routerConfig Global configuration array containing permission thresholds.
+ * @return bool Returns true if the user is logged in and a moderator; otherwise, false.
+ */
function isModerator(): bool
{
global $routerConfig;
return isLoggedIn() && $_SESSION["privilege_level"] >= $routerConfig["permissions"]["moderator"];
}
-
+/**
+ * Checks if the logged-in user is a user admin.
+ *
+ * @global array $routerConfig Global configuration array containing permission thresholds.
+ * @return bool Returns true if the user is logged in and a user admin; otherwise, false.
+ */
function isUserAdmin(): bool
{
global $routerConfig;
return isLoggedIn() && $_SESSION["privilege_level"] >= $routerConfig["permissions"]["user_admin"];
}
-
+/**
+ * Checks if the logged-in user is an admin.
+ *
+ * @global array $routerConfig Global configuration array containing permission thresholds.
+ * @return bool Returns true if the user is logged in and an admin; otherwise, false.
+ */
function isAdmin(): bool
{
global $routerConfig;
return isLoggedIn() && $_SESSION["privilege_level"] >= $routerConfig["permissions"]["admin"];
}
-
-function generateActivationToken(): string
+/**
+ * Generates a secure token for account activation or other purposes using cryptographic methods.
+ *
+ * @return string|null Returns a hexadecimal token or null in case of an error.
+ */
+function generateActivationToken(): ?string
{
try {
return bin2hex(random_bytes(16));
} catch (RandomException) {
+ return null;
}
}
-
-function isEmailAvailable($email): bool
+/**
+ * Checks if an email address is available for registration.
+ *
+ * @param string $email The email address to check.
+ * @return bool Returns true if the email is not already registered; otherwise, false.
+ *@global mysqli $mysqli Global mysqli object for database access.
+ */
+function isEmailAvailable(string $email): bool
{
global $mysqli;
$stmt = $mysqli->prepare("SELECT COUNT(*) FROM Users WHERE Email = ?");
@@ -59,7 +102,12 @@ function isEmailAvailable($email): bool
return $count === 0;
}
-
+/**
+ * Sets default session data typically used for a logged-out user(includes users that have just visited the page).
+ *
+ * @global array $routerConfig Global configuration array used for setting initial privilege levels.
+ * @return void
+ */
function setDefaultSessionData(): void
{
global $routerConfig;
@@ -71,8 +119,15 @@ function setDefaultSessionData(): void
$_SESSION["minecraft_nickname"] = "";
$_SESSION["privilege_level"] = $routerConfig["permissions"]["logged_out"];
}
-
-function verifyPassword($userID, $password): bool
+/**
+ * Verifies if the provided password matches the stored hash for the user.
+ *
+ * @param int $userID The user ID whose password is to be verified.
+ * @param string $password The password to verify.
+ * @return bool Returns true if the password matches the stored hash; otherwise, false.
+ *@global mysqli $mysqli Global mysqli object for database access.
+ */
+function verifyPassword(int $userID, string $password): bool
{
global $mysqli;
$stmt = $mysqli->prepare("SELECT PasswordHash FROM Users WHERE ID = ?");
@@ -85,7 +140,12 @@ function verifyPassword($userID, $password): bool
return !empty($password_hash) && !empty($password) && password_verify($password, $password_hash);
}
-
+/**
+ * Updates session data from the database for the logged-in user.
+ *
+ * @global mysqli $mysqli Global mysqli object for database access.
+ * @return void
+ */
function UpdateSession(): void
{
global $mysqli;
@@ -118,8 +178,15 @@ function UpdateSession(): void
$_SESSION["favorite_color"] = $favorite_color;
}
-
-function doLogin($email, $password): array
+/**
+ * Attempts to log in a user with the given credentials.
+ *
+ * @param string $email The user's email address.
+ * @param string $password The user's password.
+ * @global mysqli $mysqli Global database connection object.
+ * @return array An array containing the status of the login attempt ('Success' or 'Fail').
+ */
+function doLogin(string $email, string $password): array
{
global $mysqli;
$found = false;
@@ -149,7 +216,12 @@ function doLogin($email, $password): array
}
return $found ? ["Status" => "Success"] : ["Status" => "Fail"];
}
-
+/**
+ * Logs out the current user by resetting session data.
+ * Fails when the user wasn't logged in
+ *
+ * @return array An array with the logout status ('Success' if logged out, 'Fail' otherwise).
+ */
function doLogout(): array
{
if(isLoggedIn()){
@@ -159,8 +231,19 @@ function doLogout(): array
return ["Status" => "Fail"];
}
}
-
-function doRegister($firstname, $lastname, $email, $password, $activation_token): array
+/**
+ * Registers a new user with provided personal details and activation token.
+ *
+ * @param string $firstname The user's first name.
+ * @param string $lastname The user's last name.
+ * @param string $email The user's email.
+ * @param string $password The user's password.
+ * @param string $activation_token The activation token to verify the registration.
+ * @global mysqli $mysqli Global database connection object.
+ * @global array $routerConfig Global configuration settings.
+ * @return array An array with the registration status ('Success' or 'Fail').
+ */
+function doRegister(string $firstname, string $lastname, string $email, string $password, string $activation_token): array
{
global $mysqli, $routerConfig;
$status = ["Status" => "Fail"];
@@ -186,8 +269,15 @@ function doRegister($firstname, $lastname, $email, $password, $activation_token)
return $status;
}
-
-function changePassword($oldPassword, $newPassword): array
+/**
+ * Changes the user's password after verifying the old password.
+ *
+ * @param string $oldPassword The current password for verification.
+ * @param string $newPassword The new password to be set.
+ * @return array An array indicating whether the password change was successful ('Success' or 'Fail').
+ *@global mysqli $mysqli Global database connection object.
+ */
+function changePassword(string $oldPassword, string $newPassword): array
{
global $mysqli;
$status = ["Status" => "Fail"];
@@ -206,8 +296,17 @@ function changePassword($oldPassword, $newPassword): array
}
-// Function to update user profile
-function updateUserProfile($firstName, $lastName, $nickname, $minecraft_nickname): array
+/**
+ * Updates user profile information in the database.
+ *
+ * @param string $firstName The new first name.
+ * @param string $lastName The new last name.
+ * @param string $nickname The new nickname.
+ * @param string $minecraft_nickname The new Minecraft nickname.
+ * @return array Status of the profile update ('Success' or 'Fail').
+ *@global mysqli $mysqli Global database connection object.
+ */
+function updateUserProfile(string $firstName, string $lastName, string $nickname, string $minecraft_nickname): array
{
global $mysqli;
$status = ["Status" => "Fail"];
@@ -230,8 +329,14 @@ function updateUserProfile($firstName, $lastName, $nickname, $minecraft_nickname
return $status;
}
-// Function to update user email
-function updateUserEmail($email): array
+/**
+ * Updates the email address of the logged-in user after validation.
+ *
+ * @param string $email The new email address to update.
+ * @return array Status of the email update ('Success' or 'Fail').
+ *@global mysqli $mysqli Global database connection object.
+ */
+function updateUserEmail(string $email): array
{
global $mysqli;
$status = ["Status" => "Fail"];
@@ -274,7 +379,11 @@ function updateUserEmail($email): array
return $status;
}
-
+/**
+ * Retrieves and updates the current session with user information from the database.
+ *
+ * @return array Contains user information and status if the user is logged in.
+ */
function getUserInfo(): array
{
$output = ["Status" => "Fail"];
@@ -310,8 +419,14 @@ function getUserInfo(): array
return $output;
}
-
-function addActivationCodes($count): array
+/**
+ * Generates a specified number of activation codes for user registration and adds them to the database.
+ *
+ * @param int $count Number of activation codes to generate.
+ * @return array An array containing the generated codes and status ('Success' or 'Fail').
+ *@global mysqli $mysqli Global database connection object.
+ */
+function addActivationCodes(int $count): array
{
global $mysqli;
$activationCodes = [];
@@ -342,7 +457,12 @@ function addActivationCodes($count): array
return $output;
}
-
+/**
+ * Lists all registered users, available only to user admins.
+ *
+ * @global mysqli $mysqli Global database connection object.
+ * @return array An array containing user data and status.
+ */
function listUsers(): array
{
global $mysqli;
@@ -364,7 +484,12 @@ function listUsers(): array
return $output;
}
-
+/**
+ * Lists activation codes available for assigning to new users, available only for user admins.
+ *
+ * @global mysqli $mysqli Global database connection object.
+ * @return array An array containing activation codes and status.
+ */
function listActivationCodes(): array
{
global $mysqli;
@@ -409,8 +534,14 @@ function listActivationCodes(): array
return $output;
}
-
-function deleteUser($userID): array
+/**
+ * Deletes a user by their ID, available only to user admins.
+ *
+ * @param int $userID The ID of the user to delete.
+ * @return array Status of the delete operation ('Success' or 'Fail').
+ *@global mysqli $mysqli Global database connection object.
+ */
+function deleteUser(int $userID): array
{
global $mysqli;
$status = ["Status" => "Fail"];
@@ -425,8 +556,14 @@ function deleteUser($userID): array
}
return $status;
}
-
-function deleteActivationCode($activationCode): array
+/**
+ * Deletes an activation code, available only to user admins.
+ *
+ * @param string $activationCode The activation code to delete.
+ * @return array Status of the delete operation ('Success' or 'Fail').
+ *@global mysqli $mysqli Global database connection object.
+ */
+function deleteActivationCode(string $activationCode): array
{
global $mysqli;
$status = ["Status" => "Fail"];
diff --git a/lib/config.php b/lib/config.php
index 0db0b39..432c31e 100644
--- a/lib/config.php
+++ b/lib/config.php
@@ -1,4 +1,28 @@
` tag with custom CSS if a favorite color is set
+ * and the user is logged in. Returns an empty string if no conditions are met.
+ */
function doDynamicStyling() :string
{
$dynamic_style = "";
diff --git a/lib/endpoint.php b/lib/endpoint.php
index e54b0f0..81b9122 100644
--- a/lib/endpoint.php
+++ b/lib/endpoint.php
@@ -1,6 +1,16 @@
tags
+ * with corresponding ";
}, $inputString);
}
-
-function inlineScriptFromSrc($inputString): string
+/**
+ * Processes an HTML string to inline all external JavaScript files by replacing ";
}, $inputString);
}
-
-function minifyCss($css): string
+/**
+ * Minifies CSS content by removing comments, unnecessary whitespaces, semicolons, and optimizing other aspects of the stylesheet.
+ * Might be broken, currently disabled in the config
+ *
+ * @param string $css The original CSS content.
+ * @return string The minified CSS content.
+ */
+function minifyCss(string $css): string
{
// Remove comments
$css = preg_replace('!/\*[^*]*\*+([^/][^*]*\*+)*/!', '', $css);
@@ -64,8 +84,14 @@ function minifyCss($css): string
return trim($css);
}
-
-function minifyJs($js): string
+/**
+ * Minifies JavaScript content by removing comments, unnecessary whitespaces, and optimizing spaces around operators.
+ * Might be broken, currently disabled in the config
+ *
+ * @param string $js The original JavaScript content.
+ * @return string The minified JavaScript content.
+ */
+function minifyJs(string $js): string
{
// Remove newlines and tabs
diff --git a/lib/meme.php b/lib/meme.php
index 4ce4293..4d73134 100644
--- a/lib/meme.php
+++ b/lib/meme.php
@@ -2,7 +2,15 @@
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.
+ * @global mysqli $mysqli The database connection object.
+ * @return array Returns an associative array with the operation status and a message.
+ */
function addMeme(string $title, string $memeText, int $imageID): array
{
global $mysqli;
@@ -17,7 +25,21 @@ function addMeme(string $title, string $memeText, int $imageID): array
}
return $output;
}
-
+/**
+ * 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
{
@@ -64,7 +86,14 @@ 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.
+ *
+ * @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.
+ */
function renderMemeGallery(): string
{
global $mysqli;
@@ -105,7 +134,13 @@ function renderMemeGallery(): string
$stmtlist->close();
return $meme_gallery_out;
}
-
+/**
+ * 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.
+ */
function deleteMeme(int $memeID): array
{
global $mysqli;
@@ -126,7 +161,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.
+ */
function voteMeme(int $memeID, int $isUpvote): array
{
global $mysqli;
@@ -143,7 +185,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.
+ */
function deleteVoteMeme(int $memeID): array
{
global $mysqli;
@@ -157,7 +205,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.
+ */
function calculateNetVotes(int $memeID): array
{
global $mysqli;
@@ -193,7 +248,13 @@ function calculateNetVotes(int $memeID): array
];
}
-
+/**
+ * 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);
diff --git a/lib/navigation.php b/lib/navigation.php
index df9fe06..0080b56 100644
--- a/lib/navigation.php
+++ b/lib/navigation.php
@@ -1,11 +1,24 @@
"Success",
diff --git a/lib/newsarticle.php b/lib/newsarticle.php
index 0f80108..add6552 100644
--- a/lib/newsarticle.php
+++ b/lib/newsarticle.php
@@ -1,4 +1,15 @@
close();
}
return $output;
-}
\ No newline at end of file
+}
+
+/**
+ * Adds a comment to a news article.
+ *
+ * @param int $userId User who is commenting.
+ * @param int $newsArticleId ID of the news article.
+ * @param string $commentText The content of the comment.
+ * @param int|null $parentId ID of the parent comment if it's a reply.
+ * @return array Status array indicating success or failure.
+ * @global mysqli $mysqli The mysqli database connection object.
+ */
+function addNewsComment(int $userId, int $newsArticleId, string $commentText, ?int $parentId = null): array {
+ global $mysqli;
+
+ $output = ["Status" => "Fail"]; // Default Status is "Fail"
+
+ if (!isLoggedIn()) {
+ $output['Error'] = "User must be logged in.";
+ return $output;
+ }
+
+ // Prepare the SQL statement to prevent SQL injection
+ $stmt = $mysqli->prepare("INSERT INTO NewsComments (ParentID, UserID, NewsArticleID, CommentText) VALUES (?, ?, ?, ?);");
+
+ // Bind parameters. 'i' denotes an integer and 's' denotes a string.
+ $stmt->bind_param("iiis", $parentId, $userId, $newsArticleId, $commentText);
+
+ // Execute the query
+ if ($stmt->execute()) {
+ // Check if any rows were affected
+ if ($stmt->affected_rows > 0) {
+ $output["Status"] = "Success";
+ } else {
+ $output["Error"] = "No rows affected.";
+ }
+ } else {
+ $output["Error"] = $stmt->error;
+ }
+
+ // Close statement
+ $stmt->close();
+
+ return $output;
+}
diff --git a/lib/page.php b/lib/page.php
index a25e615..327f035 100644
--- a/lib/page.php
+++ b/lib/page.php
@@ -1,16 +1,37 @@
/', '', $content);
}
-
-function parsePageTag($input): array
+/**
+ * Parses custom `` tags from the given input string and extracts parameters.
+ * Returns the input string with `` tags removed and a list of parameters.
+ *
+ * @param string $input The input HTML or text containing `` tags.
+ * @return array Returns an associative array with 'parameters' (parsed from the tag)
+ * and 'output' (the modified input string with `` tags removed).
+ */
+function parsePageTag(string $input): array
{
// Define the pattern for the tag
$pattern = '/]+)><\/page>/i';
@@ -34,8 +55,15 @@ function parsePageTag($input): array
// If no match is found, return the original input
return ['parameters' => [], 'output' => $input];
}
-
-function renderPage($page_name = null, $site_name = null): array
+/**
+ * Renders a page based on specified page and site names, handling dynamic and static content,
+ * permissions, and error pages.
+ *
+ * @param string|null $page_name The name of the page to render. If null, uses default from request.
+ * @param string|null $site_name The name of the site to render. If null, uses default from request.
+ * @return array Returns an associative array containing the rendered page content, page name, site name, and page title.
+ */
+function renderPage(string $page_name = null, string $site_name = null): array
{
global $routerConfig;
global $routerRequest;
@@ -138,8 +166,16 @@ function renderPage($page_name = null, $site_name = null): array
];
}
-
-function getPage($site_name_in = null, $page_name_in = null): string
+/**
+ * Compiles a complete web page by injecting dynamic elements into a template skeleton,
+ * including headers, footers, and SEO tags.
+ * It is used when not going to a page by AJAX to initialize everything.
+ *
+ * @param string|null $site_name_in The site name to be used; defaults from global configuration if null.
+ * @param string|null $page_name_in The page name to be used; defaults from global configuration if null.
+ * @return string The complete HTML content of the web page ready for display.
+ */
+function getPage(string $site_name_in = null, string $page_name_in = null): string
{
$page_tmp = renderPage($page_name_in, $site_name_in);
@@ -223,8 +259,15 @@ function getPage($site_name_in = null, $page_name_in = null): string
}
return str_replace("__TEMPLATE_PAGE_TITLE__", $page_title, $out);
}
-
-function getPageEndpoint($page_name, $site_name) :array
+/**
+ * Provides an API interface to get page details including content and meta-information for routing purposes.
+ * This is what enables the page to never refresh.
+ *
+ * @param string $page_name The name of the page.
+ * @param string $site_name The name of the site.
+ * @return array Returns an array with status, page content, location URL, and title for the requested page.
+ */
+function getPageEndpoint(string $page_name, string $site_name) :array
{
$page_location = "/" . $site_name . "/" . $page_name;
$page_tmp = renderPage($page_name, $site_name);
diff --git a/lib/router.php b/lib/router.php
index e42bd7e..6436aaa 100644
--- a/lib/router.php
+++ b/lib/router.php
@@ -1,6 +1,14 @@
0 && count(array_filter(array_keys($phpArray), 'is_string')) === count($phpArray)) {
// Generate JavaScript code to save each array element to local storage
diff --git a/lib/sitemap.php b/lib/sitemap.php
index 967be22..a3a5fa1 100644
--- a/lib/sitemap.php
+++ b/lib/sitemap.php
@@ -1,8 +1,16 @@
' . PHP_EOL;
header('Content-type: application/xml');
- echo $sitemap;
+ return $sitemap;
}
\ No newline at end of file
diff --git a/lib/upload.php b/lib/upload.php
index 276ef30..efb4344 100644
--- a/lib/upload.php
+++ b/lib/upload.php
@@ -1,6 +1,12 @@
close();
return $stat;
}
-
-function doImageUpload($inFile, $outFile): bool
+/**
+ * Handles the uploading process of an image, including its conversion to webp format, rotation based on orientation, and saving.
+ *
+ * @param string $inFile The temporary file path of the uploaded file.
+ * @param string $outFile The target file path where the processed image should be saved.
+ * @return bool Returns true if the file was successfully processed and saved, false otherwise.
+ */
+function doImageUpload(string $inFile, string $outFile): bool
{
// Create Imagick object
$width = 0;
@@ -96,15 +126,22 @@ function doImageUpload($inFile, $outFile): bool
} catch (ImagickException) {
}
- // Check if the reencoding was successful
+ // Check if the reencoding was successful, if yes, save into the database.
if (file_exists($outFile)) {
return saveUploadedFileInDatabase($outFile, 'image/webp', $width, $height);
} else {
return false;
}
}
+/**
+ * Retrieves a list of files from the database, optionally filtered to include only files uploaded by the current user.
+ * Access to an unfiltered list (files of all users) is only available to moderators.
+ *
+ * @param bool $onlyMine Whether to retrieve only files uploaded by the logged-in user. If false, files from all users are returned if the user is a moderator.
+ * @return array Returns an array containing file data along with a status message.
+ */
-function listFiles($onlyMine = true): array
+function listFiles(bool $onlyMine = true): array
{
$output = ["Status" => "Success"];
require_once "lib/account.php";
@@ -156,6 +193,12 @@ function listFiles($onlyMine = true): array
return $output;
}
+/**
+ * Processes incoming files from the $_FILES global (after processed by getIncomingFiles), performs checks, and attempts to upload a file based on its type.
+ * Currently only supports valid image files.
+ *
+ * @return array Returns an array indicating the success or failure ('Status' key) of the file processing operations.
+ */
function parseIncomingFiles(): array
{
@@ -183,8 +226,15 @@ function parseIncomingFiles(): array
}
return $output;
}
+/**
+ * Generates a file path for uploading based on the type of the file, the ID of the uploader and the date and time of uploading.
+ *
+ * @param string $type The type of the file, typically used to categorize the file.
+ * @param string $filename The base name of the file, used in generating the final path.
+ * @return string Returns the full path for storing the file or an empty string if the type is not recognized.
+ */
-function getUploadPath($type = "unknown", $filename = "hehe"): string
+function getUploadPath(string $type = "unknown", string $filename = "hehe"): string
{
$type = makePathSafe($type);
$id = makePathSafe($_SESSION["ID"]);
@@ -202,6 +252,15 @@ function getUploadPath($type = "unknown", $filename = "hehe"): string
return "";
}
}
+/**
+ * Checks if a file with a given ID exists in the database and does permission checks.
+ * Access is granted to only the user's files, in order to access all files the onlyMine parameter
+ * must be false and the user must be a moderator.
+ *
+ * @param int $fileId The ID of the file to check.
+ * @param bool $onlyMine Whether to limit the search to files uploaded by the logged-in user.
+ * @return bool|string Returns the path of the file if it exists and meets the criteria, false otherwise.
+ */
function fileExists(int $fileId, bool $onlyMine = true): bool|string
{
@@ -230,7 +289,14 @@ function fileExists(int $fileId, bool $onlyMine = true): bool|string
return false;
}
}
-
+/**
+ * Adds a file to a specified group, if the user created the group or creates a new group if
+ * a group with a specified ID does not exist yet
+ *
+ * @param int $groupId The ID of the group to which the file should be added.
+ * @param int $fileId The ID of the file to add to the group.
+ * @return array Returns an associative array with a 'Status' key indicating success or failure.
+ */
function addToGroup(int $groupId, int $fileId): array
{
$output = ["Status" => "Fail"];
@@ -253,16 +319,22 @@ function addToGroup(int $groupId, int $fileId): array
}
return $output;
}
-
+/**
+ * Deletes a file entry from the database and the file system, a user can only delete his own files,
+ * except when he is a moderator, in that case he can delete all files.
+ *
+ * @param int $fileID The ID of the file to be deleted.
+ * @return array Returns an array with a 'Status' key indicating the success or failure of the deletion operation.
+ */
function deleteFile(int $fileID): array
{
global $mysqli;
$out = ["Status" => "Fail"];
if (isLoggedIn()) {
- $file_location = fileExists($fileID, !isAdmin());
- $query = !isAdmin() ? 'DELETE FROM Files WHERE ID = ? AND UploadedBy = ?' : 'DELETE FROM Files WHERE ID = ?';
+ $file_location = fileExists($fileID, !isModerator());
+ $query = !isModerator() ? 'DELETE FROM Files WHERE ID = ? AND UploadedBy = ?' : 'DELETE FROM Files WHERE ID = ?';
$stmtDelete = $mysqli->prepare($query);
- if (!isAdmin()) {
+ if (!isModerator()) {
$stmtDelete->bind_param('ii', $fileID, $_SESSION['ID']);
} else {
$stmtDelete->bind_param('i', $fileID);