PageRenderTime 45ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/core/types/ParentTreeNode.php

https://bitbucket.org/audax/testmaker-mod
PHP | 355 lines | 221 code | 44 blank | 90 comment | 38 complexity | ad27a80502997602ebaea3721de4b785 MD5 | raw file
Possible License(s): BSD-2-Clause, AGPL-1.0, BSD-3-Clause, LGPL-2.1
  1. <?php
  2. /* This file is part of testMaker.
  3. testMaker is free software; you can redistribute it and/or modify
  4. it under the terms of version 2 of the GNU General Public License as
  5. published by the Free Software Foundation.
  6. testMaker is distributed in the hope that it will be useful,
  7. but WITHOUT ANY WARRANTY; without even the implied warranty of
  8. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  9. GNU General Public License for more details.
  10. You should have received a copy of the GNU General Public License
  11. along with this program. If not, see <http://www.gnu.org/licenses/>. */
  12. /**
  13. * @package Core
  14. */
  15. /**
  16. * Needs the class it inherites from
  17. */
  18. require_once(CORE.'types/TreeNode.php');
  19. /**
  20. * @package Core
  21. */
  22. class ParentTreeNode extends TreeNode
  23. {
  24. /**#@+
  25. * @access private
  26. */
  27. var $childrenTable;
  28. var $childrenConnector;
  29. var $childrenSequence;
  30. /**#@-*/
  31. /**
  32. * This constructor has to be overwritten.
  33. * In the overwriting constructor the variables $this->table, $this->parentNode, $this->parentConnector, $this->chidrenTable, $this->childrenConnector and $this->childrenSequence has to be set to the correct database names.
  34. * After initializing those variables the overwring constructor has to call this overwritten constructor.
  35. * @param Node parent node object
  36. * @param integer ID of the node
  37. */
  38. function ParentTreeNode($id)
  39. {
  40. $this->db = &$GLOBALS['dao']->getConnection();
  41. if(!isset($this->childrenTable))
  42. {
  43. trigger_error('<b>ParentTreeNode</b>: $this->childrenTable was not set');
  44. }
  45. if(!isset($this->childrenConnector))
  46. {
  47. trigger_error('<b>ParentTreeNode</b>: $this->childrenConnector was not set');
  48. }
  49. if(!isset($this->childrenSequence))
  50. {
  51. trigger_error('<b>ParentTreeNode</b>: $this->childrenSequence was not set');
  52. }
  53. $this->TreeNode($id);
  54. }
  55. /**
  56. * This function creates an object of the correct type determinated by given id
  57. */
  58. function _returnChild($id)
  59. {
  60. trigger_error('<b>ParentTreeNode:_returnChild</b>: function not overwritten by inherited class');
  61. }
  62. /**
  63. * get all children of the current parent node
  64. * @return mixed[]
  65. */
  66. function getChildren()
  67. {
  68. if ($res = retrieve(get_class($this).'Children', $this->id)) {
  69. return $res;
  70. }
  71. $query = 'SELECT id FROM '.$this->childrenTable.' WHERE '.$this->childrenConnector.' = ? ORDER BY pos';
  72. $ids = $this->db->getAll($query, array($this->id));
  73. if($this->db->isError($ids)) {
  74. return false;
  75. }
  76. $children = array();
  77. for($i = 0; $i < count($ids); $i++)
  78. {
  79. $children[] = $this->_returnChild($ids[$i]['id']);
  80. }
  81. store(get_class($this).'Children', $this->id, $children);
  82. return $children;
  83. }
  84. /**
  85. * delete child by given id
  86. * @param integer id of question in questionblock
  87. * @return boolean
  88. */
  89. function deleteChild($id)
  90. {
  91. if(!$this->existsChild($id))
  92. {
  93. trigger_error('<b>ParentTreeNode:deleteChild</b>: $id is no valid child id in current node');
  94. return false;
  95. }
  96. $child = $this->getChildById($id);
  97. $child->cleanUp();
  98. $query = 'DELETE FROM '.$this->childrenTable.' WHERE id = ?';
  99. $result = $this->db->query($query, array($id));
  100. if($this->db->isError($result)) {
  101. return false;
  102. }
  103. return true;
  104. }
  105. /**
  106. * creates and returns a new child node
  107. * @param $values associative array of informations
  108. * @return TreeNode
  109. */
  110. function _createChild($informations)
  111. {
  112. if(array_key_exists('pos', $informations) && ($informations['pos'] != NULL) && !preg_match('/^[0-9]+$/', $informations['pos']))
  113. {
  114. trigger_error('<b>TreeNode:createChildNode</b>: $position is no valid position');
  115. return false;
  116. }
  117. if(!array_key_exists('pos', $informations) || $informations['pos'] == NULL)
  118. {
  119. $informations['pos'] = $this->getNextFreePosition();
  120. }
  121. $id = $this->db->nextId($this->childrenSequence);
  122. if($this->db->isError($id)) {
  123. return false;
  124. }
  125. $informations['id'] = $id;
  126. $informations[$this->childrenConnector] = $this->id;
  127. $values = '';
  128. $columns = '';
  129. $quote = array();
  130. for(reset($informations); list($column, $value) = each($informations); )
  131. {
  132. if(strlen($columns) > 0)
  133. {
  134. $columns .= ', ';
  135. }
  136. if(strlen($values) > 0)
  137. {
  138. $values .= ', ';
  139. }
  140. $columns .= $column;
  141. $values .= '?';
  142. $quote[] = $value;
  143. }
  144. $query = 'INSERT INTO '.$this->childrenTable.' ('.$columns.') VALUES ('.$values.')';
  145. $result = $this->db->query($query, $quote);
  146. if($this->db->isError($result)) {
  147. return false;
  148. }
  149. return $this->_returnChild($id);
  150. }
  151. /**
  152. * creates and returns a new child node
  153. * @param $position position of answer in question
  154. * @param $optionalInfos associative array of optional informations (answer)
  155. * @return TreeNode
  156. */
  157. function createChild($infos)
  158. {
  159. trigger_error('<b>ParentTreeNode:createChild</b>: function not overwritten by inherited class');
  160. }
  161. /**
  162. * Returns a copy of the current node
  163. * @param int id of target node
  164. * @param mixed[] 2-dimensional array of changed ids. First dimension containing node type as name and seconde dimension assigns old id to new id.
  165. * @return Node
  166. */
  167. function copyNode($parentId, &$changedIds)
  168. {
  169. $node = parent::copyNode($parentId, $changedIds);
  170. $children = $this->getChildren();
  171. foreach($children as $child) {
  172. $child->copyNode($node->getId(), $changedIds);
  173. }
  174. return $node;
  175. }
  176. /**
  177. * returns if a child exists in current node
  178. * @param integer id of child node
  179. * @return boolean
  180. */
  181. function existsChild($id)
  182. {
  183. if(!preg_match('/^[0-9]+$/', $id))
  184. {
  185. trigger_error("<b>ParentTreeNode:existsChild</b>: '$id' is no valid id");
  186. return false;
  187. }
  188. $query = 'SELECT count(id) from '.$this->childrenTable.' WHERE '.$this->childrenConnector.' = ? AND id = ?';
  189. $result = $this->db->getOne($query, array($this->id, $id));
  190. if($this->db->isError($result)) {
  191. return false;
  192. }
  193. if($result == 0)
  194. {
  195. return false;
  196. }
  197. else
  198. {
  199. return true;
  200. }
  201. }
  202. function existsTreeChildAtPosition($position) {
  203. return $this->existsChildAtPosition($position);
  204. }
  205. /**
  206. * Checks if any child exists at the given position
  207. * @param integer Position of child in current node
  208. * @return boolean
  209. */
  210. function existsChildAtPosition($position)
  211. {
  212. if(!preg_match('/^[0-9]+$/', $position))
  213. {
  214. trigger_error('<b>ParentTreeNode:existAnyChildrenAtPosition</b>: $position is no valid position');
  215. return false;
  216. }
  217. $query = 'SELECT count(pos) from '.$this->childrenTable.' WHERE '.$this->childrenConnector.' = ? AND pos = ?';
  218. $result = $this->db->getOne($query, array($this->id, $position));
  219. if($this->db->isError($result)) {
  220. return false;
  221. }
  222. if($result == 0)
  223. {
  224. return false;
  225. }
  226. else
  227. {
  228. return true;
  229. }
  230. }
  231. function getTreeChildByPosition($position) {
  232. return $this->getChildByPosition($position);
  233. }
  234. /**
  235. * returns the child at given Position
  236. * @param integer Position of question in questionblock
  237. * @return Answer
  238. */
  239. function getChildByPosition($position)
  240. {
  241. if(!preg_match('/^[0-9]+$/', $position))
  242. {
  243. trigger_error('<b>ParentTreeNode:getChildByPosition</b>: $position is no valid position');
  244. return false;
  245. }
  246. $query = 'SELECT count(pos) from '.$this->childrenTable.' WHERE '.$this->childrenConnector.' = ? AND pos = ?';
  247. $result = $this->db->getOne($query, array($this->id, $position));
  248. if($this->db->isError($result)) {
  249. return false;
  250. }
  251. if($result == 0 )
  252. {
  253. trigger_error('<b>ParentTreeNode:getChildByPosition</b>: no child found at $position');
  254. return false;
  255. }
  256. $query = 'SELECT id from '.$this->childrenTable.' WHERE '.$this->childrenConnector.' = ? AND pos = ?';
  257. $id = $this->db->getOne($query, array($this->id, $position));
  258. if($this->db->isError($id)) {
  259. return false;
  260. }
  261. return $this->_returnChild($id);
  262. }
  263. /**
  264. * returns the child by given id
  265. * @param integer Position of question in questionblock
  266. * @return Answer
  267. */
  268. function getChildById($id)
  269. {
  270. if(!$this->existsChild($id))
  271. {
  272. trigger_error("<b>ParentTreeNode:getChildById</b>: $id is no valid id in current node");
  273. return false;
  274. }
  275. return $this->_returnChild($id);
  276. }
  277. /**
  278. * prepares everything to delete this block itself
  279. * @return boolean
  280. */
  281. function cleanUp()
  282. {
  283. $children = $this->getChildren();
  284. for($i = 0; $i < count($children); $i++) {
  285. $this->deleteChild($children[$i]->getId());
  286. }
  287. return parent::cleanUp();
  288. }
  289. /**
  290. * returns the next free position for a child node
  291. * @return Question
  292. */
  293. function getNextFreePosition()
  294. {
  295. $query = 'SELECT pos FROM '.$this->childrenTable.' WHERE '.$this->childrenConnector.' = ? ORDER BY pos DESC LIMIT 1';
  296. if(!($position = $this->db->getOne($query, array($this->id))))
  297. {
  298. return 1;
  299. }
  300. else {
  301. if($this->db->isError($position)) {
  302. return false;
  303. }
  304. return (((int) $position) + 1);
  305. }
  306. }
  307. }
  308. ?>