Article
Build an XML-Based Content Management System with PHP
The Admin Index Page
The first page of our admin tool is the adminindex.php. This page lists all XML articles currently displayed on the site, allowing you to edit or delete them and change their status (to publish them, for example). It also allows you to create new XML articles.
The code for this page is very simple and compact. We want to include a link to the createArticle.php page. We want to open up the xml/ directory (where we'll store all the articles), pull out the names of each file and pass those names into the links to the editArticle.php page. We'll do the same for our delArticle.php page.
Here's the code for adminindex.php:
<?php
session_start();
if ($_SESSION["login"] != "true"){
header("Location:login.php");
$_SESSION["error"] = "<font color=red>You don't have privileges to see the admin page.</font>";
exit;
}
?>
<h1>Welcome to the Admin Index Page</h1>
<a href="createArticle.php">Create New XML Article</a><br><br>
<table border=0 cellspacing=0 cellpadding=3 width="85%">
<tr valign=top>
<td width="75%">
<table border=1 cellspacing=0 cellpadding=2>
<?php
$dh = opendir('./xml/');
while ($file = readdir($dh)){
if (eregi("^..?$", $file)) {
continue;
}
echo "<tr valign=top><td width=\"80%\">";
echo "<a href=\"editArticle.php?file=".$file . "\">".$file . "</a></td>";
echo "<td width=\"20%\">";
echo "<a href=\"delArticle.php?file=" .$file . "\">delete</a>";
echo " </td></tr>";
}
?>
</table>
</td></tr></table>
The Create Article Page
The createArticle.php page is very important—it allows the site administrator to create new XML articles on the site. It's just a simple form that allows site administrators to enter pertinent information. Each of the form fields maps to the XML document structure we figured out earlier.
The form will also check to make sure that users enter an ID—without an Article ID, most of the site's functionality won't work.
Here's the code for that page:
<?php
session_start();
if ($_SESSION["login"] != "true"){
header("Location:login.php");
$_SESSION["error"] = "<font color=red>You don't have privileges to see the admin page.</font>";
exit;
}
?>
<html>
<head>
<title>Create an XML Article</title>
<script>
function isReady(form){
if(form.id.value == "") {
alert("Please enter an ID!");
return false;
}
}
</script>
</head>
<body>
<h1>Create an XML Article</h1>
<a href="adminindex.php">Cancel</a><br><br>
<form name="createArticle" action="addArticle.php" method="post" onSubmit="return isReady(this)">
<table border=1 cellspacing=0 cellpadding=3>
<tr valign=top>
<td width="135">Article ID</td>
<td width="634"> <input name="id" type="text" id="id"> <br> <font size="-1">(no
spaces, must be unique)</font></td>
</tr>
<tr valign=top>
<td>Status</td>
<td>In Progress <input type="hidden" name="status" value="in progress"></td>
</tr>
<tr valign=top>
<td>Headline</td>
<td> <input name="headline" type="text" id="headline" size="60"></td>
</tr>
<tr valign=top>
<td>Author Name</td>
<td> <input name="name" type="text" id="name" size="30"></td>
</tr>
<tr valign=top>
<td>Author Email</td>
<td> <input name="email" type="text" id="email" size="30"></td>
</tr>
<tr valign=top>
<td>Keywords</td>
<td> <p>
<input name="keywords" type="text" id="keywords">
<font size="-1"><br>
</font><font size="-1">(separate keywords with commas)</font> </p></td>
</tr>
<tr valign=top>
<td>Abstract</td>
<td><textarea name="abstract" cols="50" rows="5" id="abstract"></textarea></td>
</tr>
<tr valign=top>
<td> <p>Article Body<br>
</p></td>
<td> <p>Intro paragraph:</p>
<p>
<textarea name="body[intro]" cols="70" rows="10" wrap="soft" id="body[intro]"></textarea>
</p>
<p>Main paragraph:</p>
<p>
<textarea name="body[main]" cols="70" rows="10" wrap="soft" id="body[main]" ></textarea>
</p>
<p> </p>
<p>Conclusion paragraph:</p>
<p>
<textarea name="body[conclusion]" cols="70" rows="10" wrap="soft"></textarea>
</p></td>
</tr>
<tr valign=top>
<td colspan=2> <div align="center">
<input type="submit" name="Add Article" value="Add Article">
<input name="reset" type="reset" id="reset" value="Reset">
</div></td>
</tr>
</table>
</form>
</body></html>
This form's action is set to the addArticle.php page, which uses DOMXML functions to create an XML article from the information in the form. Because this is a little complex, I'll go over the code section by section.
The first part of the code initializes our new XML file, setting the version and creating the root node, which is <article>.
<?php
//create document root
$doc = domxml_new_doc("1.0");
$root = $doc->create_element("article");
$root = $doc->append_child($root);
Next, we add an id attribute to the <article> node. First, however, we need to make sure that users have chosen a unique value, as the id will be used as the file name. We perform this check by looking at all the articles in the xml directory. If we find a filename that contains the id from the form (stored in the incoming $id variable), then we add a "–" and the number of seconds since the beginning of the UNIX epoch to our id. Although it's not considered good form to change user input without a warning, this will do for now. Finally, we add the id attribute to the <article> node.
//add ID attribute
//FIRST, let's make sure that the id they chose isn't going to overwrite a file!
$dh = opendir('./xml/');
while ($file = readdir($dh)){
$string = $id . \\\\".xml\\\\";
if (eregi("^\\.\\.?$", $file)) {
continue;
}
if (eregi($string, $file)){
$time = date("U"); //num of seconds since unix epoch
$id = $id . "-" . $time;
}
}
$root->set_attribute('id', $id);
Now that we've created the root, it's time to create each of that node's children in order. The first is <headline>. Notice that the <headline> node is a child of <article>, and that the headline text is a child of <headline>.
//create headline
$head = $doc->create_element("headline");
$head = $root->append_child($head);
$htext = $doc->create_text_node($headline);
$htext = $head->append_child($htext);
The same is true of the <author>, <email>, <abstract> and <status> nodes:
//create author name
$aname = $doc->create_element("author");
$aname = $root->append_child($aname);
$atext = $doc->create_text_node($name);
$atext = $aname->append_child($atext);
//create author email
$mail = $doc->create_element("email");
$mail = $root->append_child($mail);
$mtext = $doc->create_text_node($email);
$mtext = $mail->append_child($mtext);
//create abstract
$abs = $doc->create_element("abstract");
$abs = $root->append_child($abs);
$abstext = $doc->create_text_node($abstract);
$abstext = $abs->append_child($abstext);
//create status, always in progress when first created
$stat = $doc->create_element("status");
$stat = $root->append_child($stat);
$stat_text = $doc->create_text_node($status);
$stat_text = $stat->append_child($stat_text);
Next come the keywords:
//create keyword listing
$keylisting = $doc->create_element("keywords");
$keylisting = $root->append_child($keylisting);
$ktext = $doc->create_text_node($keywords);
$ktext = $keylisting->append_child($ktext);
The paragraphs can be handled as an array, as they are being passed in as body[lead], body[second], and so on. Our PHP code is set up to create para tags using these passed-in keys; we'll end up with tags named <para-lead>, <para-second>, and so on.
//create paras
if (is_array($body)){
foreach ($body as $K => $V){
if ($V != ""){
$para = $doc->create_element("para-$K");
$para = $root->append_child($para);
$ptext = $doc->create_text_node($V);
$ptext = $para->append_child($ptext);
//$para->set_attribute('order', $K);
}
}
}
Finally, we can write this entire XML tree to a file, using id as a filename, and send the user back to adminindex.php, where they should see the file they just created added to the list of XML articles.
//write to the file
$filename = "./xml/".$id . ".xml";
$doc->dump_file($filename, false, true);
//send user back to adminindex
header("Location:adminindex.php");