281 lines
8.7 KiB
PHP
281 lines
8.7 KiB
PHP
<?php
|
|
|
|
namespace Controllers;
|
|
|
|
class Post
|
|
{
|
|
public function index($page = '1')
|
|
{
|
|
$db = db();
|
|
$offset = ($page >= 1) ? ($page - 1) : 0;
|
|
$offset *= 10;
|
|
$sql = 'SELECT * FROM posts ORDER BY create_at DESC LIMIT ?,10';
|
|
$query = $db->prepare($sql);
|
|
$query->bindValue(1, $offset, \PDO::PARAM_INT);
|
|
$query->execute();
|
|
$posts = $query->fetchAll(\PDO::FETCH_CLASS, 'Core\\Record');
|
|
$offset += 10;
|
|
$query->bindValue(1, $offset, \PDO::PARAM_INT);
|
|
$query->execute();
|
|
$next = $query->fetchAll(\PDO::FETCH_CLASS, 'Core\\Record');
|
|
$sql = 'SELECT id, keyword, COUNT(id) AS num_of_posts FROM ('.
|
|
'tags JOIN post_tag ON id=tag_id) GROUP BY id ORDER BY keyword';
|
|
$query = $db->prepare($sql);
|
|
$query->execute();
|
|
$tags = $query->fetchAll(\PDO::FETCH_CLASS, 'Core\\Record');
|
|
$is_last = count($next) == 0 ? true : false;
|
|
return view('post.index', [
|
|
'posts' => $posts,
|
|
'tags' => $tags,
|
|
'page' => $page,
|
|
'is_last' => $is_last,
|
|
'pager_uri' => ''
|
|
]);
|
|
}
|
|
|
|
public function showCreate()
|
|
{
|
|
return view('post.create', [
|
|
'title' => '',
|
|
'content' => '',
|
|
'tags' => ''
|
|
]);
|
|
}
|
|
|
|
public function show($id)
|
|
{
|
|
$post = $this->getPost($id);
|
|
if ($post != null) {
|
|
return view('post.show', [
|
|
'post' => $post,
|
|
'tags' => $this->getTags($id),
|
|
'comments' => $this->getComments($id)
|
|
]);
|
|
}
|
|
throw new \Phroute\Phroute\Exception\HttpRouteNotFoundException;
|
|
}
|
|
|
|
public function showUpdate($id)
|
|
{
|
|
if (! $this->isAuthor($id)) {
|
|
header('HTTP/1.0 403 Forbidden');
|
|
die();
|
|
return false;
|
|
}
|
|
if ($post = $this->getPostWithTags($id)) {
|
|
return view('post.edit', ['post' => $post]);
|
|
}
|
|
throw new \Phroute\Phroute\Exception\HttpRouteNotFoundException;
|
|
}
|
|
|
|
public function create()
|
|
{
|
|
if (! $this->titleValid()) {
|
|
header('Location: /post/create');
|
|
return false;
|
|
}
|
|
$id = $this->setPost();
|
|
$tags = array_values(array_filter(
|
|
array_map('trim', explode(',', $_POST['tags']))
|
|
));
|
|
$this->setTags($tags);
|
|
$this->syncPostTag($id, $tags);
|
|
header("Location: /post/$id");
|
|
return false;
|
|
}
|
|
|
|
public function update($id)
|
|
{
|
|
if (! $this->isAuthor($id)) {
|
|
header('HTTP/1.0 403 Forbidden');
|
|
die();
|
|
return false;
|
|
}
|
|
if (! $this->titleValid()) {
|
|
header("Location: /post/$id/edit");
|
|
return false;
|
|
}
|
|
$this->updatePost($id);
|
|
$tags = array_values(array_filter(
|
|
array_map('trim', explode(',', $_POST['tags']))
|
|
));
|
|
$this->setTags($tags);
|
|
$this->syncPostTag($id, $tags);
|
|
header("Location: /post/$id");
|
|
return false;
|
|
}
|
|
|
|
public function delete($id)
|
|
{
|
|
if (! $this->isAuthor($id)) {
|
|
header('HTTP/1.0 403 Forbidden');
|
|
die();
|
|
return false;
|
|
}
|
|
$sql = 'DELETE FROM posts WHERE id=?';
|
|
$query = db()->prepare($sql);
|
|
$query->execute([$id]);
|
|
$path = parse_url($_SERVER['HTTP_REFERER'])['path'];
|
|
if (preg_match('/^\/post\//', $path)) {
|
|
header('Location: /');
|
|
return false;
|
|
}
|
|
header("Location: $path");
|
|
return false;
|
|
}
|
|
|
|
private function isAuthor($id)
|
|
{
|
|
$sql = 'SELECT author FROM posts WHERE id=?';
|
|
$query = db()->prepare($sql);
|
|
$query->execute([$id]);
|
|
$post = $query->fetchAll(\PDO::FETCH_CLASS, 'Core\\Record');
|
|
return (count($post) != 0 &&
|
|
$post[0]->author == $_SESSION['username']);
|
|
}
|
|
|
|
private function titleValid()
|
|
{
|
|
if (empty(trim($_POST['title']))) {
|
|
$_SESSION['errors'] = ['Post title cannot be empty.'];
|
|
$_SESSION['inputs'] = [
|
|
'title' => $_POST['title'],
|
|
'content' => $_POST['content'],
|
|
'tags' => $_POST['tags']
|
|
];
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
private function getPost($id)
|
|
{
|
|
$sql = 'SELECT p.*, COUNT(c.id) AS num_of_comments FROM posts AS p ' .
|
|
'LEFT JOIN comments AS c ON p.id=c.comment_to WHERE p.id=:id';
|
|
$query = db()->prepare($sql);
|
|
$query->bindValue(':id', $id, \PDO::PARAM_INT);
|
|
$query->execute();
|
|
$post = $query->fetchAll(\PDO::FETCH_CLASS, 'Core\\Record');
|
|
if (count($post) != 0) {
|
|
return $post[0];
|
|
}
|
|
return null;
|
|
}
|
|
|
|
private function getTags($id)
|
|
{
|
|
$sql = 'SELECT * FROM tags WHERE id IN ( ' .
|
|
"SELECT tag_id FROM post_tag WHERE post_id=? ) ORDER BY keyword";
|
|
$query = db()->prepare($sql);
|
|
$query->execute([$id]);
|
|
return $query->fetchAll(\PDO::FETCH_CLASS, 'Core\\Record');
|
|
}
|
|
|
|
private function getComments($id)
|
|
{
|
|
$sql = 'SELECT c.*, u.email FROM comments AS c, users AS u ' .
|
|
'WHERE c.comment_to=? AND c.author=u.name ORDER BY c.create_at';
|
|
$query = db()->prepare($sql);
|
|
$query->execute([$id]);
|
|
return $query->fetchAll(\PDO::FETCH_CLASS, 'Core\\Record');
|
|
}
|
|
|
|
private function getPostWithTags($id)
|
|
{
|
|
$sql = "SELECT p.*, GROUP_CONCAT(DISTINCT t.keyword SEPARATOR ', ') AS tags " .
|
|
'FROM posts AS p, tags AS t WHERE p.id=:id AND t.id IN ( ' .
|
|
'SELECT tag_id FROM post_tag WHERE post_id=:id ) ORDER BY t.keyword';
|
|
$query = db()->prepare($sql);
|
|
$query->bindValue(':id', $id, \PDO::PARAM_INT);
|
|
$query->execute();
|
|
$post = $query->fetchAll(\PDO::FETCH_CLASS, 'Core\\Record');
|
|
if (count($post) != 0) {
|
|
return $post[0];
|
|
}
|
|
return null;
|
|
}
|
|
|
|
private function setPost()
|
|
{
|
|
$db = db();
|
|
$sql = 'INSERT INTO posts VALUES (NULL, ?, ?, ?, DEFAULT, DEFAULT)';
|
|
$query = $db->prepare($sql);
|
|
$query->execute([
|
|
trim($_POST['title']),
|
|
trim($_POST['content']),
|
|
$_SESSION['username']
|
|
]);
|
|
return $db->lastInsertId();
|
|
}
|
|
|
|
private function updatePost($id)
|
|
{
|
|
$sql = 'UPDATE posts SET title=?, content=? WHERE id=?';
|
|
$query = db()->prepare($sql);
|
|
$query->execute([
|
|
trim($_POST['title']),
|
|
trim($_POST['content']),
|
|
$id
|
|
]);
|
|
}
|
|
|
|
private function setTags($tags)
|
|
{
|
|
if (count($tags) != 0) {
|
|
$rows = [];
|
|
foreach ($tags as $tag) {
|
|
array_push($rows, "(NULL, ?)");
|
|
}
|
|
$sql = 'INSERT INTO tags VALUES ' . implode(', ', $rows) .
|
|
' ON DUPLICATE KEY UPDATE keyword=keyword';
|
|
$query = db()->prepare($sql);
|
|
$query->execute($tags);
|
|
}
|
|
}
|
|
|
|
private function syncPostTag($post_id, $tags)
|
|
{
|
|
$db = db();
|
|
if (count($tags) != 0) {
|
|
$tuple_holders = [];
|
|
$element_holders = [];
|
|
$rows = [];
|
|
$tag_ids = $this->tagsToIds($tags);
|
|
foreach ($tag_ids as $tag_id) {
|
|
array_push($tuple_holders, '(?, ?)');
|
|
array_push($element_holders, '?');
|
|
array_push($rows, $post_id, $tag_id);
|
|
}
|
|
$sql = 'INSERT INTO post_tag VALUES ' . implode(', ', $tuple_holders) .
|
|
' ON DUPLICATE KEY UPDATE post_id=post_id';
|
|
$query = $db->prepare($sql);
|
|
$query->execute($rows);
|
|
$sql = 'DELETE FROM post_tag WHERE post_id=? AND tag_id NOT IN ' .
|
|
'(' . implode(', ', $element_holders) . ')';
|
|
$query = $db->prepare($sql);
|
|
$query->bindValue(1, $post_id, \PDO::PARAM_INT);
|
|
foreach ($tag_ids as $index => $tag_id) {
|
|
$query->bindValue($index + 2, $tag_id, \PDO::PARAM_INT);
|
|
}
|
|
$query->execute();
|
|
} else {
|
|
$sql = 'DELETE FROM post_tag WHERE post_id=?';
|
|
$query = $db->prepare($sql);
|
|
$query->execute([$post_id]);
|
|
}
|
|
}
|
|
|
|
private function tagsToIds($tags)
|
|
{
|
|
$element_holders = [];
|
|
foreach ($tags as $tag) {
|
|
array_push($element_holders, '?');
|
|
}
|
|
$sql = 'SELECT DISTINCT id FROM tags WHERE keyword IN ' .
|
|
'(' . implode(', ', $element_holders) . ') ORDER BY id';
|
|
$query = db()->prepare($sql);
|
|
$query->execute($tags);
|
|
return $query->fetchAll(\PDO::FETCH_COLUMN, 0);
|
|
}
|
|
}
|