<?php
/**
* The db2XML class provide an easy way to create XML file
* from a mysql database.
* Designed to be very flexible in the way it should create the XML file :
* Database data is extracted and saved into the object in save points
* These save points will be loaded and inserted in the XML.
* See the sample file
*
* @author Fourat ZOUARI <hide@address.com>
* @version 0.2
* @license GPL, see LICENSE
*
* TODO:
* Separate the database layer to do only XML works, database stuff should be done from other sources
* That should offer more flexibility and ease the integration of the class
*/
class db2XML {
/**
* Provides the base skeleton data for the Output XML data.
* @var string
*/
private $xmlSkeleton = null;
/**
* Handle used for mysql connection
* @var handle
*/
private $dbHandle = null;
/**
* Provides the last error message
* If empty, then no error was thrown
* @var string
*/
private $lastErrorMsg = '';
/**
* Provides saved data from database
* This data will be parsed into XML
* @var array
*/
private $DBData = array();
/**
* Returns the XML data
* This should be the output member
*
* @return string
*/
public function getXML() {
return $this->xmlSkeleton->asXML();
}
/**
* Returns saved data for a given $savePoint
*
* @return string
*/
public function getDBData($savePoint) {
if (isset($this->DBData[$savePoint])) $ret = $this->DBData[$savePoint];
else $ret = false;
return $ret;
}
/**
* Set the last error message
*
* @return void
*/
private function setLastErrorMsg($errorMsg) {
$this->lastErrorMsg = $errorMsg;
}
/**
* This handler is called on the catch() bloc
* Should allways return false
* And it sets the last error message if the $msg is not empty
*
* @return void
*/
private function exceptionHandler($msg, $code = null) {
// if the error message was defined
// so save it
if (!empty($msg)) {
$this->setLastErrorMsg($msg);
}
// if not, then load previously saved error msg
else {
$msg = $this->lastErrorMsg;
}
throw new Exception($msg, $code);
return false;
}
/**
* Gets the content of $fileName
* Returns false and set the $this->lastErrorMsg if
* 1.The file was not found
* 2.The file is not readable
*
* @param string $fileName
* @return string The file data
*/
private function getXMLfromFile($fileName) {
try {
if (!file_exists($fileName)) throw new Exception('File '.$fileName.' is not found');
if (!is_readable($fileName)) throw new Exception('File '.$fileName.' is unreadable');
$data = file_get_contents($fileName);
if ($data === false) throw new Exception('Can\'t get contents of this file '.$fileName);
// return the file data
$ret = $data;
}
catch (Exception $e) {
$ret = $this->exceptionHandler($e->getMessage());
}
return $ret;
}
/**
* Connect to mysql
* return false on failure, true on success
* defines the $this->dbHandle on success
*
* @param string $hostname
* @param string $user
* @param string $password
* @param string $dbname
* @param string $persistentDB
* @return boolean
*/
private function mysql_connect($hostname, $user, $password, $dbname, $persistentDB) {
try {
// connect to database
if ($persistentDB) {
$tmp = @mysql_pconnect($hostname, $user, $password);
}
else {
$tmp = @mysql_connect($hostname, $user, $password);
}
if ($tmp == false) throw new Exception('Can\'t connect to database. : '.mysql_error());
// sets the global db handler
$this->dbHandle = $tmp;
// select the database
$tmp = mysql_select_db($dbname, $this->dbHandle);
if ($tmp == false) throw new Exception('Can\'t select database. : '.mysql_error());
$ret = true;
}
catch (Exception $e) {
$ret = $this->exceptionHandler($e->getMessage());
}
return $ret;
}
/**
* Executes a query
* return the resource
*
* @param string $query
* @return resource
*/
private function mysql_query($query) {
try {
$tmp = mysql_query($query, $this->dbHandle);
if ($tmp == false) throw new Exception('Can\'t query database. : '.mysql_error());
$ret = $tmp;
}
catch (Exception $e) {
$ret = $this->exceptionHandler($e->getMessage());
}
return $ret;
}
/**
* Fetch results into an array
*
* @param resource $res
* @return array
*/
private function mysql_fetch_all($res) {
$ret = array();
while ($row = mysql_fetch_array($res, MYSQL_ASSOC)) {
$ret[] = $row;
}
// avoid doing $ret[0] when we have only one element in that array
//if (count($ret) == 1) $ret = $ret[0];
return $ret;
}
/**
* Build the $XMLSkelData
* if an error was thrown, return false
* The class should be intiated under a try .. catch bloc
*
* @param string $xmlSkelFile
* @param string $hostname
* @param string $user
* @param string $password
* @param string $dbname
* @param string $persistentDB
* @return boolean
*/
public function __construct($xmlSkelFile, $dbHostname, $dbUser, $dbPassword, $dbName, $persistentDB = false) {
$ret = true;
// get the XMLSkelData
$XMLSkelData = $this->getXMLfromFile($xmlSkelFile);
$this->xmlSkeleton = $XMLSkelData;
// connect to database
$this->mysql_connect($dbHostname, $dbUser, $dbPassword, $dbName, $persistentDB);
// instantiate the SimpleXMLElement
$sxe = new SimpleXMLElement($this->xmlSkeleton);
if (!$sxe) $ret = $this->exceptionHandler('Can\'t load the xmlSkeleton.');
$this->xmlSkeleton = $sxe;
return $ret;
}
/**
* Destruct the DB handle
*
* @return void
*/
public function __destruct() {
if (!is_null($this->dbHandle)) mysql_close($this->dbHandle);
}
/**
* Create a new child named $details['name']
* It sets its type if $details['attribute'] is given
* Same thing with value.
*
* @param array $details
* @param string $parent The parent element
* @return boolean
*/
public function newChild($details, $parentElement='') {
try {
// load the XML data
$sxe = $this->xmlSkeleton;
// if we have to go to a parent element
if (!empty($parentElement)) {
$parent = $sxe->xpath($parentElement);
if ($parent == false) throw new Exception('Can\'t get the parent. '.$parentElement);
$sxe = $parent[0];// set it to the root
}
// create the child
if (!isset($details['name'])) throw new Exception('You should define name of the child in the $details.');
$value = (isset($details['value'])) ? urlencode($details['value']) : null;
$child = $sxe->addChild($details['name'], $value);
// set the attributes if given
if (isset($details['attribute'])) {
if (!isset($details['attribute']['name'])) throw new Exception('You should define name of the attribute in the $details.');
if (!isset($details['attribute']['value'])) throw new Exception('You should define value of the attribute in the $details.');
$child->addAttribute($details['attribute']['name'], $details['attribute']['value']);
}
$ret = true;
}
catch (Exception $e) {
$ret = $this->exceptionHandler($e->getMessage());
}
return $ret;
}
/**
* Fetch data from DB and save it to a given save point
* Data is returned and saved to $this->DBData[$dataSavePoint] for later use
*
* @param string $dataSavePoint
* @param string $query
* @return array
*/
public function setDataFromDB($dataSavePoint, $query) {
// query and fetch results
$res = $this->mysql_query($query);
$rows = $this->mysql_fetch_all($res);
// save the data
$this->DBData[$dataSavePoint] = $rows;
// optionally return the fetched data
return $rows;
}
}
?>