diff --git a/XMLDB.php b/XMLDB.php index 174677c..726beb5 100644 --- a/XMLDB.php +++ b/XMLDB.php @@ -7,26 +7,72 @@ class XMLDB{ // Primary key protected $_primaryKey; + // Selected table + protected $_table; + // XPATH protected $_xpath; // Content of the XML DB File protected $_doc; - public function __construct($file, $pk = "id"){ + /** + * Constructor + * @param $file string path to the file to read/create + * @param $pk string name of the primary key + * @param $createIfNotExist bool create the file if it doesn't exist + */ + public function __construct($file, $pk = "id", $createIfNotExist = false){ ini_set("display_errors", "off"); ini_set("log_errors", "on"); ini_set('error_log', $_SERVER['DOCUMENT_ROOT'].'/test/XMLDB/XMLDB.log'); $this->_primaryKey = $pk; $this->_file = $file; $this->_doc = new DOMDocument; - if(@$this->_doc->load($this->_file)) + $this->_doc->preserveWhiteSpace = false; + $this->_doc->formatOutput = true; + if($this->_doc->load($this->_file)){ $this->_xpath = new DOMXpath($this->_doc); - else{ - $this->_file = $file; - $this->_doc = null; - $this->xpath = null; } + else{ + if($createIfNotExist){ + $this->createDatabase($file); + }else{ + $this->_file = null; + $this->_doc = null; + $this->xpath = null; + } + } + } + + public function createDatabase($file){ + $this->_file = $file; + $this->_doc = DOMDocument::loadXML(' + + '); + $this->_xpath = new DOMXpath($this->_doc); + return $this->save(); + } + + public function createTable($name){ + if($name == '*' || $this->tableAlreadyExists($name)) + return false; + else + return $this->insertNode(array('name'=>'table', 'attributes'=>array('name'=>$name))); + } + + /** + * @return bool + */ + public function tableAlreadyExists($tableName){ + if($this->selectTable($tableName, 'count') >= 1) + return true; + return false; + } + + + public function selectTable($name, $format = 'node'){ + return $this->select($name, null, null, null, $format); } public function isLoaded(){ @@ -36,6 +82,10 @@ class XMLDB{ return false; } + public function count($from, $id = null, $attributes = null, $childs = null){ + return $this->select($from, $id, $attributes, $childs, 'count'); + } + public function setPrimaryKey($pk){ $this->_primaryKey = $pk; } @@ -53,6 +103,8 @@ class XMLDB{ */ public function save(){ if($this->_doc != null && $this->_file != null){ + $this->_doc->preserveWhiteSpace = false; + $this->_doc->formatOutput = true; $this->_doc->save($this->_file); return true; }else{ @@ -60,20 +112,60 @@ class XMLDB{ } } + // TODO checking $request + public function requestToArray($request){ + foreach($request as $element){ + /*if($childName != null && $childValue != null) + $element = $element->parentNode;*/ + $elementValue = $element->attributes->item(0)->value; + $return[$elementValue]['attributes'] = array(); + $return[$elementValue]['childs'] = array(); + + //Retrieving Attributes + $attributes = $element->attributes; + $length = $attributes->length; + for ($i = 1; $i <= $length; $i++) { + $return[$elementValue]['attributes'][$attributes->item($i)->name] = $attributes->item($i)->value; + } + + // Retrivieving childs + $nodes = $element->childNodes; + $length = $nodes->length; + for ($i = 1; $i <= $length; $i++) { + $return[$elementValue]['childs'][$nodes->item($i)->nodeName] = $nodes->item($i)->nodeValue; + } + } + return $return; + } + + /** + * Shortcuts for select + */ + public function selectFromAttribute($table, $attributes, $format = 'array'){ + return $this->select($table, null, $attributes, null, $format); + } + + public function selectFromChilds($table, $childs, $format = 'array'){ + return $this->select($table, null, null, $childs, $format); + } + + public function selectFromPK($table, $pk, $format = "array"){ + return $this->select($table, $pk, null, null, $format); + } + /** * Allows you to get an array of the node you're looking for based on a "where" search thanks to child or attribute value - * @param $from string Name of the node you're looking for + * @param $from string Name of the table * @param $id string value of the primary key * @param $childs array name/value of the child node * @param $attributes array name/value of the attribute * @return array */ - // TODO other format - public function selectNode($from, $id = null, $attributes = null, $childs = null, $format = 'array'){ + public function select($from, $id = null, $attributes = null, $childs = null, $format = 'array'){ if (!$from) { - throw new Exception('uhoh, no "where" statement?'); + throw new Exception('uhoh, no table selected'); } - if($id != null){ + if($id != null && count($id) == 1){ $attribute .= '[@' . $this->_primaryKey . ' = "' . $id . '"]'; } if($attributes != null){ @@ -82,49 +174,65 @@ class XMLDB{ } if($childs != null){ foreach($childs as $childName=>$childValue) - $child .= '/' . $childName . '[.="' . $childValue . '"]'; + $child .= '[' . $childName . '="' . $childValue . '"]'; + /*$child .= '/' . $childName . '[.="' . $childValue . '"]'; + if(count($childs)>1){ + $child = str_replace('/', '', $child); + $child = '/'.$child; + }*/ } - $request = $this->_xpath->query('//'.$from.$attribute.$child); - $requestLength = $request->length; - if($format == "array"){ - //$return = array('length'=>$requestLength, 'request'=>'//'.$from.$attribute.$child); - foreach($request as $element){ - if($childName != null && $childValue != null) - $element = $element->parentNode; - $elementValue = $element->attributes->item(0)->value; - $return[$elementValue]['attributes'] = array(); - $return[$elementValue]['childs'] = array(); - - //Retrieving Attributes - $attributes = $element->attributes; - $length = $attributes->length; - for ($i = 1; $i <= $length; $i++) { - $return[$elementValue]['attributes'][$attributes->item($i)->name] = $attributes->item($i)->value; - } - - // Retrivieving childs - $nodes = $element->childNodes; - $length = $nodes->length; - for ($i = 1; $i <= $length; $i++) { - $return[$elementValue]['childs'][$nodes->item($i)->nodeName] = $nodes->item($i)->nodeValue; - } - } - }else if($format == "node"){ - $return = $request; + if($from == '*') + $request = $this->_xpath->query('//item'.$attribute.$child); + else + $request = $this->_xpath->query('//table[@name = "'.$from.'"]/item'.$attribute.$child); + + switch($format){ + case "node": + $return = $request; + break; + case "count": + $return = $request->length; + break; + case "array": + default: + $return = $this->requestToArray($request); } return $return; } + /** + * Same as above, but user can build his own xpath + */ + public function select_xpath($from, $xpath, $format = 'array'){ + if (!$from || !$xpath) { + throw new Exception('uhoh, no table selected'); + } + $request = $this->_xpath->query('//table[@name = "'.$from.'"]/'.$xpath); + switch($format){ + case "node": + $return = $request; + break; + case "count": + $return = $request->length; + break; + case "array": + default: + $return = $this->requestToArray($request); + } + + return $return; + } + /** * Allows you to insert a node into your DB thanks to an array - * @param $node array - * @param $where string in which node you want to put it. By default, the root of the xml file + * @param $node array with 'name' 'attributes' and 'childs' + * @param $table string in which node you want to put it. By default, the root of the xml file * @param $position string 'before' or 'after' * @return bool */ // TODO other $where and $position - public function insertNode($node, $where = null, $position = null){ + public function insertNode($node, $table = null, $position = null){ if(!is_array($node) || !isset($node['name'])) return false; @@ -143,22 +251,31 @@ class XMLDB{ } // Inserting the node into the DB - if($where == null){ + // case : creation of a new table + if($table == null){ $this->_doc->firstChild->appendChild($element); + }else{ + // case : insertion into the end of table + //TODO checking if PK already exists + $request = $this->_xpath->query('//table[@name = "'.$table.'"]'); + if($request->length != 1){ + return false; + } + $request->item(0)->appendChild($element); } return $this->save(); } /** * - * @param $node string + * @param $table string * @param $oldAttribute string name of the attribute you want to change * @param $newAttribute array name/value of the attribute you want to add * @param $forceInsert bool * @return bool */ - public function updateNodeAttribute($node, $oldAttribute, $newAttribute, $forceInsert = false){ - $request = $this->selectNode($node, null, array($oldAttribute[0]=>$oldAttribute[1]), null, 'node'); + public function updateNodeAttribute($table, $oldAttribute, $newAttribute, $forceInsert = false){ + $request = $this->select($table, null, array($oldAttribute[0]=>$oldAttribute[1]), null, 'node'); if($request->length == 1){ if(!$forceInsert){ $request->item(0)->setAttribute($oldAttribute[0],$newAttribute[1]); @@ -173,12 +290,12 @@ class XMLDB{ /** * - * @param $node string + * @param $table string * @param $value string new value of the node * @return bool */ - public function updateNodeValue($node, $attribute = null, $child = null, $value){ - $request = $this->selectNode($node, null, array($attribute[0]=>$attribute[1]), null, 'node'); + public function updateNodeValue($table, $attribute = null, $child = null, $value){ + $request = $this->select($table, null, array($attribute[0]=>$attribute[1]), null, 'node'); //$request = $this->_xpath->query('//'.$node.'[@' . $attribute[0] . ' = "' . $attribute[1] . '"]'); if($request->length == 1){ $request = $request->item(0); @@ -192,22 +309,22 @@ class XMLDB{ } - public function deleteNode($node, $id = null, $attributes = null){ + public function deleteNode($table, $id = null, $attributes = null){ if($id != null && $attributes != null) return false; if($id != null) - $request = $this->selectNode($node, $id, null, null, 'node')->item(0); + $request = $this->select($table, $id, null, null, 'node')->item(0); if($attributes != null) - $request = $this->selectNode($node, null, array($attribute[0]=>$attribute[1]), null, 'node')->item(0); + $request = $this->select($table, null, array($attribute[0]=>$attribute[1]), null, 'node')->item(0); $request->parentNode->removeChild($request); return $this->save(); } + public function moveNode($node, $from, $to){ + + } + - - - - } \ No newline at end of file diff --git a/XMLDBtestUnit.php b/XMLDBtestUnit.php index 83dcd3d..8fde625 100644 --- a/XMLDBtestUnit.php +++ b/XMLDBtestUnit.php @@ -1,59 +1,88 @@ '; +if($xmldbtest1 = new XMLDB('test.xml', 'id', true)) + echo "ok"; +else + echo "ko"; +echo '
Creating new table (should be "ok" adding table1 in test)
'; +if($xmldbtest1->createTable('table1')) + echo "ok"; +else + echo "ko"; + +echo '
loading an inexistant DB (error)
'; $xmldbtest = new XMLDB('text.xml'); if(!$xmldbtest->isLoaded()){ - echo 'can\'t load test.xml
'; - $xmldbtest = new XMLDB('config.xml'); + echo '

can\'t load test.xml
'; + $xmldbtest = new XMLDB('database.xml'); if($xmldbtest->isLoaded()){ - // Testing selectNode($from, $attributeName = null, $attributeValue = null, $childName = null, $childValue = null) - echo 'Testing empty selectNode
'; + // Testing select($from, $attributeName = null, $attributeValue = null, $childName = null, $childValue = null) + echo 'Testing empty select (exception)
'; try { - $xmldbtest->selectNode(); + $xmldbtest->select(); } catch(Exception $e){ echo $e->getMessage().'

'; } - echo 'Testing selectNode
'; - $result = $xmldbtest->selectNode('item'); + echo '
Creating new table name "*" (should be "ko" table already exist)
'; +if($xmldbtest->createTable('*')) + echo "ok"; +else + echo "ko"; + + echo '
Creating new table (should be "ko" table already exist)
'; +if($xmldbtest->createTable('table1')) + echo "ok"; +else + echo "ko"; + echo '
Testing insertNode at XML root (should insert an item named "test" into table1)
'; + if($xmldbtest->insertNode(array('name'=>'item', 'attributes'=>array('id'=>'test'), 'childs'=>array('visibility'=>'true', 'x'=>'33')), 'table1')) + echo "ok

"; + else + echo "ko

"; + + echo 'Testing select (should give 8 results - 7 from the file + 1 we created earlier)
'; + $result = $xmldbtest->select('table1'); echo count($result).' results

'; - echo 'Testing selectNode id=weather with pk
'; - $result = $xmldbtest->selectNode('item', 'weather'); + echo 'Testing select id=weather with pk (should find 1 result)
'; + $result = $xmldbtest->selectFromPK('table1', 'weather'); echo count($result).' results

'; - echo 'Testing selectNode id=weather
'; - $result = $xmldbtest->selectNode('item', null, array('id'=>'weather')); + echo 'Testing select id=weather (should find 1 result)
'; + $result = $xmldbtest->select('table1', null, array('id'=>'weather')); echo count($result).' results

'; - echo 'Testing selectNode visibility = true
'; - $result = $xmldbtest->selectNode('item', null,null,array('visibility'=>'true')); + echo 'Testing select visibility = true (should throw 6 results - 5 from the base file + 1 we created)
'; + $result = $xmldbtest->select('table1', null,null,array('visibility'=>'true')); + echo count($result).' results

'; + + echo 'Testing select visibility = true on all tables (should find 8 results - 7 from the base file + 1 we created)
'; + $result = $xmldbtest->select('*', null,null,array('visibility'=>'true')); echo count($result).' results

'; - echo 'Testing selectNode visibility = true and x = 32
'; - $result = $xmldbtest->selectNode('item', null ,null,array('visibility'=>'true', 'x'=>'32')); - echo count($result).' results

'; + echo 'Testing select visibility = true and x = 32 (experimental - should find 1)
'; + $result = $xmldbtest->selectFromChilds('table1',array('visibility'=>'true', 'x'=>'32')); + echo count($result).' results

'; - echo '
Testing insertNode at XML root
'; - if($xmldbtest->insertNode(array('name'=>'item', 'attributes'=>array('id'=>'test'), 'childs'=>array('visibility'=>'true', 'x'=>'33')))) - echo "ok

"; - else - echo "ko

"; + - echo '
Testing updatingNodeAttribute with no insert
'; - if($xmldbtest->updateNodeAttribute('item', array('id', 'links'), array('id', 'zelda'))) + echo '
Testing updatingNodeAttribute with no insert (should be ok and change the item "links" into "zelda" haha)
'; + if($xmldbtest->updateNodeAttribute('table1', array('id', 'links'), array('id', 'zelda'))) echo "ok

"; else echo "ko

"; - echo '
Testing updateNodeValue via attribute
'; - if($xmldbtest->updateNodeValue('item', array('id', 'notes'), null, 'booga!')) + echo '
Testing updateNodeValue via attribute (should be ok - inserting "booga!" into the item named "notes")
'; + if($xmldbtest->updateNodeValue('table1', array('id', 'notes'), null, 'booga!')) echo "ok

"; else echo "ko

"; - echo '
Testing deleteNode via pk
'; - if($xmldbtest->deleteNode('item', 'test', null)) + echo '
Testing deleteNode via pk (should be ok - deleting the item clock into table1)
'; + if($xmldbtest->deleteNode('table1', 'clock', null)) echo "ok

"; else echo "ko

"; diff --git a/config.xml b/database.xml similarity index 88% rename from config.xml rename to database.xml index f71ae76..1760111 100644 --- a/config.xml +++ b/database.xml @@ -1,5 +1,6 @@ - + + false 950 @@ -30,6 +31,8 @@ 32 -2 +
+ false 80 @@ -60,4 +63,5 @@ true - +
+