PageRenderTime 44ms CodeModel.GetById 15ms RepoModel.GetById 1ms app.codeStats 0ms

/xmlbulletin.model.php

https://github.com/eijin/xmlbulletin
PHP | 347 lines | 238 code | 38 blank | 71 comment | 46 complexity | 50eb104fde07158f18126352345341aa MD5 | raw file
  1. <?php
  2. /* =========================================================================
  3. Xmlbulletin is to control XML file for Bulletin Board System
  4. Copyright (C) 2011 Eiji Nakai www.smallmake.com
  5. xmlbulletin.model.php: version 1.0.0 - May 8, 2011.
  6. Xmlbulletin Project Revision 1.0.0 - May 8, 2011.
  7. Xmlbulletin is licenced under the GPL.
  8. - xmlbulletin.class.php
  9. - xmlbulletin.model.php
  10. - xmlbulletin.view.php
  11. Using my following copyleft software
  12. - utility.php
  13. GPL:
  14. This program is free software; you can redistribute it and/or
  15. modify it under the terms of the GNU General Public License
  16. as published by the Free Software Foundation; either version 2
  17. of the License, or (at your option) any later version.
  18. This program is distributed in the hope that it will be useful,
  19. but WITHOUT ANY WARRANTY; without even the implied warranty of
  20. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  21. GNU General Public License for more details.
  22. You should have received a copy of the GNU General Public License
  23. along with this program; if not, write to the Free Software
  24. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  25. ============================================================================= */
  26. include_once("utility.php");
  27. class xmlbulletinModel {
  28. /* customizable values */
  29. public $title = "XML Bulletine Board";
  30. public $xml_file_name = "";
  31. public $xml_file_path = "";
  32. public $fore = array(
  33. "xmlbulletin" => array(
  34. 'title' => 'XML Bulletine Board',
  35. 'updated' => '{date("Y-m-d H:i:s")}',
  36. 'id' => 'tag:smallmake.com,{date("Y-m-d")},{uniqid()}',
  37. 'generator' => 'xmlbulletine'
  38. )
  39. );
  40. public $fore_attributes = array();
  41. public $item_parent = "xmlbulletin";
  42. public $item = array(
  43. 'entry' => array (
  44. 'title' => '',
  45. 'id' => 'tag:smallmake.com,{date("Y-m-d")},{uniqid()}',
  46. 'published' => '{date("Y-m-d H:i:s")}',
  47. 'author' => '',
  48. 'comment' => ''
  49. )
  50. );
  51. public $item_attributes = array();
  52. public $item_validations = array();
  53. /* valuables used inside */
  54. public $validation_errors = array();
  55. public $error;
  56. public $xe;
  57. private $xmlHead = '<?xml version="1.0" encoding="utf-8"?>';
  58. private $xmlFile;
  59. private $name;
  60. private $rootName;
  61. private $itemName;
  62. private $parentPath;
  63. private $itemPath;
  64. /*
  65. * Create or Load XML File
  66. */
  67. function __construct($name) {
  68. $this->name = $name;
  69. $keys = array_keys($this->fore);
  70. $this->rootName = $keys[0];
  71. $keys = array_keys($this->item);
  72. $this->itemName = $keys[0];
  73. $this->parentPath = '/' . $this->searchPath($this->fore, $this->item_parent); // path from root to parent of item
  74. $this->itemPath = $this->parentPath . '/' . $this->itemName;
  75. //
  76. if (empty($this->xml_file_name)) {
  77. $xmlFileName = (empty($this->name)) ? 'xmlbulletin.xml' : $this->name . '.xml';
  78. $this->xmlFile = $this->xml_file_path . $xmlFileName;
  79. } else {
  80. $this->xmlFile = $this->xml_file_path . $this->xml_file_name;
  81. }
  82. if (!file_exists($this->xmlFile) || filesize($this->xmlFile)==0) {
  83. if(!$this->create()) {
  84. $this->error = "Cannot create XML file.";
  85. }
  86. }
  87. if (!$this->xe = simplexml_load_file($this->xmlFile)) {
  88. $this->error = "Cannot load XML file.";
  89. }
  90. }
  91. function searchPath($a, $p, $path=array()) {
  92. foreach($a as $k=>$v) {
  93. if ($k == $p) {
  94. return (empty($path))? $k : implode('/',$path). '/' . $k;
  95. }
  96. if(is_array($v)) {
  97. $c_path = $path;
  98. $c_path[] = $k;
  99. if (($res = $this->searchPath($v, $p, $c_path)) !== false) return $res;
  100. }
  101. }
  102. return false;
  103. }
  104. /*
  105. * TOOLS
  106. */
  107. function getObjXPath(&$obj, $pathStr) {
  108. if(substr($pathStr,0,1) == '/') { $pathStr = substr($pathStr,1); }
  109. $path = preg_split('/\//',$pathStr);
  110. $ch = $obj;
  111. foreach($path as $c) {
  112. if(!empty($c) && ($c != $path[0])) { // $path[0] is $obj itself so skip it
  113. $ch = $ch->{$c};
  114. }
  115. }
  116. return $ch;
  117. }
  118. function getDomXPath(&$dom, $pathStr) {
  119. if(substr($pathStr,0,1) == '/') { $pathStr = substr($pathStr,1); }
  120. $path = preg_split('/\//',$pathStr);
  121. $ch = $dom;
  122. foreach($path as $c) {
  123. if(!empty($c) && ($c != $path[0])) { // $path[0] is $dom itself so skip it
  124. $ch = $ch->getElementsByTagName($c);
  125. }
  126. }
  127. return $ch;
  128. }
  129. /*
  130. *
  131. */
  132. public function get_item_objects() {
  133. return $this->getObjXPath($this->xe, $this->itemPath);
  134. }
  135. /*
  136. * Create XML File
  137. */
  138. function create() {
  139. $xml = $this->xmlHead . "\n";
  140. $xml .= "<{$this->rootName}></{$this->rootName}>\n";
  141. $this->xe = new SimpleXMLElement($xml);
  142. $this->addChild_recursive($this->xe,$this->fore[$this->rootName]);
  143. $this->addAttr($this->xe,$this->fore_attributes);
  144. return $this->xe->asXML($this->xmlFile);
  145. }
  146. /*
  147. * Save XML File
  148. */
  149. function save(&$data,$pos=NULL) {
  150. $this->validation_errors = array();
  151. // $this->validate_recursive will set results to $this->validation_errors
  152. $this->validate_recursive($this->item[$this->itemName], $data[$this->itemName],array($this->itemName));
  153. if (empty($this->validation_errors)) {
  154. if($pos === NULL) {
  155. $parent = $this->getObjXPath($this->xe, $this->parentPath);
  156. $obj = $parent->addChild($this->itemName);
  157. $this->addChild_recursive($obj, $this->item[$this->itemName], $data[$this->itemName],array($this->itemName));
  158. $this->addAttr($obj,$this->item_attributes);
  159. } else {
  160. $parent = $this->getObjXPath($this->xe, $this->parentPath);
  161. $obj = $parent->{$this->itemName}[intval($pos)];
  162. $this->updateChild_recursive($obj, $this->item[$this->itemName], $data[$this->itemName],array($this->itemName));
  163. }
  164. return $this->xe->asXML($this->xmlFile);
  165. } else {
  166. return false;
  167. }
  168. }
  169. /* Set Attribute */
  170. function addAttr(&$obj, $attr) {
  171. foreach ($attr as $k=>$v) {
  172. $o = $this->getObjXPath($obj, $k);
  173. if (is_array($v)) {
  174. foreach($v as $ak=>$av) { $o->addAttribute($ak,$av); }
  175. } else {
  176. $o->addAttribute($v);
  177. }
  178. }
  179. }
  180. /*
  181. * Valudation before save
  182. * should analyze the structute of item by $this->item
  183. */
  184. function validate_recursive($item, $data=array(), $path) {
  185. foreach ($item as $k=>$v) {
  186. if(is_array($v)) {
  187. $s_path = $path;
  188. $s_path[] = $k;
  189. $this->validate_recursive($v, $data[$k], $s_path);
  190. } else {
  191. $pathStr = (empty($path))? $k : implode('/',$path). '/' . $k;
  192. $this->validate($pathStr, $k, $data[$k]);
  193. }
  194. }
  195. }
  196. function validate($pathStr, $key=NULL, $val) {
  197. $property = $this->item_properties[$pathStr];
  198. $validation = $this->item_validations[$pathStr];
  199. if(!empty($validation)) {
  200. foreach($validation as $rule=>$params) {
  201. if(is_array($params)) { // exist param
  202. $param = $params['param'];
  203. $msg = $params['message'];
  204. } else {
  205. $param = '';
  206. $msg = $params;
  207. }
  208. if (validate($rule, $param, $val)!="OK") { // <--- this is the function of utility.php
  209. $this->validation_errors[] = __($msg);
  210. }
  211. }
  212. }
  213. }
  214. /*
  215. * Update Children
  216. * should analyze the structute of item by $this->item
  217. */
  218. function updateChild_recursive(&$obj, $item, $data) {
  219. foreach($item as $k=>$v) {
  220. if (is_array($v)) {
  221. $this->updateChild_recursive($obj->{$k}, $item[$k], $data[$k]);
  222. } else {
  223. $d = $data[$k];
  224. if (is_array($d)) { $d = implode(',',$d); }
  225. if ( get_magic_quotes_gpc() ) { $d = stripslashes( $d ); }
  226. $obj->{$k} = $d;
  227. }
  228. }
  229. }
  230. /*
  231. * Add Child
  232. * should analyze the structute of item by $this->item
  233. */
  234. function addChild_recursive(&$obj,$item,$data=array(),$path=array()) {
  235. foreach($item as $k=>$v) {
  236. if(is_array($v)) {
  237. $c_path = $path;
  238. $c_path[] = $k;
  239. $ch = $obj->addChild($k);
  240. $this->addChild_recursive($ch,$item[$k],$data[$k],$c_path);
  241. } else {
  242. if (!empty($v)) {
  243. $v = $this->expandPhpStatement($v);
  244. } else {
  245. $v = $data[$k];
  246. if (is_array($v)) {
  247. foreach($v as $e) { $res .= $e . ','; }
  248. $v = substr($res, 0, strlen($res)-1);
  249. }
  250. }
  251. $obj->addChild($k,$v);
  252. }
  253. }
  254. }
  255. function expandPhpStatement($phpst) {
  256. return preg_replace_callback('/(\{.+?\})/',create_function('$proc','$func = substr($proc[0],1,strlen($proc[0])-2);eval(\'$res = \' . $func . \';\');return $res;'),$phpst);
  257. }
  258. /*
  259. * Delete XML Object
  260. */
  261. function delete($pos=NULL) {
  262. if($pos !== NULL) {
  263. $parent = $this->getObjXPath($this->xe, $this->parentPath);
  264. unset($parent->{$this->itemName}[intval($pos)]);
  265. return $this->xe->asXML($this->xmlFile);
  266. }
  267. }
  268. /*
  269. * Move up XML Object
  270. */
  271. function up($pos=NULL) {
  272. $dom = new DOMDocument;
  273. if (($dom->load($this->xmlFile))===false) echo "ERROR";
  274. $items = $this->getDomXPath($dom, $this->itemPath);
  275. if ($pos < $items->length-1 ) {
  276. $node1 = $items->item($pos);
  277. $node2 = $items->item($pos+1);
  278. $node1Clone = $node1->cloneNode(true);
  279. $node2Clone = $node2->cloneNode(true);
  280. $node1->parentNode->replaceChild($node2Clone, $node1);
  281. $node2->parentNode->replaceChild($node1Clone, $node2);
  282. $dom->save($this->xmlFile);
  283. }
  284. }
  285. /*
  286. * MOve down XML Object
  287. */
  288. function down($pos=NULL) {
  289. if ($pos > 0 ) {
  290. $dom = new DOMDocument;
  291. if (($dom->load($this->xmlFile))===false) echo "ERROR";
  292. $items = $this->getDomXPath($dom, $this->itemPath);
  293. $node1 = $items->item($pos);
  294. $node2 = $items->item($pos-1);
  295. $node1Clone = $node1->cloneNode(true);
  296. $node2Clone = $node2->cloneNode(true);
  297. $node1->parentNode->replaceChild($node2Clone, $node1);
  298. $node2->parentNode->replaceChild($node1Clone, $node2);
  299. $dom->save($this->xmlFile);
  300. }
  301. }
  302. }
  303. ?>