<?php
/**
* $Id: class.xml.php,v0.1 2005/01/30 16:36:22 stan_f Exp $
* Class encapsulating XML messages storage for a guestbook
* Performs all basic operations that should be available to manage messages
* This is free software distributed under the terms of GPL.
* You can modify the source to fit your purposes.
*
* Found that PHP 5.0.3 isn't too solid working with DOMXML. Some of necessary
* methods are not implemented yet and the old ones are history. There's lack of docs,
* so one has to guess HOW and WHAT to use :=(
*
* @project XML_Guestbook
* @author Stan F <hide@address.com>
* @site http://northernsun.spb.ru
* @depends none
* @platform *nix/win32, designed for PHP4 and for sure incompatible with PHP5
*/
/**
* Class representing one message. This is to create some logic in passing info to ANY
* message handler that I plan to implement in the future ( not only XML, but also FILE and DB )
* It isn't well documented cuz I think everything here is pretty transparent.
*/
class CommonMessage{
var $id;
var $stat;
var $name;
var $ip;
var $date;
var $email;
var $url;
var $msg;
var $_init = false;
// Constructor/PHP4
function CommonMessage( $stat, $name, $ip, $msg, $url = '', $email = '', $date = '', $id = 0 ){
$this->id = $id;
$this->stat = $stat;
$this->name = $name;
$this->ip = $ip;
$this->date = $date;
$this->email = $email;
$this->url = $url;
$this->msg = $msg;
// mark this instance initiated
$this->_init();
}
// Init the object
function _init(){
$this->_init = true;
}
// Check the init
function is_init(){
return $this->_init;
}
// Encode the messages to keep em off breaking XML
function encode(){
$vars = get_object_vars( $this );
foreach( $vars as $var_name=>$var_value ){
$this->$var_name = htmlspecialchars( $var_value );
}
}
}
/**
* Message Set class
* Encapsulates all basic operations required to manage messages and interact with the XML storage
* @var o_DOMDocument XML_MessageSet::xmltree
* @access (should be ) private
* @desc Holds the XML document contents
* @var string XML_MessageSet::xmlfile
* @access (should be ) private
* @desc XML storage filename
*/
class XML_MessageSet{
var $xmltree;
var $xmlfile;
//
// Construct the XML tree from file
// @param string $filename
//
function XML_MessageSet( $filename ){
$this->xmlfile = $filename;
$this->xmltree = domxml_open_file( $this->xmlfile );
}
//
// Save back to XML file
//
function save(){
$this->xmltree->dump_file( $this->xmlfile, false, true );
}
//
// Return ID for the new message
// @access private
//
function _id(){
$root = $this->xmltree->document_element();
$posts = $root->get_elements_by_tagname( 'post' );
$i = 0;
$max_id = 0;
// find maximal ID value
while( !empty( $posts[$i] ) ){
$mb = $posts[$i];
$max_id = $mb->get_attribute( 'id' );
$i++;
}
// increase max ID value by one to gain uniqueness and return it
return $max_id + 1;
}
//
// Add new message to XML tree
// @param o_CommonMessage $msg
// @desc CommonMessage instance containing full message info
//
function add( $msg ){
// get new ID
$id = $this->_id();
// create new 'post' element
$el = new DOMElement( 'post' );
// set ID and date *attributes*
$el->set_attribute( 'id', $id );
$el->set_attribute( 'date', date('d.m.Y H:i:s') );
// creating child nodes and appending 'em to post:
$stat = new DOMNode( 'stat' );
$stat->set_content( $msg->stat );
$el->append_child( $stat );
$name = new DOMNode( 'name' );
$name->set_content( $msg->name );
$el->append_child( $name );
$ip = new DOMNode( 'ip' );
$ip->set_content( $msg->ip );
$el->append_child( $ip );
$email = new DOMNode( 'email' );
$email->set_content( $msg->email );
$el->append_child( $email );
$url = new DOMNode( 'url' );
$url->set_content( $msg->url );
$el->append_child( $url );
$msg = new DOMNode( 'msg' );
$msg->set_content( $msg->msg );
$el->append_child( $msg );
// tie the new post to XML tree
$root = $this->xmltree->document_element();
$root->append_child( $el );
}
//
// Drop messages
// @param array $drop
// @desc Get an array of integers and remove elements with matching IDs
//
function drop( $drop ){
$root = $this->xmltree->document_element();
$posts = $root->get_elements_by_tagname( 'post' );
// loop through posts and get rid of ones with IDs contained in $drop
foreach( $posts as $post ){
if( in_array( $post->get_attribute('id'), $drop ) ){
$root->remove_child( $post );
}
}
}
//
// Replace messages with new ones: create updated node to replace
// the old one with, and replacement itself
// @param o_CommonMessage $msg
// @desc New XML element. Note that the ID should be set to nonzero _explicitly_,
// or the replacement will probably fail!
// Will replace the element with id == $msg::id.
//
function replace( $msg ){
// The algorithm is much like XML_MessageSet::add(), but instead of blind tying
// the new element will replace the old one. If ID doesn't match any existing one,
// no changes done to the tree.
// -------------------------------------------------------------------------------
// create new 'post' element
$root = $this->xmltree->document_element();
$el = new DOMElement( 'post' );
// set ID and date *attributes*
$el->set_attribute( 'id', $msg->id );
$el->set_attribute( 'date', $msg->date );
// creating child nodes and appending 'em to post:
$stat = new DOMNode( 'stat' );
$stat->set_content( '3'.$msg->stat );
$el->append_child( $stat );
$name = new DOMNode( 'name' );
$name->set_content( $msg->name );
$el->append_child( $name );
$ip = new DOMNode( 'ip' );
$ip->set_content( $msg->ip );
$el->append_child( $ip );
$email = new DOMNode( 'email' );
$email->set_content( $msg->email );
$el->append_child( $email );
$url = new DOMNode( 'url' );
$url->set_content( $msg->url );
$el->append_child( $url );
// replace the existing post
$old = $this->xmltree->get_elements_by_tagname( 'post' );
foreach( $old as $old_one ){
if( $old_one->get_attribute( 'id' ) == $msg->id ){
// NOTE THAT THERE'S A MISTAKE IN THE DOCS
// AND *THIS* ARGS ORDER IS THE RIGHT ONE!
$root->replace_child( $el, $old_one );
}
}
}
//
// Return array of CommonMessage objects
// This way, all XML manipulations are just inside the class
//
function retrieve_messages_array(){
$root = $this->xmltree->document_element();
// Retrieve all posts
$posts = $root->get_elements_by_tagname( 'post' );
$nodenames = array( 'stat', 'name', 'ip', 'email', 'url', 'msg' );
$posts_array = array();
foreach( $posts as $post ){
$id = $post->get_attribute( 'id' );
$date = $post->get_attribute( 'date' );
$name = ''; $stat = 0; $ip = ''; $email = ''; $url = ''; $msg = '';
$children = $post->child_nodes();
foreach( $children as $child ){
$_tname = $child->node_name();
if( in_array( $_tname, $nodenames ) ){
${$_tname} = $child->get_content();
}
}
$cmsg = new CommonMessage( $stat, $name, $ip, $msg, $url, $email, $date, $id );
$posts_array[] = $cmsg;
}
return $posts_array;
}
//
// Installation: create empty XML file with root element
// You can call it statically if you're lazy to create empty XML.
//
function install( $xmlfilename ){
$xmldoc = domxml_new_doc( '1.0' );
$xmldoc->add_root( 'guestbook' );
$xmldoc->dump_file( $xmlfilename );
echo "Now you can use file '$xmlfilename' as your XML storage.";
}
}
?>