446 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			446 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
<?php
 | 
						|
 | 
						|
namespace api\blog;
 | 
						|
 | 
						|
use api\utils\imgUtils;
 | 
						|
use DOMDocument;
 | 
						|
use PDO;
 | 
						|
use Psr\Http\Message\UploadedFileInterface;
 | 
						|
 | 
						|
require_once __DIR__ . "/../utils/config.php";
 | 
						|
require_once __DIR__ . "/../utils/imgUtils.php";
 | 
						|
 | 
						|
/**
 | 
						|
 * Blog Data Class
 | 
						|
 * Define all functions which either get, update, create or delete posts
 | 
						|
 */
 | 
						|
class blogData
 | 
						|
{
 | 
						|
    /**
 | 
						|
     * Get all blog posts
 | 
						|
     * @return array - Array of all blog posts or error message
 | 
						|
     */
 | 
						|
    public function getBlogPosts(): array
 | 
						|
    {
 | 
						|
        $conn = dbConn();
 | 
						|
        $stmt = $conn->prepare("SELECT * FROM blog ORDER BY dateCreated DESC;");
 | 
						|
        $stmt->execute();
 | 
						|
 | 
						|
        // set the resulting array to associative
 | 
						|
        $result = $stmt->fetchAll(PDO::FETCH_ASSOC);
 | 
						|
 | 
						|
        if ($result)
 | 
						|
        {
 | 
						|
            return $result;
 | 
						|
        }
 | 
						|
 | 
						|
        return array("errorMessage" => "Error, blog data not found");
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Get a blog post with the given ID
 | 
						|
     * @param string $title - Title of the blog post
 | 
						|
     * @return array - Array of all blog posts or error message
 | 
						|
     */
 | 
						|
    public function getBlogPost(string $title): array
 | 
						|
    {
 | 
						|
        $conn = dbConn();
 | 
						|
        $stmt = $conn->prepare("SELECT * FROM blog WHERE title = :title;");
 | 
						|
        $stmt->bindParam(":title", $title);
 | 
						|
        $stmt->execute();
 | 
						|
 | 
						|
        // set the resulting array to associative
 | 
						|
        $result = $stmt->fetch(PDO::FETCH_ASSOC);
 | 
						|
 | 
						|
        if ($result)
 | 
						|
        {
 | 
						|
            return $result;
 | 
						|
        }
 | 
						|
 | 
						|
        return array("errorMessage" => "Error, blog post could not found");
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Get the latest blog post
 | 
						|
     * @return array - Array of the latest blog post or error message
 | 
						|
     */
 | 
						|
    public function getLatestBlogPost(): array
 | 
						|
    {
 | 
						|
        $conn = dbConn();
 | 
						|
        $stmt = $conn->prepare("SELECT * FROM blog ORDER BY dateCreated DESC LIMIT 1;");
 | 
						|
        $stmt->execute();
 | 
						|
 | 
						|
        // set the resulting array to associative
 | 
						|
        $result = $stmt->fetch(PDO::FETCH_ASSOC);
 | 
						|
 | 
						|
        if ($result)
 | 
						|
        {
 | 
						|
            return $result;
 | 
						|
        }
 | 
						|
 | 
						|
        return array("errorMessage" => "Error, blog post could not found");
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Get featured blog post
 | 
						|
     * @return array - Array of the featured blog post or error message
 | 
						|
     */
 | 
						|
    public function getFeaturedBlogPost(): array
 | 
						|
    {
 | 
						|
        $conn = dbConn();
 | 
						|
        $stmt = $conn->prepare("SELECT * FROM blog WHERE featured = 1;");
 | 
						|
        $stmt->execute();
 | 
						|
 | 
						|
        $result = $stmt->fetch(PDO::FETCH_ASSOC);
 | 
						|
 | 
						|
        if ($result)
 | 
						|
        {
 | 
						|
            return $result;
 | 
						|
        }
 | 
						|
 | 
						|
        return array("errorMessage" => "Error, blog post could not found");
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Get the blog posts with the given category
 | 
						|
     * @param string $category - Category of the blog post
 | 
						|
     * @return array - Array of the blog posts with the given category or error message
 | 
						|
     */
 | 
						|
    public function getBlogPostsWithCategory(string $category): array
 | 
						|
    {
 | 
						|
        $conn = dbConn();
 | 
						|
        $stmt = $conn->prepare("SELECT * FROM blog WHERE categories LIKE :category;");
 | 
						|
        $stmt->bindParam(":category", $category);
 | 
						|
        $stmt->execute();
 | 
						|
 | 
						|
        // set the resulting array to associative
 | 
						|
        $result = $stmt->fetchAll(PDO::FETCH_ASSOC);
 | 
						|
 | 
						|
        if ($result)
 | 
						|
        {
 | 
						|
            return $result;
 | 
						|
        }
 | 
						|
 | 
						|
        return array("errorMessage" => "Error, blog post could not found");
 | 
						|
    }
 | 
						|
 | 
						|
    public function getCategories(): array
 | 
						|
    {
 | 
						|
        $conn = dbConn();
 | 
						|
        $stmt = $conn->prepare("SELECT DISTINCT categories FROM blog;");
 | 
						|
        $stmt->execute();
 | 
						|
 | 
						|
        // set the resulting array to associative
 | 
						|
        $result = $stmt->fetchAll(PDO::FETCH_ASSOC);
 | 
						|
 | 
						|
        if ($result)
 | 
						|
        {
 | 
						|
            return $result;
 | 
						|
        }
 | 
						|
 | 
						|
        return array("errorMessage" => "Error, blog post could not found");
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Delete a blog post with the given ID
 | 
						|
     * @param int $ID - ID of the blog post to delete
 | 
						|
     * @return string - Success or error message
 | 
						|
     */
 | 
						|
    public function deletePost(int $ID): string
 | 
						|
    {
 | 
						|
        $conn = dbConn();
 | 
						|
 | 
						|
        $stmtCheckPost = $conn->prepare("SELECT * FROM blog WHERE ID = :ID");
 | 
						|
        $stmtCheckPost->bindParam(":ID", $ID);
 | 
						|
        $stmtCheckPost->execute();
 | 
						|
        $result = $stmtCheckPost->fetch(PDO::FETCH_ASSOC);
 | 
						|
 | 
						|
        if (!$result)
 | 
						|
        {
 | 
						|
            return "post not found";
 | 
						|
        }
 | 
						|
 | 
						|
        if ($result["featured"] === 1)
 | 
						|
        {
 | 
						|
            return "cannot delete";
 | 
						|
        }
 | 
						|
 | 
						|
        $stmt = $conn->prepare("DELETE FROM blog WHERE ID = :ID");
 | 
						|
        $stmt->bindParam(":ID", $ID);
 | 
						|
 | 
						|
        if ($stmt->execute())
 | 
						|
        {
 | 
						|
            $imagUtils = new imgUtils();
 | 
						|
            $imagUtils->deleteDirectory("../blog/imgs/" . $result["title"] . "_" . $result["folderID"] . "/");
 | 
						|
            return "success";
 | 
						|
        }
 | 
						|
 | 
						|
        return "error";
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Update the blog post with the given ID
 | 
						|
     * @param int $ID - ID of the blog post to update
 | 
						|
     * @param string $title - Title of the blog post
 | 
						|
     * @param bool $featured - Whether the blog post is featured or not
 | 
						|
     * @param string $abstract - Abstract of the blog post i.e. a short description
 | 
						|
     * @param string $body - Body of the blog post
 | 
						|
     * @param string $dateModified - Date the blog post was modified
 | 
						|
     * @param string $categories - Categories of the blog post
 | 
						|
     * @return bool|string - Success or error message
 | 
						|
     */
 | 
						|
    public function updatePost(int $ID, string $title, bool $featured, string $abstract, string $body, string $dateModified, string $categories): bool|string
 | 
						|
    {
 | 
						|
        $conn = dbConn();
 | 
						|
 | 
						|
        $stmtCheckPost = $conn->prepare("SELECT * FROM blog WHERE ID = :ID");
 | 
						|
        $stmtCheckPost->bindParam(":ID", $ID);
 | 
						|
        $stmtCheckPost->execute();
 | 
						|
        $result = $stmtCheckPost->fetch(PDO::FETCH_ASSOC);
 | 
						|
 | 
						|
        if (!$result)
 | 
						|
        {
 | 
						|
            return "post not found";
 | 
						|
        }
 | 
						|
 | 
						|
        if (!$featured && $result["featured"] === 1)
 | 
						|
        {
 | 
						|
            return "unset feature";
 | 
						|
        }
 | 
						|
 | 
						|
        if ($featured)
 | 
						|
        {
 | 
						|
            $stmtUnsetFeatured = $conn->prepare("UPDATE blog SET featured = 0 WHERE featured = 1;");
 | 
						|
            $stmtUnsetFeatured->execute();
 | 
						|
        }
 | 
						|
 | 
						|
        $to = "../blog/imgs/" . $title . "_" . $result["folderID"] . "/";
 | 
						|
        if ($result["title"] !== $title)
 | 
						|
        {
 | 
						|
            $from = "../blog/imgs/" . $result["title"] . "_" . $result["folderID"] . "/";
 | 
						|
            mkdir($to, 0777, true);
 | 
						|
            rename($result["headerImg"], $to . basename($result["headerImg"]));
 | 
						|
            $body = $this->changeHTMLSrc($body, $to, $from);
 | 
						|
            rmdir($from);
 | 
						|
        }
 | 
						|
 | 
						|
        $from = "../blog/imgs/tmp/";
 | 
						|
        $newBody = $this->changeHTMLSrc($body, $to, $from);
 | 
						|
 | 
						|
        $stmt = $conn->prepare("UPDATE blog SET title = :title, featured = :featured, abstract = :abstract, body = :body, dateModified = :dateModified, categories = :categories WHERE ID = :ID;");
 | 
						|
        $stmt->bindParam(":ID", $ID);
 | 
						|
        $stmt->bindParam(":title", $title);
 | 
						|
        $stmt->bindParam(":featured", $featured);
 | 
						|
        $stmt->bindParam(":abstract", $abstract);
 | 
						|
        $stmt->bindParam(":body", $newBody);
 | 
						|
        $stmt->bindParam(":dateModified", $dateModified);
 | 
						|
        $stmt->bindParam(":categories", $categories);
 | 
						|
 | 
						|
        return $stmt->execute();
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Creates a new post di rectory, 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 $abstract - Abstract of the blog post i.e. a short description
 | 
						|
     * @param string $body - Body of the blog post
 | 
						|
     * @param string $dateCreated - Date the blog post was created
 | 
						|
     * @param bool $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 $abstract, string $body, string $dateCreated, bool $featured, string $categories, UploadedFileInterface $headerImg): int|string
 | 
						|
    {
 | 
						|
        $conn = dbConn();
 | 
						|
        $folderID = uniqid();
 | 
						|
        $targetFile = array("imgLocation" => "../blog/imgs/placeholder.png");
 | 
						|
 | 
						|
        $targetDir = "../blog/imgs/" . $title . "_" . $folderID . "/";
 | 
						|
        mkdir($targetDir, 0777, true);
 | 
						|
 | 
						|
        if ($headerImg !== null)
 | 
						|
        {
 | 
						|
            $imagUtils = new imgUtils();
 | 
						|
            $targetFile = $imagUtils->uploadFile($targetDir, $headerImg);
 | 
						|
        }
 | 
						|
 | 
						|
 | 
						|
        if (!is_array($targetFile))
 | 
						|
        {
 | 
						|
            return $targetFile;
 | 
						|
        }
 | 
						|
 | 
						|
        $newBody = $this->changeHTMLSrc($body, $targetDir, "../blog/imgs/tmp/");
 | 
						|
 | 
						|
 | 
						|
        if ($featured)
 | 
						|
        {
 | 
						|
            $stmtMainProject = $conn->prepare("UPDATE blog SET featured = 0 WHERE featured = 1;");
 | 
						|
            $stmtMainProject->execute();
 | 
						|
        }
 | 
						|
 | 
						|
        $stmt = $conn->prepare("INSERT INTO blog (title, dateCreated, dateModified, featured, headerImg, abstract, body, categories, folderID) 
 | 
						|
                                       VALUES (:title, :dateCreated, :dateModified, :featured, :headerImg, :abstract, :body, :categories, :folderID);");
 | 
						|
        $stmt->bindParam(":title", $title);
 | 
						|
        $stmt->bindParam(":dateCreated", $dateCreated);
 | 
						|
        $stmt->bindParam(":dateModified", $dateCreated);
 | 
						|
        $isFeatured = $featured ? 1 : 0;
 | 
						|
        $stmt->bindParam(":featured", $isFeatured);
 | 
						|
        $stmt->bindParam(":headerImg", $targetFile["imgLocation"]);
 | 
						|
        $stmt->bindParam(":abstract", $abstract);
 | 
						|
        $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";
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * 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";
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Upload the header image of the post and update the database
 | 
						|
     * @param int $ID - ID of the post
 | 
						|
     * @param UploadedFileInterface $img - Image to upload
 | 
						|
     * @return string|array - String with error message or array with the location of the uploaded file
 | 
						|
     */
 | 
						|
    public function uploadHeaderImage(int $ID, UploadedFileInterface $img): string|array
 | 
						|
    {
 | 
						|
        $conn = dbConn();
 | 
						|
        $stmt = $conn->prepare("SELECT * FROM blog WHERE ID = :ID;");
 | 
						|
        $stmt->bindParam(":ID", $ID);
 | 
						|
        $stmt->execute();
 | 
						|
        $result = $stmt->fetch(PDO::FETCH_ASSOC);
 | 
						|
 | 
						|
        if (!$result)
 | 
						|
        {
 | 
						|
            return "Couldn't find the post";
 | 
						|
        }
 | 
						|
 | 
						|
        $targetDir = "../blog/imgs/" . $result["title"] . "_" . $result["folderID"] . "/";
 | 
						|
        $imagUtils = new imgUtils();
 | 
						|
        $targetFile = $imagUtils->uploadFile($targetDir, $img);
 | 
						|
 | 
						|
        if (!is_array($targetFile))
 | 
						|
        {
 | 
						|
            return $targetFile;
 | 
						|
        }
 | 
						|
 | 
						|
        if (file_exists($targetFile["imgLocation"]))
 | 
						|
        {
 | 
						|
            unlink($result["headerImg"]);
 | 
						|
            $stmt = $conn->prepare("UPDATE blog SET headerImg = :headerImg WHERE ID = :ID;");
 | 
						|
            $stmt->bindParam(":ID", $ID);
 | 
						|
            $stmt->bindParam(":headerImg", $targetFile["imgLocation"]);
 | 
						|
            $stmt->execute();
 | 
						|
            if ($stmt->rowCount() > 0)
 | 
						|
            {
 | 
						|
                return $targetFile;
 | 
						|
            }
 | 
						|
 | 
						|
            return "Couldn't update the post";
 | 
						|
        }
 | 
						|
 | 
						|
        return "Couldn't upload the image";
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Change the HTML src of the images in the post to point to the new location
 | 
						|
     * @param string $body - Body of the post
 | 
						|
     * @param string $to - New location of the images
 | 
						|
     * @param string $from - Old location of the images
 | 
						|
     * @return string - Body of the post with the new image locations
 | 
						|
     */
 | 
						|
    public function changeHTMLSrc(string $body, string $to, string $from): string
 | 
						|
    {
 | 
						|
        $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");
 | 
						|
            $src = urldecode($src);
 | 
						|
            $srcList[] = $src;
 | 
						|
            $fileName = basename($src);
 | 
						|
 | 
						|
            $img->setAttribute("src", substr($to, 2) . $fileName);
 | 
						|
        }
 | 
						|
 | 
						|
        $files = scandir($from);
 | 
						|
        foreach ($files as $file)
 | 
						|
        {
 | 
						|
            if ($file != "." && $file != "..")
 | 
						|
            {
 | 
						|
                if (!in_array($from . $file, $srcList))
 | 
						|
                {
 | 
						|
                    unlink($from . $file);
 | 
						|
                }
 | 
						|
                else
 | 
						|
                {
 | 
						|
                    rename($from . $file, $to . $file);
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        $newBody = '';
 | 
						|
        foreach ($doc->childNodes as $node)
 | 
						|
        {
 | 
						|
            $newBody .= $htmlDoc->saveHTML($node);
 | 
						|
        }
 | 
						|
        return $newBody;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Get all posts with the given category
 | 
						|
     * @param string $category - Category of the post
 | 
						|
     * @return array - Array of all posts with the given category or error message
 | 
						|
     */
 | 
						|
    public function getPostsByCategory(string $category): array
 | 
						|
    {
 | 
						|
        $conn = dbConn();
 | 
						|
        $stmt = $conn->prepare("SELECT * FROM blog WHERE LOCATE(:category, categories) > 0;");
 | 
						|
        $stmt->bindParam(":category", $category);
 | 
						|
        $stmt->execute();
 | 
						|
        return $stmt->fetchAll(PDO::FETCH_ASSOC);
 | 
						|
    }
 | 
						|
} |