zena 1.0.0.beta3 → 1.0.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (418) hide show
  1. data/History.txt +29 -0
  2. data/Rakefile +2 -0
  3. data/TODO_ZENA_1_0 +13 -23
  4. data/app/controllers/columns_controller.rb +1 -1
  5. data/app/controllers/comments_controller.rb +4 -3
  6. data/app/controllers/documents_controller.rb +8 -11
  7. data/app/controllers/nodes_controller.rb +39 -21
  8. data/app/controllers/users_controller.rb +8 -3
  9. data/app/controllers/versions_controller.rb +2 -2
  10. data/app/controllers/virtual_classes_controller.rb +17 -11
  11. data/app/helpers/documents_helper.rb +0 -3
  12. data/app/helpers/users_helper.rb +17 -0
  13. data/app/models/cache.rb +36 -31
  14. data/app/models/column.rb +48 -5
  15. data/app/models/comment.rb +14 -5
  16. data/app/models/data_entry.rb +2 -2
  17. data/app/models/document.rb +23 -33
  18. data/app/models/idx_nodes_datetime.rb +4 -0
  19. data/app/models/idx_nodes_float.rb +4 -0
  20. data/app/models/idx_project.rb +3 -0
  21. data/app/models/node.rb +372 -308
  22. data/app/models/page.rb +1 -31
  23. data/app/models/relation.rb +4 -4
  24. data/app/models/relation_proxy.rb +128 -17
  25. data/app/models/role.rb +27 -2
  26. data/app/models/site.rb +64 -56
  27. data/app/models/template.rb +11 -12
  28. data/app/models/text_document.rb +6 -7
  29. data/app/models/user.rb +95 -46
  30. data/app/models/version.rb +2 -2
  31. data/app/models/virtual_class.rb +418 -73
  32. data/app/views/columns/_form.html.erb +1 -1
  33. data/app/views/columns/_li.html.erb +1 -1
  34. data/app/views/comments/_form.rhtml +1 -1
  35. data/app/views/comments/_li.rhtml +1 -1
  36. data/app/views/comments/_li_simple.rhtml +1 -1
  37. data/app/views/groups/_form.rhtml +1 -1
  38. data/app/views/links/_li.rhtml +1 -1
  39. data/app/views/nodes/_groups.rhtml +1 -1
  40. data/app/views/nodes/_import_results.rhtml +1 -1
  41. data/app/views/nodes/_parent.rhtml +1 -1
  42. data/app/views/nodes/_results.rhtml +1 -1
  43. data/app/views/nodes/create.rjs +4 -2
  44. data/app/views/relations/_li.erb +2 -2
  45. data/app/views/templates/document_create_tabs/_file.rhtml +1 -1
  46. data/app/views/templates/document_create_tabs/_template.rhtml +2 -2
  47. data/app/views/templates/document_create_tabs/_text_document.rhtml +2 -2
  48. data/app/views/templates/edit_tabs/_help.rhtml +1 -1
  49. data/app/views/templates/edit_tabs/_title.rhtml +0 -3
  50. data/app/views/users/_form.rhtml +2 -6
  51. data/app/views/users/_li.rhtml +1 -3
  52. data/app/views/users/create.rjs +4 -4
  53. data/app/views/users/preferences.html.erb +1 -4
  54. data/app/views/versions/custom_tab.rhtml +5 -0
  55. data/app/views/virtual_classes/_form.erb +20 -10
  56. data/app/views/virtual_classes/_li.erb +21 -8
  57. data/app/views/zafu/default/Node-+search.zafu +1 -1
  58. data/app/views/zafu/default/Node.zafu +3 -3
  59. data/bricks/captcha/lib/bricks/captcha.rb +1 -1
  60. data/bricks/mongrel/zena/deploy.rb +14 -0
  61. data/bricks/{data2pdf → pdf}/.document +0 -0
  62. data/bricks/pdf/README +33 -0
  63. data/bricks/{data2pdf → pdf}/Rakefile +0 -0
  64. data/bricks/pdf/VERSION +1 -0
  65. data/bricks/pdf/lib/bricks/pdf.rb +110 -0
  66. data/bricks/pdf/lib/bricks/pdf/engine/prince.rb +38 -0
  67. data/bricks/pdf/lib/bricks/pdf/engine/xhtml2pdf.rb +9 -0
  68. data/bricks/pdf/lib/bricks/pdf/install.rb +121 -0
  69. data/bricks/pdf/test/engines/test_prince.rb +15 -0
  70. data/bricks/pdf/test/engines/test_xhtml2pdf.rb +15 -0
  71. data/bricks/{data2pdf → pdf}/test/fixtures/application.css +0 -0
  72. data/bricks/{data2pdf → pdf}/test/fixtures/contact.html +0 -0
  73. data/bricks/{data2pdf → pdf}/test/fixtures/pisa-default.css +0 -0
  74. data/bricks/{data2pdf → pdf}/test/fixtures/sheet1.css +0 -0
  75. data/bricks/{data2pdf → pdf}/test/fixtures/sheet2.css +0 -0
  76. data/bricks/{data2pdf → pdf}/test/fixtures/simple-html.html +0 -0
  77. data/bricks/{data2pdf → pdf}/test/fixtures/simple-text.txt +0 -0
  78. data/bricks/{data2pdf → pdf}/test/helper.rb +4 -5
  79. data/bricks/pdf/test/shoulda_macros/shoulda_pdf.rb +72 -0
  80. data/bricks/pdf/zena/init.rb +5 -0
  81. data/bricks/pdf/zena/tasks.rb +17 -0
  82. data/bricks/sphinx/lib/{use_sphinx.rb → bricks/sphinx.rb} +1 -1
  83. data/bricks/tags/zena/init.rb +2 -2
  84. data/bricks/tags/zena/test/zafu/tags.yml +4 -4
  85. data/bricks/zena/zena/migrate/01_base.rb +482 -0
  86. data/config/bricks.yml +22 -6
  87. data/config/gems.yml +8 -6
  88. data/db/20100628074512_zena0x_to1x.rb +6 -1
  89. data/db/fix/024_correct_vclass_kpath.rb +11 -0
  90. data/db/fix/025_move_tag_into_vclass.rb +13 -0
  91. data/db/{migrate → fix}/026_rename_templates.rb +0 -0
  92. data/db/{migrate → fix}/045_avoid_star_in_templates.rb +0 -0
  93. data/db/{migrate → fix}/046_fix_zazen_image_tag.rb +0 -0
  94. data/db/{migrate → fix}/047_change_default_link_id_to_zero.rb +1 -3
  95. data/db/{migrate → fix}/049_fix_publish_from_is_null.rb +0 -0
  96. data/db/{migrate → fix}/20090924141459_zafu_fix_sept09.rb +0 -0
  97. data/db/{migrate → fix}/20091013100351_rename_publish_group_to_drive_group.rb +1 -3
  98. data/db/{migrate → fix}/20091124161608_rebuild_fullpath.rb +0 -1
  99. data/db/{migrate → fix}/20100115134729_rebuild_fullpath_after_fix.rb +0 -0
  100. data/db/{migrate → fix}/20100526090140_renamed_contact_model_to_base_contact.rb +2 -4
  101. data/db/{migrate → fix/old_migrations}/001_create_base.rb +0 -1
  102. data/db/{migrate → fix/old_migrations}/002_add_time_zone_to_users.rb +0 -0
  103. data/db/{migrate → fix/old_migrations}/003_add_custom_base_flag.rb +0 -0
  104. data/db/{migrate → fix/old_migrations}/004_rename_template_skin.rb +0 -0
  105. data/db/{migrate → fix/old_migrations}/005_create_cached_pages.rb +0 -0
  106. data/db/{migrate → fix/old_migrations}/006_create_sites.rb +0 -0
  107. data/db/{migrate → fix/old_migrations}/007_replace_id_by_zip.rb +0 -0
  108. data/db/{migrate → fix/old_migrations}/008_user_status.rb +0 -0
  109. data/db/{migrate → fix/old_migrations}/009_fulltext.rb +0 -0
  110. data/db/fix/old_migrations/010_create_template_content.rb +17 -0
  111. data/db/{migrate → fix/old_migrations}/011_project_to_section.rb +0 -0
  112. data/db/{migrate → fix/old_migrations}/012_add_project_id.rb +0 -0
  113. data/db/{migrate → fix/old_migrations}/013_remove_defaults.rb +0 -0
  114. data/db/{migrate → fix/old_migrations}/014_add_sort_field.rb +0 -0
  115. data/db/{migrate → fix/old_migrations}/015_add_dyn_attributes.rb +0 -0
  116. data/db/{migrate → fix/old_migrations}/016_remove_translations.rb +0 -0
  117. data/db/{migrate → fix/old_migrations}/017_rename_authorize.rb +0 -0
  118. data/db/{migrate → fix/old_migrations}/018_add_auth_option.rb +0 -0
  119. data/db/{migrate → fix/old_migrations}/019_remove_user_status.rb +0 -0
  120. data/db/{migrate → fix/old_migrations}/020_create_participation.rb +0 -0
  121. data/db/{migrate → fix/old_migrations}/021_create_relations.rb +0 -0
  122. data/db/{migrate → fix/old_migrations}/022_create_virtual_classes.rb +0 -0
  123. data/db/{migrate → fix/old_migrations}/023_ip_on_anonymous_comment.rb +0 -0
  124. data/db/{migrate → fix/old_migrations}/027_add_country_to_contacts.rb +0 -0
  125. data/db/{migrate → fix/old_migrations}/028_change_size_of_conten_type_field.rb +0 -0
  126. data/db/{migrate → fix/old_migrations}/029_create_data_entries.rb +0 -0
  127. data/db/{migrate → fix/old_migrations}/030_redit_auto_publish_site_settings.rb +0 -0
  128. data/db/{migrate → fix/old_migrations}/031_create_iformats.rb +0 -0
  129. data/db/{migrate → fix/old_migrations}/032_caches_context_as_hash.rb +0 -0
  130. data/db/{migrate → fix/old_migrations}/033_documents_kpath_change.rb +0 -0
  131. data/db/{migrate → fix/old_migrations}/034_change_file_storage.rb +0 -0
  132. data/db/{migrate → fix/old_migrations}/035_add_status_to_link.rb +0 -0
  133. data/db/{migrate → fix/old_migrations}/036_add_flag_fields_on_nodes.rb +0 -0
  134. data/db/{migrate → fix/old_migrations}/037_add_auto_create_discussion_to_v_class.rb +0 -0
  135. data/db/{migrate → fix/old_migrations}/038_create_site_attributes.rb +0 -0
  136. data/db/{migrate → fix/old_migrations}/039_default_position.rb +0 -0
  137. data/db/{migrate → fix/old_migrations}/040_second_value_for_data_entry.rb +0 -0
  138. data/db/{migrate → fix/old_migrations}/041_add_attributes_to_v_class.rb +0 -0
  139. data/db/{migrate → fix/old_migrations}/042_fix_position_should_be_float.rb +0 -0
  140. data/db/{migrate → fix/old_migrations}/043_move_user_lang_into_participation.rb +0 -0
  141. data/db/{migrate → fix/old_migrations}/044_remove_monolingual_site_option.rb +0 -0
  142. data/db/{migrate → fix/old_migrations}/048_link_source_target_can_be_null.rb +0 -0
  143. data/db/{migrate → fix/old_migrations}/050_date_in_links.rb +0 -0
  144. data/db/{migrate → fix/old_migrations}/051_add_exif_tags_to_images.rb +0 -0
  145. data/db/{migrate → fix/old_migrations}/20090825201159_insert_zero_link.rb +0 -0
  146. data/db/{migrate → fix/old_migrations}/20090825201200_merge_bricks_migrations_with_std_migrations.rb +0 -0
  147. data/db/{migrate → fix/old_migrations}/20090927125912_allow_null_in_text_fields.rb +0 -0
  148. data/db/{migrate → fix/old_migrations}/20090928133440_no_more_private_nodes.rb +0 -0
  149. data/db/{migrate → fix/old_migrations}/20090928143754_version_status_change.rb +0 -0
  150. data/db/{migrate → fix/old_migrations}/20091001084025_change_status_values_for_comments.rb +0 -0
  151. data/db/{migrate → fix/old_migrations}/20091009084057_add_vhash_in_node.rb +0 -0
  152. data/db/{migrate → fix/old_migrations}/20091014130833_fix_template_title.rb +0 -0
  153. data/db/{migrate → fix/old_migrations}/20091014183726_merge_participation_into_users.rb +0 -0
  154. data/db/{migrate → fix/old_migrations}/20091018200734_add_popup_info_to_image_format.rb +0 -0
  155. data/db/{migrate → fix/old_migrations}/20091026161708_add_persistence_token.rb +0 -0
  156. data/db/{migrate → fix/old_migrations}/20091101184952_add_session_table.rb +0 -0
  157. data/db/{migrate → fix/old_migrations}/20091123175137_add_single_access_token.rb +0 -0
  158. data/db/{migrate → fix/old_migrations}/20100125062254_add_dynamo_to_version.rb +0 -0
  159. data/db/{migrate → fix/old_migrations}/20100201133242_remove_default_status_on_version.rb +0 -0
  160. data/db/{migrate → fix/old_migrations}/20100208194210_create_attachments.rb +0 -0
  161. data/db/{migrate → fix/old_migrations}/20100210112319_change_dynamo_to_property.rb +0 -0
  162. data/db/{migrate → fix/old_migrations}/20100320145726_transform_template_contents_into_index.rb +0 -0
  163. data/db/{migrate → fix/old_migrations}/20100328125634_change_skin_name_to_id.rb +0 -0
  164. data/db/{migrate → fix/old_migrations}/20100417061257_add_properties_to_sites.rb +0 -0
  165. data/db/{migrate → fix/old_migrations}/20100419163149_rename_name_to_node_name.rb +0 -0
  166. data/db/{migrate → fix/old_migrations}/20100422091606_change_v_class_table_into_roles.rb +0 -0
  167. data/db/{migrate → fix/old_migrations}/20100422094048_node_habtm_roles.rb +0 -0
  168. data/db/{migrate → fix/old_migrations}/20100422115935_create_columns.rb +0 -0
  169. data/db/{migrate → fix/old_migrations}/20100513181529_add_site_id_to_columns.rb +0 -0
  170. data/db/{migrate → fix/old_migrations}/20100519091711_add_index_definition_to_columns.rb +0 -0
  171. data/db/{migrate → fix/old_migrations}/20100519091940_create_idx_nodes_string.rb +0 -0
  172. data/db/{migrate → fix/old_migrations}/20100519232432_create_idx_nodes_ml_string.rb +0 -0
  173. data/db/{migrate → fix/old_migrations}/20100525113858_add_porperties_to_users.rb +0 -0
  174. data/db/{migrate → fix/old_migrations}/20100527130937_change_column_index_to_string.rb +0 -0
  175. data/db/{migrate → fix/old_migrations}/20100531135128_add_fulltext_builder_fields.rb +0 -0
  176. data/db/{migrate → fix/old_migrations}/20100915062903_add_api_group_id_to_site.rb +0 -0
  177. data/db/fix/old_migrations/20100923154807_remove_base_contact.rb +84 -0
  178. data/db/fix/old_migrations/20100926192223_remove_su_user.rb +8 -0
  179. data/db/fix/old_migrations/20100927141658_add_eval_attributes_to_v_class.rb +12 -0
  180. data/db/fix/old_migrations/20100928185257_add_obvious_idx.rb +52 -0
  181. data/db/fix/old_migrations/20100929143111_remove_node_name.rb +11 -0
  182. data/db/fix/old_migrations/20101006090454_store_properties_in_long_text.rb +9 -0
  183. data/db/fix/old_migrations/20101014185753_remove_user_prototype_id.rb +9 -0
  184. data/db/fix/old_migrations/20101101084318_create_scope_index.rb +35 -0
  185. data/db/fix/old_migrations/20101109074232_create_idx_nodes_tables.rb +65 -0
  186. data/db/fix/old_migrations/20101110184235_add_role_update_to_site.rb +9 -0
  187. data/db/fix/old_migrations/20101116103920_change_scope_index.rb +31 -0
  188. data/db/fix/old_migrations/20101123125822_add_integer_idx.rb +17 -0
  189. data/db/fix/old_migrations/20101130134522_add_index_field.rb +13 -0
  190. data/db/fix/old_migrations/20101213133816_add_group_to_relation.rb +9 -0
  191. data/db/init/base/help.fr.zml +1 -1
  192. data/db/init/base/skins/default.zml +0 -1
  193. data/db/init/base/skins/default/Node-+search.zafu +1 -1
  194. data/db/init/base/skins/default/Node-tree.zafu +3 -3
  195. data/db/init/base/skins/default/Node.zafu +3 -3
  196. data/lib/bricks/loader.rb +4 -1
  197. data/lib/bricks/requirements_validation.rb +11 -6
  198. data/lib/log_recorder/lib/log_recorder.rb +2 -2
  199. data/lib/tasks/zena.rake +25 -15
  200. data/lib/zena.rb +42 -9
  201. data/lib/zena/acts/enrollable.rb +81 -99
  202. data/lib/zena/acts/secure.rb +27 -23
  203. data/lib/zena/acts/secure_node.rb +10 -55
  204. data/lib/zena/acts/serializable.rb +9 -10
  205. data/lib/zena/app.rb +0 -2
  206. data/lib/zena/code_syntax.rb +1 -1
  207. data/lib/zena/controller/test_case.rb +0 -5
  208. data/lib/zena/core_ext/string.rb +48 -20
  209. data/lib/zena/db.rb +10 -442
  210. data/lib/zena/db_helper/abstract_db.rb +184 -0
  211. data/lib/zena/db_helper/mysql.rb +150 -0
  212. data/lib/zena/db_helper/postgresql.rb +79 -0
  213. data/lib/zena/db_helper/sqlite3.rb +135 -0
  214. data/lib/zena/deploy.rb +4 -1
  215. data/lib/zena/deploy/httpd.rhtml +3 -3
  216. data/lib/zena/deploy/vhost.rhtml +1 -1
  217. data/lib/zena/foxy_parser.rb +37 -18
  218. data/lib/zena/info.rb +3 -13
  219. data/lib/zena/migrator.rb +0 -1
  220. data/lib/zena/parser/zafu_rules.rb +9 -4
  221. data/lib/zena/parser/zazen_rules.rb +5 -5
  222. data/lib/zena/parser/zena_rules.rb +1 -1
  223. data/lib/zena/remote/interface.rb +1 -1
  224. data/lib/zena/site_worker.rb +3 -3
  225. data/lib/zena/test_controller.rb +10 -10
  226. data/lib/zena/use/action.rb +66 -6
  227. data/lib/zena/use/ajax.rb +39 -13
  228. data/lib/zena/use/ancestry.rb +210 -0
  229. data/lib/zena/use/authlogic.rb +30 -1
  230. data/lib/zena/use/calendar.rb +158 -0
  231. data/lib/zena/use/conditional.rb +3 -2
  232. data/lib/zena/use/context.rb +42 -12
  233. data/lib/zena/use/dates.rb +15 -14
  234. data/lib/zena/use/display.rb +54 -7
  235. data/lib/zena/use/error_rendering.rb +1 -0
  236. data/lib/zena/use/field_index.rb +20 -0
  237. data/lib/zena/use/fixtures.rb +12 -9
  238. data/lib/zena/use/forms.rb +230 -106
  239. data/lib/zena/use/fulltext.rb +28 -14
  240. data/lib/zena/use/html_tags.rb +1 -24
  241. data/lib/zena/use/i18n.rb +69 -14
  242. data/lib/zena/use/kpath.rb +60 -0
  243. data/lib/zena/use/ml_index.rb +6 -4
  244. data/lib/zena/use/node_context.rb +63 -0
  245. data/lib/zena/use/prop_eval.rb +90 -0
  246. data/lib/zena/use/query_builder.rb +159 -29
  247. data/lib/zena/use/query_comment.rb +1 -1
  248. data/lib/zena/use/query_node.rb +147 -56
  249. data/lib/zena/use/recursion.rb +2 -2
  250. data/lib/zena/use/relations.rb +31 -19
  251. data/lib/zena/use/rendering.rb +111 -121
  252. data/lib/zena/use/scope_index.rb +230 -0
  253. data/lib/zena/use/search.rb +7 -7
  254. data/lib/zena/use/urls.rb +87 -25
  255. data/lib/zena/use/version_hash.rb +113 -113
  256. data/lib/zena/use/workflow.rb +5 -1
  257. data/lib/zena/use/zafu_attributes.rb +11 -14
  258. data/lib/zena/use/zafu_eval.rb +1 -1
  259. data/lib/zena/use/zafu_safe_definitions.rb +91 -9
  260. data/lib/zena/use/zafu_templates.rb +146 -102
  261. data/lib/zena/use/zazen.rb +5 -4
  262. data/lib/zena/zafu_compiler.rb +1 -0
  263. data/locale/en/LC_MESSAGES/zena.mo +0 -0
  264. data/locale/en/zena.po +0 -1
  265. data/locale/fr/LC_MESSAGES/zena.mo +0 -0
  266. data/locale/fr/zena.mo +0 -0
  267. data/locale/fr/zena.po +4 -4
  268. data/misc/zena +35 -0
  269. data/misc/zena_init +41 -0
  270. data/public/images/ext/{basecontact.png → contact.png} +0 -0
  271. data/public/javascripts/zena.js +35 -7
  272. data/public/stylesheets/admin.css +5 -2
  273. data/public/stylesheets/default.css +2 -1
  274. data/public/stylesheets/popup.css +1 -1
  275. data/public/stylesheets/zena.css +2 -2
  276. data/test/custom_queries/complex.host.yml +12 -5
  277. data/test/fixtures/files/Node-test.zafu +3 -3
  278. data/test/fixtures/files/translations_fr.yml +4 -2
  279. data/test/functional/documents_controller_test.rb +31 -0
  280. data/test/functional/nodes_controller_commit_test.rb +1 -5
  281. data/test/functional/nodes_controller_test.rb +92 -12
  282. data/test/functional/user_sessions_controller_test.rb +2 -2
  283. data/test/functional/users_controller_test.rb +31 -29
  284. data/test/functional/versions_controller_test.rb +2 -2
  285. data/test/functional/virtual_classes_controller_test.rb +2 -2
  286. data/test/integration/multiple_hosts_test.rb +19 -8
  287. data/test/integration/navigation_test.rb +91 -12
  288. data/test/integration/query_node/basic.yml +40 -37
  289. data/test/integration/query_node/complex.yml +23 -18
  290. data/test/integration/query_node/dates.yml +3 -3
  291. data/test/integration/query_node/errors.yml +7 -1
  292. data/test/integration/query_node/filters.yml +41 -35
  293. data/test/integration/query_node/idx_fields.yml +11 -0
  294. data/test/integration/query_node/idx_key_value.yml +77 -0
  295. data/test/integration/query_node/idx_scope.yml +33 -0
  296. data/test/integration/query_node/relations.yml +13 -13
  297. data/test/integration/query_node_test.rb +6 -10
  298. data/test/integration/zafu_compiler/action.yml +19 -6
  299. data/test/integration/zafu_compiler/ajax.yml +111 -51
  300. data/test/integration/zafu_compiler/apphelper.yml +1 -1
  301. data/test/integration/zafu_compiler/asset.yml +1 -1
  302. data/test/integration/zafu_compiler/basic.yml +42 -52
  303. data/test/integration/zafu_compiler/calendar.yml +3 -3
  304. data/test/integration/zafu_compiler/complex.yml +16 -16
  305. data/test/integration/zafu_compiler/complex_ok.yml +2 -2
  306. data/test/integration/zafu_compiler/conditional.yml +42 -33
  307. data/test/integration/zafu_compiler/data.yml +3 -3
  308. data/test/integration/zafu_compiler/dates.yml +25 -10
  309. data/test/integration/zafu_compiler/display.yml +49 -12
  310. data/test/integration/zafu_compiler/errors.yml +26 -6
  311. data/test/integration/zafu_compiler/eval.yml +4 -4
  312. data/test/integration/zafu_compiler/forms.yml +89 -15
  313. data/test/integration/zafu_compiler/i18n.yml +23 -18
  314. data/test/integration/zafu_compiler/idx_scope.yml +7 -0
  315. data/test/integration/zafu_compiler/later.yml +10 -16
  316. data/test/integration/zafu_compiler/off/off.yml +2 -2
  317. data/test/integration/zafu_compiler/query.yml +207 -0
  318. data/test/integration/zafu_compiler/recursion.yml +2 -2
  319. data/test/integration/zafu_compiler/relations.yml +144 -168
  320. data/test/integration/zafu_compiler/roles.yml +86 -10
  321. data/test/integration/zafu_compiler/rubyless.yml +49 -6
  322. data/test/integration/zafu_compiler/safe_definitions.yml +35 -6
  323. data/test/integration/zafu_compiler/search.yml +1 -1
  324. data/test/integration/zafu_compiler/security.yml +37 -0
  325. data/test/integration/zafu_compiler/urls.yml +50 -40
  326. data/test/integration/zafu_compiler/user.yml +21 -6
  327. data/test/integration/zafu_compiler/version.yml +6 -6
  328. data/test/integration/zafu_compiler/zafu_attributes.yml +43 -34
  329. data/test/integration/zafu_compiler/zazen.yml +10 -10
  330. data/test/integration/zafu_compiler_test.rb +19 -13
  331. data/test/sites/complex/nodes.yml +0 -2
  332. data/test/sites/complex/roles.yml +9 -1
  333. data/test/sites/complex/sites.yml +0 -1
  334. data/test/sites/complex/users.yml +2 -5
  335. data/test/sites/ocean/nodes.yml +2 -5
  336. data/test/sites/ocean/roles.yml +8 -0
  337. data/test/sites/ocean/sites.yml +0 -1
  338. data/test/sites/ocean/users.yml +0 -13
  339. data/test/sites/zena/columns.yml +27 -5
  340. data/test/sites/zena/idx_projects.yml +5 -0
  341. data/test/sites/zena/nodes.yml +8 -32
  342. data/test/sites/zena/relations.yml +5 -0
  343. data/test/sites/zena/roles.yml +25 -3
  344. data/test/sites/zena/sites.yml +2 -2
  345. data/test/sites/zena/users.yml +1 -21
  346. data/test/sites/zena/versions.yml +35 -12
  347. data/test/test_helper.rb +7 -0
  348. data/test/unit/after_commit_test.rb +7 -7
  349. data/test/unit/cache_test.rb +32 -0
  350. data/test/unit/cached_page_test.rb +1 -1
  351. data/test/unit/column_test.rb +31 -7
  352. data/test/unit/comment_test.rb +2 -2
  353. data/test/unit/core_ext_test.rb +38 -7
  354. data/test/unit/document_test.rb +14 -42
  355. data/test/unit/node_test.rb +311 -324
  356. data/test/unit/note_test.rb +23 -31
  357. data/test/unit/page_test.rb +16 -58
  358. data/test/unit/project_test.rb +2 -2
  359. data/test/unit/relation_proxy_test.rb +148 -21
  360. data/test/unit/relation_test.rb +23 -3
  361. data/test/unit/remote_test.rb +15 -9
  362. data/test/unit/role_test.rb +9 -0
  363. data/test/unit/site_test.rb +49 -47
  364. data/test/unit/skin_test.rb +16 -0
  365. data/test/unit/template_test.rb +60 -69
  366. data/test/unit/text_document_test.rb +15 -14
  367. data/test/unit/user_test.rb +101 -41
  368. data/test/unit/version_test.rb +4 -4
  369. data/test/unit/virtual_class_test.rb +577 -36
  370. data/test/unit/workflow_test.rb +58 -21
  371. data/test/unit/zena/acts/enrollable_test.rb +36 -127
  372. data/test/unit/zena/acts/secure_test.rb +6 -22
  373. data/test/unit/zena/acts/serializable_test.rb +18 -0
  374. data/test/unit/zena/db_test.rb +14 -14
  375. data/test/unit/zena/parser/zafu.yml +5 -3
  376. data/test/unit/zena/use/ancestry_test.rb +198 -0
  377. data/test/unit/zena/use/calendar_test.rb +8 -8
  378. data/test/unit/zena/use/dates_test.rb +2 -0
  379. data/test/unit/zena/use/fulltext_test.rb +9 -1
  380. data/test/unit/zena/use/html_tags_test.rb +2 -16
  381. data/test/unit/zena/use/i18n_test.rb +2 -2
  382. data/test/unit/zena/use/kpath_test.rb +13 -0
  383. data/test/unit/zena/use/ml_index_test.rb +60 -12
  384. data/test/unit/zena/use/prop_eval_test.rb +170 -0
  385. data/test/unit/zena/use/query_node_test.rb +9 -2
  386. data/test/unit/zena/use/rendering_test.rb +98 -1
  387. data/test/unit/zena/use/scope_index_test.rb +464 -0
  388. data/test/unit/zena/use/urls_test.rb +23 -13
  389. data/test/unit/zena/use/version_hash_test.rb +2 -2
  390. data/test/unit/zena/use/zafu_template_test.rb +21 -8
  391. data/test/unit/zena/use/zazen_test.rb +47 -47
  392. data/zena.gemspec +177 -143
  393. metadata +222 -141
  394. data/app/models/base_contact.rb +0 -79
  395. data/app/models/book.rb +0 -242
  396. data/app/models/contact_content.rb +0 -70
  397. data/app/models/contact_version.rb +0 -40
  398. data/app/models/reference.rb +0 -18
  399. data/app/views/templates/edit_tabs/_basecontact.rhtml +0 -8
  400. data/bricks/data2pdf/README +0 -19
  401. data/bricks/data2pdf/VERSION +0 -1
  402. data/bricks/data2pdf/lib/data2pdf.rb +0 -60
  403. data/bricks/data2pdf/lib/engines/prince.rb +0 -39
  404. data/bricks/data2pdf/lib/engines/xhtml2pdf.rb +0 -41
  405. data/bricks/data2pdf/lib/install.rb +0 -111
  406. data/bricks/data2pdf/test/engines/test_prince.rb +0 -14
  407. data/bricks/data2pdf/test/engines/test_xhtml2pdf.rb +0 -14
  408. data/bricks/data2pdf/test/shoulda_macros/shoulda_data2pdf.rb +0 -91
  409. data/bricks/data2pdf/test/unit/test_rendering.rb +0 -37
  410. data/config/routes.rb +0 -3
  411. data/db/migrate/010_create_template_content.rb +0 -17
  412. data/db/migrate/024_correct_vclass_kpath.rb +0 -13
  413. data/db/migrate/025_move_tag_into_vclass.rb +0 -15
  414. data/lib/version_off.rb +0 -323
  415. data/lib/zena/use/node_name.rb +0 -94
  416. data/test/integration/query_node/properties.yml +0 -41
  417. data/test/unit/base_contact_test.rb +0 -242
  418. data/test/unit/node_name_test.rb +0 -137
data/lib/zena/use/ajax.rb CHANGED
@@ -21,6 +21,11 @@ module Zena
21
21
  if !@node.errors.empty?
22
22
  page << "alert(#{@node.errors.first.join(': ')});"
23
23
  page << "return false;" # How to avoid 'onSuccess' ?
24
+ elsif params[:udom_id] == '_page'
25
+ # reload page
26
+ page << "document.location.href = document.location.href;"
27
+ else
28
+ # ?
24
29
  end
25
30
  return
26
31
  end
@@ -133,7 +138,6 @@ module Zena
133
138
  @toggle_ids ||= {}
134
139
  unless list = @toggle_ids[group_name]
135
140
  list = @toggle_ids[group_name] = []
136
- other = yield
137
141
 
138
142
  if other = yield
139
143
  found = other.rel[role].other_zips
@@ -203,21 +207,34 @@ module Zena
203
207
 
204
208
  node = pre_filter_node
205
209
 
206
- # We do not want to have duplicate ids so we use our own dom prefix.
207
- set_dom_prefix(node)
210
+ if @name.blank?
211
+ # make sure we have a scope
212
+ set_dom_prefix(node)
213
+ end
214
+
215
+ # We do not want to use the same id as the 'each' loop but we also want to
216
+ # avoid changing the node context
217
+ @drag_prefix ||= root.get_unique_name('drag', true).gsub(/[^\d\w\/]/,'_')
218
+ markup.set_id(node.dom_id(:dom_prefix => @drag_prefix))
208
219
 
209
- markup.set_id(node.dom_id)
210
220
  markup.append_param(:class, 'drag')
211
221
 
212
222
  drag = 'drag_handle' if drag == 'true'
213
223
 
214
- js_options = drag == 'all' ? ['false'] : [drag.inspect]
224
+ if drag == 'all'
225
+ js_options = ['false']
226
+ else
227
+ unless @blocks.detect{|b| b.kind_of?(String) ? b =~ /class=.#{drag}/ : (b.params[:class] == drag || (b.markup && b.markup.params[:class] == drag))}
228
+ handle = "<span class='#{drag}'>&nbsp;</span>"
229
+ end
230
+ js_options = [drag.inspect]
231
+ end
215
232
 
216
233
  if revert = @params.delete(:revert)
217
234
  js_options << (%w{true false}.include?(revert) ? revert : revert.inspect)
218
235
  end
219
236
 
220
- markup.pre_wrap[:drag] = "<% add_drag_id(\"#{node.dom_id(:erb => false)}\", #{js_options.join(', ').inspect}) -%>"
237
+ markup.pre_wrap[:drag] = "#{handle}<% add_drag_id(\"#{node.dom_id(:dom_prefix => @drag_prefix, :erb => false)}\", #{js_options.join(', ').inspect}) %>"
221
238
  end
222
239
 
223
240
  # Display an input field to filter a remote block
@@ -246,7 +263,7 @@ module Zena
246
263
  end
247
264
  out "</div></form>"
248
265
  if @params[:live] || @params[:update]
249
- out "<% filter_form(#{node}, \"#{dom_id}_f\") -%>"
266
+ out "<% filter_form(#{node}, \"#{dom_id}_f\") %>"
250
267
  end
251
268
  end
252
269
 
@@ -287,8 +304,7 @@ module Zena
287
304
  end
288
305
 
289
306
  query_params << ", :url => #{make_href(self.name, :action => 'drop')}"
290
- markup.pre_wrap[:drop] = "<% add_drop_id(\"#{dom_id}\"#{query_params}) -%>"
291
-
307
+ markup.pre_wrap[:drop] = "<% add_drop_id(\"#{dom_id}\"#{query_params}) %>"
292
308
  r_block
293
309
  end
294
310
 
@@ -304,7 +320,7 @@ module Zena
304
320
  dom_id = node.dom_id(:erb => false)
305
321
  markup.set_id(node.dom_id)
306
322
  markup.append_param(:class, 'toggle')
307
- out "<% add_toggle_id(\"#{dom_id}\", #{var.inspect}, #{role.inspect}) { #{finder} } -%>#{expand_with}"
323
+ out "<% add_toggle_id(\"#{dom_id}\", #{var.inspect}, #{RubyLess.translate_string(self, role)}) { #{finder} } %>#{expand_with}"
308
324
  end
309
325
 
310
326
  def process_toggle
@@ -334,7 +350,7 @@ module Zena
334
350
  markup.tag ||= 'div'
335
351
 
336
352
  markup.append_param(:class, 'toggle')
337
- markup.pre_wrap[:toggle] = "<% add_toggle_id(\"#{dom_id}\", #{"#{var}_tog".inspect}, #{role.inspect}) { #{finder} } -%>"
353
+ markup.pre_wrap[:toggle] = "<% add_toggle_id(\"#{dom_id}\", #{"#{var}_tog".inspect}, #{RubyLess.translate_string(self, role)}) { #{finder} } %>"
338
354
  end
339
355
 
340
356
  def r_unlink
@@ -367,7 +383,7 @@ module Zena
367
383
  opts[:default_text] = _('btn_tiny_del')
368
384
  @params[:class] ||= 'unlink'
369
385
 
370
- out "<% if #{node}.can_write? && #{node}.link_id -%>#{wrap(make_link(opts))}<% end -%>"
386
+ out "<% if #{node}.can_write? && #{node}.link_id %>#{wrap(make_link(opts))}<% end %>"
371
387
 
372
388
  #tag_to_remote
373
389
  #"<%= tag_to_remote({:url => node_path(#{node_id}) + \"#{opts[:method] != :put ? '/zafu' : ''}?#{action.join('&')}\", :method => #{opts[:method].inspect}}) %>"
@@ -377,7 +393,7 @@ module Zena
377
393
  # else
378
394
  # inner = _('btn_tiny_del')
379
395
  # end
380
- # out "#{inner}</a><% else -%>#{inner}<% end -%>"
396
+ # out "#{inner}</a><% else %>#{inner}<% end %>"
381
397
  #elsif node.will_be?(DataEntry)
382
398
  # text = get_text_for_erb
383
399
  # if text.blank?
@@ -387,6 +403,16 @@ module Zena
387
403
  #end
388
404
  end
389
405
 
406
+ protected
407
+
408
+ def need_ajax?(each_block)
409
+ return false unless each_block
410
+ # Inline editable
411
+ super ||
412
+ # unlink
413
+ each_block.descendant('unlink')
414
+ end
415
+
390
416
  end
391
417
  end # Ajax
392
418
  end # Use
@@ -0,0 +1,210 @@
1
+ module Zena
2
+ module Use
3
+ # This module handles the creation and maintenance of a 'fullpath' and cached project/section_id.
4
+ module Ancestry
5
+ module ClassMethods
6
+ def title_join
7
+ %Q{INNER JOIN idx_nodes_ml_strings AS id1 ON id1.node_id = nodes.id AND id1.key = 'title' AND id1.lang = '#{visitor.lang}'}
8
+ end
9
+
10
+ # (slow). Find a node by it's path. This is used during node importation when stored as zml files.
11
+ def find_by_path(path, parent_id = current_site.root_id)
12
+ res = nil
13
+ path = path.split('/') unless path.kind_of?(Array)
14
+ last = path.size - 1
15
+ path.each_with_index do |title, i|
16
+ klass = i == last ? self : Node
17
+ unless p = klass.find(:first,
18
+ :select => i == last ? 'nodes.*' : 'nodes.id',
19
+ :joins => title_join,
20
+ :conditions => ["parent_id = ? AND id1.value = ? AND #{secure_scope('nodes')}", parent_id, title]
21
+ )
22
+ # Block as soon as we cannot find an element
23
+ return nil
24
+ end
25
+ parent_id = p['id']
26
+ res = p if i == last
27
+ end
28
+ res
29
+ end
30
+
31
+ # (slow). Transform a list of zips into a fullpath.
32
+ def fullpath_map(path, sym = :node)
33
+ path = path.split('/') unless path.kind_of?(Array)
34
+ zips = path.reject{|e| e == '..'}
35
+ case sym
36
+ when :title
37
+ opts = {
38
+ :select => 'zip, id1.value AS title',
39
+ :joins => title_join,
40
+ :conditions => ["zip IN (?) AND #{secure_scope('nodes')}", zips],
41
+ }
42
+ when :node
43
+ opts = {
44
+ :conditions => ["zip IN (?) AND #{secure_scope('nodes')}", zips],
45
+ }
46
+ else
47
+ # not supported
48
+ raise Exception.new("#{sym} not supported for fullpath_map")
49
+ end
50
+
51
+
52
+ list = Node.find(:all, opts)
53
+
54
+ list = Hash[*(list.map{|e| [e['zip'].to_i, sym == :node ? e : e[sym.to_s]]}).flatten]
55
+
56
+ path.map do |zip|
57
+ zip == '..' ? '..' : (list[zip.to_i] || (sym == :node ? nil : '*'))
58
+ end.compact
59
+ end
60
+ end # ClassMethods
61
+
62
+ module ModelMethods
63
+ include RubyLess
64
+ safe_context :ancestors => {:class => ['Node'], :method => 'z_ancestors'}
65
+ safe_method :fullpath => String, :short_path => String
66
+
67
+ def self.included(base)
68
+ base.class_eval do
69
+ # We do not use before_save to make sure this happens after 'zip' is set in 'node_before_create'.
70
+ before_create :rebuild_paths
71
+ before_update :rebuild_paths
72
+ after_save :rebuild_children_fullpath
73
+ extend ClassMethods
74
+ end
75
+ end
76
+
77
+ # Return the list of ancestors as a Zafu compatible context.
78
+ def z_ancestors
79
+ anc = ancestors
80
+ anc.empty? ? nil : anc
81
+ end
82
+
83
+ # Return true if the current node is an ancestor for the given child
84
+ def ancestor?(child)
85
+ child.fullpath =~ %r{\A#{fullpath}}
86
+ end
87
+
88
+ # Return the list of ancestors (without self): [root, obj, obj]
89
+ # ancestors to which the visitor has no access are removed from the list
90
+ def ancestors(start=[])
91
+ if self[:id] == current_site[:root_id]
92
+ []
93
+ elsif self[:parent_id].nil?
94
+ []
95
+ else
96
+ path = fullpath.split('/')[0..-2]
97
+ [current_site.root_node].compact + (secure(Node) { Node.fullpath_map(path, :node) } || [])
98
+ end
99
+ end
100
+
101
+ # url base path. If a node is in 'projects' and projects has custom_base set, the
102
+ # node's basepath becomes 'projects', so the url will be 'projects/node34.html'.
103
+ # The basepath is cached. If rebuild is set to true, the cache is updated.
104
+ def basepath
105
+ self[:basepath]
106
+ end
107
+
108
+ # (slow). Return an array with the node title and the last two parents' titles.
109
+ def short_path
110
+ path = fullpath.split('/')
111
+ if path.size > 2
112
+ ['..'] + fullpath_as_title(path[-2..-1])
113
+ else
114
+ fullpath_as_title(path)
115
+ end
116
+ end
117
+
118
+ def pseudo_id(root_node, sym)
119
+ case sym
120
+ when :zip
121
+ self.zip
122
+ when :relative_path
123
+ full = self.fullpath
124
+ root = root_node ? root_node.fullpath : ''
125
+ "(#{fullpath_as_title(full.rel_path(root)).map(&:to_filename).join('/')})"
126
+ end
127
+ end
128
+
129
+ # (slow). Transform a list of zips into a fullpath.
130
+ def fullpath_as_title(path = fullpath)
131
+ if path == self.fullpath
132
+ @fullpath_as_title ||= secure(Node) { Node.fullpath_map(path, :title) }
133
+ else
134
+ secure(Node) { Node.fullpath_map(path, :title) }
135
+ end
136
+ end
137
+
138
+ private
139
+
140
+ def rebuild_paths
141
+ # rebuild cached fullpath / basepath
142
+ rebuild_fullpath
143
+ rebuild_basepath
144
+ # we should use a full rebuild when there are corrupt values,
145
+ # if fullpath was blank, we have no way to find all children
146
+ @need_rebuild_children_fullpath = !new_record? && (fullpath_changed? || basepath_changed?) && !fullpath_was.blank?
147
+
148
+ true
149
+ end
150
+
151
+ def rebuild_fullpath
152
+ return unless new_record? || parent_id_changed? || fullpath.nil?
153
+ if parent = parent(false)
154
+ path = parent.fullpath.split('/') + [zip]
155
+ else
156
+ path = []
157
+ end
158
+ self.fullpath = path.join('/')
159
+ end
160
+
161
+ def rebuild_basepath
162
+ return unless new_record? || parent_id_changed? || custom_base_changed? || basepath.nil?
163
+ if custom_base
164
+ self[:basepath] = self.fullpath
165
+ elsif parent = parent(false)
166
+ self[:basepath] = parent.basepath || ""
167
+ else
168
+ self[:basepath] = ""
169
+ end
170
+ end
171
+
172
+ def rebuild_children_fullpath
173
+ return true unless @need_rebuild_children_fullpath
174
+
175
+ # Update descendants
176
+ fullpath_new = self.fullpath
177
+ fullpath_new = "#{fullpath_new}/" if fullpath_was == ''
178
+ fullpath_re = fullpath_changed? ? %r{\A#{self.fullpath_was}} : nil
179
+
180
+ bases = [self.basepath]
181
+
182
+ i = 0
183
+ batch_size = 100
184
+ while true
185
+ list = Zena::Db.fetch_attributes(['id', 'fullpath', 'basepath', 'custom_base'], 'nodes', "fullpath LIKE #{Zena::Db.quote("#{fullpath_was}/%")} AND site_id = #{current_site.id} ORDER BY fullpath ASC LIMIT #{batch_size} OFFSET #{i * batch_size}")
186
+
187
+ break if list.empty?
188
+ list.each do |rec|
189
+ rec['fullpath'].sub!(fullpath_re, fullpath_new) if fullpath_re
190
+ if rec['custom_base'] == Zena::Db::TRUE_RESULT
191
+ rec['basepath'] = rec['fullpath']
192
+ bases << rec['basepath']
193
+ else
194
+ while rec['fullpath'].size <= bases.last.size
195
+ bases.pop
196
+ end
197
+ rec['basepath'] = bases.last
198
+ end
199
+ id = rec.delete('id')
200
+ Zena::Db.execute "UPDATE nodes SET #{rec.map {|k,v| "#{Zena::Db.connection.quote_column_name(k)}=#{Zena::Db.quote(v)}"}.join(', ')} WHERE id = #{id}"
201
+ end
202
+ # 50 more
203
+ i += 1
204
+ end
205
+ true
206
+ end
207
+ end # ModelMethods
208
+ end # Ancestry
209
+ end # Use
210
+ end # Zena
@@ -1,6 +1,10 @@
1
1
  module Zena
2
2
  module Use
3
3
  module Authlogic
4
+ class RenderSession < ActiveRecord::Base
5
+ set_table_name :sessions
6
+ end
7
+
4
8
  module Common
5
9
 
6
10
  def visitor
@@ -31,7 +35,7 @@ module Zena
31
35
  end
32
36
 
33
37
  def set_visitor
34
- unless site = Site.find_by_host(request.host)
38
+ unless site = forge_cookie_with_http_auth || Site.find_by_host(request.host)
35
39
  raise ActiveRecord::RecordNotFound.new("host not found #{request.host}")
36
40
  end
37
41
 
@@ -74,6 +78,31 @@ module Zena
74
78
  end
75
79
  end
76
80
 
81
+ # Create a fake cookie based on HTTP_AUTH using session_id and render_token. This is
82
+ # only used for requests to localhost.
83
+ def forge_cookie_with_http_auth
84
+ if request.host == 'localhost' && request.port == Zena::ASSET_PORT
85
+ authenticate_with_http_basic do |login, password|
86
+ # login = visitor.id
87
+ # password = persistence_token
88
+
89
+ # Temporary user to find site
90
+ user = User.find(login)
91
+ if user && site = user.site
92
+ # OK, we can set host
93
+ request.env['HTTP_HOST'] = "#{site.host}:#{Zena::ASSET_PORT}"
94
+ # forge cookie
95
+ cookies['user_credentials'] = "#{password}::#{login}"
96
+ site
97
+ else
98
+ raise ActiveRecord::RecordNotFound
99
+ end
100
+ end
101
+ else
102
+ nil
103
+ end
104
+ end
105
+
77
106
  # Secured in site with scope in set_visitor
78
107
  def http_visitor(site)
79
108
  if request.format == Mime::XML
@@ -126,6 +126,164 @@ module Zena
126
126
  end
127
127
  end # ViewMethods
128
128
 
129
+ module ZafuMethods
130
+ # Calendar methods need a rewrite...
131
+ =begin
132
+ def r_calendar
133
+ if @context[:block] == self
134
+ # called from self (storing template / rendering)
135
+ if role = @params[:assign_as]
136
+ assign_calendar(role)
137
+ else
138
+ display_calendar
139
+ end
140
+ else
141
+ # This is called first to prepare calendar
142
+ if @params[:assign_as]
143
+ fld = 'date'
144
+ table_name = 'links'
145
+ else
146
+ fld = @params[:date] || 'event_at'
147
+ if ['log_at', 'created_at', 'updated_at', 'event_at'].include?(fld) # TODO: use rubyless to learn type
148
+ table_name = 'nodes'
149
+ elsif fld == 'l_date'
150
+ fld = 'date'
151
+ table_name = 'links'
152
+ else
153
+ return parser_error("Invalid 'date' value for calendar (#{fld.inspect}).")
154
+ end
155
+ end
156
+
157
+ @date_scope = "TABLE_NAME[#{table_name}].#{fld} >= '\#{start_date.strftime('%Y-%m-%d')}' AND TABLE_NAME[#{table_name}].#{fld} <= '\#{end_date.strftime('%Y-%m-%d')}'"
158
+
159
+ new_dom_scope
160
+
161
+ # SAVED TEMPLATE
162
+ template = expand_block(self, :block => self, :saved_template => true)
163
+ out helper.save_erb_to_url(template, template_url)
164
+
165
+ # INLINE
166
+ out expand_block(self, :block => self, :saved_template => false)
167
+ end
168
+ end
169
+
170
+ private
171
+ def display_calendar
172
+ size = (params[:size] || 'large').to_sym
173
+ finder = params[:select] || 'notes in project'
174
+
175
+ if @blocks == []
176
+ # add a default <r:link/> block
177
+ if size == :tiny
178
+ @blocks = [make(:void, :method=>'void', :text=>"<em do='link' date='current_date' do='[current_date]' format='%d'/><r:else do='[current_date]' format='%d'/>")]
179
+ else
180
+ @blocks = [make(:void, :method=>'void', :text=>"<span do='show' date='current_date' format='%d'/><ul><li do='each' do='link' attr='name'/></ul><r:else do='[current_date]' format='%d'/>")]
181
+ end
182
+ remove_instance_variable(:@all_descendants)
183
+ elsif !descendant('else')
184
+ @blocks += [make(:void, :method=>'void', :text=>"<r:else do='[current_date]' format='%d'/>")]
185
+ remove_instance_variable(:@all_descendants)
186
+ end
187
+
188
+ @html_tag_done = false
189
+ @html_tag_params[:id] = erb_dom_id
190
+ @html_tag_params[:class] ||= "#{size}cal"
191
+ @html_tag ||= 'div'
192
+
193
+ finder, klass = build_finder_for(:all, finder, @params, [@date_scope])
194
+ return unless finder
195
+ return parser_error("invalid class (#{klass})") unless klass.ancestors.include?(Node)
196
+
197
+ cell_code = "<% if #{list_var} = nodes_#{list_var}[cal_#{list_var}.strftime('%Y-%m-%d %H')] %>#{expand_with(:in_if => true, :list => list_var, :date => "cal_#{list_var}", :saved_template => nil, :dom_prefix => nil, :in_calendar => true)}<% end %>"
198
+
199
+ render_html_tag(calendar_code(finder, "", cell_code, "", params))
200
+ end
201
+
202
+ # manage links from @node ---- reference ----> ...
203
+ # <div do='calendar' assign='reference' to='main' split_hours='12' />
204
+ def assign_calendar(as_role)
205
+ size = (params[:size] || 'large').to_sym
206
+ @html_tag_done = false
207
+ @html_tag_params[:id] = erb_dom_id
208
+ @html_tag_params[:class] ||= "#{size}cal"
209
+ @html_tag ||= 'div'
210
+ if rel = RelationProxy.find_by_role(as_role.singularize)
211
+ role = rel.this_role
212
+ else
213
+ return parser_error("Invalid role #{as_role.inspect}.")
214
+ end
215
+ finder, klass = build_finder_for(:all, role, @params, [@date_scope])
216
+ return unless finder
217
+ return parser_error("invalid class (#{klass})") unless klass.ancestors.include?(Node)
218
+
219
+ # SAVED TEMPLATE ========
220
+ template_url = self.template_url + 'cell'
221
+ template = "<%= cal_assign_cell(@node, #{role.inspect}, #{@params[:used].inspect}) %>"
222
+ out helper.save_erb_to_url(template, template_url)
223
+
224
+ # we call update on node 'B'
225
+ # A (main)
226
+ # ... B (other node)
227
+ # calendar (in B context) ---- role --->
228
+
229
+ cell_prefix_code = "<span><%= day_#{list_var}.strftime('%d').to_i %></span><ul>"
230
+ cell_code = "<%= #{list_var} = nodes_#{list_var}[cal_#{list_var}.strftime('%Y-%m-%d %H')]; #{node}.linked_node = #{list_var} ? #{list_var}.first : nil; cal_assign_cell(#{node}, #{role.inspect}, #{@params[:used].inspect}, params[:s] || @node.zip, cal_#{list_var}, #{template_url.inspect}) %>"
231
+ cell_postfix_code = "</ul>"
232
+ render_html_tag(calendar_code(finder, cell_prefix_code, cell_code, cell_postfix_code, params))
233
+ end
234
+
235
+ def calendar_code(finder, cell_prefix_code, cell_code, cell_postfix_code, params)
236
+ type = params[:type] ? params[:type].to_sym : :month
237
+ size = (params[:size] || 'large').to_sym
238
+ ref_date = params[:assign_as] ? 'l_date' : (params[:date] || 'event_at')
239
+
240
+ case type
241
+ when :month
242
+ title = "\"\#{_(Date::MONTHNAMES[main_date.mon])} \#{main_date.year}\""
243
+ prev_date = "\#{main_date.advance(:months => -1).strftime(\"%Y-%m-%d\")}"
244
+ next_date = "\#{main_date.advance(:months => 1).strftime(\"%Y-%m-%d\")}"
245
+ when :week
246
+ title = "\"\#{_(Date::MONTHNAMES[main_date.mon])} \#{main_date.year}\""
247
+ prev_date = "\#{main_date.advance(:days => -7).strftime(\"%Y-%m-%d\")}"
248
+ next_date = "\#{main_date.advance(:days => +7).strftime(\"%Y-%m-%d\")}"
249
+ else
250
+ return parser_error("invalid type (should be 'month' or 'week')")
251
+ end
252
+
253
+ if hours = @params[:split_hours]
254
+ hours = hours.split(',').map{|l| l.to_i}
255
+ hours << 0
256
+ hours = hours.uniq.sort
257
+ # I feel all this would be much better if we could use "each_group" but then how do we access hours ?
258
+ week_code = "<% week.step(week+6,1) do |day_#{list_var}| %>
259
+ <td<%= cal_class(day_#{list_var},#{current_date}) %>>#{cell_prefix_code}<% #{hours.inspect}.each do |set_hour|; cal_#{list_var} = Time.utc(day_#{list_var}.year,day_#{list_var}.month,day_#{list_var}.day,set_hour) %>#{cell_code}<% end %>#{cell_postfix_code}</td>
260
+ <% end %>"
261
+ (@context[:vars] ||= []) << "hour"
262
+ else
263
+ hours = nil
264
+ week_code = "<% week.step(week+6,1) do |day_#{list_var}| %>
265
+ <td<%= cal_class(day_#{list_var},#{current_date}) %>><% cal_#{list_var} = Time.utc(day_#{list_var}.year,day_#{list_var}.month,day_#{list_var}.day) %>#{cell_prefix_code}#{cell_code}#{cell_postfix_code}</td>
266
+ <% end %>"
267
+ end
268
+
269
+ res = %Q{
270
+ <h3 class='title'>
271
+ <span><%= link_to_remote(#{_('img_prev_page').inspect}, :url => #{base_class.to_s.underscore}_path(#{node_id}) + \"/zafu?t_url=#{CGI.escape(template_url)}&dom_id=#{dom_id}&date=#{prev_date}&#{start_node_s_param(:string)}\", :method => :get) %></span>
272
+ <span class='date'><%= link_to_remote(#{title}, :url => #{base_class.to_s.underscore}_path(#{node_id}) + \"/zafu?t_url=#{CGI.escape(template_url)}&dom_id=#{dom_id}&#{start_node_s_param(:string)}\", :method => :get) %></span>
273
+ <span><%= link_to_remote(#{_('img_next_page').inspect}, :url => #{base_class.to_s.underscore}_path(#{node_id}) + \"/zafu?t_url=#{CGI.escape(template_url)}&dom_id=#{dom_id}&date=#{next_date}&#{start_node_s_param(:string)}\", :method => :get) %></span>
274
+ </h3>
275
+ <table cellspacing='0' class='#{size}cal#{@params[:assign_as] ? " assign" : ''}'>
276
+ <tr class='head'><%= cal_day_names(#{size.inspect}) %></tr>
277
+ <% start_date, end_date = cal_start_end(#{current_date}, #{type.inspect}) %>
278
+ <% cal_weeks(#{ref_date.to_sym.inspect}, #{finder}, start_date, end_date, #{hours.inspect}) do |week, nodes_#{list_var}| %>
279
+ <tr class='body'>
280
+ #{week_code}
281
+ </tr>
282
+ <% end %>
283
+ </table>}
284
+ end
285
+ =end
286
+ end # ZafuMethods
129
287
  end # Calendar
130
288
  end # Use
131
289
  end # Zena