Merge pull request 'add-to-blog' (#34) from add-to-blog into master

Reviewed-on: #34
This commit is contained in:
Rohit Pai 2023-06-26 17:05:57 +01:00
commit 5ac8282fb6
177 changed files with 969 additions and 187 deletions

View File

@ -1,18 +1,20 @@
{ {
"require": { "require": {
"slim/slim-skeleton": "^4.3", "slim/slim-skeleton": "^4.3",
"ext-pdo": "*", "ext-pdo": "*",
"slim/psr7": "^1.4", "slim/psr7": "^1.4",
"nyholm/psr7": "^1.4", "nyholm/psr7": "^1.4",
"nyholm/psr7-server": "^1.0", "nyholm/psr7-server": "^1.0",
"guzzlehttp/psr7": "^2.0", "guzzlehttp/psr7": "^2.0",
"http-interop/http-factory-guzzle": "^1.2", "http-interop/http-factory-guzzle": "^1.2",
"laminas/laminas-diactoros": "^2.6", "laminas/laminas-diactoros": "^2.6",
"laminas/laminas-httphandlerrunner": "^2.0", "laminas/laminas-httphandlerrunner": "^2.0",
"selective/samesite-cookie": "^0.3.0", "selective/samesite-cookie": "^0.3.0",
"ext-json": "*", "ext-json": "*",
"slim/slim": "^4.10", "slim/slim": "^4.10",
"rbdwllr/psr-jwt": "^2.0", "rbdwllr/psr-jwt": "^2.0",
"tuupola/slim-jwt-auth": "^3.6" "tuupola/slim-jwt-auth": "^3.6",
"ext-dom": "*",
"ext-libxml": "*"
} }
} }

View File

@ -1,8 +1,12 @@
<?php <?php
namespace api\blog; namespace api\blog;
use api\utils\imgUtils;
use DOMDocument;
use PDO; use PDO;
use Psr\Http\Message\UploadedFileInterface;
require_once __DIR__ . "/../utils/config.php"; require_once __DIR__ . "/../utils/config.php";
require_once __DIR__ . "/../utils/imgUtils.php";
/** /**
* Blog Data Class * Blog Data Class
@ -14,10 +18,10 @@ class blogData
* Get all blog posts * Get all blog posts
* @return array - Array of all blog posts or error message * @return array - Array of all blog posts or error message
*/ */
function getBlogPosts(): array public function getBlogPosts(): array
{ {
$conn = dbConn(); $conn = dbConn();
$stmt = $conn->prepare("SELECT ID, title, dateCreated, dateModified, body, tags FROM blog ORDER BY dateCreated DESC;"); $stmt = $conn->prepare("SELECT ID, title, dateCreated, dateModified, body, categories FROM blog ORDER BY dateCreated DESC;");
$stmt->execute(); $stmt->execute();
// set the resulting array to associative // set the resulting array to associative
@ -36,10 +40,10 @@ class blogData
* @param string $ID - ID of the blog post to get * @param string $ID - ID of the blog post to get
* @return array - Array of all blog posts or error message * @return array - Array of all blog posts or error message
*/ */
function getBlogPost(string $ID): array public function getBlogPost(string $ID): array
{ {
$conn = dbConn(); $conn = dbConn();
$stmt = $conn->prepare("SELECT ID, title, dateCreated, dateModified, featured, headerImg, body, tags FROM blog WHERE ID = :ID;"); $stmt = $conn->prepare("SELECT ID, title, dateCreated, dateModified, featured, headerImg, body, categories FROM blog WHERE ID = :ID;");
$stmt->bindParam(":ID", $ID); $stmt->bindParam(":ID", $ID);
$stmt->execute(); $stmt->execute();
@ -58,10 +62,10 @@ class blogData
* Get the latest blog post * Get the latest blog post
* @return array - Array of the latest blog post or error message * @return array - Array of the latest blog post or error message
*/ */
function getLatestBlogPost(): array public function getLatestBlogPost(): array
{ {
$conn = dbConn(); $conn = dbConn();
$stmt = $conn->prepare("SELECT ID, title, dateCreated, dateModified, featured, headerImg, body, tags FROM blog ORDER BY dateCreated DESC LIMIT 1;"); $stmt = $conn->prepare("SELECT ID, title, dateCreated, dateModified, featured, headerImg, body, categories FROM blog ORDER BY dateCreated DESC LIMIT 1;");
$stmt->execute(); $stmt->execute();
// set the resulting array to associative // set the resulting array to associative
@ -79,10 +83,10 @@ class blogData
* Get featured blog post * Get featured blog post
* @return array - Array of the featured blog post or error message * @return array - Array of the featured blog post or error message
*/ */
function getFeaturedBlogPost(): array public function getFeaturedBlogPost(): array
{ {
$conn = dbConn(); $conn = dbConn();
$stmt = $conn->prepare("SELECT ID, title, dateCreated, dateModified, featured, headerImg, body, tags FROM blog WHERE featured = 1;"); $stmt = $conn->prepare("SELECT ID, title, dateCreated, dateModified, featured, headerImg, body, categories FROM blog WHERE featured = 1;");
$stmt->execute(); $stmt->execute();
$result = $stmt->fetch(PDO::FETCH_ASSOC); $result = $stmt->fetch(PDO::FETCH_ASSOC);
@ -94,4 +98,124 @@ class blogData
return array("errorMessage" => "Error, blog post could not found"); return array("errorMessage" => "Error, blog post could not found");
} }
/**
* Upload the images in the post to temp folder and return image location
* @param UploadedFileInterface $img - Image to upload
* @return string|array - String with error message or array with the location of the uploaded file
*/
public function uploadPostImage(UploadedFileInterface $img): string|array
{
$targetDir = "../blog/imgs/tmp/";
$imagUtils = new imgUtils();
$targetFile = $imagUtils->uploadFile($targetDir, $img);
$file = $targetDir . basename($img->getClientFilename());
if (file_exists($file))
{
return array("url" => $file);
}
if (!is_array($targetFile))
{
return $targetFile;
}
if (file_exists($targetFile["imgLocation"]))
{
return array("url" => $targetFile["imgLocation"]);
}
return "Couldn't upload the image";
}
/**
* Creates a new post directory, uploads the header image and moves the images from the
* temp folder to the new folder, then updates the post html to point to the new images, finally
* it creates the post in the database
* @param string $title - Title of the blog post
* @param string $body - Body of the blog post
* @param string $dateCreated - Date the blog post was created
* @param string $featured - Whether the blog post is featured or not
* @param string $categories - Categories of the blog post
* @param UploadedFileInterface $headerImg - Header image of the blog post
* @return int|string - ID of the blog post or error message
*/
public function createPost(string $title, string $body, string $dateCreated, string $featured, string $categories, UploadedFileInterface $headerImg): int|string
{
$conn = dbConn();
$targetFile = "";
$folderID = uniqid();
if ($headerImg !== null)
{
$targetDir = "../blog/imgs/" . $title . "_" . $folderID . "/";
mkdir($targetDir, 0777, true);
$imagUtils = new imgUtils();
$targetFile = $imagUtils->uploadFile($targetDir, $headerImg);
}
$targetFile = array("imgLocation" => ".../blog/imgs/placeholder.png");
if (!is_array($targetFile))
{
return $targetFile;
}
$htmlDoc = new DOMDocument();
$htmlDoc->loadHTML($body, LIBXML_NOERROR);
$doc = $htmlDoc->getElementsByTagName('body')->item(0);
$imgs = $doc->getElementsByTagName('img');
$srcList = array();
foreach ($imgs as $img)
{
$src = $img->getAttribute("src");
$srcList[] = $src;
$fileName = basename($src);
$img->setAttribute("src", $targetDir . $fileName);
}
$files = scandir("../blog/imgs/tmp/");
foreach ($files as $file)
{
if ($file != "." && $file != "..")
{
if (!in_array("../blog/imgs/tmp/" . $file, $srcList))
{
unlink("../blog/imgs/tmp/" . $file);
}
else
{
rename("../blog/imgs/tmp/" . $file, $targetDir . $file);
}
}
}
$newBody = '';
foreach ($doc->childNodes as $node)
{
$newBody .= $htmlDoc->saveHTML($node);
}
$stmt = $conn->prepare("INSERT INTO blog (title, dateCreated, dateModified, featured, headerImg, body, categories, folderID)
VALUES (:title, :dateCreated, :dateModified, :featured, :headerImg, :body, :categories, :folderID);");
$stmt->bindParam(":title", $title);
$stmt->bindParam(":dateCreated", $dateCreated);
$stmt->bindParam(":dateModified", $dateCreated);
$stmt->bindParam(":featured", $featured);
$stmt->bindParam(":headerImg", $targetFile["imgLocation"]);
$stmt->bindParam(":body", $newBody);
$stmt->bindParam(":categories", $categories);
$stmt->bindParam(":folderID", $folderID);
if ($stmt->execute())
{
return intval($conn->lastInsertId());
}
return "Error, couldn't create post";
}
} }

View File

@ -12,7 +12,6 @@ use Slim\App;
class blogRoutes implements routesInterface class blogRoutes implements routesInterface
{ {
private blogData $blogData; private blogData $blogData;
/** /**
* constructor used to instantiate a base blog routes, to be used in the index.php file. * constructor used to instantiate a base blog routes, to be used in the index.php file.
* @param App $app - the slim app used to create the routes * @param App $app - the slim app used to create the routes
@ -30,6 +29,54 @@ class blogRoutes implements routesInterface
*/ */
public function createRoutes(App $app): void public function createRoutes(App $app): void
{ {
// TODO: Implement createRoutes() method. $app->post("/blog/post", function (Request $request, Response $response, array $args)
{
$data = $request->getParsedBody();
$files = $request->getUploadedFiles();
$headerImg = $files["headerImg"];
if (empty($data["title"]) || empty($data["body"]) || empty($data["dateCreated"]) || empty($data["featured"]) || empty($data["categories"]))
{
// uh oh sent some empty data
$response->getBody()->write(json_encode(array("error" => "Error, empty data sent")));
return $response->withStatus(400);
}
if (empty($files["headerImg"]))
{
$headerImg = null;
}
$insertedID = $this->blogData->createPost($data["title"], $data["body"], $data["dateCreated"], $data["featured"], $data["categories"], $headerImg);
if (!is_int($insertedID))
{
// uh oh something went wrong
$response->getBody()->write(json_encode(array("error" => $insertedID)));
return $response->withStatus(500);
}
$response->getBody()->write(json_encode(array("ID" => $insertedID)));
return $response->withStatus(201);
});
$app->post("/blog/uploadPostImage", function (Request $request, Response $response)
{
$files = $request->getUploadedFiles();
if (empty($files))
{
// uh oh sent some empty data
$response->getBody()->write(json_encode(array("error" => array("message" => "Error, empty data sent"))));
return $response->withStatus(400);
}
$message = $this->blogData->uploadPostImage($files["upload"]);
if (!is_array($message))
{
$response->getBody()->write(json_encode(array("error" => array("message" => $message))));
return $response->withStatus(500);
}
$response->getBody()->write(json_encode($message));
return $response->withStatus(201);
});
} }
} }

View File

@ -1,9 +1,11 @@
<?php <?php
namespace api\project; namespace api\project;
use api\utils\imgUtils;
use PDO; use PDO;
use Psr\Http\Message\UploadedFileInterface; use Psr\Http\Message\UploadedFileInterface;
require_once __DIR__ . "/../utils/config.php"; require_once __DIR__ . "/../utils/config.php";
require_once __DIR__ . "/../utils/imgUtils.php";
/** /**
* Project Data Class * Project Data Class
@ -15,7 +17,7 @@ class projectData
* Get all project data * Get all project data
* @return array - Array of all project data or error message * @return array - Array of all project data or error message
*/ */
function getProjectData(): array public function getProjectData(): array
{ {
$conn = dbConn(); $conn = dbConn();
$stmt = $conn->prepare("SELECT ID, title, isMainProject, information, imgLocation, projectLink, gitLink FROM projects ORDER BY isMainProject DESC;"); $stmt = $conn->prepare("SELECT ID, title, isMainProject, information, imgLocation, projectLink, gitLink FROM projects ORDER BY isMainProject DESC;");
@ -43,7 +45,7 @@ class projectData
* @param string $gitLink - Link to the git repository * @param string $gitLink - Link to the git repository
* @return bool|string - True if project was updated, false if not and there was an error, or an error string * @return bool|string - True if project was updated, false if not and there was an error, or an error string
*/ */
function updateProjectData(string $ID, string $title, string $isMainProject, string $information, string $projectLink, string $gitLink): bool | string public function updateProjectData(string $ID, string $title, string $isMainProject, string $information, string $projectLink, string $gitLink): bool|string
{ {
$conn = dbConn(); $conn = dbConn();
@ -82,7 +84,7 @@ class projectData
* @param int $ID - ID of the project in the database to delete * @param int $ID - ID of the project in the database to delete
* @return string - True if project was deleted, false if not and there was an error * @return string - True if project was deleted, false if not and there was an error
*/ */
function deleteProjectData(int $ID): string public function deleteProjectData(int $ID): string
{ {
$conn = dbConn(); $conn = dbConn();
@ -121,7 +123,7 @@ class projectData
* @param string $gitLink - Link to the github repository * @param string $gitLink - Link to the github repository
* @return int|bool - ID of the project if it was added, false if not and there was an error * @return int|bool - ID of the project if it was added, false if not and there was an error
*/ */
function addProjectData(string $title, string $isMainProject, string $information, string $projectLink, string $gitLink): int|bool public function addProjectData(string $title, string $isMainProject, string $information, string $projectLink, string $gitLink): int|bool
{ {
$conn = dbConn(); $conn = dbConn();
@ -157,31 +159,15 @@ class projectData
public function uploadImage(int $ID, UploadedFileInterface $img): string | array public function uploadImage(int $ID, UploadedFileInterface $img): string | array
{ {
$targetDir = "../imgs/projects/"; $targetDir = "../imgs/projects/";
$targetFile = $targetDir . basename($img->getClientFilename()); $imgUtils = new imgUtils();
$uploadOk = 1; $targetFile = $imgUtils->uploadFile($targetDir, $img);
$imageFileType = strtolower(pathinfo($targetFile, PATHINFO_EXTENSION));
// Check if file already exists if (!is_array($targetFile))
if (file_exists($targetFile))
{ {
return "The file already exists"; return $targetFile;
} }
// Check file size if (file_exists($targetFile["imgLocation"]))
if ($img->getSize() > 2000000)
{
return "The file is too large, max 2MB";
}
// Allow certain file formats
if ($imageFileType != "jpg" && $imageFileType != "png" && $imageFileType != "jpeg" && $imageFileType != "gif")
{
return "Only JPG, JPEG, PNG & GIF files are allowed";
}
$img->moveTo($targetFile);
if (file_exists($targetFile))
{ {
$this->deleteImage($ID); $this->deleteImage($ID);
// update the database with the new image location // update the database with the new image location
@ -193,7 +179,7 @@ class projectData
if ($stmt->rowCount() > 0) if ($stmt->rowCount() > 0)
{ {
return array("imgLocation" => $targetFile); return array("imgLocation" => $targetFile["imgLocation"]);
} }
return "Couldn't update the database"; return "Couldn't update the database";

View File

@ -113,7 +113,7 @@ class projectRoutes implements routesInterface
{ {
// uh oh sent some empty data // uh oh sent some empty data
$response->getBody()->write(json_encode(array("error" => "Only some of the data was sent"))); $response->getBody()->write(json_encode(array("error" => "Only some of the data was sent")));
return $response->withStatus(400); return $response->withStatus(400)->withStatus(201);
} }
$insertedID = $this->projectData->addProjectData($data["title"], $data["isMainProject"], $data["information"], $data["projectLink"], $data["gitLink"]); $insertedID = $this->projectData->addProjectData($data["title"], $data["isMainProject"], $data["information"], $data["projectLink"], $data["gitLink"]);
@ -125,7 +125,7 @@ class projectRoutes implements routesInterface
} }
$response->getBody()->write(json_encode(array("ID" => $insertedID))); $response->getBody()->write(json_encode(array("ID" => $insertedID)));
return $response; return $response->withStatus(201);
}); });
$app->post("/projectImage/{id}", function (Request $request, Response $response, array $args) $app->post("/projectImage/{id}", function (Request $request, Response $response, array $args)
@ -147,7 +147,7 @@ class projectRoutes implements routesInterface
} }
$response->getBody()->write(json_encode($message)); $response->getBody()->write(json_encode($message));
return $response; return $response->withStatus(201);
}); });
} }
} }

View File

@ -16,7 +16,7 @@ class timelineData
* Get all education data * Get all education data
* @return array - Array of all education data or error message * @return array - Array of all education data or error message
*/ */
function getEduData(): array public function getEduData(): array
{ {
$conn = dbConn(); $conn = dbConn();
$stmt = $conn->prepare("SELECT ID, startPeriod, endPeriod, grade, course FROM edu ORDER BY startPeriod DESC;"); $stmt = $conn->prepare("SELECT ID, startPeriod, endPeriod, grade, course FROM edu ORDER BY startPeriod DESC;");
@ -36,7 +36,7 @@ class timelineData
* Get all work data * Get all work data
* @return array - Array of all work data or error message * @return array - Array of all work data or error message
*/ */
function getWorkData(): array public function getWorkData(): array
{ {
$conn = dbConn(); $conn = dbConn();
$stmt = $conn->prepare("SELECT ID, startPeriod, endPeriod, companyName, area, title FROM work ORDER BY work.startPeriod DESC;"); $stmt = $conn->prepare("SELECT ID, startPeriod, endPeriod, companyName, area, title FROM work ORDER BY work.startPeriod DESC;");
@ -61,7 +61,7 @@ class timelineData
* @param string $id - ID of the education data * @param string $id - ID of the education data
* @return bool - True if successful, false if not * @return bool - True if successful, false if not
*/ */
function updateEduData(string $dateFrom, string $dateTo, string $grade, string $course, string $id): bool public function updateEduData(string $dateFrom, string $dateTo, string $grade, string $course, string $id): bool
{ {
$conn = dbConn(); $conn = dbConn();
$stmt = $conn->prepare("UPDATE edu SET startPeriod = :dateFrom, endPeriod = :dateTo, grade = :grade, course = :course WHERE ID = :id;"); $stmt = $conn->prepare("UPDATE edu SET startPeriod = :dateFrom, endPeriod = :dateTo, grade = :grade, course = :course WHERE ID = :id;");
@ -101,7 +101,7 @@ class timelineData
* @param int $id * @param int $id
* @return bool - True if successful, false if not * @return bool - True if successful, false if not
*/ */
function deleteEduData(int $id): bool public function deleteEduData(int $id): bool
{ {
$conn = dbConn(); $conn = dbConn();
$stmt = $conn->prepare("DELETE FROM edu WHERE ID = :id;"); $stmt = $conn->prepare("DELETE FROM edu WHERE ID = :id;");
@ -130,7 +130,7 @@ class timelineData
* @param string $course - Course * @param string $course - Course
* @return bool|int - ID of the new education data or false if not successful * @return bool|int - ID of the new education data or false if not successful
*/ */
function addEduData(string $dateFrom, string $dateTo, string $grade, string $course): bool|int public function addEduData(string $dateFrom, string $dateTo, string $grade, string $course): bool|int
{ {
$conn = dbConn(); $conn = dbConn();
$stmt = $conn->prepare("INSERT INTO edu (startPeriod, endPeriod, grade, course) VALUES (:dateFrom, :dateTo, :grade, :course);"); $stmt = $conn->prepare("INSERT INTO edu (startPeriod, endPeriod, grade, course) VALUES (:dateFrom, :dateTo, :grade, :course);");
@ -139,7 +139,7 @@ class timelineData
$stmt->bindParam(":grade", $grade); $stmt->bindParam(":grade", $grade);
$stmt->bindParam(":course", $course); $stmt->bindParam(":course", $course);
if($stmt->execute()) if ($stmt->execute())
{ {
return $conn->lastInsertId(); return $conn->lastInsertId();
} }
@ -155,7 +155,7 @@ class timelineData
* @param string $title - Title * @param string $title - Title
* @return bool|int - ID of the new work data if successful, false if not * @return bool|int - ID of the new work data if successful, false if not
*/ */
function addWorkData(string $dateFrom, string $dateTo, string $companyName, string $area, string $title): bool|int public function addWorkData(string $dateFrom, string $dateTo, string $companyName, string $area, string $title): bool|int
{ {
$conn = dbConn(); $conn = dbConn();
$stmt = $conn->prepare("INSERT INTO work (startPeriod, endPeriod, companyName, area, title) VALUES (:dateFrom, :dateTo, :companyName, :area, :title);"); $stmt = $conn->prepare("INSERT INTO work (startPeriod, endPeriod, companyName, area, title) VALUES (:dateFrom, :dateTo, :companyName, :area, :title);");
@ -165,7 +165,7 @@ class timelineData
$stmt->bindParam(":area", $area); $stmt->bindParam(":area", $area);
$stmt->bindParam(":title", $title); $stmt->bindParam(":title", $title);
if($stmt->execute()) if ($stmt->execute())
{ {
return $conn->lastInsertId(); return $conn->lastInsertId();
} }

View File

@ -17,7 +17,7 @@ class userData
* @param $password string - Password * @param $password string - Password
* @return bool - True if logged in, false if not * @return bool - True if logged in, false if not
*/ */
function checkUser(string $username, string $password): bool public function checkUser(string $username, string $password): bool
{ {
$conn = dbConn(); $conn = dbConn();
$stmt = $conn->prepare("SELECT * FROM users WHERE username = :username"); $stmt = $conn->prepare("SELECT * FROM users WHERE username = :username");
@ -43,15 +43,15 @@ class userData
* @param $username string - Username * @param $username string - Username
* @return string - JWT token * @return string - JWT token
*/ */
function createToken(string $username): string public function createToken(string $username): string
{ {
$now = time(); $now = time();
$future = strtotime('+6 hour',$now); $future = strtotime('+6 hour', $now);
$secretKey = getSecretKey(); $secretKey = getSecretKey();
$payload = [ $payload = [
"jti"=>$username, "jti" => $username,
"iat"=>$now, "iat" => $now,
"exp"=>$future "exp" => $future
]; ];
return JWT::encode($payload,$secretKey,"HS256"); return JWT::encode($payload,$secretKey,"HS256");
@ -62,7 +62,7 @@ class userData
* @param string $email - Email to check * @param string $email - Email to check
* @return bool - True if email exists, false if not * @return bool - True if email exists, false if not
*/ */
function checkEmail(string $email): bool public function checkEmail(string $email): bool
{ {
$conn = dbConn(); $conn = dbConn();
$stmt = $conn->prepare("SELECT * FROM users WHERE email = :email"); $stmt = $conn->prepare("SELECT * FROM users WHERE email = :email");
@ -84,7 +84,7 @@ class userData
* @param $email - email address of the userData * @param $email - email address of the userData
* @return string - verification code * @return string - verification code
*/ */
function sendResetEmail($email): string public function sendResetEmail($email): string
{ {
//generate a random token and email the address //generate a random token and email the address
$token = uniqid("rpe-"); $token = uniqid("rpe-");
@ -119,7 +119,7 @@ class userData
* @param $password string Password * @param $password string Password
* @return bool - true if the password was changed, false if not * @return bool - true if the password was changed, false if not
*/ */
function changePassword(string $email, string $password): bool public function changePassword(string $email, string $password): bool
{ {
$conn = dbConn(); $conn = dbConn();
$stmt = $conn->prepare("UPDATE users SET password = :password WHERE email = :email"); $stmt = $conn->prepare("UPDATE users SET password = :password WHERE email = :email");

View File

@ -145,7 +145,7 @@ class userRoutes implements routesInterface
// yay, password changed // yay, password changed
unset($_SESSION["resetToken"]); unset($_SESSION["resetToken"]);
unset($_SESSION["resetEmail"]); unset($_SESSION["resetEmail"]);
return $response; return $response->withStatus(201);
} }
return $response->withStatus(500); return $response->withStatus(500);

43
dist/api/utils/imgUtils.php vendored Normal file
View File

@ -0,0 +1,43 @@
<?php
namespace api\utils;
use Psr\Http\Message\UploadedFileInterface;
class imgUtils
{
/**
* Checks and uploads a file to the given directory
* @param string $targetDir - Directory to upload the file to
* @param UploadedFileInterface $img - File to upload
* @return string|array - String with error message or array with the location of the uploaded file
*/
public function uploadFile(string $targetDir, UploadedFileInterface $img): string|array
{
$targetFile = $targetDir . basename($img->getClientFilename());
$uploadOk = 1;
$imageFileType = strtolower(pathinfo($targetFile, PATHINFO_EXTENSION));
// Check if file already exists
if (file_exists($targetFile))
{
return "The file already exists";
}
// Check file size
if ($img->getSize() > 2000000)
{
return "The file is too large, max 2MB";
}
// Allow certain file formats
if ($imageFileType != "jpg" && $imageFileType != "png" && $imageFileType != "jpeg" && $imageFileType != "gif")
{
return "Only JPG, JPEG, PNG & GIF files are allowed";
}
$img->moveTo($targetFile);
return array("imgLocation" => $targetFile);
}
}

View File

@ -27,7 +27,7 @@ class middleware
* Constructor for middleware * Constructor for middleware
* @param App $app - Slim App * @param App $app - Slim App
*/ */
function __construct(App $app) public function __construct(App $app)
{ {
$this->baseMiddleware($app); $this->baseMiddleware($app);
$this->sameSiteConfig($app); $this->sameSiteConfig($app);
@ -40,7 +40,7 @@ class middleware
* Base middleware * Base middleware
* @param App $app - Slim App * @param App $app - Slim App
*/ */
function baseMiddleware(App $app): void public function baseMiddleware(App $app): void
{ {
$app->addBodyParsingMiddleware(); $app->addBodyParsingMiddleware();
$app->addRoutingMiddleware(); $app->addRoutingMiddleware();
@ -50,7 +50,7 @@ class middleware
* SameSite Cookie Configuration * SameSite Cookie Configuration
* @param App $app - Slim App * @param App $app - Slim App
*/ */
function sameSiteConfig(App $app): void public function sameSiteConfig(App $app): void
{ {
$ssConfig = new SameSiteCookieConfiguration(["same_site" => "strict"]); $ssConfig = new SameSiteCookieConfiguration(["same_site" => "strict"]);
$app->add(new SameSiteCookieMiddleware($ssConfig)); $app->add(new SameSiteCookieMiddleware($ssConfig));
@ -60,7 +60,7 @@ class middleware
* Return all responses as JSON * Return all responses as JSON
* @param App $app - Slim App * @param App $app - Slim App
*/ */
function returnAsJSON(App $app): void public function returnAsJSON(App $app): void
{ {
$app->add(function ($request, $handler) $app->add(function ($request, $handler)
{ {
@ -73,7 +73,7 @@ class middleware
* JWT Authentication * JWT Authentication
* @param App $app - Slim App * @param App $app - Slim App
*/ */
function jwtAuth(App $app): void public function jwtAuth(App $app): void
{ {
$jwtSecret = getSecretKey(); $jwtSecret = getSecretKey();
$app->add(new JwtAuthentication([ $app->add(new JwtAuthentication([
@ -91,13 +91,17 @@ class middleware
{ {
session_destroy(); session_destroy();
$response->getBody()->write(json_encode(array("status" => "401", "message" => $response->getBody()->write(json_encode(array("status" => "401", "message" =>
"Unauthorized, please provide a valid token"))); "Unauthorized, please provide a valid token")));
return $response->withStatus(401); return $response->withStatus(401);
} }
])); ]));
} }
function errorHandling(App $app): void /**
* Error handling
* @param App $app - Slim App
*/
public function errorHandling(App $app): void
{ {
$app->add(function (ServerRequestInterface $request, RequestHandlerInterface $handler) $app->add(function (ServerRequestInterface $request, RequestHandlerInterface $handler)
{ {

BIN
dist/blog/imgs/placeholder.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

View File

@ -1 +1 @@
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title>Blog</title></head><body>this is a test<script src="/blog/index.js"></script></body></html> <!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title>Blog</title></head><body>this is a test<script src="/blog/js/index.js"></script></body></html>

2
dist/css/main.css vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

6
dist/editor/js/CKEditor/ckeditor.js vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1 @@
!function(e){const n=e.af=e.af||{};n.dictionary=Object.assign(n.dictionary||{},{"%0 of %1":"%0 van %1","Align center":"Belyn in die middel","Align left":"Belyn links","Align right":"Belyn regs","Block quote":"Verwysingsaanhaling",Bold:"Vet",Cancel:"Kanselleer",Code:"Bronkode",Find:"Soek","Find and replace":"Soek en vervang","Find in text…":"Soek in teks …","Insert code block":"Voeg bronkodeblok in",Italic:"Kursief",Justify:"Belyn beide kante","Match case":"Hooflettersensitief","Next result":"Volgende resultaat","Plain text":"Gewone skrif","Previous result":"Vorige resultaat","Remove color":"Verwyder kleur","Remove Format":"Verwyder formatering",Replace:"Vervang","Replace all":"Vervang alles","Replace with…":"Vervang met ...","Restore default":"Herstel verstek",Save:"Stoor","Show more items":"Wys meer items","Show options":"Wys opsies",Strikethrough:"Deurstreep",Subscript:"Onderskrif",Superscript:"Boskrif","Text alignment":"Teksbelyning","Text alignment toolbar":"Teksbelyning nutsbank","Text to find must not be empty.":"Soekteks mag nie leeg wees nie.","Tip: Find some text first in order to replace it.":"Wenk: Soek eers 'n bietjie teks om dit te vervang.",Underline:"Onderstreep","Whole words only":"Slegs hele woorde"}),n.getPluralForm=function(e){return 1!=e}}(window.CKEDITOR_TRANSLATIONS||(window.CKEDITOR_TRANSLATIONS={}));

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1 @@
!function(e){const t=e.ast=e.ast||{};t.dictionary=Object.assign(t.dictionary||{},{"%0 of %1":"",Aquamarine:"",Black:"",Blue:"",Bold:"Negrina","Break text":"","Bulleted List":"Llista con viñetes","Bulleted list styles toolbar":"",Cancel:"Encaboxar","Caption for image: %0":"","Caption for the image":"","Centered image":"","Change image text alternative":"",Circle:"",Code:"",Decimal:"","Decimal with leading zero":"","Dim grey":"",Disc:"",Downloadable:"","Dropdown toolbar":"","Edit block":"","Edit link":"","Editor block content toolbar":"","Editor contextual toolbar":"","Editor editing area: %0":"","Editor toolbar":"","Enter image caption":"","Full size image":"Imaxen a tamañu completu",Green:"",Grey:"",HEX:"","Image resize list":"","Image toolbar":"","image widget":"complementu d'imaxen","In line":"",Insert:"","Insert image":"","Insert image via URL":"",Italic:"Cursiva","Left aligned image":"","Light blue":"","Light green":"","Light grey":"",Link:"Enllazar","Link image":"","Link URL":"URL del enllaz","List properties":"","Lower-latin":"","Lowerroman":"",Next:"","Numbered List":"Llista numberada","Numbered list styles toolbar":"","Open in a new tab":"","Open link in new tab":"",Orange:"",Original:"",Previous:"",Purple:"",Red:"",Redo:"Refacer","Remove color":"","Resize image":"","Resize image to %0":"","Resize image to the original size":"","Restore default":"","Reversed order":"","Rich Text Editor":"Editor de testu arriquecíu","Right aligned image":"",Save:"Guardar","Show more items":"","Side image":"Imaxen llateral",Square:"","Start at":"","Start index must be greater than 0.":"",Strikethrough:"",Subscript:"",Superscript:"","Text alternative":"","This link has no URL":"","To-do List":"","Toggle the circle list style":"","Toggle the decimal list style":"","Toggle the decimal with leading zero list style":"","Toggle the disc list style":"","Toggle the lowerlatin list style":"","Toggle the lowerroman list style":"","Toggle the square list style":"","Toggle the upperlatin list style":"","Toggle the upperroman list style":"",Turquoise:"",Underline:"",Undo:"Desfacer",Unlink:"Desenllazar",Update:"","Update image URL":"","Upload failed":"","Upper-latin":"","Upper-roman":"",White:"","Wrap text":"",Yellow:""}),t.getPluralForm=function(e){return 1!=e}}(window.CKEDITOR_TRANSLATIONS||(window.CKEDITOR_TRANSLATIONS={}));

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1 @@
!function(e){const i=e.bs=e.bs||{};i.dictionary=Object.assign(i.dictionary||{},{"%0 of %1":"%0 od %1",Accept:"","Align center":"Centrirati","Align left":"Lijevo poravnanje","Align right":"Desno poravnanje",Big:"","Block quote":"Citat",Bold:"Podebljano","Break text":"",Cancel:"Poništi","Caption for image: %0":"","Caption for the image":"","Centered image":"Centrirana slika","Change image text alternative":"Promijeni ALT atribut za sliku","Choose heading":"Odaberi naslov",Code:"Kod",Default:"Zadani","Document colors":"","Edit source":"Uredi izvor","Empty snippet content":"HTML odlomak nema sadžaj","Enter image caption":"Unesi naziv slike",Find:"Pronađi","Find and replace":"Pronađi i zamijeni","Find in text…":"Pronađi u tekstu","Font Background Color":"Boja pozadine","Font Color":"Boja","Font Family":"Font","Font Size":"Veličina fonta","Full size image":"",Heading:"Naslov","Heading 1":"Naslov 1","Heading 2":"Naslov 2","Heading 3":"Naslov 3","Heading 4":"Naslov 4","Heading 5":"Naslov 5","Heading 6":"Naslov 6","Horizontal line":"Horizontalna linija","HTML snippet":"HTML odlomak",Huge:"","Image resize list":"Lista veličina slike","Image toolbar":"","image widget":"","In line":"",Insert:"Umetni","Insert code block":"Umetni kod blok","Insert HTML":"Umetni HTML","Insert image":"Umetni sliku","Insert image via URL":"Umetni sliku preko URLa",Italic:"Zakrivljeno",Justify:"","Left aligned image":"Lijevo poravnata slika","Match case":"Podudaranje","Next result":"","No preview available":"Pregled nedostupan",Original:"Original",Paragraph:"Paragraf","Paste raw HTML here...":"Zalijepi HTML ovdje...","Plain text":"Tekst","Previous result":"Prethodni rezultat","Remove color":"Ukloni boju",Replace:"Zamijeni","Replace all":"Zamijeni sve","Replace with…":"Zamijeni sa...","Resize image":"Promijeni veličinu slike","Resize image to %0":"","Resize image to the original size":"Postavi originalnu veličinu slike","Restore default":"Vrati na zadano","Right aligned image":"Desno poravnata slika",Save:"Sačuvaj","Save changes":"Sačuvaj izmjene","Show more items":"Prikaži više stavki","Show options":"Prikaži opcije","Side image":"",Small:"",Strikethrough:"Precrtano",Subscript:"",Superscript:"","Text alignment":"Poravnanje teksta","Text alignment toolbar":"Traka za poravnanje teksta","Text alternative":"ALT atribut","Text to find must not be empty.":"Unesite tekst za pretragu.",Tiny:"","Tip: Find some text first in order to replace it.":"","Type or paste your content here.":"Unesite ili zalijepite vaš sadržaj ovdje","Type your title":"Unesite naslov",Underline:"Podcrtano",Update:"Ažuriraj","Update image URL":"Ažuriraj URL slike","Upload failed":"Učitavanje slike nije uspjelo","Whole words only":"Samo cijele riječi","Wrap text":"Prelomi tekst"}),i.getPluralForm=function(e){return e%10==1&&e%100!=11?0:e%10>=2&&e%10<=4&&(e%100<10||e%100>=20)?1:2}}(window.CKEDITOR_TRANSLATIONS||(window.CKEDITOR_TRANSLATIONS={}));

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1 @@
!function(e){const i=e.eo=e.eo||{};i.dictionary=Object.assign(i.dictionary||{},{"%0 of %1":"",Aquamarine:"",Black:"",Blue:"",Bold:"grasa","Break text":"","Bulleted List":"Bula Listo","Bulleted list styles toolbar":"",Cancel:"Nuligi","Caption for image: %0":"","Caption for the image":"","Centered image":"","Change image text alternative":"Ŝanĝu la alternativan tekston de la bildo","Choose heading":"Elektu ĉapon",Circle:"",Code:"",Decimal:"","Decimal with leading zero":"","Dim grey":"",Disc:"",Downloadable:"","Dropdown toolbar":"","Edit block":"","Edit link":"","Editor block content toolbar":"","Editor contextual toolbar":"","Editor editing area: %0":"","Editor toolbar":"","Enter image caption":"Skribu klarigon pri la bildo","Full size image":"Bildo kun reala dimensio",Green:"",Grey:"",Heading:"Ĉapo","Heading 1":"Ĉapo 1","Heading 2":"Ĉapo 2","Heading 3":"Ĉapo 3","Heading 4":"","Heading 5":"","Heading 6":"",HEX:"","Image resize list":"","Image toolbar":"","image widget":"bilda fenestraĵo","In line":"",Insert:"","Insert image":"Enmetu bildon","Insert image via URL":"",Italic:"kursiva","Left aligned image":"","Light blue":"","Light green":"","Light grey":"",Link:"Ligilo","Link image":"","Link URL":"URL de la ligilo","List properties":"","Lower-latin":"","Lowerroman":"",Next:"","Numbered List":"Numerita Listo","Numbered list styles toolbar":"","Open in a new tab":"","Open link in new tab":"",Orange:"",Original:"",Paragraph:"Paragrafo",Previous:"",Purple:"",Red:"",Redo:"Refari","Remove color":"","Resize image":"","Resize image to %0":"","Resize image to the original size":"","Restore default":"","Reversed order":"","Rich Text Editor":"Redaktilo de Riĉa Teksto","Right aligned image":"",Save:"Konservi","Show more items":"","Side image":"Flanka biildo",Square:"","Start at":"","Start index must be greater than 0.":"",Strikethrough:"",Subscript:"",Superscript:"","Text alternative":"Alternativa teksto","This link has no URL":"","To-do List":"","Toggle the circle list style":"","Toggle the decimal list style":"","Toggle the decimal with leading zero list style":"","Toggle the disc list style":"","Toggle the lowerlatin list style":"","Toggle the lowerroman list style":"","Toggle the square list style":"","Toggle the upperlatin list style":"","Toggle the upperroman list style":"",Turquoise:"","Type or paste your content here.":"","Type your title":"",Underline:"",Undo:"Malfari",Unlink:"Malligi",Update:"","Update image URL":"","Upload failed":"","Upper-latin":"","Upper-roman":"",White:"","Wrap text":"",Yellow:""}),i.getPluralForm=function(e){return 1!=e}}(window.CKEDITOR_TRANSLATIONS||(window.CKEDITOR_TRANSLATIONS={}));

View File

@ -0,0 +1 @@
!function(e){const r=e["es-co"]=e["es-co"]||{};r.dictionary=Object.assign(r.dictionary||{},{"%0 of %1":"%0 de %1","Align center":"Centrar","Align left":"Alinear a la izquierda","Align right":"Alinear a la derecha","Block quote":"Cita de bloque",Bold:"Negrita",Cancel:"Cancelar","Characters: %0":"Caracteres: %0",Code:"Código","Insert code block":"Insertar bloque de código",Italic:"Cursiva",Justify:"Justificar","Plain text":"Texto plano","Remove color":"Quitar color","Restore default":"Restaurar valores predeterminados",Save:"Guardar","Show more items":"Mostrar más elementos",Strikethrough:"Tachado",Subscript:"Subíndice",Superscript:"Superíndice","Text alignment":"Alineación de texto","Text alignment toolbar":"Herramientas de alineación de texto",Underline:"Subrayado","Upload in progress":"Carga en progreso","Words: %0":"Palabras: %0"}),r.getPluralForm=function(e){return 1==e?0:0!=e&&e%1e6==0?1:2}}(window.CKEDITOR_TRANSLATIONS||(window.CKEDITOR_TRANSLATIONS={}));

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1 @@
!function(e){const t=e.eu=e.eu||{};t.dictionary=Object.assign(t.dictionary||{},{"%0 of %1":"",Aquamarine:"",Black:"","Block quote":"Aipua",Blue:"",Bold:"Lodia","Break text":"","Bulleted List":"Buletdun zerrenda","Bulleted list styles toolbar":"",Cancel:"Utzi","Caption for image: %0":"","Caption for the image":"","Centered image":"Zentratutako irudia","Change image text alternative":"Aldatu irudiaren ordezko testua","Choose heading":"Aukeratu izenburua",Circle:"",Code:"Kodea",Decimal:"","Decimal with leading zero":"","Dim grey":"",Disc:"",Downloadable:"","Dropdown toolbar":"","Edit block":"","Edit link":"","Editor block content toolbar":"","Editor contextual toolbar":"","Editor editing area: %0":"","Editor toolbar":"","Enter image caption":"Sartu irudiaren epigrafea","Full size image":"Tamaina osoko irudia",Green:"",Grey:"",Heading:"Izenburua","Heading 1":"Izenburua 1","Heading 2":"Izenburua 2","Heading 3":"Izenburua 3","Heading 4":"","Heading 5":"","Heading 6":"",HEX:"","Image resize list":"","Image toolbar":"","image widget":"irudi widgeta","In line":"",Insert:"","Insert image":"Txertatu irudia","Insert image via URL":"",Italic:"Etzana","Left aligned image":"Ezkerrean lerrokatutako irudia","Light blue":"","Light green":"","Light grey":"",Link:"Esteka","Link image":"","Link URL":"Estekaren URLa","List properties":"","Lower-latin":"","Lowerroman":"",Next:"","Numbered List":"Zenbakidun zerrenda","Numbered list styles toolbar":"","Open in a new tab":"","Open link in new tab":"",Orange:"",Original:"",Paragraph:"Paragrafoa",Previous:"",Purple:"",Red:"",Redo:"Berregin","Remove color":"","Resize image":"","Resize image to %0":"","Resize image to the original size":"","Restore default":"","Reversed order":"","Rich Text Editor":"Testu aberastuaren editorea","Right aligned image":"Eskuinean lerrokatutako irudia",Save:"Gorde","Show more items":"","Side image":"Alboko irudia",Square:"","Start at":"","Start index must be greater than 0.":"",Strikethrough:"",Subscript:"",Superscript:"","Text alternative":"Ordezko testua","This link has no URL":"","To-do List":"","Toggle the circle list style":"","Toggle the decimal list style":"","Toggle the decimal with leading zero list style":"","Toggle the disc list style":"","Toggle the lowerlatin list style":"","Toggle the lowerroman list style":"","Toggle the square list style":"","Toggle the upperlatin list style":"","Toggle the upperroman list style":"",Turquoise:"","Type or paste your content here.":"","Type your title":"",Underline:"Azpimarra",Undo:"Desegin",Unlink:"Desestekatu",Update:"","Update image URL":"","Upload failed":"Kargatzeak huts egin du","Upper-latin":"","Upper-roman":"",White:"","Wrap text":"",Yellow:""}),t.getPluralForm=function(e){return 1!=e}}(window.CKEDITOR_TRANSLATIONS||(window.CKEDITOR_TRANSLATIONS={}));

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1 @@
!function(o){const e=o.gu=o.gu||{};e.dictionary=Object.assign(e.dictionary||{},{"%0 of %1":"","Block quote":" વિચાર ટાંકો",Bold:"ઘાટુ - બોલ્ડ્",Cancel:"",Code:"",Italic:"ત્રાંસુ - ઇટલિક્","Remove color":"","Restore default":"",Save:"","Show more items":"",Strikethrough:"",Subscript:"",Superscript:"",Underline:"નીચે લિટી - અન્ડરલાઇન્"}),e.getPluralForm=function(o){return 1!=o}}(window.CKEDITOR_TRANSLATIONS||(window.CKEDITOR_TRANSLATIONS={}));

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1 @@
!function(e){const a=e.jv=e.jv||{};a.dictionary=Object.assign(a.dictionary||{},{"%0 of %1":"%0 saking %1",Accept:"","Align center":"Rata tengah","Align left":"Rata kiwa","Align right":"Rata tengen",Big:"Ageng","Blue marker":"Penandha biru",Bold:"Kandhel","Break text":"","Bulleted List":"","Bulleted list styles toolbar":"",Cancel:"Batal","Caption for image: %0":"","Caption for the image":"","Centered image":"Gambar ing tengah","Change image text alternative":"","Choose heading":"","Choose language":"Pilih basa",Circle:"Bunder",Code:"Kode",Decimal:"","Decimal with leading zero":"",Default:"Default",Disc:"Kaset","Document colors":"Warni dokumen","Edit source":"","Empty snippet content":"","Enter image caption":"",Find:"Pados","Find and replace":"Pados lan gantos","Find in text…":"Pados ing seratan","Font Background Color":"Warni Latar Aksara","Font Color":"Warni aksara","Font Family":"Jinising Aksara","Font Size":"Ukuran aksara","Full size image":"Gambar ukuran kebak","Green marker":"Panandha ijem","Green pen":"Pen ijem",Heading:"","Heading 1":"","Heading 2":"","Heading 3":"","Heading 4":"","Heading 5":"","Heading 6":"",Highlight:"Sorot","Horizontal line":"Garis horisontal","HTML object":"Obyek HTML","HTML snippet":"",Huge:"Langkung ageng","Image resize list":"","Image toolbar":"","image widget":"","In line":"",Insert:"Tambah","Insert code block":"","Insert HTML":"Tambahaken HTML","Insert image":"Tambahaken gambar","Insert image via URL":"Tambah gambar saking URL",Italic:"Miring",Justify:"Rata kiwa tengen",Language:"Basa","Left aligned image":"Gambar ing kiwa","List properties":"","Lower-latin":"","Lowerroman":"","Match case":"Samikaken aksara","Next result":"Kasil salajengipun","No preview available":"","Numbered List":"","Numbered list styles toolbar":"",Original:"Asli",Paragraph:"","Paste raw HTML here...":"","Pink marker":"Penandha abrit jambon","Plain text":"Seratan biasa","Previous result":"Kasil saderengipun","Red pen":"Penandha abrit","Remove color":"Busek warni","Remove highlight":"Busek sorot","Remove language":"Busek basa",Replace:"Gantos","Replace all":"Gantos sedaya","Replace with…":"Gantos kaliyan...","Resize image":"","Resize image to %0":"","Resize image to the original size":"","Restore default":"Mangsulaken default","Reversed order":"Dipunwangsul","Right aligned image":"Gambar ing tengen",Save:"Rimat","Save changes":"","Show more items":"Tampilaken langkung kathah","Show options":"Tampilaken pilihan","Side image":"",Small:"Alit",Square:"Kotak","Start at":"Wiwit saking","Start index must be greater than 0.":"",Strikethrough:"Seratan dicoret",Subscript:"",Superscript:"","Text alignment":"Perataan seratan","Text alignment toolbar":"","Text alternative":"","Text highlight toolbar":"","Text to find must not be empty.":"Seratan ingkang dipunpadosi mboten angsal kosong.",Tiny:"Langkung alit","Tip: Find some text first in order to replace it.":"","To-do List":"","Toggle the circle list style":"","Toggle the decimal list style":"","Toggle the decimal with leading zero list style":"","Toggle the disc list style":"","Toggle the lowerlatin list style":"","Toggle the lowerroman list style":"","Toggle the square list style":"","Toggle the upperlatin list style":"","Toggle the upperroman list style":"","Type or paste your content here.":"Serataken utawi nyukani babagan ing ngriki","Type your title":"Serataken irah-irahan",Underline:"Garis ngandhap",Update:"","Update image URL":"","Upload failed":"","Upper-latin":"","Upper-roman":"","Whole words only":"Sedayaning ukanten","Wrap text":"","Yellow marker":"Panandha jene"}),a.getPluralForm=function(e){return 0}}(window.CKEDITOR_TRANSLATIONS||(window.CKEDITOR_TRANSLATIONS={}));

View File

@ -0,0 +1 @@
!function(n){const t=n.kk=n.kk||{};t.dictionary=Object.assign(t.dictionary||{},{"Align center":"Ортадан туралау","Align left":"Солға туралау","Align right":"Оңға туралау",Justify:"","Text alignment":"Мәтінді туралау","Text alignment toolbar":"Мәтінді туралау құралдар тақтасы"}),t.getPluralForm=function(n){return 1!=n}}(window.CKEDITOR_TRANSLATIONS||(window.CKEDITOR_TRANSLATIONS={}));

View File

@ -0,0 +1 @@
!function(e){const t=e.km=e.km||{};t.dictionary=Object.assign(t.dictionary||{},{"%0 of %1":"","Align center":"តម្រឹម​កណ្ដាល","Align left":"តម្រឹម​ឆ្វេង","Align right":"តម្រឹម​ស្ដាំ",Aquamarine:"",Black:"","Block quote":"ប្លុក​ពាក្យ​សម្រង់",Blue:"",Bold:"ដិត","Break text":"","Bulleted List":"បញ្ជី​ជា​ចំណុច","Bulleted list styles toolbar":"",Cancel:"បោះបង់","Caption for image: %0":"","Caption for the image":"","Centered image":"","Change image text alternative":"","Choose heading":"ជ្រើសរើស​ក្បាលអត្ថបទ",Circle:"",Code:"កូដ",Decimal:"","Decimal with leading zero":"","Dim grey":"",Disc:"",Downloadable:"","Dropdown toolbar":"","Edit block":"","Edit link":"","Editor block content toolbar":"","Editor contextual toolbar":"","Editor editing area: %0":"","Editor toolbar":"","Enter image caption":"បញ្ចូល​ពាក្យ​ពណ៌នា​រូបភាព","Full size image":"រូបភាព​ពេញ​ទំហំ",Green:"",Grey:"",Heading:"ក្បាលអត្ថបទ","Heading 1":"ក្បាលអត្ថបទ 1","Heading 2":"ក្បាលអត្ថបទ 2","Heading 3":"ក្បាលអត្ថបទ 3","Heading 4":"","Heading 5":"","Heading 6":"",HEX:"","Image resize list":"","Image toolbar":"","image widget":"វិដជិត​រូបភាព","In line":"",Insert:"","Insert image":"បញ្ចូល​រូបភាព","Insert image via URL":"",Italic:"ទ្រេត",Justify:"តម្រឹម​សងខាង","Left aligned image":"","Light blue":"","Light green":"","Light grey":"",Link:"តំណ","Link image":"","Link URL":"URL តំណ","List properties":"","Lower-latin":"","Lowerroman":"",Next:"","Numbered List":"បញ្ជី​ជា​លេខ","Numbered list styles toolbar":"","Open in a new tab":"","Open link in new tab":"",Orange:"",Original:"",Paragraph:"កថាខណ្ឌ",Previous:"",Purple:"",Red:"",Redo:"ធ្វើ​វិញ","Remove color":"","Resize image":"","Resize image to %0":"","Resize image to the original size":"","Restore default":"","Reversed order":"","Rich Text Editor":"កម្មវិធី​កែសម្រួល​អត្ថបទ​សម្បូរបែប","Right aligned image":"",Save:"រក្សាទុ","Show more items":"","Side image":"រូបភាព​នៅ​ខាង",Square:"","Start at":"","Start index must be greater than 0.":"",Strikethrough:"ឆូតកណ្ដាល",Subscript:"អក្សរ​តូចក្រោម",Superscript:"អក្សរ​តូចលើ","Text alignment":"ការ​តម្រឹម​អក្សរ","Text alignment toolbar":"របារ​ឧបករណ៍​តម្រឹម​អក្សរ","Text alternative":"","This link has no URL":"","To-do List":"","Toggle the circle list style":"","Toggle the decimal list style":"","Toggle the decimal with leading zero list style":"","Toggle the disc list style":"","Toggle the lowerlatin list style":"","Toggle the lowerroman list style":"","Toggle the square list style":"","Toggle the upperlatin list style":"","Toggle the upperroman list style":"",Turquoise:"","Type or paste your content here.":"","Type your title":"",Underline:"គូស​បន្ទាត់​ក្រោម",Undo:"លែង​ធ្វើ​វិញ",Unlink:"ផ្ដាច់​តំណ",Update:"","Update image URL":"","Upload failed":"អាប់ឡូត​មិនបាន","Upper-latin":"","Upper-roman":"",White:"","Wrap text":"",Yellow:""}),t.getPluralForm=function(e){return 0}}(window.CKEDITOR_TRANSLATIONS||(window.CKEDITOR_TRANSLATIONS={}));

View File

@ -0,0 +1 @@
!function(e){const t=e.kn=e.kn||{};t.dictionary=Object.assign(t.dictionary||{},{"%0 of %1":"",Aquamarine:"",Black:"","Block quote":"‍‍‍‍ಗುರುತಿಸಲಾದ ‍‍ಉಲ್ಲೇಖ",Blue:"",Bold:"‍‍ದಪ್ಪ","Break text":"","Bulleted List":"‍‍ಬುಲೆಟ್ ಪಟ್ಟಿ","Bulleted list styles toolbar":"",Cancel:"ರದ್ದುಮಾಡು","Caption for image: %0":"","Caption for the image":"","Centered image":"","Change image text alternative":"‍ಚಿತ್ರದ ಬದಲಿ ಪಠ್ಯ ಬದಲಾಯಿಸು","Choose heading":"ಶೀರ್ಷಿಕೆ ಆಯ್ಕೆಮಾಡು",Circle:"",Code:"",Decimal:"","Decimal with leading zero":"","Dim grey":"",Disc:"",Downloadable:"","Dropdown toolbar":"","Edit block":"","Edit link":"","Editor block content toolbar":"","Editor contextual toolbar":"","Editor editing area: %0":"","Editor toolbar":"","Enter image caption":"‍ಚಿತ್ರದ ಶೀರ್ಷಿಕೆ ಸೇರಿಸು","Full size image":"‍ಪೂರ್ಣ ‍‍ಅಳತೆಯ ಚಿತ್ರ",Green:"",Grey:"",Heading:"ಶೀರ್ಷಿಕೆ","Heading 1":"ಶೀರ್ಷಿಕೆ 1","Heading 2":"ಶೀರ್ಷಿಕೆ 2","Heading 3":"ಶೀರ್ಷಿಕೆ 3","Heading 4":"","Heading 5":"","Heading 6":"",HEX:"","Image resize list":"","Image toolbar":"","image widget":"‍ಚಿತ್ರ ವಿಜೆಟ್","In line":"",Insert:"","Insert image":"","Insert image via URL":"",Italic:"‍ಇಟಾಲಿಕ್","Left aligned image":"","Light blue":"","Light green":"","Light grey":"",Link:"‍ಕೊಂಡಿ","Link image":"","Link URL":"‍ಕೊಂಡಿ ಸಂಪರ್ಕಿಸು","List properties":"","Lower-latin":"","Lowerroman":"",Next:"","Numbered List":"‍ಸಂಖ್ಯೆಯ ಪಟ್ಟಿ‍","Numbered list styles toolbar":"","Open in a new tab":"","Open link in new tab":"",Orange:"",Original:"",Paragraph:"ಪ್ಯಾರಾಗ್ರಾಫ್",Previous:"",Purple:"",Red:"",Redo:"‍ಮತ್ತೆ ಮಾಡು","Remove color":"","Resize image":"","Resize image to %0":"","Resize image to the original size":"","Restore default":"","Reversed order":"","Rich Text Editor":"‍ಸಮೃದ್ಧ ಪಠ್ಯ ಸಂಪಾದಕ‍‍","Right aligned image":"",Save:"ಉಳಿಸು","Show more items":"","Side image":"‍ಪಕ್ಕದ ಚಿತ್ರ",Square:"","Start at":"","Start index must be greater than 0.":"",Strikethrough:"",Subscript:"",Superscript:"","Text alternative":"‍ಪಠ್ಯದ ಬದಲಿ","This link has no URL":"","To-do List":"","Toggle the circle list style":"","Toggle the decimal list style":"","Toggle the decimal with leading zero list style":"","Toggle the disc list style":"","Toggle the lowerlatin list style":"","Toggle the lowerroman list style":"","Toggle the square list style":"","Toggle the upperlatin list style":"","Toggle the upperroman list style":"",Turquoise:"","Type or paste your content here.":"","Type your title":"",Underline:"",Undo:"‍‍ರದ್ದು",Unlink:"‍ಕೊಂಡಿ ತೆಗೆ",Update:"","Update image URL":"","Upload failed":"","Upper-latin":"","Upper-roman":"",White:"","Wrap text":"",Yellow:""}),t.getPluralForm=function(e){return e>1}}(window.CKEDITOR_TRANSLATIONS||(window.CKEDITOR_TRANSLATIONS={}));

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1 @@
!function(o){const r=o.oc=o.oc||{};r.dictionary=Object.assign(r.dictionary||{},{"%0 of %1":"",Bold:"Gras",Cancel:"Anullar",Code:"",Italic:"Italica","Remove color":"","Restore default":"",Save:"Enregistrar","Show more items":"",Strikethrough:"",Subscript:"",Superscript:"",Underline:""}),r.getPluralForm=function(o){return o>1}}(window.CKEDITOR_TRANSLATIONS||(window.CKEDITOR_TRANSLATIONS={}));

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1 @@
!function(e){const t=e.si=e.si||{};t.dictionary=Object.assign(t.dictionary||{},{"%0 of %1":"",Bold:"තදකුරු","Break text":"","Bulleted List":"බුලටිත ලැයිස්තුව","Bulleted list styles toolbar":"",Cancel:"","Caption for image: %0":"","Caption for the image":"","Centered image":"","Change image text alternative":"",Circle:"",Code:"",Decimal:"","Decimal with leading zero":"",Disc:"","Enter image caption":"","Full size image":"","Image resize list":"","Image toolbar":"","image widget":"","In line":"",Insert:"","Insert image":"පින්තූරය ඇතුල් කරන්න","Insert image via URL":"",Italic:"ඇලකුරු","Left aligned image":"","List properties":"","Lower-latin":"","Lowerroman":"","Numbered List":"අංකිත ලැයිස්තුව","Numbered list styles toolbar":"",Original:"",Redo:"නැවත කරන්න","Remove color":"","Resize image":"","Resize image to %0":"","Resize image to the original size":"","Restore default":"","Reversed order":"","Right aligned image":"",Save:"","Show more items":"","Side image":"",Square:"","Start at":"","Start index must be greater than 0.":"",Strikethrough:"",Subscript:"",Superscript:"","Text alternative":"","To-do List":"","Toggle the circle list style":"","Toggle the decimal list style":"","Toggle the decimal with leading zero list style":"","Toggle the disc list style":"","Toggle the lowerlatin list style":"","Toggle the lowerroman list style":"","Toggle the square list style":"","Toggle the upperlatin list style":"","Toggle the upperroman list style":"",Underline:"",Undo:"අහෝසි කරන්න",Update:"","Update image URL":"","Upload failed":"උඩුගත කිරීම අසාර්ථක විය","Upper-latin":"","Upper-roman":"","Wrap text":""}),t.getPluralForm=function(e){return 1!=e}}(window.CKEDITOR_TRANSLATIONS||(window.CKEDITOR_TRANSLATIONS={}));

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1 @@
!function(e){const o=e.sl=e.sl||{};o.dictionary=Object.assign(o.dictionary||{},{"%0 of %1":"",Accept:"","Align cell text to the bottom":"","Align cell text to the center":"","Align cell text to the left":"","Align cell text to the middle":"","Align cell text to the right":"","Align cell text to the top":"","Align center":"Sredinska poravnava","Align left":"Poravnava levo","Align right":"Poravnava desno","Align table to the left":"","Align table to the right":"",Alignment:"",Aquamarine:"Akvamarin",Background:"",Big:"Veliko",Black:"Črna","Block quote":"Blokiraj citat",Blue:"Modra","Blue marker":"Modra oznaka",Bold:"Krepko",Border:"",Cancel:"Prekliči","Cell properties":"","Center table":"","Choose heading":"Izberi naslov",Code:"Koda",Color:"","Color picker":"",Column:"",Dashed:"",Default:"Privzeto","Delete column":"","Delete row":"","Dim grey":"Temno siva",Dimensions:"","Document colors":"Barve dokumenta",Dotted:"",Double:"","Dropdown toolbar":"","Edit block":"","Edit source":"Uredi izvorno kodo","Editor block content toolbar":"","Editor contextual toolbar":"","Editor editing area: %0":"","Editor toolbar":"","Empty snippet content":"","Enter table caption":"","Font Background Color":"Barva ozadja pisave","Font Color":"Barva pisave","Font Family":"Vrsta oz. tip pisave","Font Size":"Velikost pisave",Green:"Zelena","Green marker":"Zelena oznaka","Green pen":"Zeleno pisalo",Grey:"Siva",Groove:"","Header column":"","Header row":"",Heading:"Naslov","Heading 1":"Naslov 1","Heading 2":"Naslov 2","Heading 3":"Naslov 3","Heading 4":"Naslov 4","Heading 5":"Naslov 5","Heading 6":"Naslov 6",Height:"",HEX:"",Highlight:"Označi","Horizontal line":"Vodoravna črta","Horizontal text alignment toolbar":"","HTML snippet":"HTML izsek",Huge:"Ogromno","Insert column left":"","Insert column right":"","Insert HTML":"Vstavi HTML","Insert row above":"","Insert row below":"","Insert table":"Vstavi tabelo",Inset:"",Italic:"Poševno",Justify:"Postavi na sredino","Justify cell text":"","Light blue":"Svetlo modra","Light green":"Svetlo zelena","Light grey":"Svetlo siva","Merge cell down":"","Merge cell left":"","Merge cell right":"","Merge cell up":"","Merge cells":"",Next:"","No preview available":"",None:"",Orange:"Oranžna",Outset:"",Padding:"",Paragraph:"Odstavek","Paste raw HTML here...":"Prilepi HTML kodo ...","Pink marker":"Rožnata oznaka",Previous:"",Purple:"Vijolična",Red:"Rdeča","Red pen":"Rdeče pisalo","Remove color":"Odstrani barvo","Remove highlight":"Odstrani oznako","Restore default":"","Rich Text Editor":"",Ridge:"",Row:"",Save:"Shrani","Save changes":"Shrani spremembe","Select column":"","Select row":"","Show more items":"",Small:"Majhna",Solid:"","Split cell horizontally":"","Split cell vertically":"",Strikethrough:"Prečrtano",Style:"",Subscript:"Naročnik",Superscript:"Nadpis","Table alignment toolbar":"","Table cell text alignment":"","Table properties":"","Table toolbar":"","Text alignment":"Poravnava besedila","Text alignment toolbar":"Orodna vrstica besedila","Text highlight toolbar":"Orodna vrstica označevanja",'The color is invalid. Try "#FF0000" or "rgb(255,0,0)" or "red".':"",'The value is invalid. Try "10px" or "2em" or simply "2".':"",Tiny:"Drobna","Toggle caption off":"","Toggle caption on":"",Turquoise:"Turkizna","Type or paste your content here.":"Vnesi ali prilepi vsebino","Type your title":"Vnesi naslov",Underline:"Podčrtaj","Vertical text alignment toolbar":"",White:"Bela",Width:"",Yellow:"Rumena","Yellow marker":"Rumena oznaka"}),o.getPluralForm=function(e){return e%100==1?0:e%100==2?1:e%100==3||e%100==4?2:3}}(window.CKEDITOR_TRANSLATIONS||(window.CKEDITOR_TRANSLATIONS={}));

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1 @@
!function(e){const t=e.tt=e.tt||{};t.dictionary=Object.assign(t.dictionary||{},{"%0 of %1":"","Align cell text to the bottom":"","Align cell text to the center":"","Align cell text to the left":"","Align cell text to the middle":"","Align cell text to the right":"","Align cell text to the top":"","Align table to the left":"","Align table to the right":"",Alignment:"",Aquamarine:"Аквамарин",Background:"",Black:"Кара",Blue:"Зәңгәр",Bold:"Калын",Border:"","Break text":"","Bulleted List":"","Bulleted list styles toolbar":"",Cancel:"Баш тарт","Caption for image: %0":"","Caption for the image":"","Cell properties":"","Center table":"","Centered image":"","Change image text alternative":"","Choose language":"",Circle:"Түгәрәк",Code:"Код",Color:"Төс","Color picker":"",Column:"",Dashed:"",Decimal:"","Decimal with leading zero":"","Delete column":"","Delete row":"","Dim grey":"",Dimensions:"",Disc:"Диск",Dotted:"",Double:"",Downloadable:"","Dropdown toolbar":"","Edit block":"","Edit link":"","Editor block content toolbar":"","Editor contextual toolbar":"","Editor editing area: %0":"","Editor toolbar":"","Enter image caption":"","Enter table caption":"",Find:"Таб","Find and replace":"","Find in text…":"Текстта таб...","Full size image":"",Green:"Яшел",Grey:"Соры",Groove:"","Header column":"","Header row":"",Height:"",HEX:"","Horizontal text alignment toolbar":"","Image resize list":"","Image toolbar":"","image widget":"","In line":"",Insert:"","Insert column left":"","Insert column right":"","Insert image":"","Insert image via URL":"","Insert row above":"","Insert row below":"","Insert table":"",Inset:"",Italic:"","Justify cell text":"",Language:"Тел","Left aligned image":"","Light blue":"Ачык зәңгәр","Light green":"Ачык яшел","Light grey":"Ачык соры",Link:"Сылтама","Link image":"","Link URL":"","List properties":"","Lower-latin":"","Lowerroman":"","Match case":"","Merge cell down":"","Merge cell left":"","Merge cell right":"","Merge cell up":"","Merge cells":"",Next:"","Next result":"",None:"","Numbered List":"","Numbered list styles toolbar":"","Open in a new tab":"","Open link in new tab":"",Orange:"Кызгылт",Original:"",Outset:"",Padding:"",Previous:"","Previous result":"",Purple:"Шәмәхә",Red:"Кызыл",Redo:"Кабатла","Remove color":"","Remove language":"",Replace:"","Replace all":"","Replace with…":"","Resize image":"","Resize image to %0":"","Resize image to the original size":"","Restore default":"","Reversed order":"","Rich Text Editor":"",Ridge:"","Right aligned image":"",Row:"",Save:"Сакла","Select column":"","Select row":"","Show more items":"","Show options":"","Side image":"",Solid:"","Split cell horizontally":"","Split cell vertically":"",Square:"","Start at":"","Start index must be greater than 0.":"",Strikethrough:"",Style:"",Subscript:"",Superscript:"","Table alignment toolbar":"","Table cell text alignment":"","Table properties":"","Table toolbar":"","Text alternative":"","Text to find must not be empty.":"",'The color is invalid. Try "#FF0000" or "rgb(255,0,0)" or "red".':"",'The value is invalid. Try "10px" or "2em" or simply "2".':"","This link has no URL":"","Tip: Find some text first in order to replace it.":"","To-do List":"","Toggle caption off":"","Toggle caption on":"","Toggle the circle list style":"","Toggle the decimal list style":"","Toggle the decimal with leading zero list style":"","Toggle the disc list style":"","Toggle the lowerlatin list style":"","Toggle the lowerroman list style":"","Toggle the square list style":"","Toggle the upperlatin list style":"","Toggle the upperroman list style":"",Turquoise:"Фервоз",Underline:"",Undo:"",Unlink:"",Update:"Яңарт","Update image URL":"","Upload failed":"","Upper-latin":"","Upper-roman":"","Vertical text alignment toolbar":"",White:"Ак","Whole words only":"",Width:"","Wrap text":"",Yellow:"Сары"}),t.getPluralForm=function(e){return 0}}(window.CKEDITOR_TRANSLATIONS||(window.CKEDITOR_TRANSLATIONS={}));

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1 +0,0 @@
function showErrorMessage(e){document.querySelector("#loginError").classList.remove("hidden"),document.querySelector("#loginError div").innerText=e}document.addEventListener("DOMContentLoaded",(e=>{fetch("/api/user/isLoggedIn").then((e=>{e.ok&&(window.location.href="./editor.html")}))})),document.querySelector("#login form").addEventListener("submit",(e=>{e.preventDefault();let r=new FormData;if(e.target.username.value.length>0&&e.target.password.value.length>0)return r.append("username",e.target.username.value),r.append("password",e.target.password.value),void fetch("/api/user/login",{method:"POST",body:r}).then((e=>{e.ok?window.location.href="./editor.html":400!==e.status?(document.querySelector("#loginError").classList.remove("hidden"),document.querySelector("#loginError div").innerHTML="Invalid username or password"):showErrorMessage("Please type in a username and password.")}));document.querySelector("#loginError").classList.remove("hidden"),document.querySelector("#loginError div").innerHTML="Please type in a username and password"})),document.querySelector("#loginError .close").addEventListener("click",(()=>document.querySelector("#loginError").classList.toggle("hidden")));

View File

@ -1,8 +1,12 @@
<?php <?php
namespace api\blog; namespace api\blog;
use api\utils\imgUtils;
use DOMDocument;
use PDO; use PDO;
use Psr\Http\Message\UploadedFileInterface;
require_once __DIR__ . "/../utils/config.php"; require_once __DIR__ . "/../utils/config.php";
require_once __DIR__ . "/../utils/imgUtils.php";
/** /**
* Blog Data Class * Blog Data Class
@ -14,10 +18,10 @@ class blogData
* Get all blog posts * Get all blog posts
* @return array - Array of all blog posts or error message * @return array - Array of all blog posts or error message
*/ */
function getBlogPosts(): array public function getBlogPosts(): array
{ {
$conn = dbConn(); $conn = dbConn();
$stmt = $conn->prepare("SELECT ID, title, dateCreated, dateModified, body, tags FROM blog ORDER BY dateCreated DESC;"); $stmt = $conn->prepare("SELECT ID, title, dateCreated, dateModified, body, categories FROM blog ORDER BY dateCreated DESC;");
$stmt->execute(); $stmt->execute();
// set the resulting array to associative // set the resulting array to associative
@ -36,10 +40,10 @@ class blogData
* @param string $ID - ID of the blog post to get * @param string $ID - ID of the blog post to get
* @return array - Array of all blog posts or error message * @return array - Array of all blog posts or error message
*/ */
function getBlogPost(string $ID): array public function getBlogPost(string $ID): array
{ {
$conn = dbConn(); $conn = dbConn();
$stmt = $conn->prepare("SELECT ID, title, dateCreated, dateModified, featured, headerImg, body, tags FROM blog WHERE ID = :ID;"); $stmt = $conn->prepare("SELECT ID, title, dateCreated, dateModified, featured, headerImg, body, categories FROM blog WHERE ID = :ID;");
$stmt->bindParam(":ID", $ID); $stmt->bindParam(":ID", $ID);
$stmt->execute(); $stmt->execute();
@ -58,10 +62,10 @@ class blogData
* Get the latest blog post * Get the latest blog post
* @return array - Array of the latest blog post or error message * @return array - Array of the latest blog post or error message
*/ */
function getLatestBlogPost(): array public function getLatestBlogPost(): array
{ {
$conn = dbConn(); $conn = dbConn();
$stmt = $conn->prepare("SELECT ID, title, dateCreated, dateModified, featured, headerImg, body, tags FROM blog ORDER BY dateCreated DESC LIMIT 1;"); $stmt = $conn->prepare("SELECT ID, title, dateCreated, dateModified, featured, headerImg, body, categories FROM blog ORDER BY dateCreated DESC LIMIT 1;");
$stmt->execute(); $stmt->execute();
// set the resulting array to associative // set the resulting array to associative
@ -79,10 +83,10 @@ class blogData
* Get featured blog post * Get featured blog post
* @return array - Array of the featured blog post or error message * @return array - Array of the featured blog post or error message
*/ */
function getFeaturedBlogPost(): array public function getFeaturedBlogPost(): array
{ {
$conn = dbConn(); $conn = dbConn();
$stmt = $conn->prepare("SELECT ID, title, dateCreated, dateModified, featured, headerImg, body, tags FROM blog WHERE featured = 1;"); $stmt = $conn->prepare("SELECT ID, title, dateCreated, dateModified, featured, headerImg, body, categories FROM blog WHERE featured = 1;");
$stmt->execute(); $stmt->execute();
$result = $stmt->fetch(PDO::FETCH_ASSOC); $result = $stmt->fetch(PDO::FETCH_ASSOC);
@ -94,4 +98,124 @@ class blogData
return array("errorMessage" => "Error, blog post could not found"); return array("errorMessage" => "Error, blog post could not found");
} }
/**
* Upload the images in the post to temp folder and return image location
* @param UploadedFileInterface $img - Image to upload
* @return string|array - String with error message or array with the location of the uploaded file
*/
public function uploadPostImage(UploadedFileInterface $img): string|array
{
$targetDir = "../blog/imgs/tmp/";
$imagUtils = new imgUtils();
$targetFile = $imagUtils->uploadFile($targetDir, $img);
$file = $targetDir . basename($img->getClientFilename());
if (file_exists($file))
{
return array("url" => $file);
}
if (!is_array($targetFile))
{
return $targetFile;
}
if (file_exists($targetFile["imgLocation"]))
{
return array("url" => $targetFile["imgLocation"]);
}
return "Couldn't upload the image";
}
/**
* Creates a new post directory, uploads the header image and moves the images from the
* temp folder to the new folder, then updates the post html to point to the new images, finally
* it creates the post in the database
* @param string $title - Title of the blog post
* @param string $body - Body of the blog post
* @param string $dateCreated - Date the blog post was created
* @param string $featured - Whether the blog post is featured or not
* @param string $categories - Categories of the blog post
* @param UploadedFileInterface $headerImg - Header image of the blog post
* @return int|string - ID of the blog post or error message
*/
public function createPost(string $title, string $body, string $dateCreated, string $featured, string $categories, UploadedFileInterface $headerImg): int|string
{
$conn = dbConn();
$targetFile = "";
$folderID = uniqid();
if ($headerImg !== null)
{
$targetDir = "../blog/imgs/" . $title . "_" . $folderID . "/";
mkdir($targetDir, 0777, true);
$imagUtils = new imgUtils();
$targetFile = $imagUtils->uploadFile($targetDir, $headerImg);
}
$targetFile = array("imgLocation" => ".../blog/imgs/placeholder.png");
if (!is_array($targetFile))
{
return $targetFile;
}
$htmlDoc = new DOMDocument();
$htmlDoc->loadHTML($body, LIBXML_NOERROR);
$doc = $htmlDoc->getElementsByTagName('body')->item(0);
$imgs = $doc->getElementsByTagName('img');
$srcList = array();
foreach ($imgs as $img)
{
$src = $img->getAttribute("src");
$srcList[] = $src;
$fileName = basename($src);
$img->setAttribute("src", $targetDir . $fileName);
}
$files = scandir("../blog/imgs/tmp/");
foreach ($files as $file)
{
if ($file != "." && $file != "..")
{
if (!in_array("../blog/imgs/tmp/" . $file, $srcList))
{
unlink("../blog/imgs/tmp/" . $file);
}
else
{
rename("../blog/imgs/tmp/" . $file, $targetDir . $file);
}
}
}
$newBody = '';
foreach ($doc->childNodes as $node)
{
$newBody .= $htmlDoc->saveHTML($node);
}
$stmt = $conn->prepare("INSERT INTO blog (title, dateCreated, dateModified, featured, headerImg, body, categories, folderID)
VALUES (:title, :dateCreated, :dateModified, :featured, :headerImg, :body, :categories, :folderID);");
$stmt->bindParam(":title", $title);
$stmt->bindParam(":dateCreated", $dateCreated);
$stmt->bindParam(":dateModified", $dateCreated);
$stmt->bindParam(":featured", $featured);
$stmt->bindParam(":headerImg", $targetFile["imgLocation"]);
$stmt->bindParam(":body", $newBody);
$stmt->bindParam(":categories", $categories);
$stmt->bindParam(":folderID", $folderID);
if ($stmt->execute())
{
return intval($conn->lastInsertId());
}
return "Error, couldn't create post";
}
} }

View File

@ -12,7 +12,6 @@ use Slim\App;
class blogRoutes implements routesInterface class blogRoutes implements routesInterface
{ {
private blogData $blogData; private blogData $blogData;
/** /**
* constructor used to instantiate a base blog routes, to be used in the index.php file. * constructor used to instantiate a base blog routes, to be used in the index.php file.
* @param App $app - the slim app used to create the routes * @param App $app - the slim app used to create the routes
@ -30,6 +29,54 @@ class blogRoutes implements routesInterface
*/ */
public function createRoutes(App $app): void public function createRoutes(App $app): void
{ {
// TODO: Implement createRoutes() method. $app->post("/blog/post", function (Request $request, Response $response, array $args)
{
$data = $request->getParsedBody();
$files = $request->getUploadedFiles();
$headerImg = $files["headerImg"];
if (empty($data["title"]) || empty($data["body"]) || empty($data["dateCreated"]) || empty($data["featured"]) || empty($data["categories"]))
{
// uh oh sent some empty data
$response->getBody()->write(json_encode(array("error" => "Error, empty data sent")));
return $response->withStatus(400);
}
if (empty($files["headerImg"]))
{
$headerImg = null;
}
$insertedID = $this->blogData->createPost($data["title"], $data["body"], $data["dateCreated"], $data["featured"], $data["categories"], $headerImg);
if (!is_int($insertedID))
{
// uh oh something went wrong
$response->getBody()->write(json_encode(array("error" => $insertedID)));
return $response->withStatus(500);
}
$response->getBody()->write(json_encode(array("ID" => $insertedID)));
return $response->withStatus(201);
});
$app->post("/blog/uploadPostImage", function (Request $request, Response $response)
{
$files = $request->getUploadedFiles();
if (empty($files))
{
// uh oh sent some empty data
$response->getBody()->write(json_encode(array("error" => array("message" => "Error, empty data sent"))));
return $response->withStatus(400);
}
$message = $this->blogData->uploadPostImage($files["upload"]);
if (!is_array($message))
{
$response->getBody()->write(json_encode(array("error" => array("message" => $message))));
return $response->withStatus(500);
}
$response->getBody()->write(json_encode($message));
return $response->withStatus(201);
});
} }
} }

View File

@ -1,9 +1,11 @@
<?php <?php
namespace api\project; namespace api\project;
use api\utils\imgUtils;
use PDO; use PDO;
use Psr\Http\Message\UploadedFileInterface; use Psr\Http\Message\UploadedFileInterface;
require_once __DIR__ . "/../utils/config.php"; require_once __DIR__ . "/../utils/config.php";
require_once __DIR__ . "/../utils/imgUtils.php";
/** /**
* Project Data Class * Project Data Class
@ -15,7 +17,7 @@ class projectData
* Get all project data * Get all project data
* @return array - Array of all project data or error message * @return array - Array of all project data or error message
*/ */
function getProjectData(): array public function getProjectData(): array
{ {
$conn = dbConn(); $conn = dbConn();
$stmt = $conn->prepare("SELECT ID, title, isMainProject, information, imgLocation, projectLink, gitLink FROM projects ORDER BY isMainProject DESC;"); $stmt = $conn->prepare("SELECT ID, title, isMainProject, information, imgLocation, projectLink, gitLink FROM projects ORDER BY isMainProject DESC;");
@ -43,7 +45,7 @@ class projectData
* @param string $gitLink - Link to the git repository * @param string $gitLink - Link to the git repository
* @return bool|string - True if project was updated, false if not and there was an error, or an error string * @return bool|string - True if project was updated, false if not and there was an error, or an error string
*/ */
function updateProjectData(string $ID, string $title, string $isMainProject, string $information, string $projectLink, string $gitLink): bool | string public function updateProjectData(string $ID, string $title, string $isMainProject, string $information, string $projectLink, string $gitLink): bool|string
{ {
$conn = dbConn(); $conn = dbConn();
@ -82,7 +84,7 @@ class projectData
* @param int $ID - ID of the project in the database to delete * @param int $ID - ID of the project in the database to delete
* @return string - True if project was deleted, false if not and there was an error * @return string - True if project was deleted, false if not and there was an error
*/ */
function deleteProjectData(int $ID): string public function deleteProjectData(int $ID): string
{ {
$conn = dbConn(); $conn = dbConn();
@ -121,7 +123,7 @@ class projectData
* @param string $gitLink - Link to the github repository * @param string $gitLink - Link to the github repository
* @return int|bool - ID of the project if it was added, false if not and there was an error * @return int|bool - ID of the project if it was added, false if not and there was an error
*/ */
function addProjectData(string $title, string $isMainProject, string $information, string $projectLink, string $gitLink): int|bool public function addProjectData(string $title, string $isMainProject, string $information, string $projectLink, string $gitLink): int|bool
{ {
$conn = dbConn(); $conn = dbConn();
@ -157,31 +159,15 @@ class projectData
public function uploadImage(int $ID, UploadedFileInterface $img): string | array public function uploadImage(int $ID, UploadedFileInterface $img): string | array
{ {
$targetDir = "../imgs/projects/"; $targetDir = "../imgs/projects/";
$targetFile = $targetDir . basename($img->getClientFilename()); $imgUtils = new imgUtils();
$uploadOk = 1; $targetFile = $imgUtils->uploadFile($targetDir, $img);
$imageFileType = strtolower(pathinfo($targetFile, PATHINFO_EXTENSION));
// Check if file already exists if (!is_array($targetFile))
if (file_exists($targetFile))
{ {
return "The file already exists"; return $targetFile;
} }
// Check file size if (file_exists($targetFile["imgLocation"]))
if ($img->getSize() > 2000000)
{
return "The file is too large, max 2MB";
}
// Allow certain file formats
if ($imageFileType != "jpg" && $imageFileType != "png" && $imageFileType != "jpeg" && $imageFileType != "gif")
{
return "Only JPG, JPEG, PNG & GIF files are allowed";
}
$img->moveTo($targetFile);
if (file_exists($targetFile))
{ {
$this->deleteImage($ID); $this->deleteImage($ID);
// update the database with the new image location // update the database with the new image location
@ -193,7 +179,7 @@ class projectData
if ($stmt->rowCount() > 0) if ($stmt->rowCount() > 0)
{ {
return array("imgLocation" => $targetFile); return array("imgLocation" => $targetFile["imgLocation"]);
} }
return "Couldn't update the database"; return "Couldn't update the database";

View File

@ -113,7 +113,7 @@ class projectRoutes implements routesInterface
{ {
// uh oh sent some empty data // uh oh sent some empty data
$response->getBody()->write(json_encode(array("error" => "Only some of the data was sent"))); $response->getBody()->write(json_encode(array("error" => "Only some of the data was sent")));
return $response->withStatus(400); return $response->withStatus(400)->withStatus(201);
} }
$insertedID = $this->projectData->addProjectData($data["title"], $data["isMainProject"], $data["information"], $data["projectLink"], $data["gitLink"]); $insertedID = $this->projectData->addProjectData($data["title"], $data["isMainProject"], $data["information"], $data["projectLink"], $data["gitLink"]);
@ -125,7 +125,7 @@ class projectRoutes implements routesInterface
} }
$response->getBody()->write(json_encode(array("ID" => $insertedID))); $response->getBody()->write(json_encode(array("ID" => $insertedID)));
return $response; return $response->withStatus(201);
}); });
$app->post("/projectImage/{id}", function (Request $request, Response $response, array $args) $app->post("/projectImage/{id}", function (Request $request, Response $response, array $args)
@ -147,7 +147,7 @@ class projectRoutes implements routesInterface
} }
$response->getBody()->write(json_encode($message)); $response->getBody()->write(json_encode($message));
return $response; return $response->withStatus(201);
}); });
} }
} }

View File

@ -16,7 +16,7 @@ class timelineData
* Get all education data * Get all education data
* @return array - Array of all education data or error message * @return array - Array of all education data or error message
*/ */
function getEduData(): array public function getEduData(): array
{ {
$conn = dbConn(); $conn = dbConn();
$stmt = $conn->prepare("SELECT ID, startPeriod, endPeriod, grade, course FROM edu ORDER BY startPeriod DESC;"); $stmt = $conn->prepare("SELECT ID, startPeriod, endPeriod, grade, course FROM edu ORDER BY startPeriod DESC;");
@ -36,7 +36,7 @@ class timelineData
* Get all work data * Get all work data
* @return array - Array of all work data or error message * @return array - Array of all work data or error message
*/ */
function getWorkData(): array public function getWorkData(): array
{ {
$conn = dbConn(); $conn = dbConn();
$stmt = $conn->prepare("SELECT ID, startPeriod, endPeriod, companyName, area, title FROM work ORDER BY work.startPeriod DESC;"); $stmt = $conn->prepare("SELECT ID, startPeriod, endPeriod, companyName, area, title FROM work ORDER BY work.startPeriod DESC;");
@ -61,7 +61,7 @@ class timelineData
* @param string $id - ID of the education data * @param string $id - ID of the education data
* @return bool - True if successful, false if not * @return bool - True if successful, false if not
*/ */
function updateEduData(string $dateFrom, string $dateTo, string $grade, string $course, string $id): bool public function updateEduData(string $dateFrom, string $dateTo, string $grade, string $course, string $id): bool
{ {
$conn = dbConn(); $conn = dbConn();
$stmt = $conn->prepare("UPDATE edu SET startPeriod = :dateFrom, endPeriod = :dateTo, grade = :grade, course = :course WHERE ID = :id;"); $stmt = $conn->prepare("UPDATE edu SET startPeriod = :dateFrom, endPeriod = :dateTo, grade = :grade, course = :course WHERE ID = :id;");
@ -101,7 +101,7 @@ class timelineData
* @param int $id * @param int $id
* @return bool - True if successful, false if not * @return bool - True if successful, false if not
*/ */
function deleteEduData(int $id): bool public function deleteEduData(int $id): bool
{ {
$conn = dbConn(); $conn = dbConn();
$stmt = $conn->prepare("DELETE FROM edu WHERE ID = :id;"); $stmt = $conn->prepare("DELETE FROM edu WHERE ID = :id;");
@ -130,7 +130,7 @@ class timelineData
* @param string $course - Course * @param string $course - Course
* @return bool|int - ID of the new education data or false if not successful * @return bool|int - ID of the new education data or false if not successful
*/ */
function addEduData(string $dateFrom, string $dateTo, string $grade, string $course): bool|int public function addEduData(string $dateFrom, string $dateTo, string $grade, string $course): bool|int
{ {
$conn = dbConn(); $conn = dbConn();
$stmt = $conn->prepare("INSERT INTO edu (startPeriod, endPeriod, grade, course) VALUES (:dateFrom, :dateTo, :grade, :course);"); $stmt = $conn->prepare("INSERT INTO edu (startPeriod, endPeriod, grade, course) VALUES (:dateFrom, :dateTo, :grade, :course);");
@ -139,7 +139,7 @@ class timelineData
$stmt->bindParam(":grade", $grade); $stmt->bindParam(":grade", $grade);
$stmt->bindParam(":course", $course); $stmt->bindParam(":course", $course);
if($stmt->execute()) if ($stmt->execute())
{ {
return $conn->lastInsertId(); return $conn->lastInsertId();
} }
@ -155,7 +155,7 @@ class timelineData
* @param string $title - Title * @param string $title - Title
* @return bool|int - ID of the new work data if successful, false if not * @return bool|int - ID of the new work data if successful, false if not
*/ */
function addWorkData(string $dateFrom, string $dateTo, string $companyName, string $area, string $title): bool|int public function addWorkData(string $dateFrom, string $dateTo, string $companyName, string $area, string $title): bool|int
{ {
$conn = dbConn(); $conn = dbConn();
$stmt = $conn->prepare("INSERT INTO work (startPeriod, endPeriod, companyName, area, title) VALUES (:dateFrom, :dateTo, :companyName, :area, :title);"); $stmt = $conn->prepare("INSERT INTO work (startPeriod, endPeriod, companyName, area, title) VALUES (:dateFrom, :dateTo, :companyName, :area, :title);");
@ -165,7 +165,7 @@ class timelineData
$stmt->bindParam(":area", $area); $stmt->bindParam(":area", $area);
$stmt->bindParam(":title", $title); $stmt->bindParam(":title", $title);
if($stmt->execute()) if ($stmt->execute())
{ {
return $conn->lastInsertId(); return $conn->lastInsertId();
} }

View File

@ -17,7 +17,7 @@ class userData
* @param $password string - Password * @param $password string - Password
* @return bool - True if logged in, false if not * @return bool - True if logged in, false if not
*/ */
function checkUser(string $username, string $password): bool public function checkUser(string $username, string $password): bool
{ {
$conn = dbConn(); $conn = dbConn();
$stmt = $conn->prepare("SELECT * FROM users WHERE username = :username"); $stmt = $conn->prepare("SELECT * FROM users WHERE username = :username");
@ -43,15 +43,15 @@ class userData
* @param $username string - Username * @param $username string - Username
* @return string - JWT token * @return string - JWT token
*/ */
function createToken(string $username): string public function createToken(string $username): string
{ {
$now = time(); $now = time();
$future = strtotime('+6 hour',$now); $future = strtotime('+6 hour', $now);
$secretKey = getSecretKey(); $secretKey = getSecretKey();
$payload = [ $payload = [
"jti"=>$username, "jti" => $username,
"iat"=>$now, "iat" => $now,
"exp"=>$future "exp" => $future
]; ];
return JWT::encode($payload,$secretKey,"HS256"); return JWT::encode($payload,$secretKey,"HS256");
@ -62,7 +62,7 @@ class userData
* @param string $email - Email to check * @param string $email - Email to check
* @return bool - True if email exists, false if not * @return bool - True if email exists, false if not
*/ */
function checkEmail(string $email): bool public function checkEmail(string $email): bool
{ {
$conn = dbConn(); $conn = dbConn();
$stmt = $conn->prepare("SELECT * FROM users WHERE email = :email"); $stmt = $conn->prepare("SELECT * FROM users WHERE email = :email");
@ -84,7 +84,7 @@ class userData
* @param $email - email address of the userData * @param $email - email address of the userData
* @return string - verification code * @return string - verification code
*/ */
function sendResetEmail($email): string public function sendResetEmail($email): string
{ {
//generate a random token and email the address //generate a random token and email the address
$token = uniqid("rpe-"); $token = uniqid("rpe-");
@ -119,7 +119,7 @@ class userData
* @param $password string Password * @param $password string Password
* @return bool - true if the password was changed, false if not * @return bool - true if the password was changed, false if not
*/ */
function changePassword(string $email, string $password): bool public function changePassword(string $email, string $password): bool
{ {
$conn = dbConn(); $conn = dbConn();
$stmt = $conn->prepare("UPDATE users SET password = :password WHERE email = :email"); $stmt = $conn->prepare("UPDATE users SET password = :password WHERE email = :email");

View File

@ -145,7 +145,7 @@ class userRoutes implements routesInterface
// yay, password changed // yay, password changed
unset($_SESSION["resetToken"]); unset($_SESSION["resetToken"]);
unset($_SESSION["resetEmail"]); unset($_SESSION["resetEmail"]);
return $response; return $response->withStatus(201);
} }
return $response->withStatus(500); return $response->withStatus(500);

View File

@ -0,0 +1,43 @@
<?php
namespace api\utils;
use Psr\Http\Message\UploadedFileInterface;
class imgUtils
{
/**
* Checks and uploads a file to the given directory
* @param string $targetDir - Directory to upload the file to
* @param UploadedFileInterface $img - File to upload
* @return string|array - String with error message or array with the location of the uploaded file
*/
public function uploadFile(string $targetDir, UploadedFileInterface $img): string|array
{
$targetFile = $targetDir . basename($img->getClientFilename());
$uploadOk = 1;
$imageFileType = strtolower(pathinfo($targetFile, PATHINFO_EXTENSION));
// Check if file already exists
if (file_exists($targetFile))
{
return "The file already exists";
}
// Check file size
if ($img->getSize() > 2000000)
{
return "The file is too large, max 2MB";
}
// Allow certain file formats
if ($imageFileType != "jpg" && $imageFileType != "png" && $imageFileType != "jpeg" && $imageFileType != "gif")
{
return "Only JPG, JPEG, PNG & GIF files are allowed";
}
$img->moveTo($targetFile);
return array("imgLocation" => $targetFile);
}
}

View File

@ -27,7 +27,7 @@ class middleware
* Constructor for middleware * Constructor for middleware
* @param App $app - Slim App * @param App $app - Slim App
*/ */
function __construct(App $app) public function __construct(App $app)
{ {
$this->baseMiddleware($app); $this->baseMiddleware($app);
$this->sameSiteConfig($app); $this->sameSiteConfig($app);
@ -40,7 +40,7 @@ class middleware
* Base middleware * Base middleware
* @param App $app - Slim App * @param App $app - Slim App
*/ */
function baseMiddleware(App $app): void public function baseMiddleware(App $app): void
{ {
$app->addBodyParsingMiddleware(); $app->addBodyParsingMiddleware();
$app->addRoutingMiddleware(); $app->addRoutingMiddleware();
@ -50,7 +50,7 @@ class middleware
* SameSite Cookie Configuration * SameSite Cookie Configuration
* @param App $app - Slim App * @param App $app - Slim App
*/ */
function sameSiteConfig(App $app): void public function sameSiteConfig(App $app): void
{ {
$ssConfig = new SameSiteCookieConfiguration(["same_site" => "strict"]); $ssConfig = new SameSiteCookieConfiguration(["same_site" => "strict"]);
$app->add(new SameSiteCookieMiddleware($ssConfig)); $app->add(new SameSiteCookieMiddleware($ssConfig));
@ -60,7 +60,7 @@ class middleware
* Return all responses as JSON * Return all responses as JSON
* @param App $app - Slim App * @param App $app - Slim App
*/ */
function returnAsJSON(App $app): void public function returnAsJSON(App $app): void
{ {
$app->add(function ($request, $handler) $app->add(function ($request, $handler)
{ {
@ -73,7 +73,7 @@ class middleware
* JWT Authentication * JWT Authentication
* @param App $app - Slim App * @param App $app - Slim App
*/ */
function jwtAuth(App $app): void public function jwtAuth(App $app): void
{ {
$jwtSecret = getSecretKey(); $jwtSecret = getSecretKey();
$app->add(new JwtAuthentication([ $app->add(new JwtAuthentication([
@ -91,13 +91,17 @@ class middleware
{ {
session_destroy(); session_destroy();
$response->getBody()->write(json_encode(array("status" => "401", "message" => $response->getBody()->write(json_encode(array("status" => "401", "message" =>
"Unauthorized, please provide a valid token"))); "Unauthorized, please provide a valid token")));
return $response->withStatus(401); return $response->withStatus(401);
} }
])); ]));
} }
function errorHandling(App $app): void /**
* Error handling
* @param App $app - Slim App
*/
public function errorHandling(App $app): void
{ {
$app->add(function (ServerRequestInterface $request, RequestHandlerInterface $handler) $app->add(function (ServerRequestInterface $request, RequestHandlerInterface $handler)
{ {

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

View File

@ -6,6 +6,6 @@
</head> </head>
<body> <body>
this is a test this is a test
<script src="/blog/index.js"></script> <script src="/blog/js/index.js"></script>
</body> </body>
</html> </html>

Some files were not shown because too many files have changed in this diff Show More