zena 0.16.9 → 1.0.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (572) hide show
  1. data/.gitignore +16 -3
  2. data/CREDITS +8 -4
  3. data/History.txt +12 -15
  4. data/app/controllers/application_controller.rb +1 -0
  5. data/app/controllers/columns_controller.rb +130 -0
  6. data/app/controllers/documents_controller.rb +16 -4
  7. data/app/controllers/groups_controller.rb +1 -5
  8. data/app/controllers/iformats_controller.rb +1 -5
  9. data/app/controllers/nodes_controller.rb +116 -41
  10. data/app/controllers/preferences_controller.rb +2 -0
  11. data/app/controllers/relations_controller.rb +1 -5
  12. data/app/controllers/sites_controller.rb +1 -5
  13. data/app/controllers/user_sessions_controller.rb +8 -3
  14. data/app/controllers/users_controller.rb +23 -11
  15. data/app/controllers/versions_controller.rb +29 -46
  16. data/app/controllers/virtual_classes_controller.rb +20 -12
  17. data/app/helpers/documents_helper.rb +5 -1
  18. data/app/models/attachment.rb +41 -0
  19. data/app/models/base_contact.rb +79 -0
  20. data/app/models/cache.rb +2 -2
  21. data/app/models/cached_page.rb +5 -4
  22. data/app/models/column.rb +90 -0
  23. data/app/models/comment.rb +3 -1
  24. data/app/models/contact_content.rb +5 -5
  25. data/app/models/contact_version.rb +2 -2
  26. data/app/models/data_entry.rb +9 -8
  27. data/app/models/discussion.rb +4 -0
  28. data/app/models/document.rb +170 -42
  29. data/app/models/document_content.rb +5 -9
  30. data/app/models/group.rb +4 -3
  31. data/app/models/idx_nodes_ml_string.rb +5 -0
  32. data/app/models/idx_nodes_string.rb +5 -0
  33. data/app/models/idx_template.rb +35 -0
  34. data/app/models/iformat.rb +4 -4
  35. data/app/models/image.rb +193 -26
  36. data/app/models/link.rb +1 -1
  37. data/app/models/node.rb +358 -338
  38. data/app/models/note.rb +2 -4
  39. data/app/models/page.rb +10 -8
  40. data/app/models/reference.rb +1 -1
  41. data/app/models/relation.rb +40 -1
  42. data/app/models/relation_proxy.rb +37 -40
  43. data/app/models/role.rb +19 -0
  44. data/app/models/site.rb +54 -24
  45. data/app/models/skin.rb +1 -16
  46. data/app/models/template.rb +92 -62
  47. data/app/models/template_content.rb +12 -6
  48. data/app/models/text_document.rb +69 -36
  49. data/app/models/text_document_content.rb +3 -3
  50. data/app/models/user.rb +34 -13
  51. data/app/models/version.rb +47 -291
  52. data/app/models/virtual_class.rb +26 -29
  53. data/app/views/columns/_add.html.erb +6 -0
  54. data/app/views/columns/_form.html.erb +36 -0
  55. data/app/views/columns/_li.html.erb +11 -0
  56. data/app/views/columns/create.rjs +8 -0
  57. data/app/views/columns/destroy.rjs +6 -0
  58. data/app/views/columns/edit.html.erb +5 -0
  59. data/app/views/columns/index.html.erb +15 -0
  60. data/app/views/columns/new.html.erb +2 -0
  61. data/app/views/columns/show.rjs +1 -0
  62. data/app/views/columns/update.rjs +5 -0
  63. data/app/views/comments/_li.rhtml +1 -1
  64. data/app/views/comments/create.rjs +1 -1
  65. data/app/views/comments/index.rhtml +1 -1
  66. data/app/views/comments/publish.rjs +1 -1
  67. data/app/views/comments/remove.rjs +1 -1
  68. data/app/views/data_entries/_li.html.erb +1 -1
  69. data/app/views/discussions/create.rjs +1 -1
  70. data/app/views/documents/_crop.rhtml +4 -4
  71. data/app/views/documents/crop_form.rjs +1 -1
  72. data/app/views/documents/new.rhtml +1 -1
  73. data/app/views/documents/show.rhtml +4 -4
  74. data/app/views/groups/_form.rhtml +1 -1
  75. data/app/views/groups/index.rhtml +1 -1
  76. data/app/views/iformats/_form.rhtml +1 -1
  77. data/app/views/iformats/create.rjs +1 -1
  78. data/app/views/iformats/index.rhtml +1 -1
  79. data/app/views/links/create.rjs +1 -1
  80. data/app/views/links/destroy.rjs +1 -1
  81. data/app/views/links/show.rjs +1 -1
  82. data/app/views/nodes/_dates.rhtml +2 -2
  83. data/app/views/nodes/_gallery.rhtml +2 -2
  84. data/app/views/nodes/_list_nodes.rhtml +2 -2
  85. data/app/views/nodes/_parent.rhtml +1 -1
  86. data/app/views/nodes/_position.rhtml +2 -2
  87. data/app/views/nodes/_results.rhtml +1 -1
  88. data/app/views/nodes/create.rjs +1 -4
  89. data/app/views/nodes/destroy.erb +0 -0
  90. data/app/views/nodes/import.rhtml +1 -1
  91. data/app/views/nodes/save_text.rjs +3 -3
  92. data/app/views/nodes/table_update.rjs +1 -2
  93. data/app/views/nodes/update.rjs +1 -1
  94. data/app/views/relations/_form.erb +15 -15
  95. data/app/views/relations/_li.erb +5 -11
  96. data/app/views/relations/create.rjs +1 -1
  97. data/app/views/relations/index.erb +1 -1
  98. data/app/views/sites/_form.erb +3 -3
  99. data/app/views/sites/_li.erb +1 -1
  100. data/app/views/sites/index.erb +1 -1
  101. data/app/views/templates/document_create_tabs/_file.rhtml +3 -3
  102. data/app/views/templates/document_create_tabs/_template.rhtml +9 -9
  103. data/app/views/templates/document_create_tabs/{_text_doc.rhtml → _text_document.rhtml} +4 -4
  104. data/app/views/templates/edit_tabs/{_contact.rhtml → _basecontact.rhtml} +2 -2
  105. data/app/views/templates/edit_tabs/_document.rhtml +3 -3
  106. data/app/views/templates/edit_tabs/_help.rhtml +2 -2
  107. data/app/views/templates/edit_tabs/_image.rhtml +4 -4
  108. data/app/views/templates/edit_tabs/_template.rhtml +6 -6
  109. data/app/views/templates/edit_tabs/_text.rhtml +1 -1
  110. data/app/views/templates/edit_tabs/_textdocument.rhtml +4 -4
  111. data/app/views/templates/edit_tabs/_title.rhtml +9 -14
  112. data/app/views/users/_form.rhtml +1 -1
  113. data/app/views/users/change_info.rjs +1 -1
  114. data/app/views/users/change_password.rjs +1 -1
  115. data/app/views/users/index.rhtml +1 -1
  116. data/app/views/users/preferences.html.erb +10 -4
  117. data/app/views/users/update.rjs +1 -1
  118. data/app/views/versions/_list.rhtml +1 -1
  119. data/app/views/versions/_tr.rhtml +1 -1
  120. data/app/views/versions/backup.rjs +1 -1
  121. data/app/views/versions/destroy.rjs +6 -2
  122. data/app/views/versions/diff.rjs +1 -1
  123. data/app/views/versions/edit.rhtml +14 -6
  124. data/app/views/versions/preview.rjs +1 -1
  125. data/app/views/versions/show.rjs +1 -1
  126. data/app/views/virtual_classes/_add.erb +1 -1
  127. data/app/views/virtual_classes/_form.erb +15 -10
  128. data/app/views/virtual_classes/_li.erb +13 -7
  129. data/app/views/virtual_classes/create.rjs +2 -2
  130. data/app/views/virtual_classes/edit.html.erb +7 -0
  131. data/app/views/virtual_classes/index.erb +2 -2
  132. data/app/views/zafu/default/Node-+adminLayout.zafu +47 -0
  133. data/app/views/zafu/default/Node-+index.zafu +1 -0
  134. data/app/views/{templates/defaults/+login.zafu → zafu/default/Node-+login.zafu} +9 -7
  135. data/app/views/zafu/default/Node-+notFound.zafu +14 -0
  136. data/app/views/zafu/default/Node-+popupLayout.zafu +24 -0
  137. data/app/views/zafu/default/Node-+search.zafu +23 -0
  138. data/app/views/zafu/default/Node.zafu +95 -0
  139. data/bin/zena +0 -2
  140. data/bricks/captcha/lib/bricks/captcha.rb +62 -0
  141. data/bricks/captcha/zena/init.rb +11 -0
  142. data/bricks/data2pdf/.document +5 -0
  143. data/bricks/data2pdf/README +19 -0
  144. data/bricks/data2pdf/Rakefile +36 -0
  145. data/bricks/data2pdf/VERSION +1 -0
  146. data/bricks/data2pdf/lib/data2pdf.rb +60 -0
  147. data/bricks/data2pdf/lib/engines/prince.rb +39 -0
  148. data/bricks/data2pdf/lib/engines/xhtml2pdf.rb +41 -0
  149. data/bricks/data2pdf/lib/install.rb +111 -0
  150. data/bricks/data2pdf/test/engines/test_prince.rb +14 -0
  151. data/bricks/data2pdf/test/engines/test_xhtml2pdf.rb +14 -0
  152. data/bricks/data2pdf/test/fixtures/application.css +241 -0
  153. data/bricks/data2pdf/test/fixtures/contact.html +153 -0
  154. data/bricks/data2pdf/test/fixtures/pisa-default.css +207 -0
  155. data/bricks/data2pdf/test/fixtures/sheet1.css +207 -0
  156. data/bricks/data2pdf/test/fixtures/sheet2.css +207 -0
  157. data/bricks/data2pdf/test/fixtures/simple-html.html +337 -0
  158. data/bricks/data2pdf/test/fixtures/simple-text.txt +1 -0
  159. data/bricks/data2pdf/test/helper.rb +23 -0
  160. data/bricks/data2pdf/test/shoulda_macros/shoulda_data2pdf.rb +91 -0
  161. data/bricks/data2pdf/test/unit/test_rendering.rb +37 -0
  162. data/bricks/math/{patch/application_helper.rb → lib/bricks/math.rb} +0 -4
  163. data/bricks/math/zena/init.rb +4 -0
  164. data/bricks/sphinx/README +2 -2
  165. data/bricks/sphinx/lib/use_sphinx.rb +7 -11
  166. data/bricks/sphinx/{misc → zena}/deploy.rb +0 -0
  167. data/bricks/sphinx/{patch/node.rb → zena/init.rb} +1 -3
  168. data/bricks/sphinx/{migrate → zena/migrate}/20091102171258_add_delta_for_sphinx.rb +0 -0
  169. data/bricks/sphinx/{misc → zena}/sphinx.yml +0 -0
  170. data/bricks/sphinx/{misc → zena}/tasks.rb +0 -0
  171. data/bricks/tags/lib/{has_tags.rb → bricks/tags.rb} +12 -24
  172. data/bricks/tags/zena/init.rb +21 -0
  173. data/bricks/tags/{test → zena/test}/sites/zena/links.yml +0 -0
  174. data/bricks/tags/{test → zena/test}/unit/tags_test.rb +1 -1
  175. data/bricks/tags/zena/test/zafu/tags.yml +41 -0
  176. data/bricks/worker/README +2 -2
  177. data/bricks/worker/{misc → zena}/deploy.rb +0 -0
  178. data/bricks/worker/{misc → zena}/init.rb +2 -1
  179. data/bricks/worker/{migrate → zena/migrate}/20091104191643_create_delayed_jobs_table.rb +0 -0
  180. data/bricks/worker/{misc → zena}/tasks.rb +0 -0
  181. data/bricks/worker/{misc → zena}/worker +0 -0
  182. data/config/bricks.yml +2 -0
  183. data/config/deploy.rb +2 -7
  184. data/config/environment.rb +3 -5
  185. data/config/gems.yml +9 -4
  186. data/db/20100628074512_zena0x_to1x.rb +223 -0
  187. data/db/init/base/help.en.zml +3 -3
  188. data/db/init/base/help.fr.zml +3 -3
  189. data/db/init/base/skins.zml +2 -2
  190. data/db/init/base/skins/default.zml +4 -4
  191. data/db/init/base/skins/default/Node-+adminLayout.zafu +8 -7
  192. data/db/init/base/skins/default/Node-+login.zafu +9 -7
  193. data/db/init/base/skins/default/Node-+search.zafu +4 -1
  194. data/db/init/base/skins/default/Node-tree.zafu +3 -3
  195. data/db/init/base/skins/default/Node.zafu +20 -20
  196. data/db/init/base/skins/default/Project.zafu +1 -1
  197. data/db/init/base/skins/default/notes.zafu +5 -5
  198. data/db/init/base/skins/default/style.css +17 -12
  199. data/db/migrate/001_create_base.rb +1 -1
  200. data/db/migrate/008_user_status.rb +1 -1
  201. data/db/migrate/020_create_participation.rb +3 -3
  202. data/db/migrate/024_correct_vclass_kpath.rb +5 -3
  203. data/db/migrate/025_move_tag_into_vclass.rb +7 -5
  204. data/db/migrate/030_redit_auto_publish_site_settings.rb +2 -2
  205. data/db/migrate/032_caches_context_as_hash.rb +4 -2
  206. data/db/migrate/046_fix_zazen_image_tag.rb +2 -2
  207. data/db/migrate/047_change_default_link_id_to_zero.rb +4 -2
  208. data/db/migrate/20090825201159_insert_zero_link.rb +1 -1
  209. data/db/migrate/20090924141459_zafu_fix_sept09.rb +2 -2
  210. data/db/migrate/20100125062254_add_dynamo_to_version.rb +9 -0
  211. data/db/migrate/20100201133242_remove_default_status_on_version.rb +9 -0
  212. data/db/migrate/20100208194210_create_attachments.rb +17 -0
  213. data/db/migrate/20100210112319_change_dynamo_to_property.rb +9 -0
  214. data/db/migrate/20100320145726_transform_template_contents_into_index.rb +13 -0
  215. data/db/migrate/20100328125634_change_skin_name_to_id.rb +31 -0
  216. data/db/migrate/20100417061257_add_properties_to_sites.rb +9 -0
  217. data/db/migrate/20100419163149_rename_name_to_node_name.rb +9 -0
  218. data/db/migrate/20100422091606_change_v_class_table_into_roles.rb +27 -0
  219. data/db/migrate/20100422094048_node_habtm_roles.rb +13 -0
  220. data/db/migrate/20100422115935_create_columns.rb +15 -0
  221. data/db/migrate/20100513181529_add_site_id_to_columns.rb +9 -0
  222. data/db/migrate/20100519091711_add_index_definition_to_columns.rb +9 -0
  223. data/db/migrate/20100519091940_create_idx_nodes_string.rb +14 -0
  224. data/db/migrate/20100519232432_create_idx_nodes_ml_string.rb +15 -0
  225. data/db/migrate/20100525113858_add_porperties_to_users.rb +9 -0
  226. data/db/migrate/20100526090140_renamed_contact_model_to_base_contact.rb +13 -0
  227. data/db/migrate/20100527130937_change_column_index_to_string.rb +9 -0
  228. data/db/migrate/20100531135128_add_fulltext_builder_fields.rb +28 -0
  229. data/doc/zafu_changes.yml +2 -2
  230. data/lib/bricks/loader.rb +48 -26
  231. data/lib/exif_data.rb +21 -1
  232. data/lib/gettext_strings.rb +8 -1
  233. data/lib/tasks/zena.rake +55 -20
  234. data/lib/version_off.rb +323 -0
  235. data/lib/zazen_parser.rb +9 -0
  236. data/lib/zena.rb +13 -14
  237. data/lib/zena/acts/enrollable.rb +232 -0
  238. data/lib/zena/acts/secure.rb +86 -506
  239. data/lib/zena/acts/secure_node.rb +483 -0
  240. data/lib/zena/acts/serializable.rb +149 -0
  241. data/lib/zena/app.rb +36 -23
  242. data/lib/zena/code_syntax.rb +26 -2
  243. data/lib/zena/controller/test_case.rb +23 -2
  244. data/lib/zena/core_ext/file_utils.rb +3 -3
  245. data/lib/zena/core_ext/string.rb +2 -2
  246. data/lib/zena/db.rb +180 -24
  247. data/lib/zena/deploy.rb +140 -183
  248. data/lib/zena/deploy/awstats.conf.rhtml +4 -4
  249. data/lib/zena/deploy/httpd.rhtml +1 -2
  250. data/lib/zena/deploy/stats.vhost.rhtml +7 -7
  251. data/lib/zena/deploy/vhost.rhtml +1 -1
  252. data/lib/zena/deploy/vhost_www.rhtml +4 -4
  253. data/lib/zena/foxy_parser.rb +345 -295
  254. data/lib/zena/info.rb +1 -2
  255. data/lib/zena/integration/test_case.rb +70 -0
  256. data/lib/zena/loader/yaml_loader.rb +80 -0
  257. data/lib/zena/migrator.rb +2 -2
  258. data/lib/zena/parser.rb +19 -17
  259. data/lib/zena/parser/zafu_rules.rb +7 -0
  260. data/lib/zena/parser/zafu_tags.rb +2 -2
  261. data/lib/zena/parser/zazen_rules.rb +9 -29
  262. data/lib/zena/parser/zena_rules.rb +2 -2
  263. data/lib/zena/refactor/act_as_content.rb +6 -0
  264. data/lib/zena/routes.rb +9 -3
  265. data/lib/zena/site_worker.rb +48 -0
  266. data/lib/zena/test_controller.rb +49 -12
  267. data/lib/zena/use.rb +47 -0
  268. data/lib/zena/use/action.rb +230 -0
  269. data/lib/zena/use/ajax.rb +287 -13
  270. data/lib/zena/use/authlogic.rb +28 -12
  271. data/lib/zena/use/calendar.rb +2 -2
  272. data/lib/zena/use/conditional.rb +41 -0
  273. data/lib/zena/use/context.rb +187 -0
  274. data/lib/zena/use/dates.rb +87 -30
  275. data/lib/zena/use/display.rb +598 -0
  276. data/lib/zena/use/dyn_attributes.rb +4 -4
  277. data/lib/zena/use/error_rendering.rb +3 -1
  278. data/lib/zena/use/fixtures.rb +56 -22
  279. data/lib/zena/use/forms.rb +584 -0
  280. data/lib/zena/use/fulltext.rb +90 -0
  281. data/lib/zena/use/grid.rb +12 -7
  282. data/lib/zena/use/html_tags.rb +8 -459
  283. data/lib/zena/use/i18n.rb +172 -109
  284. data/lib/zena/use/image_builder.rb +1 -2
  285. data/lib/zena/use/ml_index.rb +56 -0
  286. data/lib/zena/use/nested_attributes_alias.rb +2 -2
  287. data/lib/zena/use/node_name.rb +94 -0
  288. data/lib/zena/use/query_builder.rb +355 -0
  289. data/lib/zena/use/query_comment.rb +63 -73
  290. data/lib/zena/use/query_node.rb +404 -317
  291. data/lib/zena/use/recursion.rb +71 -0
  292. data/lib/zena/use/refactor.rb +27 -40
  293. data/lib/zena/use/relations.rb +9 -3
  294. data/lib/zena/use/rendering.rb +143 -116
  295. data/lib/zena/use/search.rb +79 -21
  296. data/lib/zena/use/test_helper.rb +17 -9
  297. data/lib/zena/use/upload.rb +1 -1
  298. data/lib/zena/use/urls.rb +534 -28
  299. data/lib/zena/use/version_hash.rb +154 -0
  300. data/lib/zena/use/workflow.rb +635 -0
  301. data/lib/zena/use/zafu_attributes.rb +205 -0
  302. data/lib/zena/use/zafu_eval.rb +21 -0
  303. data/lib/zena/use/zafu_safe_definitions.rb +36 -0
  304. data/lib/zena/use/zafu_templates.rb +459 -0
  305. data/lib/zena/use/zazen.rb +53 -23
  306. data/lib/zena/view/test_case.rb +56 -7
  307. data/lib/zena/webdav_adapter.rb +8 -8
  308. data/lib/zena/zafu_compiler.rb +25 -0
  309. data/locale/de/LC_MESSAGES/zena.mo +0 -0
  310. data/locale/de/zena.mo +0 -0
  311. data/locale/de/zena.po +920 -781
  312. data/locale/en/LC_MESSAGES/zena.mo +0 -0
  313. data/locale/en/zena.mo +0 -0
  314. data/locale/en/zena.po +530 -405
  315. data/locale/fr/LC_MESSAGES/zena.mo +0 -0
  316. data/locale/fr/zena.mo +0 -0
  317. data/locale/fr/zena.po +588 -432
  318. data/locale/zena.pot +391 -353
  319. data/old_zafu/action.rb +129 -0
  320. data/{lib/zafu → old_zafu}/ajax.rb +0 -24
  321. data/{lib/zafu → old_zafu}/attributes.rb +2 -2
  322. data/{lib/zafu → old_zafu}/calendar.rb +1 -1
  323. data/{lib/zafu → old_zafu}/context.rb +4 -8
  324. data/{lib/zafu → old_zafu}/core/html.rb +1 -1
  325. data/old_zafu/core/move_to_parser.rb +74 -0
  326. data/old_zafu/dates.rb +20 -0
  327. data/{lib/zafu → old_zafu}/display.rb +33 -146
  328. data/{lib/zafu → old_zafu}/eval.rb +0 -0
  329. data/{lib/zafu → old_zafu}/experimental.rb +1 -1
  330. data/{lib/zafu → old_zafu}/i18n.rb +1 -1
  331. data/{lib/zafu → old_zafu}/meta.rb +0 -0
  332. data/old_zafu/query_node.rb +278 -0
  333. data/{lib/zafu → old_zafu}/refactor.rb +2 -12
  334. data/old_zafu/support/context.rb +146 -0
  335. data/{lib/zafu → old_zafu}/support/dom.rb +1 -43
  336. data/{lib/zafu → old_zafu}/support/erb.rb +0 -0
  337. data/{lib/zafu → old_zafu}/support/flow.rb +1 -13
  338. data/old_zafu/support/forms.rb +7 -0
  339. data/old_zafu/support/links.rb +75 -0
  340. data/{lib → old_zafu}/zafu_parser.rb +2 -2
  341. data/public/images/attach_window.png +0 -0
  342. data/public/images/dettach_window.png +0 -0
  343. data/public/images/ext/{contact.png → basecontact.png} +0 -0
  344. data/public/images/toggle_off.png +0 -0
  345. data/public/images/toggle_on.png +0 -0
  346. data/public/images/window/bottom_left.png +0 -0
  347. data/public/images/window/bottom_mid.png +0 -0
  348. data/public/images/window/bottom_right.png +0 -0
  349. data/public/images/window/center_left.png +0 -0
  350. data/public/images/window/center_right.png +0 -0
  351. data/public/images/window/close.png +0 -0
  352. data/public/images/window/maximize.png +0 -0
  353. data/public/images/window/minimize.png +0 -0
  354. data/public/images/window/overlay.png +0 -0
  355. data/public/images/window/sizer.png +0 -0
  356. data/public/images/window/top_left.png +0 -0
  357. data/public/images/window/top_mid.png +0 -0
  358. data/public/images/window/top_right.png +0 -0
  359. data/public/javascripts/builder.js +1 -3
  360. data/public/javascripts/controls.js +3 -5
  361. data/public/javascripts/dragdrop.js +5 -8
  362. data/public/javascripts/effects.js +6 -15
  363. data/public/javascripts/prototype.js +1574 -1020
  364. data/public/javascripts/scriptaculous.js +13 -7
  365. data/public/javascripts/slider.js +5 -7
  366. data/public/javascripts/sound.js +6 -4
  367. data/public/javascripts/unittest.js +69 -71
  368. data/public/javascripts/window.js +1843 -0
  369. data/public/javascripts/zena.js +216 -16
  370. data/public/stylesheets/admin.css +18 -13
  371. data/public/stylesheets/default.css +18 -17
  372. data/public/stylesheets/popup.css +4 -4
  373. data/public/stylesheets/window.css +155 -0
  374. data/public/stylesheets/zena.css +9 -8
  375. data/test/custom_queries/complex.host.yml +8 -8
  376. data/test/fixtures/files/Node-test.zafu +11 -11
  377. data/test/fixtures/files/import.tgz +0 -0
  378. data/test/fixtures/files/simple.zml.gz +0 -0
  379. data/test/fixtures/import/photos.en.zml +3 -3
  380. data/test/fixtures/import/photos/bird.jpg.en.zml +1 -1
  381. data/test/fixtures/import/photos/bird.jpg.fr.zml +1 -1
  382. data/test/fixtures/import/simple.zml +2 -2
  383. data/test/functional/application_controller_test.rb +2 -41
  384. data/test/functional/columns_controller_test.rb +140 -0
  385. data/test/functional/data_entries_controller_test.rb +1 -1
  386. data/test/functional/documents_controller_test.rb +88 -5
  387. data/test/functional/nodes_controller_commit_test.rb +71 -0
  388. data/test/functional/nodes_controller_test.rb +393 -93
  389. data/test/functional/note_controller_test.rb +5 -5
  390. data/test/functional/relations_controller_test.rb +1 -1
  391. data/test/functional/users_controller_test.rb +72 -14
  392. data/test/functional/versions_controller_test.rb +9 -8
  393. data/test/functional/virtual_classes_controller_test.rb +142 -65
  394. data/test/integration/multiple_hosts_test.rb +28 -20
  395. data/test/integration/navigation_test.rb +121 -83
  396. data/test/integration/query_node/basic.yml +128 -0
  397. data/test/integration/query_node/comments.yml +23 -0
  398. data/test/integration/query_node/complex.yml +111 -0
  399. data/test/integration/query_node/dates.yml +22 -0
  400. data/test/integration/query_node/errors.yml +12 -0
  401. data/test/integration/query_node/filters.yml +123 -0
  402. data/test/integration/query_node/properties.yml +41 -0
  403. data/test/integration/query_node/relations.yml +75 -0
  404. data/test/integration/query_node_test.rb +189 -0
  405. data/test/integration/xml_api_test.rb +166 -0
  406. data/test/integration/zafu_compiler/action.yml +67 -0
  407. data/test/integration/zafu_compiler/ajax.yml +263 -0
  408. data/test/{unit/zena/zena_tags → integration/zafu_compiler}/apphelper.yml +0 -0
  409. data/test/integration/zafu_compiler/asset.yml +13 -0
  410. data/test/integration/zafu_compiler/basic.yml +518 -0
  411. data/test/integration/zafu_compiler/calendar.yml +35 -0
  412. data/test/{unit/zena/zena_tags → integration/zafu_compiler}/complex.yml +16 -16
  413. data/test/integration/zafu_compiler/conditional.yml +173 -0
  414. data/test/{unit/zena/zena_tags → integration/zafu_compiler}/data.yml +3 -3
  415. data/test/integration/zafu_compiler/dates.yml +58 -0
  416. data/test/integration/zafu_compiler/display.yml +273 -0
  417. data/test/integration/zafu_compiler/errors.yml +79 -0
  418. data/test/{unit/zena/zena_tags → integration/zafu_compiler}/eval.yml +6 -2
  419. data/test/integration/zafu_compiler/forms.yml +130 -0
  420. data/test/integration/zafu_compiler/i18n.yml +107 -0
  421. data/test/integration/zafu_compiler/later.yml +31 -0
  422. data/test/integration/zafu_compiler/off/off.yml +15 -0
  423. data/test/integration/zafu_compiler/recursion.yml +28 -0
  424. data/test/integration/zafu_compiler/relations.yml +487 -0
  425. data/test/integration/zafu_compiler/roles.yml +28 -0
  426. data/test/{unit/zena/zena_tags → integration/zafu_compiler}/rubyless.yml +10 -9
  427. data/test/integration/zafu_compiler/safe_definitions.yml +65 -0
  428. data/test/integration/zafu_compiler/search.yml +13 -0
  429. data/test/integration/zafu_compiler/security.yml +30 -0
  430. data/test/integration/zafu_compiler/site.yml +14 -0
  431. data/test/integration/zafu_compiler/urls.yml +189 -0
  432. data/test/integration/zafu_compiler/user.yml +32 -0
  433. data/test/integration/zafu_compiler/version.yml +47 -0
  434. data/test/integration/zafu_compiler/workflow.yml +36 -0
  435. data/test/integration/zafu_compiler/zafu_attributes.yml +169 -0
  436. data/test/{unit/zena/zena_tags → integration/zafu_compiler}/zazen.yml +7 -3
  437. data/test/{unit/zena/zena_tags_test.rb → integration/zafu_compiler_test.rb} +137 -57
  438. data/test/sites/complex/nodes.yml +48 -47
  439. data/test/sites/complex/{virtual_classes.yml → roles.yml} +2 -1
  440. data/test/sites/ocean/nodes.yml +7 -7
  441. data/test/sites/ocean/versions.yml +30 -21
  442. data/test/sites/zena/columns.yml +12 -0
  443. data/test/sites/zena/nodes.yml +33 -32
  444. data/test/sites/zena/{virtual_classes.yml → roles.yml} +11 -1
  445. data/test/sites/zena/sites.yml +4 -1
  446. data/test/sites/zena/users.yml +5 -4
  447. data/test/sites/zena/versions.yml +398 -279
  448. data/test/test_helper.rb +2 -1
  449. data/test/test_zena.rb +3 -8
  450. data/test/unit/after_commit_test.rb +103 -0
  451. data/test/unit/attachment_test.rb +266 -0
  452. data/test/unit/base_contact_test.rb +242 -0
  453. data/test/unit/cached_page_test.rb +6 -6
  454. data/test/unit/column_test.rb +77 -0
  455. data/test/unit/comment_test.rb +1 -1
  456. data/test/unit/data_entry_test.rb +8 -2
  457. data/test/unit/document_test.rb +393 -211
  458. data/test/unit/exif_data_test.rb +1 -1
  459. data/test/unit/iformat_test.rb +9 -9
  460. data/test/unit/image_test.rb +358 -284
  461. data/test/unit/multi_version_test.rb +4 -0
  462. data/test/unit/multiversion_test.rb +2 -1013
  463. data/test/unit/node_name_test.rb +137 -0
  464. data/test/unit/node_test.rb +374 -461
  465. data/test/unit/note_test.rb +23 -23
  466. data/test/unit/page_test.rb +23 -23
  467. data/test/unit/project_test.rb +2 -2
  468. data/test/unit/relation_proxy_test.rb +25 -6
  469. data/test/unit/relation_test.rb +156 -24
  470. data/test/unit/role_test.rb +122 -0
  471. data/test/unit/section_test.rb +2 -2
  472. data/test/unit/site_test.rb +48 -12
  473. data/test/unit/skin_test.rb +0 -13
  474. data/test/unit/template_test.rb +361 -314
  475. data/test/unit/text_document_test.rb +105 -33
  476. data/test/unit/transparent_version_test.rb +4 -0
  477. data/test/unit/user_test.rb +10 -10
  478. data/test/unit/version_test.rb +209 -301
  479. data/test/unit/virtual_class_test.rb +21 -29
  480. data/test/unit/workflow_test.rb +1075 -0
  481. data/test/unit/zena/acts/enrollable_test.rb +211 -0
  482. data/test/unit/{secure_test.rb → zena/acts/secure_test.rb} +190 -105
  483. data/test/unit/zena/acts/serializable_test.rb +85 -0
  484. data/test/unit/zena/db_test.rb +27 -14
  485. data/test/unit/zena/parser/zazen.yml +1 -1
  486. data/test/unit/zena/use/action_test.rb +109 -0
  487. data/test/unit/zena/use/calendar_test.rb +8 -8
  488. data/test/unit/zena/use/dates_test.rb +10 -0
  489. data/test/unit/zena/use/dates_view_methods_test.rb +8 -12
  490. data/test/unit/zena/use/fulltext_test.rb +82 -0
  491. data/test/unit/zena/use/html_tags_test.rb +225 -201
  492. data/test/unit/zena/use/i18n_test.rb +56 -26
  493. data/test/unit/zena/use/ml_index_test.rb +129 -0
  494. data/test/unit/zena/use/nested_attributes_alias_view_test.rb +10 -10
  495. data/test/unit/zena/use/query_node_test.rb +104 -0
  496. data/test/unit/zena/use/refactor_test.rb +4 -15
  497. data/test/unit/zena/use/rendering_test.rb +23 -16
  498. data/test/unit/zena/use/upload_test.rb +2 -2
  499. data/test/unit/zena/use/urls_test.rb +2 -0
  500. data/test/unit/zena/use/version_hash_test.rb +126 -0
  501. data/test/unit/zena/use/zafu_template_test.rb +135 -0
  502. data/test/unit/zena/use/zazen_test.rb +85 -61
  503. data/vendor/plugins/gettext_i18n_rails/README.markdown +26 -22
  504. data/vendor/plugins/gettext_i18n_rails/Rakefile +31 -5
  505. data/vendor/plugins/gettext_i18n_rails/VERSION +1 -0
  506. data/vendor/plugins/gettext_i18n_rails/gettext_i18n_rails.gemspec +64 -0
  507. data/vendor/plugins/gettext_i18n_rails/init.rb +7 -3
  508. data/vendor/plugins/gettext_i18n_rails/lib/gettext_i18n_rails.rb +5 -6
  509. data/vendor/plugins/gettext_i18n_rails/lib/gettext_i18n_rails/active_record.rb +6 -2
  510. data/vendor/plugins/gettext_i18n_rails/lib/gettext_i18n_rails/backend.rb +1 -1
  511. data/vendor/plugins/gettext_i18n_rails/lib/gettext_i18n_rails/model_attributes_finder.rb +2 -2
  512. data/vendor/plugins/gettext_i18n_rails/{tasks → lib/tasks}/gettext_rails_i18n.rake +10 -9
  513. data/vendor/plugins/gettext_i18n_rails/spec/gettext_i18n_rails/action_controller_spec.rb +7 -3
  514. data/vendor/plugins/gettext_i18n_rails/spec/gettext_i18n_rails/active_record_spec.rb +7 -5
  515. data/vendor/plugins/gettext_i18n_rails/spec/gettext_i18n_rails/backend_spec.rb +7 -7
  516. data/vendor/plugins/gettext_i18n_rails/spec/gettext_i18n_rails_spec.rb +4 -0
  517. data/vendor/plugins/gettext_i18n_rails/spec/spec_helper.rb +11 -9
  518. data/vendor/plugins/mysql_timezone_utc/init.rb +1 -0
  519. data/vendor/plugins/mysql_timezone_utc/lib/mysql_timezone_utc.rb +14 -0
  520. data/vendor/plugins/postgresql_timezone_utc/init.rb +1 -0
  521. data/vendor/plugins/postgresql_timezone_utc/lib/postgresql_timezone_utc.rb +14 -0
  522. data/zena.gemspec +281 -123
  523. metadata +354 -160
  524. data/app/models/contact.rb +0 -32
  525. data/app/models/document_version.rb +0 -13
  526. data/app/models/image_version.rb +0 -21
  527. data/app/models/text_document_version.rb +0 -29
  528. data/app/views/templates/defaults/+adminLayout.zafu +0 -69
  529. data/bricks/captcha/patch/application_controller.rb +0 -10
  530. data/bricks/captcha/patch/application_helper.rb +0 -32
  531. data/bricks/captcha/patch/site.rb +0 -2
  532. data/bricks/captcha/zafu/captcha.rb +0 -29
  533. data/bricks/tags/patch/node.rb +0 -15
  534. data/bricks/tags/test/zafu/tags.yml +0 -40
  535. data/db/schema.rb +0 -295
  536. data/lib/zafu/action.rb +0 -285
  537. data/lib/zafu/core/move_to_parser.rb +0 -167
  538. data/lib/zafu/dates.rb +0 -58
  539. data/lib/zafu/support/context.rb +0 -265
  540. data/lib/zafu/support/forms.rb +0 -461
  541. data/lib/zafu/support/links.rb +0 -306
  542. data/lib/zena/acts/multiversion.rb +0 -755
  543. data/lib/zena/fix/mysql_connection.rb +0 -17
  544. data/lib/zena/use/query_node_finders.rb +0 -91
  545. data/lib/zena/use/zafu.rb +0 -514
  546. data/test/helpers/query_node/basic.yml +0 -149
  547. data/test/helpers/query_node/comments.yml +0 -18
  548. data/test/helpers/query_node/complex.yml +0 -98
  549. data/test/helpers/query_node/filters.yml +0 -110
  550. data/test/helpers/query_node/relations.yml +0 -43
  551. data/test/helpers/query_node_test.rb +0 -116
  552. data/test/sites/ocean/contact_contents.yml +0 -19
  553. data/test/sites/ocean/template_contents.yml +0 -8
  554. data/test/sites/zena/contact_contents.yml +0 -55
  555. data/test/sites/zena/document_contents.yml +0 -76
  556. data/test/sites/zena/dyn_attributes.yml +0 -43
  557. data/test/sites/zena/template_contents.yml +0 -103
  558. data/test/unit/contact_content_test.rb +0 -33
  559. data/test/unit/contact_test.rb +0 -39
  560. data/test/unit/contact_version_test.rb +0 -48
  561. data/test/unit/document_content_test.rb +0 -110
  562. data/test/unit/document_version_test.rb +0 -11
  563. data/test/unit/dyn_attributes_test.rb +0 -229
  564. data/test/unit/image_content_test.rb +0 -154
  565. data/test/unit/image_version_test.rb +0 -18
  566. data/test/unit/template_content_test.rb +0 -9
  567. data/test/unit/text_document_version_test.rb +0 -37
  568. data/test/unit/zena/use/zafu_test.rb +0 -41
  569. data/test/unit/zena/zena_tags/ajax.yml +0 -233
  570. data/test/unit/zena/zena_tags/basic.yml +0 -1306
  571. data/test/unit/zena/zena_tags/errors.yml +0 -71
  572. data/test/unit/zena/zena_tags/relations.yml +0 -405
data/app/models/cache.rb CHANGED
@@ -22,8 +22,8 @@ class Cache < ActiveRecord::Base
22
22
  def sweep(hash)
23
23
  if kpath = hash[:kpath]
24
24
  klasses = []
25
- kpath.split(//).each_index { |i| klasses << kpath[0..i].inspect }
26
- kpath_selector = " AND kpath IN (#{klasses.join(',')})"
25
+ kpath.split(//).each_index { |i| klasses << kpath[0..i] }
26
+ kpath_selector = " AND kpath IN (#{klasses.map{|k| connection.quote(k)}.join(',')})"
27
27
  else
28
28
  kpath_selector = ""
29
29
  end
@@ -109,9 +109,9 @@ class CachedPage < ActiveRecord::Base
109
109
  def cached_page_after_save
110
110
  # create cache file
111
111
  filepath = "#{SITES_ROOT}#{path}"
112
- FileUtils.mkpath(File.dirname(filepath))
112
+ FileUtils.mkpath(File.dirname(filepath)) # if symlink points to a dead file, exist? returns false...
113
+ FileUtils.rm(filepath) if File.exist?(filepath) || File.symlink?(filepath)
113
114
  if content_path
114
- FileUtils.rm(filepath) if File.exist?(filepath)
115
115
  FileUtils.symlink_or_copy(content_path, filepath)
116
116
  else
117
117
  File.open(filepath, "wb+") { |f| f.write(content_data) }
@@ -120,7 +120,7 @@ class CachedPage < ActiveRecord::Base
120
120
  # create join values from context for automatic expire
121
121
  if (ids = @expire_with_ids || visitor.visited_node_ids) != []
122
122
  values = ids.compact.uniq.map {|id| [self[:id], id]}
123
- Zena::Db.insert_many('cached_pages_nodes', ['cached_page_id', 'node_id'], values)
123
+ Zena::Db.insert_many('cached_pages_nodes', %w{cached_page_id node_id}, values)
124
124
  end
125
125
  end
126
126
 
@@ -128,7 +128,8 @@ class CachedPage < ActiveRecord::Base
128
128
  def cached_page_on_destroy
129
129
  filepath = "#{SITES_ROOT}#{path.gsub('..','')}" # just in case...
130
130
  CachedPage.logger.info "remove #{filepath}"
131
- FileUtils.rm(filepath) if File.exist?(filepath)
131
+ # if symlink points to a dead file, exist? returns false...
132
+ FileUtils.rm(filepath) if File.exist?(filepath) || File.symlink?(filepath)
132
133
  CachedPage.connection.execute "DELETE FROM cached_pages_nodes WHERE cached_page_id = '#{id}'"
133
134
  end
134
135
  end
@@ -0,0 +1,90 @@
1
+ class Column < ActiveRecord::Base
2
+ attr_accessor :import_result
3
+ include RubyLess
4
+ include Property::StoredColumn
5
+ TYPES_FOR_FORM = %w{string datetime integer}
6
+ INDICES_FOR_FORM = %w{string ml_string}
7
+
8
+ belongs_to :role
9
+ before_validation :set_defaults
10
+
11
+ validates_presence_of :role
12
+ validates_uniqueness_of :name, :scope => :site_id
13
+ validate :name_not_in_models
14
+
15
+ class << self
16
+ include Zena::Acts::Secure
17
+
18
+ def roles_for_form
19
+ secure(Role) { Role.all(:order => 'kpath ASC') }.map {|r| [r.name, r.id]}
20
+ end
21
+
22
+ # Import a hash of virtual class definitions and try to build the virtual classes.
23
+ def import(data)
24
+ data.keys.map do |klass|
25
+ build_column(klass, data)
26
+ end
27
+ end
28
+
29
+ # Build a virtual class from a name and a hash of virtual class definitions. If
30
+ # the superclass is in the data hash, it is built first.
31
+ def build_column(klass, data)
32
+ # TODO
33
+ # return data[klass]['result'] if data[klass].has_key?('result')
34
+ # if virtual_class = Node.get_class(klass)
35
+ # if virtual_class.superclass.to_s == data[klass]['superclass']
36
+ # virtual_class.import_result = 'same'
37
+ # return data[klass]['result'] = virtual_class
38
+ # else
39
+ # virtual_class.errors.add(:base, 'conflict')
40
+ # return data[klass]['result'] = virtual_class
41
+ # end
42
+ # else
43
+ # superclass_name = data[klass]['superclass']
44
+ # if data[superclass_name]
45
+ # superclass = build_virtual_class(superclass_name, data)
46
+ # unless superclass.errors.empty?
47
+ # virtual_class = VirtualClass.new(:name => klass, :superclass => superclass_name, :create_group_id => current_site.public_group_id)
48
+ # virtual_class.errors.add(:base, 'conflict in superclass')
49
+ # return data[klass]['result'] = virtual_class
50
+ # end
51
+ # elsif superclass = Node.get_class(superclass_name)
52
+ # # ok
53
+ # else
54
+ # virtual_class = VirtualClass.new(:name => klass, :superclass => superclass_name, :create_group_id => current_site.public_group_id)
55
+ # virtual_class.errors.add(:base, 'missing superclass')
56
+ # return data[klass]['result'] = virtual_class
57
+ # end
58
+ #
59
+ # # build
60
+ # create_group_id = superclass.kind_of?(VirtualClass) ? superclass.create_group_id : current_site.public_group_id
61
+ # virtual_class = create(data[klass].merge(:name => klass, :create_group_id => create_group_id))
62
+ # virtual_class.import_result = 'new'
63
+ # return data[klass]['result'] = virtual_class
64
+ # end
65
+ end
66
+
67
+ def export
68
+ # TODO
69
+ end
70
+ end
71
+
72
+ def kpath
73
+ @kpath ||= role.kpath
74
+ end
75
+
76
+ protected
77
+ def set_defaults
78
+ self[:site_id] = current_site.id
79
+ end
80
+
81
+ def name_not_in_models
82
+ Node.native_classes.each do |kpath, klass|
83
+ if column = klass.schema.columns[self.name]
84
+ # find column origin
85
+ errors.add(:name, _('has already been taken in %s') % column.role.name)
86
+ break
87
+ end
88
+ end
89
+ end
90
+ end
@@ -6,7 +6,7 @@ belong to the user _anon_ (see #User) and must have the 'athor_name' field set.
6
6
  If anonymous is moderated (User#moderated?), all public comments are set to 'prop' and are not directly seen on the site.
7
7
  =end
8
8
  class Comment < ActiveRecord::Base
9
- include RubyLess::SafeClass
9
+ include RubyLess
10
10
 
11
11
  safe_attribute :title, :created_at, :updated_at, :status
12
12
  safe_method :text => String, :author_name => {:class => String, :nil => true},
@@ -21,6 +21,8 @@ class Comment < ActiveRecord::Base
21
21
  before_validation :comment_before_validation
22
22
  after_save :sweep_cache
23
23
 
24
+ include Zena::Use::QueryComment::ModelMethods
25
+
24
26
  def author
25
27
  @author ||= secure(User) { User.find(self[:user_id]) }
26
28
  end
@@ -1,9 +1,9 @@
1
1
  =begin rdoc
2
- Used by Contact to store contact data. See the documentation on this class for more information.
2
+ Used by BaseContact to store contact data. See the documentation on this class for more information.
3
3
 
4
4
  === Attributes
5
5
 
6
- Provides the following attributes to Contact :
6
+ Provides the following attributes to BaseContact :
7
7
 
8
8
  first_name:: first name
9
9
  name:: name
@@ -16,7 +16,7 @@ email:: email address
16
16
  birthday:: birthday (date)
17
17
  =end
18
18
  class ContactContent < ActiveRecord::Base
19
- include RubyLess::SafeClass
19
+ include RubyLess
20
20
  safe_method :created_at => Time, :updated_at => Time, :fullname => String, :initials => String,
21
21
  :address => String
22
22
  safe_attribute :name, :first_name, :city, :country, :telephone, :mobile, :email, :zip
@@ -26,8 +26,8 @@ class ContactContent < ActiveRecord::Base
26
26
  after_initialize :set_contact_content_defaults
27
27
  before_validation :content_before_validation
28
28
 
29
- extend Zena::Acts::Multiversion
30
- act_as_content
29
+ #extend Zena::Use::Multiversion
30
+ #act_as_content
31
31
 
32
32
  # Full contact name to show in views.
33
33
  def fullname(first_name = self.first_name, name = self.name)
@@ -1,11 +1,11 @@
1
1
  =begin rdoc
2
- This class stores version text for Contact. See Version for details.
2
+ This class stores version text for BaseContact. See Version for details.
3
3
 
4
4
  === Content
5
5
 
6
6
  Uses ContactContent.
7
7
  =end
8
- class ContactVersion < Version
8
+ class BaseContactVersion < Version
9
9
 
10
10
  def self.content_class
11
11
  ContactContent
@@ -13,13 +13,13 @@ A visitor needs write access in all nodes the data should link to. A visitor als
13
13
  A visitor can edit a data entry if he/she has write access to the reference node (node_a).
14
14
  =end
15
15
  class DataEntry < ActiveRecord::Base
16
- include RubyLess::SafeClass
16
+ include RubyLess
17
17
  safe_attribute :created_at, :updated_at, :date, :text, :value_a, :value_b
18
18
  safe_context :value => {:class => Number, :method => 'value_a'},
19
19
  :node_a_zip => Number, :node_b_zip => Number,
20
20
  :node_c_zip => Number, :node_d_zip => Number,
21
21
  :node_a => 'Node', :node_b => 'Node', :node_c => 'Node',
22
- :node_d => 'Node', :nodes => ['Node'], :author => 'Contact', :user => 'User'
22
+ :node_d => 'Node', :nodes => ['Node'], :author => 'BaseContact', :user => 'User'
23
23
 
24
24
  attr_protected :site_id
25
25
 
@@ -36,23 +36,24 @@ class DataEntry < ActiveRecord::Base
36
36
  end
37
37
 
38
38
  # modify attributes so ext sees 'zip' values but we store 'ids'
39
- def self.transform_attributes(new_attributes)
39
+ def self.transform_attributes(new_attributes, base_node = nil, parse_dates = true)
40
40
  attributes = new_attributes.stringify_keys
41
41
 
42
42
  attributes.keys.each do |key|
43
43
  if key == 'date'
44
+ next unless parse_dates
44
45
  attributes[key] = attributes[key].to_utc(_('datetime'), visitor.tz)
45
46
  elsif key =~ /^(\w+)_id$/
46
47
  if key[0..4] == 'node_'
47
- attributes[key] = Node.translate_pseudo_id(attributes[key]) || attributes[key]
48
+ attributes[key] = Node.translate_pseudo_id(attributes[key], :id, base_node) || attributes[key]
48
49
  else
49
- attributes[key] = Node.translate_pseudo_id(attributes[key]) || attributes[key]
50
+ attributes[key] = Node.translate_pseudo_id(attributes[key], :id, base_node) || attributes[key]
50
51
  end
51
52
  elsif key == 'text'
52
53
  # translate zazen
53
54
  value = attributes[key]
54
55
  if value.kind_of?(String)
55
- attributes[key] = ZazenParser.new(value,:helper=>self, :node=>self).render(:translate_ids=>:zip)
56
+ attributes[key] = ZazenParser.new(value,:helper=>self, :node=>base_node).render(:translate_ids=>:zip)
56
57
  end
57
58
  end
58
59
  end
@@ -96,8 +97,8 @@ class DataEntry < ActiveRecord::Base
96
97
  end
97
98
 
98
99
  # Update a data entry's attributes, transforming the attributes first from the visitor's context to internal context.
99
- def update_attributes_with_transformation(new_attributes)
100
- update_attributes(DataEntry.transform_attributes(new_attributes))
100
+ def update_attributes_with_transformation(new_attributes, parse_dates = true)
101
+ update_attributes(DataEntry.transform_attributes(new_attributes, ref_node, parse_dates))
101
102
  end
102
103
 
103
104
  def clone
@@ -8,6 +8,10 @@ language and if the current visitor is a commentator (User.commentator?).
8
8
  =end
9
9
  class Discussion < ActiveRecord::Base
10
10
 
11
+ include RubyLess
12
+ safe_context :comments => ['Comment']
13
+ safe_method :comments_count => Number
14
+
11
15
  attr_protected :site_id
12
16
  has_many :all_comments, :class_name=>'Comment', :foreign_key=>'discussion_id', :order=>'created_at ASC', :dependent=>:delete_all
13
17
  belongs_to :node
@@ -27,13 +27,28 @@ The version class used by documents is the DocumentVersion.
27
27
 
28
28
  Content (file data) is managed by the DocumentContent. This class is responsible for storing the file and retrieving the data. It provides the following attributes to the Document :
29
29
 
30
- c_size:: file size
31
- c_ext:: file extension
32
- c_content_type:: file content-type
30
+ size:: file size
31
+ ext:: file extension
32
+ content_type:: file content-type
33
33
  =end
34
34
  # should be a sub-class of Node, not Page (#184). Write a migration, fix fixtures and test.
35
35
  class Document < Node
36
- safe_method :filename => String
36
+
37
+ include Versions::Attachment
38
+ store_attachments_in :version, :attachment_class => 'Attachment'
39
+
40
+ property do |p|
41
+ p.integer 'size'
42
+ p.string 'content_type'
43
+ p.string 'ext'
44
+ end
45
+
46
+ safe_property :size, :content_type, :ext
47
+ safe_method :filename => String, :file => File, :filepath => String
48
+
49
+ validate :valid_file
50
+ validate :valid_content_type
51
+ after_save :clear_new_file
37
52
 
38
53
  class << self
39
54
 
@@ -47,32 +62,24 @@ class Document < Node
47
62
  def new(attrs = {})
48
63
 
49
64
  scope = self.scoped_methods[0] || {}
50
- klass = self
65
+
51
66
  attrs = attrs.stringify_keys
52
- file = attrs['c_file'] || ((attrs['version_attributes'] || {})['content_attributes'] || {})['file']
53
- if file && file.respond_to?(:content_type)
67
+ file = attrs['file'] || ((attrs['version_attributes'] || {})['content_attributes'] || {})['file']
68
+ if attrs['content_type']
69
+ content_type = attrs['content_type']
70
+ elsif file && file.respond_to?(:content_type)
54
71
  content_type = file.content_type
55
- elsif ct = attrs['c_content_type'] || ((attrs['version_attributes'] || {})['content_attributes'] || {})['content_type']
72
+ elsif ct = attrs['content_type']
56
73
  content_type = ct
57
- elsif attrs['name'] =~ /^.*\.(\w+)$/ && types = Zena::EXT_TO_TYPE[$1.downcase]
74
+ elsif attrs['node_name'] =~ /^.*\.(\w+)$/ && types = Zena::EXT_TO_TYPE[$1.downcase]
75
+ content_type = types[0]
76
+ elsif attrs['title'] =~ /^.*\.(\w+)$/ && types = Zena::EXT_TO_TYPE[$1.downcase]
58
77
  content_type = types[0]
59
78
  end
60
79
 
61
- if content_type
62
- if Image.accept_content_type?(content_type)
63
- klass = Image
64
- elsif Template.accept_content_type?(content_type)
65
- klass = Template
66
- elsif TextDocument.accept_content_type?(content_type)
67
- klass = TextDocument
68
- end
69
- elsif self == Document
70
- # no content_type means no file. Only TextDocuments can be created without files
71
- content_type = 'text/plain'
72
- klass = TextDocument
73
- end
80
+ klass = document_class_from_content_type(content_type)
74
81
 
75
- attrs['c_content_type'] = content_type
82
+ attrs['content_type'] = content_type
76
83
 
77
84
  if klass != self
78
85
  klass.with_scope(scope) { klass.o_new(attrs) }
@@ -85,6 +92,50 @@ class Document < Node
85
92
  def change_to_classes_for_form
86
93
  classes_for_form(:class => 'Document', :without => 'Image')
87
94
  end
95
+
96
+ # Return document class and content_type from content_type
97
+ def document_class_from_content_type(content_type)
98
+ if content_type
99
+ if Image.accept_content_type?(content_type)
100
+ Image
101
+ elsif Template.accept_content_type?(content_type)
102
+ Template
103
+ elsif TextDocument.accept_content_type?(content_type)
104
+ TextDocument
105
+ else
106
+ self
107
+ end
108
+ elsif self == Document
109
+ # no content_type means no file. Only TextDocuments can be created without files
110
+ TextDocument
111
+ else
112
+ self
113
+ end
114
+ end
115
+
116
+ # Return true if the content_type can change independantly from the file
117
+ def accept_content_type_change?
118
+ false
119
+ end
120
+ end # class << self
121
+
122
+ # Create an attachment with a file in file system. Create a new version if file is updated.
123
+ def file=(new_file)
124
+ if new_file = super(new_file)
125
+ self.size = new_file.kind_of?(StringIO) ? new_file.size : new_file.stat.size
126
+ @new_file = new_file
127
+ end
128
+ end
129
+
130
+ # Return the file size.
131
+ def size(mode=nil)
132
+ if prop['size']
133
+ prop['size']
134
+ elsif !new_record? && File.exist?(self.filepath)
135
+ prop['size'] = File.size(self.filepath)
136
+ self.save
137
+ prop['size']
138
+ end
88
139
  end
89
140
 
90
141
  # Return true if the document is an image.
@@ -92,40 +143,117 @@ class Document < Node
92
143
  kind_of?(Image)
93
144
  end
94
145
 
95
- # Return the document's public filename using the name and the file extension.
146
+ # Get the document's public filename using the name and the file extension.
96
147
  def filename
97
- "#{name}.#{version.content.ext}"
148
+ version.attachment.filename
149
+ end
150
+
151
+ # Get the file path defined in attachment.
152
+ def filepath(format=nil)
153
+ version.attachment.filepath(format)
98
154
  end
99
155
 
156
+ # Get the node's rootpath with the file's extention.
100
157
  def rootpath
101
- super + ".#{version.content.ext}"
158
+ super + ".#{prop['ext']}"
102
159
  end
103
160
 
104
- private
161
+ protected
105
162
  def set_defaults
106
- base = name
107
- base = version.title if base.blank?
108
- if base.blank? && file = version.content.file
109
- base = file.original_filename
163
+ set_defaults_from_file
164
+
165
+ self.ext = get_extension if self.ext.blank? || @new_file
166
+
167
+ if title.to_s =~ /\A(.*)\.#{self.ext}$/i
168
+ self.title = $1
110
169
  end
111
170
 
112
- if base
113
- if base =~ /(.*)\.(\w+)$/
114
- self.name = $1 if new_record?
115
- self.version.content.ext ||= $2
171
+ if node_name.to_s =~ /\A(.*)\.#{self.ext}$/i
172
+ self.node_name = $1
173
+ end
174
+
175
+ super
176
+
177
+ set_attachment_filename
178
+ true
179
+ end
180
+
181
+ # Overwriten in TextDocument
182
+ def set_attachment_filename
183
+ if @new_file
184
+ version.attachment.filename = "#{title}.#{ext}"
185
+ end
186
+ end
187
+
188
+ # Make sure we have a file.
189
+ def valid_file
190
+ if new_record? && !@new_file
191
+ errors.add('file', "can't be blank")
192
+ false
193
+ else
194
+ true
195
+ end
196
+ end
197
+
198
+ # Make sure the new file
199
+ def valid_content_type
200
+ return true unless prop.content_type_changed?
201
+
202
+ if !@new_file && !self.class.accept_content_type_change?
203
+ errors.add('content_type', 'incompatible with this file')
204
+ return false
205
+ end
206
+
207
+ klass = Document.document_class_from_content_type(content_type)
208
+
209
+ if klass != self.class
210
+ if @new_file
211
+ errors.add('file', 'incompatible with this class')
116
212
  else
117
- self.name = base if new_record?
213
+ errors.add('content_type', 'incompatible with this class')
118
214
  end
119
- if version.title.to_s =~ /\A(.*)\.#{version.content.ext}$/i
120
- version.title = $1
215
+ end
216
+ end
217
+
218
+ def clear_new_file
219
+ @new_file = nil
220
+ true
221
+ end
222
+
223
+ def set_defaults_from_file
224
+ return unless @new_file
225
+ self.content_type = @new_file.content_type unless prop.content_type_changed?
226
+
227
+ if base = node_name || title || @new_file.original_filename
228
+ if base =~ /(.*)\.(\w+)$/
229
+ self.node_name = $1 if new_record?
230
+ else
231
+ self.node_name = base if new_record?
121
232
  end
122
233
  end
123
- super
124
234
  end
125
235
 
126
- # Make sure name is unique
127
- def node_before_validation
128
- get_unique_name_in_scope('ND%')
236
+ # Make sure node_name is unique. This should be run after sync_node_name, this is why we
237
+ # hack around the name and use super.
238
+ def sync_node_name
129
239
  super
240
+ get_unique_node_name_in_scope('ND%')
130
241
  end
242
+
243
+ def get_extension
244
+ extensions = Zena::TYPE_TO_EXT[prop['content_type']]
245
+ if extensions && content_type != 'application/octet-stream' # use 'bin' extension only if we do not have any other ext.
246
+ (prop['ext'] && extensions.include?(prop['ext'].downcase)) ? self.prop['ext'].downcase : extensions[0]
247
+ elsif @new_file
248
+ # unknown content_type or 'application/octet-stream', just keep the extension we have
249
+ if @new_file.original_filename =~ /\w\.(\w+)$/
250
+ $1.downcase
251
+ else
252
+ 'bin'
253
+ end
254
+ else
255
+ nil
256
+ end
257
+ end
258
+
131
259
  end