wheels 0.0.48 → 0.0.49

Sign up to get free protection for your applications and to get access to all the features.
Files changed (215) hide show
  1. data/VERSION +1 -1
  2. data/app/controllers/access_control_entries_controller.rb +4 -4
  3. data/app/controllers/external_links_controller.rb +5 -0
  4. data/app/controllers/feedbacks_controller.rb +10 -0
  5. data/app/controllers/menus_controller.rb +2 -0
  6. data/app/controllers/pages_controller.rb +16 -29
  7. data/app/controllers/sitemaps_controller.rb +135 -0
  8. data/app/helpers/application_helper.rb +4 -3
  9. data/app/helpers/external_links_helper.rb +2 -0
  10. data/app/helpers/feedbacks_helper.rb +2 -0
  11. data/app/helpers/menus_helper.rb +2 -0
  12. data/app/helpers/sitemaps_helper.rb +12 -0
  13. data/app/mailers/feedback_mailer.rb +10 -0
  14. data/app/models/ability.rb +2 -1
  15. data/app/models/access_control_entry.rb +17 -15
  16. data/app/models/external_link.rb +4 -0
  17. data/app/models/feedback.rb +13 -0
  18. data/app/models/image.rb +1 -1
  19. data/app/models/menu.rb +4 -0
  20. data/app/models/page.rb +2 -5
  21. data/app/models/sitemap.rb +153 -0
  22. data/app/models/user.rb +7 -1
  23. data/app/validators/email_validator.rb +22 -0
  24. data/app/views/access_control_entries/_form.html.haml +1 -1
  25. data/app/views/access_control_entries/_index.html.haml +3 -3
  26. data/app/views/access_control_entries/_show.html.haml +1 -1
  27. data/app/views/external_links/_fields_for.html.haml +2 -0
  28. data/app/views/external_links/_form.html.haml +18 -0
  29. data/app/views/external_links/_show.html.haml +7 -0
  30. data/app/views/external_links/edit.html.haml +7 -0
  31. data/app/views/external_links/index.html.haml +23 -0
  32. data/app/views/external_links/new.html.haml +5 -0
  33. data/app/views/external_links/show.html.haml +2 -0
  34. data/app/views/feedback_mailer/submit_feedback.html.haml +22 -0
  35. data/app/views/feedbacks/_form.html.haml +37 -0
  36. data/app/views/feedbacks/index.html.haml +27 -0
  37. data/app/views/feedbacks/new.html.haml +5 -0
  38. data/app/views/feedbacks/show.html.haml +19 -0
  39. data/app/views/layouts/application.html.haml +21 -16
  40. data/app/views/layouts/bare.html.haml +2 -0
  41. data/app/views/loadbehind/_view.js.haml +1 -2
  42. data/app/views/menus/_form.html.haml +13 -0
  43. data/app/views/menus/edit.html.haml +7 -0
  44. data/app/views/menus/index.html.haml +19 -0
  45. data/app/views/menus/new.html.haml +5 -0
  46. data/app/views/menus/show.html.haml +7 -0
  47. data/app/views/pages/_child_pages_links.html.haml +1 -1
  48. data/app/views/pages/_control_panel.html.haml +1 -6
  49. data/app/views/pages/_form.html.haml +2 -2
  50. data/app/views/pages/_form_fields.html.haml +7 -2
  51. data/app/views/pages/_show.html.haml +4 -0
  52. data/app/views/pages/create.js.haml +2 -1
  53. data/app/views/pages/destroy.js.haml +3 -0
  54. data/app/views/pages/edit.js.haml +4 -0
  55. data/app/views/pages/index.html.haml +4 -2
  56. data/app/views/pages/index.js.haml +3 -0
  57. data/app/views/pages/new.js.haml +3 -0
  58. data/app/views/pages/show.html.haml +2 -10
  59. data/app/views/pages/show.js.haml +3 -0
  60. data/app/views/pages/update.js.haml +2 -2
  61. data/app/views/sitemaps/edit.html.haml +12 -0
  62. data/app/views/sitemaps/edit.js.erb +0 -0
  63. data/app/views/sitemaps/index.html.haml +93 -0
  64. data/app/views/sitemaps/index.json.erb +23 -0
  65. data/app/views/sitemaps/new.html.haml +8 -0
  66. data/app/views/sitemaps/new.js.erb +0 -0
  67. data/app/views/users/edit.html.haml +45 -0
  68. data/db/migrate/{add_fields_to_users.rb → 0010_add_fields_to_users.rb} +0 -0
  69. data/db/migrate/{create_blogs.rb → 0020_create_blogs.rb} +0 -0
  70. data/db/migrate/{create_galleries.rb → 0030_create_galleries.rb} +0 -0
  71. data/db/migrate/{create_images.rb → 0040_create_images.rb} +0 -0
  72. data/db/migrate/{create_profiles.rb → 0050_create_profiles.rb} +0 -0
  73. data/db/migrate/{insert_admin_user_and_roles.rb → 0060_insert_admin_user_and_roles.rb} +0 -0
  74. data/db/migrate/{create_pages.rb → 0070_create_pages.rb} +0 -0
  75. data/db/migrate/{create_forums.rb → 0080_create_forums.rb} +0 -0
  76. data/db/migrate/{create_discussions.rb → 0090_create_discussions.rb} +0 -0
  77. data/db/migrate/{create_forum_messages.rb → 0100_create_forum_messages.rb} +0 -0
  78. data/db/migrate/{create_access_control_entries.rb → 0110_create_access_control_entries.rb} +3 -3
  79. data/db/migrate/{create_attachments.rb → 0120_create_attachments.rb} +0 -4
  80. data/db/migrate/{create_roles.rb → 0130_create_roles.rb} +0 -0
  81. data/db/migrate/0140_create_feedbacks.rb +20 -0
  82. data/db/migrate/0150_create_external_links.rb +14 -0
  83. data/db/migrate/0160_create_sitemaps.rb +17 -0
  84. data/db/migrate/0170_create_menus.rb +14 -0
  85. data/lib/development_mail_interceptor.rb +7 -0
  86. data/lib/generators/wheels/recipes/wheels.rb +18 -12
  87. data/lib/wheels/base.rb +7 -0
  88. data/lib/wheels/routes.rb +8 -3
  89. data/lib/wheels.rb +2 -0
  90. data/public/javascripts/jquery-validate/additional-methods.js +259 -0
  91. data/public/javascripts/jquery-validate/changelog.txt +239 -0
  92. data/public/javascripts/jquery-validate/jquery.validate.js +1146 -0
  93. data/public/javascripts/jquery-validate/jquery.validate.min.js +16 -0
  94. data/public/javascripts/jquery-validate/jquery.validate.pack.js +15 -0
  95. data/public/javascripts/jquery-validate/lib/jquery-1.4.2.js +6240 -0
  96. data/public/javascripts/jquery-validate/lib/jquery.form.js +660 -0
  97. data/public/javascripts/jquery-validate/lib/jquery.js +4376 -0
  98. data/public/javascripts/jquery-validate/lib/jquery.metadata.js +122 -0
  99. data/public/javascripts/jquery-validate/localization/messages_ar.js +24 -0
  100. data/public/javascripts/jquery-validate/localization/messages_bg.js +23 -0
  101. data/public/javascripts/jquery-validate/localization/messages_cn.js +23 -0
  102. data/public/javascripts/jquery-validate/localization/messages_cs.js +23 -0
  103. data/public/javascripts/jquery-validate/localization/messages_da.js +20 -0
  104. data/public/javascripts/jquery-validate/localization/messages_de.js +20 -0
  105. data/public/javascripts/jquery-validate/localization/messages_el.js +24 -0
  106. data/public/javascripts/jquery-validate/localization/messages_es.js +23 -0
  107. data/public/javascripts/jquery-validate/localization/messages_fa.js +23 -0
  108. data/public/javascripts/jquery-validate/localization/messages_fi.js +21 -0
  109. data/public/javascripts/jquery-validate/localization/messages_fr.js +23 -0
  110. data/public/javascripts/jquery-validate/localization/messages_he.js +23 -0
  111. data/public/javascripts/jquery-validate/localization/messages_hu.js +20 -0
  112. data/public/javascripts/jquery-validate/localization/messages_it.js +23 -0
  113. data/public/javascripts/jquery-validate/localization/messages_kk.js +23 -0
  114. data/public/javascripts/jquery-validate/localization/messages_lt.js +23 -0
  115. data/public/javascripts/jquery-validate/localization/messages_lv.js +23 -0
  116. data/public/javascripts/jquery-validate/localization/messages_nl.js +23 -0
  117. data/public/javascripts/jquery-validate/localization/messages_no.js +23 -0
  118. data/public/javascripts/jquery-validate/localization/messages_pl.js +23 -0
  119. data/public/javascripts/jquery-validate/localization/messages_ptbr.js +23 -0
  120. data/public/javascripts/jquery-validate/localization/messages_ptpt.js +23 -0
  121. data/public/javascripts/jquery-validate/localization/messages_ro.js +23 -0
  122. data/public/javascripts/jquery-validate/localization/messages_ru.js +23 -0
  123. data/public/javascripts/jquery-validate/localization/messages_se.js +21 -0
  124. data/public/javascripts/jquery-validate/localization/messages_sk.js +20 -0
  125. data/public/javascripts/jquery-validate/localization/messages_tr.js +23 -0
  126. data/public/javascripts/jquery-validate/localization/messages_tw.js +23 -0
  127. data/public/javascripts/jquery-validate/localization/messages_ua.js +23 -0
  128. data/public/javascripts/jquery-validate/localization/methods_de.js +12 -0
  129. data/public/javascripts/jquery-validate/localization/methods_nl.js +9 -0
  130. data/public/javascripts/jquery-validate/localization/methods_pt.js +9 -0
  131. data/public/javascripts/jquery-validate/todo +172 -0
  132. data/public/javascripts/jquery.cookie.js +96 -0
  133. data/public/javascripts/jquery.filedrop.js +253 -0
  134. data/public/javascripts/jquery.hotkeys.js +99 -0
  135. data/public/javascripts/jquery.js +6240 -0
  136. data/public/javascripts/jquery.jstree.js +3510 -0
  137. data/public/javascripts/jquery.uploadify.js +26 -0
  138. data/public/javascripts/jquery.validate.js +1147 -0
  139. data/public/javascripts/sitemap_jstree.js +329 -0
  140. data/public/javascripts/swfobject.js +4 -0
  141. data/public/jstree/_demo/_dump.sql +20 -0
  142. data/public/jstree/_demo/_inc/__mysql_errors.log +0 -0
  143. data/public/jstree/_demo/_inc/class._database.php +146 -0
  144. data/public/jstree/_demo/_inc/class._database_i.php +152 -0
  145. data/public/jstree/_demo/_inc/class.tree.php +602 -0
  146. data/public/jstree/_demo/_install.txt +6 -0
  147. data/public/jstree/_demo/config.php +14 -0
  148. data/public/jstree/_demo/index.html +262 -0
  149. data/public/jstree/_demo/server.php +69 -0
  150. data/public/jstree/_docs/!style.css +37 -0
  151. data/public/jstree/_docs/_drive.png +0 -0
  152. data/public/jstree/_docs/_html_data.html +2 -0
  153. data/public/jstree/_docs/_json_data.json +4 -0
  154. data/public/jstree/_docs/_search_data.json +6 -0
  155. data/public/jstree/_docs/_search_result.json +1 -0
  156. data/public/jstree/_docs/_xml_flat.xml +12 -0
  157. data/public/jstree/_docs/_xml_nest.xml +18 -0
  158. data/public/jstree/_docs/checkbox.html +148 -0
  159. data/public/jstree/_docs/contextmenu.html +120 -0
  160. data/public/jstree/_docs/cookies.html +96 -0
  161. data/public/jstree/_docs/core.html +622 -0
  162. data/public/jstree/_docs/crrm.html +315 -0
  163. data/public/jstree/_docs/dnd.html +197 -0
  164. data/public/jstree/_docs/hotkeys.html +81 -0
  165. data/public/jstree/_docs/html_data.html +174 -0
  166. data/public/jstree/_docs/index.html +75 -0
  167. data/public/jstree/_docs/json_data.html +240 -0
  168. data/public/jstree/_docs/languages.html +138 -0
  169. data/public/jstree/_docs/search.html +114 -0
  170. data/public/jstree/_docs/sort.html +84 -0
  171. data/public/jstree/_docs/syntax/!script.js +2232 -0
  172. data/public/jstree/_docs/syntax/!style.css +511 -0
  173. data/public/jstree/_docs/syntax/clipboard.swf +0 -0
  174. data/public/jstree/_docs/syntax/help.png +0 -0
  175. data/public/jstree/_docs/syntax/magnifier.png +0 -0
  176. data/public/jstree/_docs/syntax/page_white_code.png +0 -0
  177. data/public/jstree/_docs/syntax/page_white_copy.png +0 -0
  178. data/public/jstree/_docs/syntax/printer.png +0 -0
  179. data/public/jstree/_docs/syntax/wrapping.png +0 -0
  180. data/public/jstree/_docs/themeroller.html +98 -0
  181. data/public/jstree/_docs/themes.html +126 -0
  182. data/public/jstree/_docs/types.html +173 -0
  183. data/public/jstree/_docs/ui.html +188 -0
  184. data/public/jstree/_docs/unique.html +70 -0
  185. data/public/jstree/_docs/xml_data.html +214 -0
  186. data/public/jstree/_lib/jquery.cookie.js +96 -0
  187. data/public/jstree/_lib/jquery.hotkeys.js +99 -0
  188. data/public/jstree/_lib/jquery.js +6240 -0
  189. data/public/jstree/jquery.jstree.js +3510 -0
  190. data/public/jstree/jstree.html +237 -0
  191. data/public/jstree/themes/apple/bg.jpg +0 -0
  192. data/public/jstree/themes/apple/d.png +0 -0
  193. data/public/jstree/themes/apple/dot_for_ie.gif +0 -0
  194. data/public/jstree/themes/apple/style.css +60 -0
  195. data/public/jstree/themes/apple/throbber.gif +0 -0
  196. data/public/jstree/themes/classic/d.png +0 -0
  197. data/public/jstree/themes/classic/dot_for_ie.gif +0 -0
  198. data/public/jstree/themes/classic/style.css +59 -0
  199. data/public/jstree/themes/classic/throbber.gif +0 -0
  200. data/public/jstree/themes/default/d.gif +0 -0
  201. data/public/jstree/themes/default/d.png +0 -0
  202. data/public/jstree/themes/default/style.css +73 -0
  203. data/public/jstree/themes/default/throbber.gif +0 -0
  204. data/public/jstree/themes/default-rtl/d.gif +0 -0
  205. data/public/jstree/themes/default-rtl/d.png +0 -0
  206. data/public/jstree/themes/default-rtl/dots.gif +0 -0
  207. data/public/jstree/themes/default-rtl/style.css +83 -0
  208. data/public/jstree/themes/default-rtl/throbber.gif +0 -0
  209. data/public/stylesheets/sass/dreamy.sass +21 -56
  210. data/public/stylesheets/sass/menu.sass +43 -9
  211. data/public/stylesheets/sass/uploadify.sass +52 -0
  212. data/public/stylesheets/ui-lightness/images/ui-icons_228ef1_256x240.png +0 -0
  213. data/public/stylesheets/ui-lightness/jquery-ui-1.8.4.custom.css +549 -0
  214. data/wheels.gemspec +187 -15
  215. metadata +188 -16
@@ -0,0 +1,602 @@
1
+ <?php
2
+ class _tree_struct {
3
+ // Structure table and fields
4
+ protected $table = "";
5
+ protected $fields = array(
6
+ "id" => false,
7
+ "parent_id" => false,
8
+ "position" => false,
9
+ "left" => false,
10
+ "right" => false,
11
+ "level" => false
12
+ );
13
+
14
+ // Constructor
15
+ function __construct($table = "tree", $fields = array()) {
16
+ $this->table = $table;
17
+ if(!count($fields)) {
18
+ foreach($this->fields as $k => &$v) { $v = $k; }
19
+ }
20
+ else {
21
+ foreach($fields as $key => $field) {
22
+ switch($key) {
23
+ case "id":
24
+ case "parent_id":
25
+ case "position":
26
+ case "left":
27
+ case "right":
28
+ case "level":
29
+ $this->fields[$key] = $field;
30
+ break;
31
+ }
32
+ }
33
+ }
34
+ // Database
35
+ $this->db = new _database;
36
+ }
37
+
38
+ function _get_node($id) {
39
+ $this->db->query("SELECT `".implode("` , `", $this->fields)."` FROM `".$this->table."` WHERE `".$this->fields["id"]."` = ".(int) $id);
40
+ $this->db->nextr();
41
+ return $this->db->nf() === 0 ? false : $this->db->get_row("assoc");
42
+ }
43
+ function _get_children($id, $recursive = false) {
44
+ $children = array();
45
+ if($recursive) {
46
+ $node = $this->_get_node($id);
47
+ $this->db->query("SELECT `".implode("` , `", $this->fields)."` FROM `".$this->table."` WHERE `".$this->fields["left"]."` >= ".(int) $node[$this->fields["left"]]." AND `".$this->fields["right"]."` <= ".(int) $node[$this->fields["right"]]." ORDER BY `".$this->fields["left"]."` ASC");
48
+ }
49
+ else {
50
+ $this->db->query("SELECT `".implode("` , `", $this->fields)."` FROM `".$this->table."` WHERE `".$this->fields["parent_id"]."` = ".(int) $id." ORDER BY `".$this->fields["position"]."` ASC");
51
+ }
52
+ while($this->db->nextr()) $children[$this->db->f($this->fields["id"])] = $this->db->get_row("assoc");
53
+ return $children;
54
+ }
55
+ function _get_path($id) {
56
+ $node = $this->_get_node($id);
57
+ $path = array();
58
+ if(!$node === false) return false;
59
+ $this->db->query("SELECT `".implode("` , `", $this->fields)."` FROM `".$this->table."` WHERE `".$this->fields["left"]."` <= ".(int) $node[$this->fields["left"]]." AND `".$this->fields["right"]."` >= ".(int) $node[$this->fields["right"]]);
60
+ while($this->db->nextr()) $path[$this->db->f($this->fields["id"])] = $this->db->get_row("assoc");
61
+ return $path;
62
+ }
63
+
64
+ function _create($parent, $position) {
65
+ return $this->_move(0, $parent, $position);
66
+ }
67
+ function _remove($id) {
68
+ if((int)$id === 1) { return false; }
69
+ $data = $this->_get_node($id);
70
+ $lft = (int)$data[$this->fields["left"]];
71
+ $rgt = (int)$data[$this->fields["right"]];
72
+ $dif = $rgt - $lft + 1;
73
+
74
+ // deleting node and its children
75
+ $this->db->query("" .
76
+ "DELETE FROM `".$this->table."` " .
77
+ "WHERE `".$this->fields["left"]."` >= ".$lft." AND `".$this->fields["right"]."` <= ".$rgt
78
+ );
79
+ // shift left indexes of nodes right of the node
80
+ $this->db->query("".
81
+ "UPDATE `".$this->table."` " .
82
+ "SET `".$this->fields["left"]."` = `".$this->fields["left"]."` - ".$dif." " .
83
+ "WHERE `".$this->fields["left"]."` > ".$rgt
84
+ );
85
+ // shift right indexes of nodes right of the node and the node's parents
86
+ $this->db->query("" .
87
+ "UPDATE `".$this->table."` " .
88
+ "SET `".$this->fields["right"]."` = `".$this->fields["right"]."` - ".$dif." " .
89
+ "WHERE `".$this->fields["right"]."` > ".$lft
90
+ );
91
+
92
+ $pid = (int)$data[$this->fields["parent_id"]];
93
+ $pos = (int)$data[$this->fields["position"]];
94
+
95
+ // Update position of siblings below the deleted node
96
+ $this->db->query("" .
97
+ "UPDATE `".$this->table."` " .
98
+ "SET `".$this->fields["position"]."` = `".$this->fields["position"]."` - 1 " .
99
+ "WHERE `".$this->fields["parent_id"]."` = ".$pid." AND `".$this->fields["position"]."` > ".$pos
100
+ );
101
+ return true;
102
+ }
103
+ function _move($id, $ref_id, $position = 0, $is_copy = false) {
104
+ if((int)$ref_id === 0 || (int)$id === 1) { return false; }
105
+ $sql = array(); // Queries executed at the end
106
+ $node = $this->_get_node($id); // Node data
107
+ $nchildren = $this->_get_children($id); // Node children
108
+ $ref_node = $this->_get_node($ref_id); // Ref node data
109
+ $rchildren = $this->_get_children($ref_id);// Ref node children
110
+
111
+ $ndif = 2;
112
+ $node_ids = array(-1);
113
+ if($node !== false) {
114
+ $node_ids = array_keys($this->_get_children($id, true));
115
+ // TODO: should be !$is_copy && , but if copied to self - screws some right indexes
116
+ if(in_array($ref_id, $node_ids)) return false;
117
+ $ndif = $node[$this->fields["right"]] - $node[$this->fields["left"]] + 1;
118
+ }
119
+ if($position >= count($rchildren)) {
120
+ $position = count($rchildren);
121
+ }
122
+
123
+ // Not creating or copying - old parent is cleaned
124
+ if($node !== false && $is_copy == false) {
125
+ $sql[] = "" .
126
+ "UPDATE `".$this->table."` " .
127
+ "SET `".$this->fields["position"]."` = `".$this->fields["position"]."` - 1 " .
128
+ "WHERE " .
129
+ "`".$this->fields["parent_id"]."` = ".$node[$this->fields["parent_id"]]." AND " .
130
+ "`".$this->fields["position"]."` > ".$node[$this->fields["position"]];
131
+ $sql[] = "" .
132
+ "UPDATE `".$this->table."` " .
133
+ "SET `".$this->fields["left"]."` = `".$this->fields["left"]."` - ".$ndif." " .
134
+ "WHERE `".$this->fields["left"]."` > ".$node[$this->fields["right"]];
135
+ $sql[] = "" .
136
+ "UPDATE `".$this->table."` " .
137
+ "SET `".$this->fields["right"]."` = `".$this->fields["right"]."` - ".$ndif." " .
138
+ "WHERE " .
139
+ "`".$this->fields["right"]."` > ".$node[$this->fields["left"]]." AND " .
140
+ "`".$this->fields["id"]."` NOT IN (".implode(",", $node_ids).") ";
141
+ }
142
+ // Preparing new parent
143
+ $sql[] = "" .
144
+ "UPDATE `".$this->table."` " .
145
+ "SET `".$this->fields["position"]."` = `".$this->fields["position"]."` + 1 " .
146
+ "WHERE " .
147
+ "`".$this->fields["parent_id"]."` = ".$ref_id." AND " .
148
+ "`".$this->fields["position"]."` >= ".$position." " .
149
+ ( $is_copy ? "" : " AND `".$this->fields["id"]."` NOT IN (".implode(",", $node_ids).") ");
150
+
151
+ $ref_ind = $ref_id === 0 ? (int)$rchildren[count($rchildren) - 1][$this->fields["right"]] + 1 : (int)$ref_node[$this->fields["right"]];
152
+ $ref_ind = max($ref_ind, 1);
153
+
154
+ $self = ($node !== false && !$is_copy && (int)$node[$this->fields["parent_id"]] == $ref_id && $position > $node[$this->fields["position"]]) ? 1 : 0;
155
+ foreach($rchildren as $k => $v) {
156
+ if($v[$this->fields["position"]] - $self == $position) {
157
+ $ref_ind = (int)$v[$this->fields["left"]];
158
+ break;
159
+ }
160
+ }
161
+ if($node !== false && !$is_copy && $node[$this->fields["left"]] < $ref_ind) {
162
+ $ref_ind -= $ndif;
163
+ }
164
+
165
+ $sql[] = "" .
166
+ "UPDATE `".$this->table."` " .
167
+ "SET `".$this->fields["left"]."` = `".$this->fields["left"]."` + ".$ndif." " .
168
+ "WHERE " .
169
+ "`".$this->fields["left"]."` >= ".$ref_ind." " .
170
+ ( $is_copy ? "" : " AND `".$this->fields["id"]."` NOT IN (".implode(",", $node_ids).") ");
171
+ $sql[] = "" .
172
+ "UPDATE `".$this->table."` " .
173
+ "SET `".$this->fields["right"]."` = `".$this->fields["right"]."` + ".$ndif." " .
174
+ "WHERE " .
175
+ "`".$this->fields["right"]."` >= ".$ref_ind." " .
176
+ ( $is_copy ? "" : " AND `".$this->fields["id"]."` NOT IN (".implode(",", $node_ids).") ");
177
+
178
+ $ldif = $ref_id == 0 ? 0 : $ref_node[$this->fields["level"]] + 1;
179
+ $idif = $ref_ind;
180
+ if($node !== false) {
181
+ $ldif = $node[$this->fields["level"]] - ($ref_node[$this->fields["level"]] + 1);
182
+ $idif = $node[$this->fields["left"]] - $ref_ind;
183
+ if($is_copy) {
184
+ $sql[] = "" .
185
+ "INSERT INTO `".$this->table."` (" .
186
+ "`".$this->fields["parent_id"]."`, " .
187
+ "`".$this->fields["position"]."`, " .
188
+ "`".$this->fields["left"]."`, " .
189
+ "`".$this->fields["right"]."`, " .
190
+ "`".$this->fields["level"]."`" .
191
+ ") " .
192
+ "SELECT " .
193
+ "".$ref_id.", " .
194
+ "`".$this->fields["position"]."`, " .
195
+ "`".$this->fields["left"]."` - (".($idif + ($node[$this->fields["left"]] >= $ref_ind ? $ndif : 0))."), " .
196
+ "`".$this->fields["right"]."` - (".($idif + ($node[$this->fields["left"]] >= $ref_ind ? $ndif : 0))."), " .
197
+ "`".$this->fields["level"]."` - (".$ldif.") " .
198
+ "FROM `".$this->table."` " .
199
+ "WHERE " .
200
+ "`".$this->fields["id"]."` IN (".implode(",", $node_ids).") " .
201
+ "ORDER BY `".$this->fields["level"]."` ASC";
202
+ }
203
+ else {
204
+ $sql[] = "" .
205
+ "UPDATE `".$this->table."` SET " .
206
+ "`".$this->fields["parent_id"]."` = ".$ref_id.", " .
207
+ "`".$this->fields["position"]."` = ".$position." " .
208
+ "WHERE " .
209
+ "`".$this->fields["id"]."` = ".$id;
210
+ $sql[] = "" .
211
+ "UPDATE `".$this->table."` SET " .
212
+ "`".$this->fields["left"]."` = `".$this->fields["left"]."` - (".$idif."), " .
213
+ "`".$this->fields["right"]."` = `".$this->fields["right"]."` - (".$idif."), " .
214
+ "`".$this->fields["level"]."` = `".$this->fields["level"]."` - (".$ldif.") " .
215
+ "WHERE " .
216
+ "`".$this->fields["id"]."` IN (".implode(",", $node_ids).") ";
217
+ }
218
+ }
219
+ else {
220
+ $sql[] = "" .
221
+ "INSERT INTO `".$this->table."` (" .
222
+ "`".$this->fields["parent_id"]."`, " .
223
+ "`".$this->fields["position"]."`, " .
224
+ "`".$this->fields["left"]."`, " .
225
+ "`".$this->fields["right"]."`, " .
226
+ "`".$this->fields["level"]."` " .
227
+ ") " .
228
+ "VALUES (" .
229
+ $ref_id.", " .
230
+ $position.", " .
231
+ $idif.", " .
232
+ ($idif + 1).", " .
233
+ $ldif.
234
+ ")";
235
+ }
236
+ foreach($sql as $q) { $this->db->query($q); }
237
+ $ind = $this->db->insert_id();
238
+ if($is_copy) $this->_fix_copy($ind, $position);
239
+ return $node === false || $is_copy ? $ind : true;
240
+ }
241
+ function _fix_copy($id, $position) {
242
+ $node = $this->_get_node($id);
243
+ $children = $this->_get_children($id, true);
244
+
245
+ $map = array();
246
+ for($i = $node[$this->fields["left"]] + 1; $i < $node[$this->fields["right"]]; $i++) {
247
+ $map[$i] = $id;
248
+ }
249
+ foreach($children as $cid => $child) {
250
+ if((int)$cid == (int)$id) {
251
+ $this->db->query("UPDATE `".$this->table."` SET `".$this->fields["position"]."` = ".$position." WHERE `".$this->fields["id"]."` = ".$cid);
252
+ continue;
253
+ }
254
+ $this->db->query("UPDATE `".$this->table."` SET `".$this->fields["parent_id"]."` = ".$map[(int)$child[$this->fields["left"]]]." WHERE `".$this->fields["id"]."` = ".$cid);
255
+ for($i = $child[$this->fields["left"]] + 1; $i < $child[$this->fields["right"]]; $i++) {
256
+ $map[$i] = $cid;
257
+ }
258
+ }
259
+ }
260
+
261
+ function _reconstruct() {
262
+ $this->db->query("" .
263
+ "CREATE TEMPORARY TABLE `temp_tree` (" .
264
+ "`".$this->fields["id"]."` INTEGER NOT NULL, " .
265
+ "`".$this->fields["parent_id"]."` INTEGER NOT NULL, " .
266
+ "`". $this->fields["position"]."` INTEGER NOT NULL" .
267
+ ") type=HEAP"
268
+ );
269
+ $this->db->query("" .
270
+ "INSERT INTO `temp_tree` " .
271
+ "SELECT " .
272
+ "`".$this->fields["id"]."`, " .
273
+ "`".$this->fields["parent_id"]."`, " .
274
+ "`".$this->fields["position"]."` " .
275
+ "FROM `".$this->table."`"
276
+ );
277
+
278
+ $this->db->query("" .
279
+ "CREATE TEMPORARY TABLE `temp_stack` (" .
280
+ "`".$this->fields["id"]."` INTEGER NOT NULL, " .
281
+ "`".$this->fields["left"]."` INTEGER, " .
282
+ "`".$this->fields["right"]."` INTEGER, " .
283
+ "`".$this->fields["level"]."` INTEGER, " .
284
+ "`stack_top` INTEGER NOT NULL, " .
285
+ "`".$this->fields["parent_id"]."` INTEGER, " .
286
+ "`".$this->fields["position"]."` INTEGER " .
287
+ ") type=HEAP"
288
+ );
289
+ $counter = 2;
290
+ $this->db->query("SELECT COUNT(*) FROM temp_tree");
291
+ $this->db->nextr();
292
+ $maxcounter = (int) $this->db->f(0) * 2;
293
+ $currenttop = 1;
294
+ $this->db->query("" .
295
+ "INSERT INTO `temp_stack` " .
296
+ "SELECT " .
297
+ "`".$this->fields["id"]."`, " .
298
+ "1, " .
299
+ "NULL, " .
300
+ "0, " .
301
+ "1, " .
302
+ "`".$this->fields["parent_id"]."`, " .
303
+ "`".$this->fields["position"]."` " .
304
+ "FROM `temp_tree` " .
305
+ "WHERE `".$this->fields["parent_id"]."` = 0"
306
+ );
307
+ $this->db->query("DELETE FROM `temp_tree` WHERE `".$this->fields["parent_id"]."` = 0");
308
+
309
+ while ($counter <= $maxcounter) {
310
+ $this->db->query("" .
311
+ "SELECT " .
312
+ "`temp_tree`.`".$this->fields["id"]."` AS tempmin, " .
313
+ "`temp_tree`.`".$this->fields["parent_id"]."` AS pid, " .
314
+ "`temp_tree`.`".$this->fields["position"]."` AS lid " .
315
+ "FROM `temp_stack`, `temp_tree` " .
316
+ "WHERE " .
317
+ "`temp_stack`.`".$this->fields["id"]."` = `temp_tree`.`".$this->fields["parent_id"]."` AND " .
318
+ "`temp_stack`.`stack_top` = ".$currenttop." " .
319
+ "ORDER BY `temp_tree`.`".$this->fields["position"]."` ASC LIMIT 1"
320
+ );
321
+
322
+ if ($this->db->nextr()) {
323
+ $tmp = $this->db->f("tempmin");
324
+
325
+ $q = "INSERT INTO temp_stack (stack_top, `".$this->fields["id"]."`, `".$this->fields["left"]."`, `".$this->fields["right"]."`, `".$this->fields["level"]."`, `".$this->fields["parent_id"]."`, `".$this->fields["position"]."`) VALUES(".($currenttop + 1).", ".$tmp.", ".$counter.", NULL, ".$currenttop.", ".$this->db->f("pid").", ".$this->db->f("lid").")";
326
+ $this->db->query($q);
327
+ $this->db->query("DELETE FROM `temp_tree` WHERE `".$this->fields["id"]."` = ".$tmp);
328
+ $counter++;
329
+ $currenttop++;
330
+ }
331
+ else {
332
+ $this->db->query("" .
333
+ "UPDATE temp_stack SET " .
334
+ "`".$this->fields["right"]."` = ".$counter.", " .
335
+ "`stack_top` = -`stack_top` " .
336
+ "WHERE `stack_top` = ".$currenttop
337
+ );
338
+ $counter++;
339
+ $currenttop--;
340
+ }
341
+ }
342
+
343
+ $temp_fields = $this->fields;
344
+ unset($temp_fields["parent_id"]);
345
+ unset($temp_fields["position"]);
346
+ unset($temp_fields["left"]);
347
+ unset($temp_fields["right"]);
348
+ unset($temp_fields["level"]);
349
+ if(count($temp_fields) > 1) {
350
+ $this->db->query("" .
351
+ "CREATE TEMPORARY TABLE `temp_tree2` " .
352
+ "SELECT `".implode("`, `", $temp_fields)."` FROM `".$this->table."` "
353
+ );
354
+ }
355
+ $this->db->query("TRUNCATE TABLE `".$this->table."`");
356
+ $this->db->query("" .
357
+ "INSERT INTO ".$this->table." (" .
358
+ "`".$this->fields["id"]."`, " .
359
+ "`".$this->fields["parent_id"]."`, " .
360
+ "`".$this->fields["position"]."`, " .
361
+ "`".$this->fields["left"]."`, " .
362
+ "`".$this->fields["right"]."`, " .
363
+ "`".$this->fields["level"]."` " .
364
+ ") " .
365
+ "SELECT " .
366
+ "`".$this->fields["id"]."`, " .
367
+ "`".$this->fields["parent_id"]."`, " .
368
+ "`".$this->fields["position"]."`, " .
369
+ "`".$this->fields["left"]."`, " .
370
+ "`".$this->fields["right"]."`, " .
371
+ "`".$this->fields["level"]."` " .
372
+ "FROM temp_stack " .
373
+ "ORDER BY `".$this->fields["id"]."`"
374
+ );
375
+ if(count($temp_fields) > 1) {
376
+ $sql = "" .
377
+ "UPDATE `".$this->table."` v, `temp_tree2` SET v.`".$this->fields["id"]."` = v.`".$this->fields["id"]."` ";
378
+ foreach($temp_fields as $k => $v) {
379
+ if($k == "id") continue;
380
+ $sql .= ", v.`".$v."` = `temp_tree2`.`".$v."` ";
381
+ }
382
+ $sql .= " WHERE v.`".$this->fields["id"]."` = `temp_tree2`.`".$this->fields["id"]."` ";
383
+ $this->db->query($sql);
384
+ }
385
+ }
386
+
387
+ function _analyze() {
388
+ $report = array();
389
+
390
+ $this->db->query("" .
391
+ "SELECT " .
392
+ "`".$this->fields["left"]."` FROM `".$this->table."` s " .
393
+ "WHERE " .
394
+ "`".$this->fields["parent_id"]."` = 0 "
395
+ );
396
+ $this->db->nextr();
397
+ if($this->db->nf() == 0) {
398
+ $report[] = "[FAIL]\tNo root node.";
399
+ }
400
+ else {
401
+ $report[] = ($this->db->nf() > 1) ? "[FAIL]\tMore than one root node." : "[OK]\tJust one root node.";
402
+ }
403
+ $report[] = ($this->db->f(0) != 1) ? "[FAIL]\tRoot node's left index is not 1." : "[OK]\tRoot node's left index is 1.";
404
+
405
+ $this->db->query("" .
406
+ "SELECT " .
407
+ "COUNT(*) FROM `".$this->table."` s " .
408
+ "WHERE " .
409
+ "`".$this->fields["parent_id"]."` != 0 AND " .
410
+ "(SELECT COUNT(*) FROM `".$this->table."` WHERE `".$this->fields["id"]."` = s.`".$this->fields["parent_id"]."`) = 0 ");
411
+ $this->db->nextr();
412
+ $report[] = ($this->db->f(0) > 0) ? "[FAIL]\tMissing parents." : "[OK]\tNo missing parents.";
413
+
414
+ $this->db->query("SELECT MAX(`".$this->fields["right"]."`) FROM `".$this->table."`");
415
+ $this->db->nextr();
416
+ $n = $this->db->f(0);
417
+ $this->db->query("SELECT COUNT(*) FROM `".$this->table."`");
418
+ $this->db->nextr();
419
+ $c = $this->db->f(0);
420
+ $report[] = ($n/2 != $c) ? "[FAIL]\tRight index does not match node count." : "[OK]\tRight index matches count.";
421
+
422
+ $this->db->query("" .
423
+ "SELECT COUNT(`".$this->fields["id"]."`) FROM `".$this->table."` s " .
424
+ "WHERE " .
425
+ "(SELECT COUNT(*) FROM `".$this->table."` WHERE " .
426
+ "`".$this->fields["right"]."` < s.`".$this->fields["right"]."` AND " .
427
+ "`".$this->fields["left"]."` > s.`".$this->fields["left"]."` AND " .
428
+ "`".$this->fields["level"]."` = s.`".$this->fields["level"]."` + 1" .
429
+ ") != " .
430
+ "(SELECT COUNT(*) FROM `".$this->table."` WHERE " .
431
+ "`".$this->fields["parent_id"]."` = s.`".$this->fields["id"]."`" .
432
+ ") "
433
+ );
434
+ $this->db->nextr();
435
+ $report[] = ($this->db->f(0) > 0) ? "[FAIL]\tAdjacency and nested set do not match." : "[OK]\tNS and AJ match";
436
+
437
+ return implode("<br />",$report);
438
+ }
439
+
440
+ function _dump($output = false) {
441
+ $nodes = array();
442
+ $this->db->query("SELECT * FROM ".$this->table." ORDER BY `".$this->fields["left"]."`");
443
+ while($this->db->nextr()) $nodes[] = $this->db->get_row("assoc");
444
+ if($output) {
445
+ echo "<pre>";
446
+ foreach($nodes as $node) {
447
+ echo str_repeat("&#160;",(int)$node[$this->fields["level"]] * 2);
448
+ echo $node[$this->fields["id"]]." (".$node[$this->fields["left"]].",".$node[$this->fields["right"]].",".$node[$this->fields["level"]].",".$node[$this->fields["parent_id"]].",".$node[$this->fields["position"]].")<br />";
449
+ }
450
+ echo str_repeat("-",40);
451
+ echo "</pre>";
452
+ }
453
+ return $nodes;
454
+ }
455
+ function _drop() {
456
+ $this->db->query("TRUNCATE TABLE `".$this->table."`");
457
+ $this->db->query("" .
458
+ "INSERT INTO `".$this->table."` (" .
459
+ "`".$this->fields["id"]."`, " .
460
+ "`".$this->fields["parent_id"]."`, " .
461
+ "`".$this->fields["position"]."`, " .
462
+ "`".$this->fields["left"]."`, " .
463
+ "`".$this->fields["right"]."`, " .
464
+ "`".$this->fields["level"]."` " .
465
+ ") " .
466
+ "VALUES (" .
467
+ "1, " .
468
+ "0, " .
469
+ "0, " .
470
+ "1, " .
471
+ "2, " .
472
+ "0 ".
473
+ ")");
474
+ }
475
+ }
476
+
477
+ class json_tree extends _tree_struct {
478
+ function __construct($table = "tree", $fields = array(), $add_fields = array("title" => "title", "type" => "type")) {
479
+ parent::__construct($table, $fields);
480
+ $this->fields = array_merge($this->fields, $add_fields);
481
+ $this->add_fields = $add_fields;
482
+ }
483
+
484
+ function create_node($data) {
485
+ $id = parent::_create((int)$data[$this->fields["id"]], (int)$data[$this->fields["position"]]);
486
+ if($id) {
487
+ $data["id"] = $id;
488
+ $this->set_data($data);
489
+ return "{ \"status\" : 1, \"id\" : ".(int)$id." }";
490
+ }
491
+ return "{ \"status\" : 0 }";
492
+ }
493
+ function set_data($data) {
494
+ if(count($this->add_fields) == 0) { return "{ \"status\" : 1 }"; }
495
+ $s = "UPDATE `".$this->table."` SET `".$this->fields["id"]."` = `".$this->fields["id"]."` ";
496
+ foreach($this->add_fields as $k => $v) {
497
+ if(isset($data[$k])) $s .= ", `".$this->fields[$v]."` = \"".$this->db->escape($data[$k])."\" ";
498
+ else $s .= ", `".$this->fields[$v]."` = `".$this->fields[$v]."` ";
499
+ }
500
+ $s .= "WHERE `".$this->fields["id"]."` = ".(int)$data["id"];
501
+ $this->db->query($s);
502
+ return "{ \"status\" : 1 }";
503
+ }
504
+ function rename_node($data) { return $this->set_data($data); }
505
+
506
+ function move_node($data) {
507
+ $id = parent::_move((int)$data["id"], (int)$data["ref"], (int)$data["position"], (int)$data["copy"]);
508
+ if(!$id) return "{ \"status\" : 0 }";
509
+ if((int)$data["copy"] && count($this->add_fields)) {
510
+ $ids = array_keys($this->_get_children($id, true));
511
+ $data = $this->_get_children((int)$data["id"], true);
512
+
513
+ $i = 0;
514
+ foreach($data as $dk => $dv) {
515
+ $s = "UPDATE `".$this->table."` SET `".$this->fields["id"]."` = `".$this->fields["id"]."` ";
516
+ foreach($this->add_fields as $k => $v) {
517
+ if(isset($dv[$k])) $s .= ", `".$this->fields[$v]."` = \"".$this->db->escape($dv[$k])."\" ";
518
+ else $s .= ", `".$this->fields[$v]."` = `".$this->fields[$v]."` ";
519
+ }
520
+ $s .= "WHERE `".$this->fields["id"]."` = ".$ids[$i];
521
+ $this->db->query($s);
522
+ $i++;
523
+ }
524
+ }
525
+ return "{ \"status\" : 1, \"id\" : ".$id." }";
526
+ }
527
+ function remove_node($data) {
528
+ $id = parent::_remove((int)$data["id"]);
529
+ return "{ \"status\" : 1 }";
530
+ }
531
+ function get_children($data) {
532
+ $tmp = $this->_get_children((int)$data["id"]);
533
+ if((int)$data["id"] === 1 && count($tmp) === 0) {
534
+ $this->_create_default();
535
+ $tmp = $this->_get_children((int)$data["id"]);
536
+ }
537
+ $result = array();
538
+ if((int)$data["id"] === 0) return json_encode($result);
539
+ foreach($tmp as $k => $v) {
540
+ $result[] = array(
541
+ "attr" => array("id" => "node_".$k, "rel" => $v[$this->fields["type"]]),
542
+ "data" => $v[$this->fields["title"]],
543
+ "state" => ((int)$v[$this->fields["right"]] - (int)$v[$this->fields["left"]] > 1) ? "closed" : ""
544
+ );
545
+ }
546
+ return json_encode($result);
547
+ }
548
+ function search($data) {
549
+ $this->db->query("SELECT `".$this->fields["left"]."`, `".$this->fields["right"]."` FROM `".$this->table."` WHERE `".$this->fields["title"]."` LIKE '%".$this->db->escape($data["search_str"])."%'");
550
+ if($this->db->nf() === 0) return "[]";
551
+ $q = "SELECT DISTINCT `".$this->fields["id"]."` FROM `".$this->table."` WHERE 0 ";
552
+ while($this->db->nextr()) {
553
+ $q .= " OR (`".$this->fields["left"]."` < ".(int)$this->db->f(0)." AND `".$this->fields["right"]."` > ".(int)$this->db->f(1).") ";
554
+ }
555
+ $result = array();
556
+ $this->db->query($q);
557
+ while($this->db->nextr()) { $result[] = "#node_".$this->db->f(0); }
558
+ return json_encode($result);
559
+ }
560
+
561
+ function _create_default() {
562
+ $this->_drop();
563
+ $this->create_node(array(
564
+ "id" => 1,
565
+ "position" => 0,
566
+ "title" => "C:",
567
+ "type" => "drive"
568
+ ));
569
+ $this->create_node(array(
570
+ "id" => 1,
571
+ "position" => 1,
572
+ "title" => "D:",
573
+ "type" => "drive"
574
+ ));
575
+ $this->create_node(array(
576
+ "id" => 2,
577
+ "position" => 0,
578
+ "title" => "_demo",
579
+ "type" => "folder"
580
+ ));
581
+ $this->create_node(array(
582
+ "id" => 2,
583
+ "position" => 1,
584
+ "title" => "_docs",
585
+ "type" => "folder"
586
+ ));
587
+ $this->create_node(array(
588
+ "id" => 4,
589
+ "position" => 0,
590
+ "title" => "index.html",
591
+ "type" => "default"
592
+ ));
593
+ $this->create_node(array(
594
+ "id" => 5,
595
+ "position" => 1,
596
+ "title" => "doc.html",
597
+ "type" => "default"
598
+ ));
599
+ }
600
+ }
601
+
602
+ ?>
@@ -0,0 +1,6 @@
1
+ 1) Create a database and a user with all privileges for this database.
2
+ 2) Edit the config.php file and update the configuration for the database at the top of the file
3
+ 3) Import the _dump.sql in your newly created database
4
+ 4) You are ready to go
5
+
6
+ *) PLEASE NOTE THAT THE PHP TREE CLASS HAS NOT BEEN THOROUGHLY TESTED
@@ -0,0 +1,14 @@
1
+ <?php
2
+ // Database config & class
3
+ $db_config = array(
4
+ "servername"=> "localhost",
5
+ "username" => "root",
6
+ "password" => "",
7
+ "database" => "jstree"
8
+ );
9
+ if(extension_loaded("mysqli")) require_once("_inc/class._database_i.php");
10
+ else require_once("_inc/class._database.php");
11
+
12
+ // Tree class
13
+ require_once("_inc/class.tree.php");
14
+ ?>