Developing Article Blog CMS

This commit is contained in:
Samuel Ortion 2021-04-02 10:13:23 +02:00
parent 3ef76404a7
commit 52dd9b6ce0
9 changed files with 437 additions and 1 deletions

View File

@ -28,7 +28,7 @@ include("$root/analytics/matomo.php");
<h3>Author</h3>
<p>This website is developped with &#9829; by Samuel ORTION, a juvenile <em>Geekus biologicus</em>.</p>
<h3>Source code</h3>
<p>This project is available under the GNU Affero GPL v3 license at <a href="https://forge.ortion.xyz/UncleSamulus/chiro-canto">https://forge.ortion.xyz/UncleSamulus/chiro-canto</a>.</p>
<p>This project is available under the GNU Affero GPL v3 license at <a href="https://forge.ortion.xyz/Chiro-Canto/chiro-canto">https://forge.ortion.xyz/Chiro-Canto/chiro-canto</a>.</p>
</section>
<?php include("$root/footer.php");?>
</body>

122
public/articles/Article.php Normal file
View File

@ -0,0 +1,122 @@
<?php
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
$root = realpath($_SERVER["DOCUMENT_ROOT"]);
require "$root/database/credentials.php";
// Connect the database
try {
$db = new PDO("mysql:host=$host;dbname=$database;charset=utf8",
$user,
$password,
array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
));
} catch (Exception $e) {
die("Error : ".$e->getMessage());
}
class Article
{
public $id = null;
public $publication_date = null;
public $modification_date = null;
public $title = null;
public $summary = null;
public $content = null;
public $author_id = null;
public function __construct( $data=array() ) {
if ( isset( $data['id'] ) ) $this->id = (int) $data['id'];
if ( isset( $data['publication_date'] ) ) $this->publication_date = (int) $data['publication_date'];
if ( isset( $data['modification_date'] ) ) $this->modification_date = (int) $data['modification_date'];
if ( isset( $data['title'] ) ) $this->title = preg_replace ( "/[^\.\,\-\_\'\"\@\?\!\:\$ a-zA-Z0-9()]/", "", $data['title'] );
if ( isset( $data['summary'] ) ) $this->summary = preg_replace ( "/[^\.\,\-\_\'\"\@\?\!\:\$ a-zA-Z0-9()]/", "", $data['summary'] );
if ( isset( $data['content'] ) ) $this->content = $data['content'];
if ( isset( $data['author_id'] ) ) $this->author_id = $data['author_id'];
}
public function storeFormValues($params) {
$this->__construct($params);
if (isset($params['publication_date'])) {
$publication_date = explode('-', $params['publication_date']);
if(count($publication_date) == 3) {
list($y, $m, $d) = $publication_date;
$this->publication_date = mktime(0, 0, 0, $m, $d, $y);
}
}
}
public static function getById($id)
{
global $db;
$req = $db->prepare('SELECT *, UNIX_TIMESTAMP(publication_date) AS publication_date FROM articles WHERE id=:id');
$req->execute(array(
"id"=>$id
));
if ($data = $req->fetch()) {
return new Article($data);
}
}
public static function getList($num = 1000000) {
global $db;
$req = $db->prepare('SELECT *, UNIX_TIMESTAMP(created_on) AS publication_date FROM articles ORDER BY created_on DESC LIMIT 5');
$req->execute();//array(
// "num_rows"=>$num
// ));
$list = array();
while ($row = $req->fetch()) {
$article = new Article($row);
$list[] = $article;
}
return $list;
}
public function insert() {
if (! is_null($this->id)) {
trigger_error("Article::insert(): Attempt to insert an Article object that already has its ID property set (to $this->id).", E_USER_ERROR);
}
global $db;
$req = $db->prepare('INSERT INTO articles (publication_date, modification_date, title, summary, content) VALUES (FROM_UNIXTIME(:publication_date), FROM_UNIXTIME(:modification_date), :title, :summary, :content, :author_id');
$req->execute(array(
"publication_date"=>$this->publication_date,
"modification_date"=>$this->modification_date,
"title"=>$this->title,
"summary"=>$this->summary,
"content"=>$this->content,
"author_id"=>$this->author_id
));
$this->id = $db->lastInsertedId();
}
public function update() {
if (is_null($this->id))
{
trigger_error("Article::update(): Attempt to update an Article object that does not have its ID property set.", E_USER_ERROR);
}
global $db;
$req = $db->prepare('UPDATE article SET modification_date=FROM_UNIXTIMESTAMP(:modification_date), title=:title, summary=:summary, content=:content WHERE id=:id');
$req->execute(array(
"modification_date"=>$this->modification_date,
"title"=>$this->title,
"summary"=>$this->summary,
"content"=>$this->content,
"id"=>$this->id
));
}
public function delete() {
if (is_null($this->id))
{
trigger_error( "Article::delete(): Attempt to delete an Article object that does not have its ID property set.", E_USER_ERROR);
}
global $db;
$req = $db->prepare('DELETE FROM articles WHERE id=:id LIMIT 1');
$req->execute(array(
"id"=>$this->id
));
}
}
?>

89
public/articles/admin.php Normal file
View File

@ -0,0 +1,89 @@
<?php
$root = realpath($_SERVER["DOCUMENT_ROOT"]);
session_start();
require("config.php");
require("Article.php");
$action = isset($_GET['action']) ? $_GET['action'] : "";
$username = isset($_SESSION['username']) ? $_SESSION['username'] : "";
if ($username == "") {
$_SESSION['error_msg'] = "You need to be logged in as administrator to perform these tasks.";
header("Location: $root/auth/login");
}
switch ($action) {
case 'new':
newArticle();
break;
case 'edit':
edit();
break;
case 'delete':
delete();
break;
default:
listArticles();
}
function newArticle() {
if (isset($_POST['save'])) {
$article = new Article;
$article->storeFormValues($_POST);
$article->insert();
header("Location: admin.php?status=saved");
} elseif (isset($_POST['cancel'])) {
header("Location: admin.php");
} else {
$results['article'] = new Article;
require("edit.php");
}
}
function edit() {
$results = array();
$results['pageTitle'] = "Edit Article";
$result['form'] = "edit";
if (isset($_POST['save'])) {
if (!$article = Article::getById((int)$_POST['id'])) {
header( "Location: admin.php?error=notFound" );
return;
}
$article->storeFormValues($_POST);
$article->update();
header("Location: admin.php?status=saved");
} elseif (isset($_POST['cancel'])) {
header("Location: admin.php");
} else {
$results['article'] = Article::getById((int)$_GET['article']);
require("edit.php");
}
}
function delete() {
if (!$article = Article::getById((int) $_GET['article'])) {
header("Location: admin.php?error=notFound");
return;
}
$article->delete();
header("Location: admin.php?status=deleted");
}
function listArticles() {
$results = array();
$data = Article::getList();
$results['articles'] = $data['results'];
$results['totalRows'] = $data['totalRows'];
$results['pageTitle'] = "All Articles";
if (isset($_GET['error'])) {
if ($_GET['error'] == "notFound") {
$results['error'] = "Error: Article not found.";
}
}
if ( isset( $_GET['status'] ) ) {
if ( $_GET['status'] == "saved" ) $results['status'] = "Your changes have been saved.";
if ( $_GET['status'] == "deleted" ) $results['status'] = "Article deleted.";
}
require("list.php");
}
?>

View File

@ -0,0 +1,43 @@
<?php
session_start();
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
$root = realpath($_SERVER["DOCUMENT_ROOT"]);
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Explore | Chiro - Canto</title>
<link rel="stylesheet" type="text/css" href="/styles/style.css">
</head>
<?php
include("$root/analytics/matomo.php");
?>
<body>
<?php include("$root/menu.php");?>
<?php include("$root/header.php");?>
<h2>Articles Archive</h2>
<ul id="headlines" class="arcive">
<?php
foreach ($results['articles'] as $article) {
?>
<li>
<h2><span class="pub-date"><?=date('j F Y', $article->publication_date)?></span>
<a href="?action=view&article=<?=$article->id?>"><?=htmlspecialchars($article->title)?></a>
</h2>
<p class="summary"><?php echo htmlspecialchars($article->summary)?></p>
</li>
<?php
}
?>
</ul>
<p><a href="?action=archive">Article Archive</a></p>
<?php include("$root/footer.php");?>
</body>
<script src="/scripts/script.js"></script>
</html>

View File

@ -0,0 +1,3 @@
<?php
define("HOMEPAGE_NUM_ARTICLES", 5);
?>

25
public/articles/home.php Normal file
View File

@ -0,0 +1,25 @@
<?php
session_start();
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
$root = realpath($_SERVER["DOCUMENT_ROOT"]);
?>
<h2>Articles Home</h2>
<ul>
<?php
print_r($results);
foreach ($results['articles'] as $article) {
?>
<li>
<h2><span class="pub-date"><?=date('j F Y', $article->publication_date)?></span>
<a href="?action=view&article=<?=$article->id?>"><?=htmlspecialchars($article->title)?></a>
</h2>
<p class="summary"><?php echo htmlspecialchars($article->summary)?></p>
</li>
<?php
}
?>
</ul>
<p><a href="?action=archive">Article Archive</a></p>

73
public/articles/index.php Normal file
View File

@ -0,0 +1,73 @@
<?php
$root = realpath($_SERVER["DOCUMENT_ROOT"]);
require("$root/articles/config.php");
require("$root/articles/Article.php");
function archive() {
$result = array();
$data = Article::getList();
$result['articles'] = $data['results'];
$result['totalRows'] = $data['totalRows'];
$result['pageTitle'] = "Article Archive | Chiro - Canto";
require("$root/articles/archive.php");
}
function view() {
if (! isset($_GET['article']) || ! $_GET['article']) {
home();
return;
}
$results = array();
$results['article'] = Article::getById( (int)$_GET["articleId"] );
$results['pageTitle'] = $results['article']->title . " | Chiro - Canto";
require("$root/articles/view.php");
}
function home() {
$results = array();
$data = Article::getList(HOMEPAGE_NUM_ARTICLES);
$results['articles'] = $data['results'];
$results['totalRows'] = $data['totalRows'];
$results['pageTitle'] = "Articles | Chiro - Canto";
require("home.php");
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Articles | Chiro - Canto</title>
<link rel="stylesheet" type="text/css" href="/styles/style.css">
</head>
<?php
include("$root/analytics/matomo.php");
?>
<body>
<?php include("$root/menu.php");?>
<?php include("$root/header.php");?>
<section>
<?php
$action = isset($_GET['action']) ? $_GET['action'] : "";
switch ($action) {
case 'archive':
archive();
break;
case 'view':
view();
break;
default:
home();
}
?>
<h2>Articles</h2>
<article>
<h3></h3>
</article>
</section>
<?php include("$root/footer.php");?>
</body>
<script src="/scripts/script.js"></script>
</html>

49
public/articles/list.php Normal file
View File

@ -0,0 +1,49 @@
<?php
session_start();
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
$root = realpath($_SERVER["DOCUMENT_ROOT"]);
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Explore | Chiro - Canto</title>
<link rel="stylesheet" type="text/css" href="/styles/style.css">
</head>
<?php
include("$root/analytics/matomo.php");
?>
<body>
<?php include("$root/menu.php");?>
<?php include("$root/header.php");?>
<h2>All Articles</h2>
<?php if (isset($results['error'])) { ?>
<div class="error"><?php echo $results['error'] ?></div>
<?php }
if (isset($results['status'])) {?>
<div class="status"><?php echo $results['status'] ?></div>
<?php } ?>
<table>
<tr>
<th>Publication Date</th>
<th>Article</th>
</tr>
<?php foreach($results['articles'] as $article) { ?>
<tr>
<td><?php echo date('j M Y', $article->publication_date)?></td>
<td>
<?php echo $article->title?>
</td>
</tr>
<?php } ?>
</table>
<p><a href="admin.php?action=new">New article</a></p>
<p><a href="./">Return to Homepage</a></p>
<?php include("$root/footer.php");?>
</body>
<script src="/scripts/script.js"></script>
</html>

32
public/articles/view.php Normal file
View File

@ -0,0 +1,32 @@
<?php
session_start();
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
$root = realpath($_SERVER["DOCUMENT_ROOT"]);
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Explore | Chiro - Canto</title>
<link rel="stylesheet" type="text/css" href="/styles/style.css">
</head>
<?php
include("$root/analytics/matomo.php");
?>
<body>
<?php include("$root/menu.php");?>
<?php include("$root/header.php");?>
<h2>Article</h2>
<h3><?php echo htmlspecialchars($results['article']->title)?></h3>
<div><?php echo htmlspecialchars($results['article']->summary)?></div>
<div><?php echo $results['article']->content?></div>
<p class="pub-date">Published on <?php echo date('j F Y', $results['article']->publication_date)?></p>
<p><a href="./">Return to Homepage</a></p>
<?php include("$root/footer.php");?>
</body>
<script src="/scripts/script.js"></script>
</html>