Lesson 6 - NOO-CMS - Article editor in PHP
In the previous lesson, NOO-CMS - User registration in PHP, we finished up the administration page for our simple content management system in PHP. In today's lesson, we will be adding a user log-in form as well as an article editor.
Signing-in
Let's create a sign-in.php script. The HTML part will be as follows:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8" /> <link rel="stylesheet" href="style.css" type="text/css" /> <title>Sign-in to administration</title> </head> <body> <article> <div id="centerer"> <header> <h1>Sign in to administration</h1> </header> <section> <?php if (isset($notice)) echo('<p>' . $notice . '</p>'); ?> <form method="post"> Name<br /> <input type="text" name="name" /><br /> password<br /> <input type="password" name="password" /><br /> <input type="submit" value="Sign-in" /> </form> <p>If you don't have an account yet, <a href="sign-up.php">sign-up</a>.</p> </section> <div class="clear"></div> </div> </article> </body> </html>
HTe code above includes a PHP directive used for error notice printing (if needed) and a form with name and password input fields. The code is almost the same as the registration form and should be easy to understand.
Now insert the following block of PHP above the HTML:
<?php session_start(); require('Db.php'); Db::connect('127.0.0.1', 'noocms_db', 'root', ''); if (isset($_SESSION['user_id'])) { header('Location: administration.php'); exit(); } if ($_POST) { $user = Db::queryOne(' SELECT user_id, admin FROM user WHERE name=? AND password=SHA1(?) ', $_POST['name'], $_POST['password'] . "t&#ssdf54gh"); if (!$user) $notice = 'Invalid name or password.'; else { $_SESSION['user_id'] = $user['user_id']; $_SESSION['user_name'] = $_POST['name']; $_SESSION['user_admin'] = $user['admin']; header('Location: administration.php'); exit(); } } ?>
The first couple of lines make the session accessible and establish a connection with the database. If the user is already signed in, we don't display the sign-in page. Instead, we redirect him/her to the administration page and terminate the script.
If the form is sent, we "salt" the password with the same salt we used for signing-in. Using the SHA1() SQL function we will, once again, compute a hash. The script will then try to find users with the given name and hash, we store an error notice in case of failure. If the query is successful, we sign the user in by storing the data provided by the session. Last of all, we redirect him/her to the administration page.
Go ahead and test it out by signing back in. If you are still signed in from last time, sign-out and sign back in again.

Assigning admin role
Each and every user has an admin column, which contains either a value of 0 or 1 based on whether a user is an administrator. This value can only be set by an administrator through phpMyAdmin. Let's move to phpMyAdmin and switch the value from 0 to 1 (all you have to do is click on it and change the value).

Now sign-out and sign back in again.
Article editor
Great, now let's move on to the article editor! Create an editor.php file and insert the following block of HTML into it:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8" /> <link rel="stylesheet" href="style.css" type="text/css" /> <title>Article editor</title> </head> <body> <article> <div id="centerer"> <header> <h1>Article editor</h1> </header> <section> <?php if (isset($notice)) echo('<p>' . $notice . '</p>'); ?> <form method="post"> <input type="hidden" name="article_id" value="<?= htmlspecialchars($article['article_id']) ?>" /><br /> title<br /> <input type="text" name="title" value="<?= htmlspecialchars($article['title']) ?>" /><br /> URL<br /> <input type="text" name="url" value="<?= htmlspecialchars($article['url']) ?>" /><br /> Description<br /> <input type="text" name="description" value="<?= htmlspecialchars($article['description']) ?>" /><br /> <textarea name="content"><?= htmlspecialchars($article['content']) ?></textarea> <input type="submit" value="Submit" /> </form> </section> <div class="clear"></div> </div> </article> <script type="text/javascript" src="//cdn.tinymce.com/4/tinymce.min.js"></script> <script type="text/javascript"> tinymce.init({ selector: "textarea[name=content]", plugins: [ "advlist autolink lists link image charmap print preview anchor", "searchreplace visualblocks code fullscreen", "insertdatetime media table contextmenu paste" ], toolbar: "insertfile undo redo | styleselect | bold italic | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | link image", entities: "160,nbsp", entity_encoding: "named", entity_encoding: "raw" }); </script> </body> </html>
All the code is, is a simple HTML form and an error notice printing condition. Data is filled into the form fields through the $article array. One last thing, the form has a hidden field with the ID of a given article. Based on whether the user is publishing a new article (in which case the hidden field will be empty) or editing an existing article (in which case it would contain the article ID).
At the bottom of the file, things get quite interesting. We load the TinyMCE WYSIWIYG editor, an editor that has the same interface as MS Word. It generates an HTML code based on what we click.
The first script references a content delivery network (CDN), from which we download the TinyMCE. The second contains the configuration needed to use the editor. The way it is set up now means that we chose to create an editor from a textarea named content. The following code sets the plugins and turns-off the encoding that converts accent characters to entities, which causes very nasty problems in countries that use them.
Add the following block of PHP above the HTML code:
<?php session_start(); if (empty($_SESSION['user_admin'])) die('Access denied'); require('Db.php'); Db::connect('127.0.0.1', 'noocms_db', 'root', ''); $article = array( 'article_id' => '', 'title' => '', 'content' => '', 'url' => '', 'description' => '', ); if ($_POST) { if (!$_POST['article_id']) { Db::query(' INSERT INTO article (title, content, url, description) VALUES (?, ?, ?, ?) ', $_POST['title'], $_POST['content'], $_POST['url'], $_POST['description'], $_POST['keywords']); } else { Db::query(' UPDATE article SET title=?, content=?, url=?, description=? WHERE article_id=? ', $_POST['title'], $_POST['content'], $_POST['url'], $_POST['description'], $_POST['keywords'], $_POST['article_id']); } header('Location: index.php?article=' . $_POST['url']); exit(); } else if (isset($_GET['url'])) { $loadedArticle = Db::queryOne(' SELECT * FROM article WHERE url=? ', $_GET['url']); if ($loadedArticle) $article = $loadedArticle; else $message = 'Article was not found'; } ?>
If a user is not an administrator, we terminate the entire script and print an error message. To check whether an administrator has signed-in, the isset() function will not suffice. In this case, we'll have to use the empty() function. Remember, that there may be a 'user_admin' key in the session, but it must contain a value of 0 to meet the requirements.
After that, we connect to the database and prepare an array with empty values and store it in a variable named $article. We do this to keep the form empty in case a new article is created and also to avoid having PHP notify us of non-existing variables.
If the form was submitted, we check the hidden field. If it's empty, we insert a new article into the database. If there already is a value, we update the article with the given ID. We have yet to use the SQL UPDATE command yet but don't worry, it's very simple. All we'll have to do is set the needed columns using SET. The main thing here is not to forget the WHERE clause. We'll have to specify which rows are to be updated. Every single article would be updated with the new values otherwise!
We redirect to the article after adding or editing it.
If the form wasn't submitted, we check whether there is an article URL in GET. Meaning that we're trying to edit an article, so we try to load data into the $article variable from the actual article through the URL. The data would then be filled into form fields. We print an error message in case of failure.
Now run the editor and insert a new article with the URL set to "home". This article will be our homepage:

Make sure you save the article into the database! In the next lesson, NOO-CMS - Displaying articles in PHP, we will add the finishing touches to our NOO-CMS.
Did you have a problem with anything? Download the sample application below and compare it with your project, you will find the error easily.
Download
By downloading the following file, you agree to the license terms
Downloaded 93x (391.82 kB)
Application includes source codes in language PHP