alchemy_cms 2.1.beta1 → 2.1.beta5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (555) hide show
  1. data/.gitignore +2 -1
  2. data/.rspec +2 -2
  3. data/.travis.yml +2 -1
  4. data/Gemfile +8 -9
  5. data/README.md +10 -10
  6. data/Rakefile +0 -1
  7. data/alchemy_cms.gemspec +7 -9
  8. data/app/assets/images/alchemy/icons.png +0 -0
  9. data/app/assets/javascripts/alchemy/alchemy.base.js +8 -2
  10. data/app/assets/javascripts/alchemy/{alchemy.dragndrop.js → alchemy.dragndrop.js.erb} +3 -3
  11. data/app/assets/javascripts/alchemy/alchemy.element_editor_selector.js +1 -1
  12. data/app/assets/javascripts/alchemy/alchemy.growler.js +3 -3
  13. data/app/assets/javascripts/alchemy/alchemy.js +10 -15
  14. data/app/assets/javascripts/alchemy/alchemy.link_overlay.js +6 -2
  15. data/app/assets/javascripts/alchemy/alchemy.page_sorter.js +1 -1
  16. data/app/assets/javascripts/alchemy/alchemy.preview.js +1 -1
  17. data/app/assets/javascripts/alchemy/alchemy.routes.js.erb +38 -0
  18. data/app/assets/javascripts/alchemy/alchemy.swf_upload.js +360 -0
  19. data/app/assets/javascripts/alchemy/alchemy.windows.js +32 -17
  20. data/app/assets/javascripts/alchemy/preview.js +1 -0
  21. data/{vendor → app}/assets/javascripts/tiny_mce/plugins/alchemy_link/editor_plugin.js +0 -0
  22. data/{vendor → app}/assets/javascripts/tiny_mce/plugins/alchemy_link/langs/de.js +0 -0
  23. data/{vendor → app}/assets/javascripts/tiny_mce/plugins/alchemy_link/langs/en.js +0 -0
  24. data/{vendor/assets/javascripts/tiny_mce/plugins/inlinepopups/skins/alchemy/window.css.erb → app/assets/javascripts/tiny_mce/plugins/inlinepopups/skins/alchemy/window.css.scss} +15 -33
  25. data/app/assets/stylesheets/alchemy/_defaults.scss +4 -16
  26. data/app/assets/stylesheets/alchemy/alchemy.css +2 -2
  27. data/app/assets/stylesheets/alchemy/base.css.scss +161 -205
  28. data/app/assets/stylesheets/alchemy/elements.css.scss +15 -8
  29. data/app/assets/stylesheets/alchemy/{jquery-ui.alchemy.css → jquery-ui.alchemy.css.scss} +41 -45
  30. data/app/assets/stylesheets/alchemy/jquery.sb.css.scss +14 -10
  31. data/app/assets/stylesheets/alchemy/{tinymce_content.css → tinymce_content.css.scss} +7 -6
  32. data/app/assets/stylesheets/alchemy/{tinymce_dialog.css → tinymce_dialog.css.scss} +7 -7
  33. data/app/controllers/alchemy/admin/attachments_controller.rb +131 -0
  34. data/app/controllers/alchemy/admin/base_controller.rb +118 -0
  35. data/app/controllers/alchemy/admin/clipboard_controller.rb +46 -0
  36. data/app/controllers/alchemy/admin/contents_controller.rb +55 -0
  37. data/app/controllers/alchemy/admin/dashboard_controller.rb +15 -0
  38. data/app/controllers/alchemy/admin/elements_controller.rb +123 -0
  39. data/app/controllers/alchemy/admin/essence_audios_controller.rb +12 -0
  40. data/app/controllers/alchemy/admin/essence_files_controller.rb +27 -0
  41. data/app/controllers/alchemy/admin/essence_flashes_controller.rb +12 -0
  42. data/app/controllers/alchemy/admin/essence_pictures_controller.rb +91 -0
  43. data/app/controllers/alchemy/admin/essence_videos_controller.rb +12 -0
  44. data/app/controllers/alchemy/admin/languages_controller.rb +7 -0
  45. data/app/controllers/alchemy/admin/layoutpages_controller.rb +13 -0
  46. data/app/controllers/alchemy/admin/pages_controller.rb +253 -0
  47. data/app/controllers/alchemy/admin/pictures_controller.rb +139 -0
  48. data/app/controllers/alchemy/admin/resources_controller.rb +132 -0
  49. data/app/controllers/alchemy/admin/trash_controller.rb +24 -0
  50. data/app/controllers/alchemy/admin/users_controller.rb +81 -0
  51. data/app/controllers/alchemy/attachments_controller.rb +30 -0
  52. data/app/controllers/alchemy/base_controller.rb +137 -0
  53. data/app/controllers/alchemy/elements_controller.rb +18 -0
  54. data/app/controllers/alchemy/messages_controller.rb +115 -0
  55. data/app/controllers/alchemy/pages_controller.rb +169 -0
  56. data/app/controllers/alchemy/pictures_controller.rb +62 -0
  57. data/app/controllers/alchemy/user_sessions_controller.rb +80 -0
  58. data/app/helpers/alchemy/admin/attachments_helper.rb +11 -0
  59. data/app/helpers/alchemy/admin/base_helper.rb +423 -0
  60. data/app/helpers/alchemy/admin/contents_helper.rb +75 -0
  61. data/app/helpers/alchemy/admin/elements_helper.rb +118 -0
  62. data/app/helpers/alchemy/admin/essences_helper.rb +78 -0
  63. data/app/helpers/alchemy/admin/pages_helper.rb +46 -0
  64. data/app/helpers/alchemy/admin/pictures_helper.rb +30 -0
  65. data/app/helpers/alchemy/base_helper.rb +65 -0
  66. data/app/helpers/alchemy/elements_helper.rb +173 -0
  67. data/app/helpers/alchemy/essences_helper.rb +101 -0
  68. data/app/helpers/alchemy/pages_helper.rb +550 -0
  69. data/app/mailers/alchemy/messages.rb +17 -0
  70. data/app/mailers/alchemy/notifications.rb +25 -0
  71. data/app/models/alchemy.rb +7 -0
  72. data/app/models/alchemy/attachment.rb +82 -0
  73. data/app/models/alchemy/cell.rb +61 -0
  74. data/app/models/alchemy/content.rb +163 -0
  75. data/app/models/alchemy/element.rb +479 -0
  76. data/app/models/alchemy/essence_audio.rb +19 -0
  77. data/app/models/alchemy/essence_date.rb +22 -0
  78. data/app/models/alchemy/essence_file.rb +19 -0
  79. data/app/models/alchemy/essence_flash.rb +17 -0
  80. data/app/models/alchemy/essence_html.rb +21 -0
  81. data/app/models/alchemy/essence_picture.rb +29 -0
  82. data/app/models/alchemy/essence_richtext.rb +63 -0
  83. data/app/models/alchemy/essence_text.rb +40 -0
  84. data/app/models/alchemy/essence_video.rb +19 -0
  85. data/app/models/alchemy/folded_page.rb +5 -0
  86. data/app/models/alchemy/language.rb +90 -0
  87. data/app/models/alchemy/message.rb +71 -0
  88. data/app/models/alchemy/page.rb +548 -0
  89. data/app/models/alchemy/picture.rb +100 -0
  90. data/app/models/alchemy/user.rb +72 -0
  91. data/app/models/alchemy/user_session.rb +12 -0
  92. data/app/sweepers/alchemy/content_sweeper.rb +22 -0
  93. data/app/sweepers/alchemy/pages_sweeper.rb +49 -0
  94. data/app/sweepers/alchemy/pictures_sweeper.rb +23 -0
  95. data/app/views/{admin → alchemy/admin}/attachments/_archive_overlay.html.erb +6 -6
  96. data/app/views/{admin → alchemy/admin}/attachments/_attachment.html.erb +14 -14
  97. data/app/views/{admin → alchemy/admin}/attachments/_file_to_assign.html.erb +0 -0
  98. data/app/views/alchemy/admin/attachments/_files_list.html.erb +25 -0
  99. data/app/views/{admin → alchemy/admin}/attachments/create.js.erb +0 -0
  100. data/app/views/{admin → alchemy/admin}/attachments/destroy.js.erb +0 -0
  101. data/app/views/{admin → alchemy/admin}/attachments/edit.html.erb +2 -2
  102. data/app/views/alchemy/admin/attachments/index.html.erb +18 -0
  103. data/app/views/{admin → alchemy/admin}/attachments/new.html.erb +3 -3
  104. data/app/views/{admin → alchemy/admin}/clipboard/clear.js.erb +1 -1
  105. data/app/views/alchemy/admin/clipboard/index.html.erb +19 -0
  106. data/app/views/alchemy/admin/clipboard/insert.js.erb +14 -0
  107. data/app/views/alchemy/admin/clipboard/remove.js.erb +10 -0
  108. data/app/views/{admin → alchemy/admin}/contents/_missing.html.erb +4 -4
  109. data/app/views/{admin → alchemy/admin}/contents/create.js.erb +10 -10
  110. data/app/views/{admin → alchemy/admin}/contents/destroy.js.erb +0 -0
  111. data/app/views/{admin → alchemy/admin}/contents/new.html.erb +1 -1
  112. data/app/views/{admin → alchemy/admin}/contents/order.js.erb +0 -0
  113. data/app/views/alchemy/admin/dashboard/index.html.erb +96 -0
  114. data/app/views/{admin → alchemy/admin}/elements/_add_content.html.erb +2 -2
  115. data/app/views/{admin → alchemy/admin}/elements/_element.html.erb +3 -3
  116. data/app/views/{admin → alchemy/admin}/elements/_element_foot.html.erb +8 -8
  117. data/app/views/{admin → alchemy/admin}/elements/_element_head.html.erb +4 -4
  118. data/app/views/{admin → alchemy/admin}/elements/_elements_select.html.erb +2 -2
  119. data/app/views/alchemy/admin/elements/_new_element_form.html.erb +30 -0
  120. data/app/views/{admin → alchemy/admin}/elements/_picture_editor.html.erb +3 -3
  121. data/app/views/{admin → alchemy/admin}/elements/create.js.erb +2 -2
  122. data/app/views/{admin → alchemy/admin}/elements/destroy.js.erb +1 -1
  123. data/app/views/{admin → alchemy/admin}/elements/fold.js.erb +2 -2
  124. data/app/views/{admin → alchemy/admin}/elements/index.html.erb +1 -10
  125. data/app/views/{admin → alchemy/admin}/elements/list.js.erb +2 -2
  126. data/app/views/alchemy/admin/elements/new.html.erb +41 -0
  127. data/app/views/{admin → alchemy/admin}/elements/order.js.erb +1 -1
  128. data/app/views/{admin → alchemy/admin}/elements/trash.js.erb +1 -1
  129. data/app/views/{admin → alchemy/admin}/elements/update.js.erb +1 -1
  130. data/app/views/{admin → alchemy/admin}/essence_files/assign.js.erb +1 -1
  131. data/app/views/{admin → alchemy/admin}/essence_files/edit.html.erb +23 -23
  132. data/app/views/{admin → alchemy/admin}/essence_pictures/assign.js.erb +2 -2
  133. data/app/views/{admin → alchemy/admin}/essence_pictures/crop.html.erb +15 -6
  134. data/app/views/{admin → alchemy/admin}/essence_pictures/destroy.js.erb +1 -1
  135. data/app/views/{admin → alchemy/admin}/essence_pictures/edit.html.erb +11 -11
  136. data/app/views/{admin → alchemy/admin}/essence_pictures/save_link.js.erb +0 -0
  137. data/app/views/{admin → alchemy/admin}/essence_pictures/update.js.erb +2 -2
  138. data/app/views/alchemy/admin/languages/_language.html.erb +36 -0
  139. data/app/views/{admin → alchemy/admin}/layoutpages/_layoutpage.html.erb +18 -18
  140. data/app/views/alchemy/admin/layoutpages/index.html.erb +65 -0
  141. data/app/views/{admin → alchemy/admin}/pages/_contactform_links.html.erb +6 -6
  142. data/app/views/alchemy/admin/pages/_create_language_form.html.erb +38 -0
  143. data/app/views/{admin → alchemy/admin}/pages/_external_link.html.erb +9 -9
  144. data/app/views/{admin → alchemy/admin}/pages/_file_link.html.erb +13 -13
  145. data/app/views/{admin → alchemy/admin}/pages/_internal_link.html.erb +8 -8
  146. data/app/views/{admin → alchemy/admin}/pages/_new_page_form.html.erb +6 -6
  147. data/app/views/{admin → alchemy/admin}/pages/_page.html.erb +25 -25
  148. data/app/views/{admin → alchemy/admin}/pages/_page_for_links.html.erb +6 -6
  149. data/app/views/{admin → alchemy/admin}/pages/_page_infos.html.erb +3 -3
  150. data/app/views/{admin → alchemy/admin}/pages/_page_status.html.erb +4 -4
  151. data/app/views/{admin → alchemy/admin}/pages/_sitemap.html.erb +21 -21
  152. data/app/views/alchemy/admin/pages/configure.html.erb +71 -0
  153. data/app/views/{admin → alchemy/admin}/pages/configure_external.html.erb +9 -9
  154. data/app/views/{admin → alchemy/admin}/pages/destroy.js.erb +2 -2
  155. data/app/views/alchemy/admin/pages/edit.html.erb +181 -0
  156. data/app/views/alchemy/admin/pages/flush.js.erb +2 -0
  157. data/app/views/{admin → alchemy/admin}/pages/fold.js.erb +0 -0
  158. data/app/views/alchemy/admin/pages/index.html.erb +104 -0
  159. data/app/views/{admin → alchemy/admin}/pages/link.html.erb +4 -4
  160. data/app/views/alchemy/admin/pages/locked.html.erb +3 -0
  161. data/app/views/{admin → alchemy/admin}/pages/new.html.erb +8 -8
  162. data/app/views/{admin → alchemy/admin}/pages/show.html.erb +0 -0
  163. data/app/views/{admin → alchemy/admin}/pages/sort.js.erb +0 -0
  164. data/app/views/{admin → alchemy/admin}/pages/unlock.js.erb +1 -1
  165. data/app/views/{admin → alchemy/admin}/pages/update.js.erb +5 -5
  166. data/app/views/{admin → alchemy/admin}/partials/_flash.html.erb +0 -0
  167. data/app/views/{admin → alchemy/admin}/partials/_flash_notices.html.erb +1 -1
  168. data/app/views/alchemy/admin/partials/_main_navigation_entry.html.erb +14 -0
  169. data/app/views/alchemy/admin/partials/_pagination_links.html.erb +5 -0
  170. data/app/views/{admin → alchemy/admin}/partials/_remote_pagination_links.html.erb +2 -2
  171. data/app/views/{admin → alchemy/admin}/partials/_remote_search_form.html.erb +2 -2
  172. data/app/views/{admin → alchemy/admin}/partials/_search_form.html.erb +6 -7
  173. data/app/views/alchemy/admin/partials/_sub_navigation_tab.html.erb +8 -0
  174. data/app/views/alchemy/admin/partials/_upload_form.html.erb +129 -0
  175. data/app/views/{admin → alchemy/admin}/pictures/_archive_overlay.html.erb +3 -3
  176. data/app/views/{admin → alchemy/admin}/pictures/_filter_and_size_bar.html.erb +15 -15
  177. data/app/views/{admin → alchemy/admin}/pictures/_picture.html.erb +7 -7
  178. data/app/views/{admin → alchemy/admin}/pictures/_picture_to_assign.html.erb +2 -2
  179. data/app/views/alchemy/admin/pictures/_pictures_list.html.erb +14 -0
  180. data/app/views/{admin → alchemy/admin}/pictures/archive_overlay.js.erb +0 -0
  181. data/app/views/{admin → alchemy/admin}/pictures/create.js.erb +3 -3
  182. data/app/views/{admin → alchemy/admin}/pictures/flush.js.erb +0 -0
  183. data/app/views/alchemy/admin/pictures/index.html.erb +83 -0
  184. data/app/views/{admin → alchemy/admin}/pictures/new.html.erb +3 -3
  185. data/app/views/alchemy/admin/pictures/show_in_window.html.erb +1 -0
  186. data/app/views/{admin → alchemy/admin}/pictures/update.js.erb +0 -0
  187. data/app/views/alchemy/admin/resources/_form.html.erb +20 -0
  188. data/app/views/alchemy/admin/resources/_resource.html.erb +35 -0
  189. data/app/views/alchemy/admin/resources/_table.html.erb +23 -0
  190. data/app/views/alchemy/admin/resources/destroy.js.erb +1 -0
  191. data/app/views/{admin/languages → alchemy/admin/resources}/edit.html.erb +0 -0
  192. data/app/views/alchemy/admin/resources/index.html.erb +19 -0
  193. data/app/views/{admin/languages → alchemy/admin/resources}/new.html.erb +0 -0
  194. data/app/views/{admin → alchemy/admin}/trash/clear.js.erb +1 -1
  195. data/app/views/{admin → alchemy/admin}/trash/index.html.erb +4 -4
  196. data/app/views/alchemy/admin/users/_table.html.erb +54 -0
  197. data/app/views/{admin → alchemy/admin}/users/_user.html.erb +14 -12
  198. data/app/views/{admin → alchemy/admin}/users/edit.html.erb +0 -0
  199. data/app/views/alchemy/admin/users/index.html.erb +41 -0
  200. data/app/views/{admin → alchemy/admin}/users/new.html.erb +1 -1
  201. data/app/views/{attachments → alchemy/attachments}/show.html.erb +0 -0
  202. data/app/views/alchemy/base/500.html.erb +5 -0
  203. data/app/views/alchemy/base/error_notice.js.erb +2 -0
  204. data/app/views/alchemy/base/permission_denied.js.erb +2 -0
  205. data/app/views/alchemy/{redirect.js.erb → base/redirect.js.erb} +0 -0
  206. data/app/views/alchemy/{remote_errors.js.erb → base/remote_errors.js.erb} +0 -0
  207. data/app/views/alchemy/{update.js.erb → base/update.js.erb} +0 -0
  208. data/app/views/{elements → alchemy/elements}/_article_editor.html.erb +0 -0
  209. data/app/views/{elements → alchemy/elements}/_article_view.html.erb +1 -1
  210. data/app/views/{elements → alchemy/elements}/_bild_editor.html.erb +0 -0
  211. data/app/views/{elements → alchemy/elements}/_bild_text_editor.html.erb +0 -0
  212. data/app/views/{elements → alchemy/elements}/_bild_text_view.html.erb +1 -1
  213. data/app/views/{elements → alchemy/elements}/_bild_view.html.erb +1 -1
  214. data/app/views/{elements → alchemy/elements}/_claim_editor.html.erb +0 -0
  215. data/app/views/{elements → alchemy/elements}/_claim_view.html.erb +0 -0
  216. data/app/views/{elements → alchemy/elements}/_contactform_editor.html.erb +0 -0
  217. data/app/views/{elements → alchemy/elements}/_contactform_view.html.erb +0 -0
  218. data/app/views/{elements → alchemy/elements}/_editor_not_found.html.erb +1 -1
  219. data/app/views/{elements → alchemy/elements}/_footnote_editor.html.erb +0 -0
  220. data/app/views/{elements → alchemy/elements}/_footnote_view.html.erb +0 -0
  221. data/app/views/{elements → alchemy/elements}/_header_editor.html.erb +0 -0
  222. data/app/views/{elements → alchemy/elements}/_header_view.html.erb +1 -1
  223. data/app/views/{elements → alchemy/elements}/_headline_editor.html.erb +0 -0
  224. data/app/views/{elements → alchemy/elements}/_headline_view.html.erb +0 -0
  225. data/app/views/{elements → alchemy/elements}/_image_mosaic_editor.html.erb +0 -0
  226. data/app/views/{elements → alchemy/elements}/_image_mosaic_view.html.erb +1 -1
  227. data/app/views/{elements → alchemy/elements}/_intro_editor.html.erb +0 -0
  228. data/app/views/{elements → alchemy/elements}/_intro_image_text_editor.html.erb +0 -0
  229. data/app/views/{elements → alchemy/elements}/_intro_image_text_view.html.erb +1 -1
  230. data/app/views/{elements → alchemy/elements}/_intro_view.html.erb +0 -0
  231. data/app/views/{elements → alchemy/elements}/_news_editor.html.erb +0 -0
  232. data/app/views/{elements → alchemy/elements}/_news_view.html.erb +0 -0
  233. data/app/views/alchemy/elements/_searchresult_editor.html.erb +1 -0
  234. data/app/views/alchemy/elements/_searchresult_view.html.erb +4 -0
  235. data/app/views/alchemy/elements/_sitemap_editor.html.erb +3 -0
  236. data/app/views/{elements → alchemy/elements}/_sitemap_view.html.erb +2 -2
  237. data/app/views/{elements → alchemy/elements}/_sitename_editor.html.erb +0 -0
  238. data/app/views/{elements → alchemy/elements}/_sitename_view.html.erb +0 -0
  239. data/app/views/{elements → alchemy/elements}/_subheadline_editor.html.erb +0 -0
  240. data/app/views/{elements → alchemy/elements}/_subheadline_view.html.erb +0 -0
  241. data/app/views/{elements → alchemy/elements}/_text_editor.html.erb +0 -0
  242. data/app/views/{elements → alchemy/elements}/_text_view.html.erb +0 -0
  243. data/app/views/{elements → alchemy/elements}/_view_not_found.html.erb +0 -0
  244. data/app/views/alchemy/elements/show.html.erb +6 -0
  245. data/app/views/{elements → alchemy/elements}/show.js.erb +1 -1
  246. data/app/views/alchemy/essences/_essence_audio_editor.html.erb +1 -0
  247. data/app/views/{essences → alchemy/essences}/_essence_audio_view.html.erb +0 -0
  248. data/app/views/{essences → alchemy/essences}/_essence_date_editor.html.erb +0 -0
  249. data/app/views/{essences → alchemy/essences}/_essence_date_view.html.erb +0 -0
  250. data/app/views/{essences → alchemy/essences}/_essence_file_editor.html.erb +9 -9
  251. data/app/views/{essences → alchemy/essences}/_essence_file_view.html.erb +1 -1
  252. data/app/views/alchemy/essences/_essence_flash_editor.html.erb +1 -0
  253. data/app/views/{essences → alchemy/essences}/_essence_flash_view.html.erb +0 -0
  254. data/app/views/{essences → alchemy/essences}/_essence_html_editor.html.erb +0 -0
  255. data/app/views/{essences → alchemy/essences}/_essence_html_view.html.erb +0 -0
  256. data/app/views/{essences → alchemy/essences}/_essence_picture_editor.html.erb +8 -8
  257. data/app/views/{essences → alchemy/essences}/_essence_picture_tools.html.erb +11 -11
  258. data/app/views/{essences → alchemy/essences}/_essence_picture_view.html.erb +2 -4
  259. data/app/views/alchemy/essences/_essence_richtext_editor.html.erb +11 -0
  260. data/app/views/{essences → alchemy/essences}/_essence_richtext_view.html.erb +0 -0
  261. data/app/views/{essences → alchemy/essences}/_essence_text_editor.html.erb +6 -6
  262. data/app/views/{essences → alchemy/essences}/_essence_text_view.html.erb +0 -0
  263. data/app/views/alchemy/essences/_essence_video_editor.html.erb +1 -0
  264. data/app/views/{essences → alchemy/essences}/_essence_video_view.html.erb +1 -1
  265. data/app/views/{messages → alchemy/messages}/contact_form_mail.html.erb +0 -0
  266. data/app/views/{messages → alchemy/messages}/contact_form_mail.text.erb +0 -0
  267. data/app/views/{messages → alchemy/messages}/new.html.erb +0 -0
  268. data/app/views/{navigation → alchemy/navigation}/_image_link.html.erb +0 -0
  269. data/app/views/{navigation → alchemy/navigation}/_link.html.erb +1 -1
  270. data/app/views/{navigation → alchemy/navigation}/_renderer.html.erb +0 -0
  271. data/app/views/alchemy/notifications/admin_user_created.text.erb +13 -0
  272. data/app/views/alchemy/notifications/registered_user_created.text.erb +10 -0
  273. data/app/views/{page_layouts → alchemy/page_layouts}/_contact.html.erb +0 -0
  274. data/app/views/{page_layouts → alchemy/page_layouts}/_external.html.erb +0 -0
  275. data/app/views/{page_layouts → alchemy/page_layouts}/_intro.html.erb +0 -0
  276. data/app/views/{page_layouts → alchemy/page_layouts}/_layout_footer.html.erb +0 -0
  277. data/app/views/{page_layouts → alchemy/page_layouts}/_layout_header.html.erb +0 -0
  278. data/app/views/{page_layouts → alchemy/page_layouts}/_news.html.erb +0 -0
  279. data/app/views/{_newsletter_layout.html.erb → alchemy/page_layouts/_newsletter_layout.html.erb} +0 -0
  280. data/app/views/{page_layouts → alchemy/page_layouts}/_search.html.erb +0 -0
  281. data/app/views/{page_layouts → alchemy/page_layouts}/_standard.html.erb +0 -0
  282. data/app/views/{pages → alchemy/pages}/show.html.erb +0 -0
  283. data/app/views/{pages → alchemy/pages}/show.rss.builder +0 -0
  284. data/app/views/{pages → alchemy/pages}/sitemap.xml.erb +0 -0
  285. data/app/views/{pictures → alchemy/pictures}/show.gif.flexi +0 -0
  286. data/app/views/{pictures → alchemy/pictures}/show.jpg.flexi +0 -0
  287. data/app/views/{pictures → alchemy/pictures}/show.png.flexi +0 -0
  288. data/app/views/{pictures → alchemy/pictures}/thumbnail.png.flexi +0 -0
  289. data/app/views/{pictures → alchemy/pictures}/zoom.png.flexi +0 -0
  290. data/app/views/alchemy/search/_result.html.erb +9 -0
  291. data/app/views/alchemy/user_sessions/leave.html.erb +11 -0
  292. data/app/views/alchemy/user_sessions/login.html.erb +47 -0
  293. data/app/views/alchemy/user_sessions/logout.html.erb +3 -0
  294. data/app/views/alchemy/user_sessions/signup.html.erb +14 -0
  295. data/app/views/layouts/{alchemy.html.erb → alchemy/admin.html.erb} +23 -17
  296. data/app/views/layouts/alchemy/login.html.erb +37 -0
  297. data/app/views/layouts/alchemy/pages.html.erb +29 -0
  298. data/app/views/layouts/{sitemap.xml.erb → alchemy/sitemap.xml.erb} +0 -0
  299. data/config/alchemy/config.yml +2 -80
  300. data/config/alchemy/modules.yml +70 -0
  301. data/config/alchemy/page_layouts.yml +2 -0
  302. data/config/authorization_rules.rb +32 -39
  303. data/config/locales/alchemy.de.yml +789 -0
  304. data/config/locales/alchemy.en.yml +587 -0
  305. data/config/routes.rb +144 -142
  306. data/db/migrate/20111116125112_namespace_models.rb +23 -0
  307. data/lib/alchemy/auth_engine.rb +7 -0
  308. data/lib/alchemy/capistrano.rb +4 -1
  309. data/lib/alchemy/engine.rb +39 -25
  310. data/lib/alchemy/essence.rb +5 -1
  311. data/lib/alchemy/i18n.rb +47 -0
  312. data/lib/alchemy/modules.rb +38 -0
  313. data/lib/alchemy/page_layout.rb +98 -56
  314. data/lib/alchemy/seeder.rb +60 -110
  315. data/lib/alchemy/tinymce.rb +2 -2
  316. data/lib/alchemy/version.rb +3 -3
  317. data/lib/alchemy_cms.rb +23 -23
  318. data/lib/rails/generators/alchemy/elements/elements_generator.rb +1 -1
  319. data/lib/rails/generators/alchemy/elements/templates/editor.html.erb +1 -1
  320. data/lib/rails/generators/alchemy/elements/templates/view.html.erb +2 -2
  321. data/lib/rails/generators/alchemy/page_layouts/page_layouts_generator.rb +1 -1
  322. data/lib/rails/generators/alchemy/plugin/plugin_generator.rb +0 -1
  323. data/lib/rails/generators/alchemy/scaffold/files/pages.html.erb +1 -1
  324. data/lib/rails/generators/alchemy/scaffold/scaffold_generator.rb +34 -34
  325. data/lib/tasks/install.rake +2 -9
  326. data/lib/tasks/upgrade.rake +69 -208
  327. data/spec/controllers/admin/clipboard_controller_spec.rb +33 -35
  328. data/spec/controllers/admin/contents_controller_spec.rb +5 -5
  329. data/spec/controllers/admin/elements_controller_spec.rb +22 -0
  330. data/spec/controllers/admin/trash_controller_spec.rb +5 -5
  331. data/spec/controllers/base_controller_spec.rb +67 -0
  332. data/spec/controllers/pages_controller_spec.rb +6 -6
  333. data/spec/dummy/config/application.rb +1 -8
  334. data/spec/dummy/config/routes.rb +2 -57
  335. data/spec/dummy/db/schema.rb +27 -27
  336. data/spec/factories.rb +8 -8
  337. data/spec/helpers/{alchemy_helper_spec.rb → admin/base_helper_spec.rb} +8 -1
  338. data/spec/helpers/admin/contents_helper_spec.rb +25 -0
  339. data/spec/helpers/admin/elements_helper_spec.rb +31 -3
  340. data/spec/helpers/admin/essences_helper_spec.rb +27 -0
  341. data/spec/helpers/elements_helper_spec.rb +99 -21
  342. data/spec/helpers/essences_helper_spec.rb +1 -18
  343. data/spec/helpers/pages_helper_spec.rb +212 -26
  344. data/spec/integration/admin/pages_controller_spec.rb +56 -0
  345. data/spec/integration/navigation_spec.rb +1 -1
  346. data/spec/integration/pages_controller_spec.rb +85 -68
  347. data/spec/integration/security_spec.rb +49 -22
  348. data/spec/models/content_spec.rb +3 -3
  349. data/spec/models/element_spec.rb +19 -11
  350. data/spec/models/essence_richtext_spec.rb +2 -2
  351. data/spec/models/language_spec.rb +36 -7
  352. data/spec/models/page_spec.rb +57 -13
  353. data/spec/models/user_spec.rb +1 -1
  354. data/spec/page_layout_spec.rb +13 -3
  355. data/spec/routing_spec.rb +12 -8
  356. data/spec/spec_helper.rb +8 -9
  357. data/spec/support/controller_hacks.rb +37 -0
  358. data/vendor/assets/javascripts/swfupload/SWFObject License.txt +4 -0
  359. data/vendor/assets/javascripts/swfupload/swfupload.cookies.js +53 -0
  360. data/vendor/assets/javascripts/swfupload/swfupload.js +1 -1
  361. data/vendor/assets/javascripts/swfupload/{queue.js → swfupload.queue.js} +97 -97
  362. data/vendor/assets/javascripts/swfupload/swfupload.speed.js +342 -0
  363. data/vendor/assets/javascripts/swfupload/swfupload.swfobject.js +111 -0
  364. data/vendor/assets/javascripts/tiny_mce/license.txt +504 -504
  365. data/vendor/assets/javascripts/tiny_mce/plugins/autoresize/editor_plugin.js +1 -1
  366. data/vendor/assets/javascripts/tiny_mce/plugins/fullscreen/fullscreen.htm +110 -110
  367. data/vendor/assets/javascripts/tiny_mce/plugins/inlinepopups/skins/clearlooks2/img/alert.gif +0 -0
  368. data/vendor/assets/javascripts/tiny_mce/plugins/inlinepopups/skins/clearlooks2/img/button.gif +0 -0
  369. data/vendor/assets/javascripts/tiny_mce/plugins/inlinepopups/skins/clearlooks2/img/buttons.gif +0 -0
  370. data/vendor/assets/javascripts/tiny_mce/plugins/inlinepopups/skins/clearlooks2/img/confirm.gif +0 -0
  371. data/vendor/assets/javascripts/tiny_mce/plugins/inlinepopups/skins/clearlooks2/img/corners.gif +0 -0
  372. data/vendor/assets/javascripts/tiny_mce/plugins/inlinepopups/skins/clearlooks2/img/horizontal.gif +0 -0
  373. data/vendor/assets/javascripts/tiny_mce/plugins/inlinepopups/skins/clearlooks2/img/vertical.gif +0 -0
  374. data/vendor/assets/javascripts/tiny_mce/plugins/inlinepopups/skins/clearlooks2/window.css +90 -0
  375. data/vendor/assets/javascripts/tiny_mce/plugins/inlinepopups/template.htm +387 -387
  376. data/vendor/assets/javascripts/tiny_mce/plugins/paste/js/pastetext.js +36 -36
  377. data/vendor/assets/javascripts/tiny_mce/plugins/paste/js/pasteword.js +51 -51
  378. data/vendor/assets/javascripts/tiny_mce/plugins/paste/pastetext.htm +26 -26
  379. data/vendor/assets/javascripts/tiny_mce/plugins/paste/pasteword.htm +21 -21
  380. data/vendor/assets/javascripts/tiny_mce/plugins/table/cell.htm +180 -180
  381. data/vendor/assets/javascripts/tiny_mce/plugins/table/css/cell.css +16 -16
  382. data/vendor/assets/javascripts/tiny_mce/plugins/table/css/row.css +25 -25
  383. data/vendor/assets/javascripts/tiny_mce/plugins/table/css/table.css +13 -13
  384. data/vendor/assets/javascripts/tiny_mce/plugins/table/editor_plugin.js +1 -1
  385. data/vendor/assets/javascripts/tiny_mce/plugins/table/js/cell.js +319 -319
  386. data/vendor/assets/javascripts/tiny_mce/plugins/table/js/merge_cells.js +27 -27
  387. data/vendor/assets/javascripts/tiny_mce/plugins/table/js/row.js +237 -237
  388. data/vendor/assets/javascripts/tiny_mce/plugins/table/js/table.js +484 -450
  389. data/vendor/assets/javascripts/tiny_mce/plugins/table/merge_cells.htm +32 -32
  390. data/vendor/assets/javascripts/tiny_mce/plugins/table/row.htm +158 -158
  391. data/vendor/assets/javascripts/tiny_mce/plugins/table/table.htm +188 -188
  392. data/vendor/assets/javascripts/tiny_mce/themes/advanced/about.htm +52 -52
  393. data/vendor/assets/javascripts/tiny_mce/themes/advanced/anchor.htm +26 -26
  394. data/vendor/assets/javascripts/tiny_mce/themes/advanced/charmap.htm +55 -51
  395. data/vendor/assets/javascripts/tiny_mce/themes/advanced/color_picker.htm +74 -74
  396. data/vendor/assets/javascripts/tiny_mce/themes/advanced/editor_template.js +1 -1
  397. data/vendor/assets/javascripts/tiny_mce/themes/advanced/image.htm +80 -80
  398. data/vendor/assets/javascripts/tiny_mce/themes/advanced/js/about.js +73 -73
  399. data/vendor/assets/javascripts/tiny_mce/themes/advanced/js/anchor.js +43 -43
  400. data/vendor/assets/javascripts/tiny_mce/themes/advanced/js/charmap.js +363 -355
  401. data/vendor/assets/javascripts/tiny_mce/themes/advanced/js/color_picker.js +329 -329
  402. data/vendor/assets/javascripts/tiny_mce/themes/advanced/js/image.js +251 -251
  403. data/vendor/assets/javascripts/tiny_mce/themes/advanced/js/link.js +153 -153
  404. data/vendor/assets/javascripts/tiny_mce/themes/advanced/js/source_editor.js +56 -56
  405. data/vendor/assets/javascripts/tiny_mce/themes/advanced/langs/en_dlg.js +1 -1
  406. data/vendor/assets/javascripts/tiny_mce/themes/advanced/link.htm +57 -57
  407. data/vendor/assets/javascripts/tiny_mce/themes/advanced/shortcuts.htm +47 -47
  408. data/vendor/assets/javascripts/tiny_mce/themes/advanced/skins/default/content.css +50 -50
  409. data/vendor/assets/javascripts/tiny_mce/themes/advanced/skins/default/dialog.css +117 -117
  410. data/vendor/assets/javascripts/tiny_mce/themes/advanced/skins/default/ui.css +214 -214
  411. data/vendor/assets/javascripts/tiny_mce/themes/advanced/skins/highcontrast/content.css +24 -0
  412. data/vendor/assets/javascripts/tiny_mce/themes/advanced/skins/highcontrast/dialog.css +105 -0
  413. data/vendor/assets/javascripts/tiny_mce/themes/advanced/skins/highcontrast/ui.css +102 -0
  414. data/vendor/assets/javascripts/tiny_mce/themes/advanced/skins/o2k7/content.css +48 -48
  415. data/vendor/assets/javascripts/tiny_mce/themes/advanced/skins/o2k7/dialog.css +117 -117
  416. data/vendor/assets/javascripts/tiny_mce/themes/advanced/skins/o2k7/ui.css +217 -217
  417. data/vendor/assets/javascripts/tiny_mce/themes/advanced/skins/o2k7/ui_black.css +7 -7
  418. data/vendor/assets/javascripts/tiny_mce/themes/advanced/skins/o2k7/ui_silver.css +5 -5
  419. data/vendor/assets/javascripts/tiny_mce/themes/advanced/source_editor.htm +25 -25
  420. data/vendor/assets/javascripts/tiny_mce/tiny_mce.js +1 -1
  421. data/vendor/assets/javascripts/tiny_mce/utils/editable_selects.js +70 -70
  422. data/vendor/assets/javascripts/tiny_mce/utils/form_utils.js +210 -210
  423. data/vendor/assets/javascripts/tiny_mce/utils/mctabs.js +161 -161
  424. data/vendor/assets/javascripts/tiny_mce/utils/validate.js +252 -252
  425. metadata +432 -465
  426. data/app/controllers/admin/attachments_controller.rb +0 -136
  427. data/app/controllers/admin/clipboard_controller.rb +0 -43
  428. data/app/controllers/admin/contents_controller.rb +0 -60
  429. data/app/controllers/admin/elements_controller.rb +0 -134
  430. data/app/controllers/admin/essence_audios_controller.rb +0 -10
  431. data/app/controllers/admin/essence_files_controller.rb +0 -25
  432. data/app/controllers/admin/essence_flashes_controller.rb +0 -10
  433. data/app/controllers/admin/essence_pictures_controller.rb +0 -84
  434. data/app/controllers/admin/essence_videos_controller.rb +0 -10
  435. data/app/controllers/admin/languages_controller.rb +0 -64
  436. data/app/controllers/admin/layoutpages_controller.rb +0 -12
  437. data/app/controllers/admin/pages_controller.rb +0 -251
  438. data/app/controllers/admin/pictures_controller.rb +0 -143
  439. data/app/controllers/admin/trash_controller.rb +0 -28
  440. data/app/controllers/admin/users_controller.rb +0 -73
  441. data/app/controllers/admin_controller.rb +0 -76
  442. data/app/controllers/alchemy_controller.rb +0 -245
  443. data/app/controllers/attachments_controller.rb +0 -28
  444. data/app/controllers/elements_controller.rb +0 -16
  445. data/app/controllers/messages_controller.rb +0 -113
  446. data/app/controllers/pages_controller.rb +0 -150
  447. data/app/controllers/pictures_controller.rb +0 -63
  448. data/app/helpers/admin/attachments_helper.rb +0 -7
  449. data/app/helpers/admin/elements_helper.rb +0 -112
  450. data/app/helpers/admin/pages_helper.rb +0 -38
  451. data/app/helpers/admin/pictures_helper.rb +0 -26
  452. data/app/helpers/alchemy_helper.rb +0 -379
  453. data/app/helpers/contents_helper.rb +0 -69
  454. data/app/helpers/elements_helper.rb +0 -170
  455. data/app/helpers/essences_helper.rb +0 -167
  456. data/app/helpers/layout_helper.rb +0 -37
  457. data/app/helpers/pages_helper.rb +0 -503
  458. data/app/mailers/messages.rb +0 -15
  459. data/app/mailers/notifications.rb +0 -23
  460. data/app/models/attachment.rb +0 -80
  461. data/app/models/cell.rb +0 -59
  462. data/app/models/content.rb +0 -145
  463. data/app/models/element.rb +0 -476
  464. data/app/models/essence_audio.rb +0 -17
  465. data/app/models/essence_date.rb +0 -20
  466. data/app/models/essence_file.rb +0 -17
  467. data/app/models/essence_flash.rb +0 -15
  468. data/app/models/essence_html.rb +0 -19
  469. data/app/models/essence_picture.rb +0 -27
  470. data/app/models/essence_richtext.rb +0 -61
  471. data/app/models/essence_text.rb +0 -38
  472. data/app/models/essence_video.rb +0 -17
  473. data/app/models/folded_page.rb +0 -3
  474. data/app/models/language.rb +0 -83
  475. data/app/models/message.rb +0 -69
  476. data/app/models/page.rb +0 -545
  477. data/app/models/picture.rb +0 -98
  478. data/app/models/user.rb +0 -70
  479. data/app/models/user_session.rb +0 -10
  480. data/app/sweepers/content_sweeper.rb +0 -20
  481. data/app/sweepers/pages_sweeper.rb +0 -47
  482. data/app/sweepers/pictures_sweeper.rb +0 -21
  483. data/app/views/_contact.html.erb +0 -3
  484. data/app/views/_intro.html.erb +0 -3
  485. data/app/views/_news.html.erb +0 -3
  486. data/app/views/_search.html.erb +0 -3
  487. data/app/views/_standard.html.erb +0 -1
  488. data/app/views/admin/attachments/_files_list.html.erb +0 -24
  489. data/app/views/admin/attachments/index.html.erb +0 -30
  490. data/app/views/admin/clipboard/index.html.erb +0 -19
  491. data/app/views/admin/clipboard/insert.js.erb +0 -14
  492. data/app/views/admin/clipboard/remove.js.erb +0 -10
  493. data/app/views/admin/elements/_new_element_form.html.erb +0 -25
  494. data/app/views/admin/elements/new.html.erb +0 -33
  495. data/app/views/admin/index.html.erb +0 -102
  496. data/app/views/admin/infos.html.erb +0 -5
  497. data/app/views/admin/languages/_form.html.erb +0 -34
  498. data/app/views/admin/languages/_language.html.erb +0 -35
  499. data/app/views/admin/languages/destroy.js.erb +0 -1
  500. data/app/views/admin/languages/index.html.erb +0 -41
  501. data/app/views/admin/layoutpages/index.html.erb +0 -75
  502. data/app/views/admin/leave.html.erb +0 -11
  503. data/app/views/admin/login.html.erb +0 -46
  504. data/app/views/admin/logout.html.erb +0 -5
  505. data/app/views/admin/pages/_create_language_form.html.erb +0 -43
  506. data/app/views/admin/pages/configure.html.erb +0 -71
  507. data/app/views/admin/pages/edit.html.erb +0 -185
  508. data/app/views/admin/pages/flush.js.erb +0 -2
  509. data/app/views/admin/pages/index.html.erb +0 -108
  510. data/app/views/admin/pages/locked.html.erb +0 -3
  511. data/app/views/admin/partials/_mainnavigation_entry.html.erb +0 -27
  512. data/app/views/admin/partials/_pagination_links.html.erb +0 -5
  513. data/app/views/admin/partials/_per_page_links.html.erb +0 -17
  514. data/app/views/admin/partials/_sub_navigation.html.erb +0 -14
  515. data/app/views/admin/partials/_upload_form.html.erb +0 -119
  516. data/app/views/admin/pictures/_pictures_list.html.erb +0 -12
  517. data/app/views/admin/pictures/index.html.erb +0 -89
  518. data/app/views/admin/pictures/show_in_window.html.erb +0 -1
  519. data/app/views/admin/signup.html.erb +0 -16
  520. data/app/views/admin/users/_table.html.erb +0 -54
  521. data/app/views/admin/users/index.html.erb +0 -41
  522. data/app/views/alchemy/error_notice.js.erb +0 -1
  523. data/app/views/alchemy/permission_denied.js.erb +0 -2
  524. data/app/views/elements/_searchresult_editor.html.erb +0 -1
  525. data/app/views/elements/_searchresult_view.html.erb +0 -49
  526. data/app/views/elements/_sitemap_editor.html.erb +0 -3
  527. data/app/views/elements/show.html.erb +0 -6
  528. data/app/views/essences/_essence_audio_editor.html.erb +0 -1
  529. data/app/views/essences/_essence_flash_editor.html.erb +0 -1
  530. data/app/views/essences/_essence_richtext_editor.html.erb +0 -9
  531. data/app/views/essences/_essence_video_editor.html.erb +0 -1
  532. data/app/views/layouts/login.html.erb +0 -59
  533. data/app/views/layouts/pages.html.erb +0 -29
  534. data/app/views/notifications/admin_user_created.text.erb +0 -13
  535. data/app/views/notifications/registered_user_created.text.erb +0 -10
  536. data/app/views/page_layouts/_newsletter_layout.html.erb +0 -1
  537. data/config/initializers/authorization.rb +0 -4
  538. data/config/initializers/fast_gettext.rb +0 -3
  539. data/config/locales/de.yml +0 -377
  540. data/config/locales/en.yml +0 -371
  541. data/lib/alchemy/controller.rb +0 -79
  542. data/lib/rails/generators/alchemy/plugin/templates/gettext.rb +0 -2
  543. data/lib/tasks/gettext.rake +0 -120
  544. data/lib/translation_extras/alchemy_core_modules.rb +0 -11
  545. data/locale/alchemy.pot +0 -1749
  546. data/locale/de/alchemy.po +0 -1795
  547. data/locale/en/alchemy.po +0 -1745
  548. data/locale/missing_translations.rb +0 -4
  549. data/locale/model_attributes.rb +0 -56
  550. data/spec/helpers/contents_helper_spec.rb +0 -27
  551. data/vendor/assets/javascripts/jquery-1.6.2.min.js +0 -18
  552. data/vendor/assets/javascripts/jquery-ui-custom-1.8.16.min.js +0 -550
  553. data/vendor/assets/javascripts/swfupload/fileprogress.js +0 -203
  554. data/vendor/assets/javascripts/swfupload/handlers.js +0 -171
  555. data/vendor/assets/javascripts/tiny_mce/jquery.tinymce.js +0 -1
@@ -0,0 +1,19 @@
1
+ module Alchemy
2
+ class EssenceAudio < ActiveRecord::Base
3
+
4
+ acts_as_essence(
5
+ :ingredient_column => :attachment,
6
+ :preview_text_method => :name
7
+ )
8
+
9
+ belongs_to :attachment
10
+
11
+ # Saves the ingredient
12
+ def save_ingredient(params, options = {})
13
+ return true if params.blank?
14
+ self.attachment_id = params["attachment_id"].to_s
15
+ self.save
16
+ end
17
+
18
+ end
19
+ end
@@ -0,0 +1,22 @@
1
+ module Alchemy
2
+ class EssenceDate < ActiveRecord::Base
3
+
4
+ acts_as_essence(
5
+ :ingredient_column => :date
6
+ )
7
+
8
+ # Returns self.date for the Element#preview_text method.
9
+ def preview_text(foo=nil)
10
+ return "" if date.blank?
11
+ ::I18n.l(date)
12
+ end
13
+
14
+ # Saves the ingredient
15
+ def save_ingredient(params, options = {})
16
+ return true if params.blank?
17
+ self.date = DateTime.parse(params['date'].values.join('-'))
18
+ self.save
19
+ end
20
+
21
+ end
22
+ end
@@ -0,0 +1,19 @@
1
+ module Alchemy
2
+ class EssenceFile < ActiveRecord::Base
3
+
4
+ acts_as_essence(
5
+ :ingredient_column => :attachment,
6
+ :preview_text_method => :name
7
+ )
8
+
9
+ belongs_to :attachment
10
+
11
+ # Saves the ingredient
12
+ def save_ingredient(params, options = {})
13
+ return true if params.blank?
14
+ self.attachment_id = params["attachment_id"].to_s
15
+ self.save
16
+ end
17
+
18
+ end
19
+ end
@@ -0,0 +1,17 @@
1
+ module Alchemy
2
+ class EssenceFlash < ActiveRecord::Base
3
+
4
+ acts_as_essence(
5
+ :ingredient_column => :attachment,
6
+ :preview_text_method => :name
7
+ )
8
+
9
+ # Saves the ingredient
10
+ def save_ingredient(params, options = {})
11
+ return true if params.blank?
12
+ self.attachment_id = params["attachment_id"].to_s
13
+ self.save
14
+ end
15
+
16
+ end
17
+ end
@@ -0,0 +1,21 @@
1
+ module Alchemy
2
+ class EssenceHtml < ActiveRecord::Base
3
+
4
+ acts_as_essence(
5
+ :ingredient_column => :source
6
+ )
7
+
8
+ # Returns the first x (default = 30) (HTML escaped) characters from self.source for the Element#preview_text method.
9
+ def preview_text(maxlength = 30)
10
+ CGI.escapeHTML(source.to_s)[0..maxlength]
11
+ end
12
+
13
+ # Saves the ingredient
14
+ def save_ingredient(params, options = {})
15
+ return true if params.blank?
16
+ self.source = params["source"].to_s
17
+ self.save
18
+ end
19
+
20
+ end
21
+ end
@@ -0,0 +1,29 @@
1
+ module Alchemy
2
+ class EssencePicture < ActiveRecord::Base
3
+
4
+ acts_as_essence(
5
+ :ingredient_column => :picture,
6
+ :preview_text_method => :name
7
+ )
8
+
9
+ belongs_to :picture
10
+ before_save :replace_newlines
11
+
12
+ def replace_newlines
13
+ return nil if caption.nil?
14
+ caption.gsub!(/(\r\n|\r|\n)/, "<br/>")
15
+ end
16
+
17
+ # Saves the ingredient
18
+ def save_ingredient(params, options = {})
19
+ return true if params.blank?
20
+ self.link_class_name = params['link_class_name']
21
+ self.link_target = params['link_target']
22
+ self.link = params['link']
23
+ self.link_title = params['link_title']
24
+ self.picture_id = params['picture_id']
25
+ self.save
26
+ end
27
+
28
+ end
29
+ end
@@ -0,0 +1,63 @@
1
+ module Alchemy
2
+ class EssenceRichtext < ActiveRecord::Base
3
+
4
+ acts_as_essence(
5
+ :preview_text_column => :stripped_body
6
+ )
7
+
8
+ # Require acts_as_ferret only if Ferret full text search is enabled (default).
9
+ # You can disable it in +config/alchemy/config.yml+
10
+ if Alchemy::Config.get(:ferret) == true
11
+ require 'acts_as_ferret'
12
+ acts_as_ferret(
13
+ :fields => {
14
+ :stripped_body => {:store => :yes}
15
+ },
16
+ :remote => false
17
+ )
18
+ before_save :check_ferret_indexing
19
+ end
20
+
21
+ before_save :strip_content
22
+
23
+ # Saves the ingredient
24
+ def save_ingredient(params, options = {})
25
+ return true if params.blank?
26
+ self.body = params['body'].to_s
27
+ self.public = options[:public]
28
+ self.save
29
+ end
30
+
31
+ private
32
+
33
+ def strip_content
34
+ self.stripped_body = strip_tags(self.body)
35
+ end
36
+
37
+ def check_ferret_indexing
38
+ if self.do_not_index
39
+ self.disable_ferret(:always)
40
+ end
41
+ end
42
+
43
+ # Stripping HTML Tags and only returns plain text.
44
+ def strip_tags(html)
45
+ return html if html.blank?
46
+ if html.index("<")
47
+ text = ""
48
+ tokenizer = HTML::Tokenizer.new(html)
49
+ while token = tokenizer.next
50
+ node = HTML::Node.parse(nil, 0, 0, token, false)
51
+ # result is only the content of any Text nodes
52
+ text << node.to_s if node.class == HTML::Text
53
+ end
54
+ # strip any comments, and if they have a newline at the end (ie. line with
55
+ # only a comment) strip that too
56
+ text.gsub(/<!--(.*?)-->[\n]?/m, "")
57
+ else
58
+ html # already plain text
59
+ end
60
+ end
61
+
62
+ end
63
+ end
@@ -0,0 +1,40 @@
1
+ module Alchemy
2
+ class EssenceText < ActiveRecord::Base
3
+
4
+ acts_as_essence
5
+
6
+ # Require acts_as_ferret only if Ferret full text search is enabled (default).
7
+ # You can disable it in +config/alchemy/config.yml+
8
+ if Alchemy::Config.get(:ferret) == true
9
+ require 'acts_as_ferret'
10
+ acts_as_ferret(
11
+ :fields => {
12
+ :body => {:store => :yes}
13
+ },
14
+ :remote => false
15
+ )
16
+ before_save :check_ferret_indexing
17
+ end
18
+
19
+ # Saves the content from params
20
+ def save_ingredient(params, options = {})
21
+ return true if params.blank?
22
+ self.body = params["body"]
23
+ self.link = params["link"]
24
+ self.link_title = params["link_title"]
25
+ self.link_class_name = params["link_class_name"]
26
+ self.link_target = params["link_target"]
27
+ self.public = options[:public]
28
+ self.save
29
+ end
30
+
31
+ private
32
+
33
+ def check_ferret_indexing
34
+ if self.do_not_index
35
+ self.disable_ferret(:always)
36
+ end
37
+ end
38
+
39
+ end
40
+ end
@@ -0,0 +1,19 @@
1
+ module Alchemy
2
+ class EssenceVideo < ActiveRecord::Base
3
+
4
+ acts_as_essence(
5
+ :ingredient_column => :attachment,
6
+ :preview_text_method => :name
7
+ )
8
+
9
+ belongs_to :attachment
10
+
11
+ # Saves the ingredient
12
+ def save_ingredient(params, options = {})
13
+ return true if params.blank?
14
+ self.attachment_id = params["attachment_id"].to_s
15
+ self.save
16
+ end
17
+
18
+ end
19
+ end
@@ -0,0 +1,5 @@
1
+ module Alchemy
2
+ class FoldedPage < ActiveRecord::Base
3
+ belongs_to :page
4
+ end
5
+ end
@@ -0,0 +1,90 @@
1
+ module Alchemy
2
+ class Language < ActiveRecord::Base
3
+
4
+ validates_presence_of :name
5
+ validates_presence_of :code
6
+ validates_presence_of :page_layout
7
+ validates_presence_of :frontpage_name
8
+ validates_uniqueness_of :code
9
+ validate :presence_of_default_language
10
+ validate :publicity_of_default_language
11
+ has_many :pages
12
+ after_destroy :delete_language_root_page
13
+ validates_format_of :code, :with => /^[a-z]{2}$/
14
+ before_destroy :check_for_default
15
+ after_update :set_pages_language, :if => proc { |m| m.code_changed? }
16
+ after_update :unpublish_pages, :if => proc { changes[:public] == [true, false] }
17
+ before_save :remove_old_default, :if => proc { |m| m.default_changed? && m != Language.get_default }
18
+
19
+ scope :published, where(:public => true)
20
+
21
+ def self.all_for_created_language_trees
22
+ find(Page.language_roots.collect(&:language_id))
23
+ end
24
+
25
+ def self.all_codes_for_published
26
+ self.published.collect(&:code)
27
+ rescue
28
+ []
29
+ end
30
+
31
+ def self.get_default
32
+ self.find_by_default(true)
33
+ end
34
+
35
+ def label(attrib)
36
+ if attrib.to_sym == :code
37
+ self.code
38
+ else
39
+ Alchemy::I18n.t(self.code, :default => self.name)
40
+ end
41
+ end
42
+
43
+ private
44
+
45
+ def publicity_of_default_language
46
+ if self.default? && !self.public?
47
+ errors.add(:base, Alchemy::I18n.t("Default language has to be public"))
48
+ return false
49
+ else
50
+ return true
51
+ end
52
+ end
53
+
54
+ def presence_of_default_language
55
+ if Language.get_default == self && self.default_changed?
56
+ errors.add(:base, Alchemy::I18n.t("We need at least one default."))
57
+ return false
58
+ else
59
+ return true
60
+ end
61
+ end
62
+
63
+ def remove_old_default
64
+ lang = Language.get_default
65
+ return true if lang.nil?
66
+ lang.default = false
67
+ lang.save(:validate => false)
68
+ end
69
+
70
+ def set_pages_language
71
+ pages.update_all :language_code => self.code
72
+ end
73
+
74
+ def check_for_default
75
+ raise "Default language is not deletable" if self.default?
76
+ end
77
+
78
+ def delete_language_root_page
79
+ page = Page.language_root_for(id)
80
+ page.destroy if page
81
+ layoutroot = Page.layout_root_for(id)
82
+ layoutroot.destroy if layoutroot
83
+ end
84
+
85
+ def unpublish_pages
86
+ self.pages.update_all(:public => false)
87
+ end
88
+
89
+ end
90
+ end
@@ -0,0 +1,71 @@
1
+ # This is a tableless model only used for validating Contactform Fields.
2
+ # You can specify the fields for your contactform in the config/alchemy/config.yml file in the :mailer options
3
+ #
4
+ # === Options:
5
+ #
6
+ # - form_layout_name: A Alchemy::PageLayout name (String). Used to render the contactform on a page with this layout.
7
+ #
8
+ # === Validating fields:
9
+ #
10
+ # Pass the field name as symbol and a message_id (will be translated) to :validate_fields:
11
+ #
12
+ # === Translating the validation messages:
13
+ #
14
+ # Validationmessages will be send to +Alchemy::I18n.t+ method with the scope +"alchemy.contactform.validations.#{field[1][:message].to_s}"+.
15
+ # So a +name+ field with the validation message_id +blank_name+ will be available for translation in your locale files like:
16
+ #
17
+ # de:
18
+ # contactform:
19
+ # validations:
20
+ # blank_name: 'Bitte geben Sie Ihren Namen an'
21
+ #
22
+ # === Example Contactform Configuration:
23
+ #
24
+ # :mailer:
25
+ # :form_layout_name: contact
26
+ # :fields: [subject, name, email, message, info]
27
+ # :validate_fields:
28
+ # :name:
29
+ # :message: blank_name
30
+ # :email:
31
+ # :message: blank_email
32
+
33
+ module Alchemy
34
+ class Message
35
+
36
+ @@config = Alchemy::Config.get(:mailer)
37
+
38
+ extend ActiveModel::Naming
39
+ include ActiveModel::Validations
40
+ include ActiveModel::Conversion
41
+
42
+ attr_accessor :contact_form_id, :ip
43
+ @@config[:fields].each do |field|
44
+ attr_accessor field.to_sym
45
+ end
46
+
47
+ @@config[:validate_fields].each do |field|
48
+ validates_presence_of field[0], :message => '^' + Alchemy::I18n.t(field[1][:message].to_s, :scope => "contactform.validations")
49
+ if field[0].to_s.include?('email')
50
+ validates_format_of field[0], :with => Authlogic::Regex.email, :message => '^' + Alchemy::I18n.t('alchemy.contactform.validations.wrong_email_format'), :if => :email_is_filled
51
+ end
52
+ end
53
+
54
+ def initialize(attributes = {})
55
+ attributes.keys.each do |a|
56
+ send("#{a}=", attributes[a])
57
+ end
58
+ end
59
+
60
+ def persisted? #:nodoc:
61
+ false
62
+ end
63
+
64
+ private
65
+
66
+ def email_is_filled #:nodoc:
67
+ !email.blank?
68
+ end
69
+
70
+ end
71
+ end
@@ -0,0 +1,548 @@
1
+ # encoding: UTF-8
2
+ module Alchemy
3
+ class Page < ActiveRecord::Base
4
+
5
+ RESERVED_PAGE_LAYOUTS = %w(rootpage)
6
+ RESERVED_URLNAMES = %w(admin messages)
7
+
8
+ acts_as_nested_set
9
+ stampable
10
+
11
+ has_many :folded_pages
12
+ has_many :cells, :dependent => :destroy
13
+ has_many :elements, :dependent => :destroy, :order => :position
14
+ has_and_belongs_to_many :to_be_sweeped_elements, :class_name => 'Alchemy::Element', :uniq => true, :join_table => 'alchemy_elements_alchemy_pages'
15
+ belongs_to :language
16
+
17
+ validates_presence_of :name, :message => '^'+Alchemy::I18n.t("please enter a name")
18
+ validates_presence_of :page_layout, :message => '^'+Alchemy::I18n.t("Please choose a page layout.")
19
+ validates_presence_of :parent_id, :message => '^'+Alchemy::I18n.t("No parent page was given."), :unless => :rootpage?
20
+ validates_length_of :urlname, :minimum => 3, :too_short => Alchemy::I18n.t("urlname_to_short"), :if => :urlname_entered?
21
+ validates_uniqueness_of :urlname, :message => '^'+Alchemy::I18n.t("URL-Name already token"), :scope => 'language_id', :if => :urlname_entered?
22
+ validates :page_layout, :exclusion => { :in => RESERVED_PAGE_LAYOUTS, :message => '^'+Alchemy::I18n.t("This page_layout name is reserved.") }, :unless => :rootpage?
23
+ validates :urlname, :exclusion => { :in => RESERVED_URLNAMES, :message => '^'+Alchemy::I18n.t("This urlname is reserved.") }
24
+
25
+ attr_accessor :do_not_autogenerate
26
+ attr_accessor :do_not_sweep
27
+ attr_accessor :do_not_validate_language
28
+
29
+ before_save :set_url_name, :unless => Proc.new { |page| page.redirects_to_external? }
30
+ before_save :set_title, :unless => Proc.new { |page| page.redirects_to_external? }
31
+ before_save :set_language_code
32
+ after_create :autogenerate_elements, :unless => Proc.new { |page| page.do_not_autogenerate }
33
+ after_create :create_cells
34
+ after_save :set_restrictions_to_child_pages
35
+
36
+ scope :language_roots, where(:language_root => true)
37
+ scope :layoutpages, where(:layoutpage => true)
38
+ scope :all_locked, where(:locked => true)
39
+ scope :all_locked_by, lambda { |user| where(:locked => true, :locked_by => user.id) }
40
+ scope :not_locked, where(:locked => false)
41
+ scope :visible, where(:visible => true)
42
+ scope :published, where(:public => true)
43
+ scope :accessable, where(:restricted => false)
44
+ scope :restricted, where(:restricted => true)
45
+ scope :public_language_roots, lambda {
46
+ where(:language_root => true).where("language_code IN ('#{Language.all_codes_for_published.join('\',\'')}')").where(:public => true)
47
+ }
48
+ scope :all_last_edited_from, lambda { |user| where(:updater_id => user.id).order('updated_at DESC').limit(5) }
49
+ # Returns all pages that have the given language_id
50
+ scope :with_language, lambda { |language_id| where(:language_id => language_id) }
51
+ # Returns all pages that are not locked and public.
52
+ # Used for flushing all page caches at once.
53
+ scope :flushables, public.not_locked
54
+ scope :contentpages, where("pages.layoutpage = 0 AND pages.parent_id IS NOT NULL")
55
+
56
+ # Finds selected elements from page.
57
+ #
58
+ # Options are:
59
+ #
60
+ # :only => Array of element names # Returns only elements with given names
61
+ # :except => Array of element names # Returns all elements except the ones with given names
62
+ # :count => Integer # Limit the count of returned elements
63
+ # :offset => Integer # Starts with an offset while returning elements
64
+ # :random => Boolean # Returning elements randomly shuffled
65
+ # :from_cell => Cell # Returning elements from given cell
66
+ #
67
+ # Returns only public elements by default.
68
+ # Pass true as second argument to get all elements.
69
+ #
70
+ def find_selected_elements(options = {}, show_non_public = false)
71
+ if options[:from_cell].class.name == 'Alchemy::Cell'
72
+ elements = options[:from_cell].elements
73
+ else
74
+ elements = self.elements.not_in_cell
75
+ end
76
+ if !options[:only].blank?
77
+ elements = self.elements.named(options[:only])
78
+ elsif !options[:except].blank?
79
+ elements = self.elements.excluded(options[:except])
80
+ end
81
+ elements = elements.offset(options[:offset]).limit(options[:count])
82
+ elements = elements.order("RAND()") if options[:random]
83
+ if show_non_public
84
+ elements
85
+ else
86
+ elements.published
87
+ end
88
+ end
89
+
90
+ def find_elements(options = {}, show_non_public = false) #:nodoc:
91
+ # TODO: What is this? A Kind of proxy method? Why not rendering the elements directly if you already have them????
92
+ if !options[:collection].blank? && options[:collection].is_a?(Array)
93
+ return options[:collection]
94
+ else
95
+ find_selected_elements(options, show_non_public)
96
+ end
97
+ end
98
+
99
+ # Returns all elements that should be feeded via rss.
100
+ #
101
+ # Define feedable elements in your +page_layouts.yml+:
102
+ #
103
+ # - name: news
104
+ # feed: true
105
+ # feed_elements: [element_name, element_2_name]
106
+ #
107
+ def feed_elements
108
+ elements.find_all_by_name(definition['feed_elements'])
109
+ end
110
+
111
+ def elements_grouped_by_cells
112
+ group = ActiveSupport::OrderedHash.new
113
+ self.cells.each { |cell| group[cell] = cell.elements.not_trashed }
114
+ if element_names_not_in_cell.any?
115
+ group[Cell.new({:name => 'for_other_elements'})] = elements.not_trashed.not_in_cell
116
+ end
117
+ return group
118
+ end
119
+
120
+ def element_names_from_cells
121
+ cell_definitions.collect { |c| c['elements'] }.flatten.uniq
122
+ end
123
+
124
+ def element_names_not_in_cell
125
+ layout_description['elements'].uniq - element_names_from_cells
126
+ end
127
+
128
+ # Finds the previous page on the same structure level. Otherwise it returns nil.
129
+ # Options:
130
+ # => :restricted => boolean (standard: nil) - next restricted page (true), skip restricted pages (false), ignore restriction (nil)
131
+ # => :public => boolean (standard: true) - next public page (true), skip public pages (false)
132
+ def previous_page(options = {})
133
+ default_options = {
134
+ :restricted => nil,
135
+ :public => true
136
+ }
137
+ options = default_options.merge(options)
138
+ find_next_or_previous_page("previous", options)
139
+ end
140
+
141
+ # Finds the next page on the same structure level. Otherwise it returns nil.
142
+ # Options:
143
+ # => :restricted => boolean (standard: nil) - next restricted page (true), skip restricted pages (false), ignore restriction (nil)
144
+ # => :public => boolean (standard: true) - next public page (true), skip public pages (false)
145
+ def next_page(options = {})
146
+ default_options = {
147
+ :restricted => nil,
148
+ :public => true
149
+ }
150
+ options = default_options.merge(options)
151
+ find_next_or_previous_page("next", options)
152
+ end
153
+
154
+ def find_first_public(page)
155
+ if(page.public == true)
156
+ return page
157
+ end
158
+ page.children.each do |child|
159
+ result = find_first_public(child)
160
+ if(result!=nil)
161
+ return result
162
+ end
163
+ end
164
+ return nil
165
+ end
166
+
167
+ def name_entered?
168
+ !self.name.blank?
169
+ end
170
+
171
+ def urlname_entered?
172
+ !self.urlname.blank?
173
+ end
174
+
175
+ def set_url_name
176
+ self.urlname = convert_url_name((self.urlname.blank? ? self.name : self.urlname))
177
+ end
178
+
179
+ def set_title
180
+ self.title = self.name
181
+ end
182
+
183
+ def show_in_navigation?
184
+ if visible?
185
+ return true
186
+ end
187
+ return false
188
+ end
189
+
190
+ def lock(user)
191
+ self.locked = true
192
+ self.locked_by = user.id
193
+ self.save(:validate => false)
194
+ end
195
+
196
+ def unlock
197
+ self.locked = false
198
+ self.locked_by = nil
199
+ self.do_not_sweep = true
200
+ self.save
201
+ end
202
+
203
+ def public_elements
204
+ self.elements.select{ |m| m.public? }
205
+ end
206
+
207
+ # Returns the name of the creator of this page.
208
+ def creator
209
+ @page_creator ||= User.find_by_id(creator_id)
210
+ return Alchemy::I18n.t('unknown') if @page_creator.nil?
211
+ @page_creator.name
212
+ end
213
+
214
+ # Returns the name of the last updater of this page.
215
+ def updater
216
+ @page_updater = User.find_by_id(updater_id)
217
+ return Alchemy::I18n.t('unknown') if @page_updater.nil?
218
+ @page_updater.name
219
+ end
220
+
221
+ # Returns the name of the user currently editing this page.
222
+ def current_editor
223
+ @current_editor = User.find_by_id(locked_by)
224
+ return Alchemy::I18n.t('unknown') if @current_editor.nil?
225
+ @current_editor.name
226
+ end
227
+
228
+ def locker
229
+ User.find_by_id(self.locked_by)
230
+ end
231
+
232
+ def fold(user_id, status)
233
+ folded_page = FoldedPage.find_or_create_by_user_id_and_page_id(user_id, self.id)
234
+ folded_page.update_attributes(:folded => status)
235
+ folded_page.save
236
+ end
237
+
238
+ def folded?(user_id)
239
+ folded_page = FoldedPage.find_by_user_id_and_page_id(user_id, self.id)
240
+ return false if folded_page.nil?
241
+ folded_page.folded
242
+ end
243
+
244
+ def elements_by_type type
245
+ elements.select{|m| type.include? m.name}
246
+ end
247
+
248
+ # Returns the translated explanation of seven the page stati.
249
+ # TODO: Let I18n do this!
250
+ def humanized_status
251
+ case self.status
252
+ when 0
253
+ return Alchemy::I18n.t('page_status_visible_public_locked')
254
+ when 1
255
+ return Alchemy::I18n.t('page_status_visible_unpublic_locked')
256
+ when 2
257
+ return Alchemy::I18n.t('page_status_invisible_public_locked')
258
+ when 3
259
+ return Alchemy::I18n.t('page_status_invisible_unpublic_locked')
260
+ when 4
261
+ return Alchemy::I18n.t('page_status_visible_public')
262
+ when 5
263
+ return Alchemy::I18n.t('page_status_visible_unpublic')
264
+ when 6
265
+ return Alchemy::I18n.t('page_status_invisible_public')
266
+ when 7
267
+ return Alchemy::I18n.t('page_status_invisible_unpublic')
268
+ end
269
+ end
270
+
271
+ # Returns the status code. Used by humanized_status and the page status icon inside the sitemap rendered by Pages.index.
272
+ def status
273
+ if self.locked
274
+ if self.public? && self.visible?
275
+ return 0
276
+ elsif !self.public? && self.visible?
277
+ return 1
278
+ elsif self.public? && !self.visible?
279
+ return 2
280
+ elsif !self.public? && !self.visible?
281
+ return 3
282
+ end
283
+ else
284
+ if self.public? && self.visible?
285
+ return 4
286
+ elsif !self.public? && self.visible?
287
+ return 5
288
+ elsif self.public? && !self.visible?
289
+ return 6
290
+ elsif !self.public? && !self.visible?
291
+ return 7
292
+ end
293
+ end
294
+ end
295
+
296
+ def has_controller?
297
+ !Alchemy::PageLayout.get(self.page_layout).nil? && !Alchemy::PageLayout.get(self.page_layout)["controller"].blank?
298
+ end
299
+
300
+ def controller_and_action
301
+ if self.has_controller?
302
+ {:controller => self.layout_description["controller"], :action => self.layout_description["action"]}
303
+ end
304
+ end
305
+
306
+ # Returns the self#page_layout description from config/alchemy/page_layouts.yml file.
307
+ def layout_description
308
+ description = Alchemy::PageLayout.get(self.page_layout)
309
+ if self.root? || self.layoutpage?
310
+ return {}
311
+ elsif description.nil?
312
+ raise "Description could not be found for page layout named #{self.page_layout}. Please check page_layouts.yml file."
313
+ else
314
+ description
315
+ end
316
+ end
317
+ alias_method :definition, :layout_description
318
+
319
+ def cell_definitions
320
+ cell_names = self.layout_description['cells']
321
+ return [] if cell_names.blank?
322
+ Cell.all_definitions_for(cell_names)
323
+ end
324
+
325
+ # Returns translated name of the pages page_layout value.
326
+ # Page layout names are defined inside the config/alchemy/page_layouts.yml file.
327
+ # Translate the name in your config/locales language yml file.
328
+ def layout_display_name
329
+ Alchemy::I18n.t("alchemy.page_layout_names.#{page_layout}", :default => page_layout.camelize)
330
+ end
331
+
332
+ def renamed?
333
+ self.name_was != self.name || self.urlname_was != self.urlname
334
+ end
335
+
336
+ def changed_publicity?
337
+ self.public_was != self.public
338
+ end
339
+
340
+ def set_restrictions_to_child_pages
341
+ return nil if self.restricted_was == self.restricted
342
+ descendants.each do |child|
343
+ child.restricted = restricted
344
+ child.save
345
+ end
346
+ end
347
+
348
+ def contains_feed?
349
+ definition["feed"]
350
+ end
351
+
352
+ # Returns true or false if the pages layout_description for config/alchemy/page_layouts.yml contains redirects_to_external: true
353
+ def redirects_to_external?
354
+ definition["redirects_to_external"]
355
+ end
356
+
357
+ def first_public_child
358
+ self.children.where(:public => true).limit(1).first
359
+ end
360
+
361
+ def self.language_root_for(language_id)
362
+ self.language_roots.find_by_language_id(language_id)
363
+ end
364
+
365
+ # Creates a copy of source (a Page object) and does a copy of all elements depending to source.
366
+ # You can pass any kind of Page#attributes as a difference to source.
367
+ # Notice: It prevents the element auto_generator from running.
368
+ def self.copy(source, differences = {})
369
+ attributes = source.attributes.symbolize_keys.merge(differences)
370
+ attributes.merge!(
371
+ :do_not_autogenerate => true,
372
+ :do_not_sweep => true,
373
+ :visible => false,
374
+ :public => false,
375
+ :locked => false,
376
+ :locked_by => nil
377
+ )
378
+ page = self.new(attributes.except(["id", "updated_at", "created_at", "created_id", "updater_id"]))
379
+ if page.save
380
+ # copy the page´s cells
381
+ source.cells.each do |cell|
382
+ new_cell = Cell.create(:name => cell.name, :page_id => page.id)
383
+ end
384
+ # copy the page´s elements
385
+ source.elements.each do |element|
386
+ # detect cell for element
387
+ # if cell is nil also pass nil to element.cell_id
388
+ cell = nil
389
+ cell = page.cells.detect{ |c| c.name == element.cell.name } if element.cell
390
+ new_element = Element.copy(element, :page_id => page.id, :cell_id => (cell.blank? ? nil : cell.id))
391
+ new_element.move_to_bottom
392
+ end
393
+ return page
394
+ else
395
+ raise page.errors.full_messages
396
+ end
397
+ end
398
+
399
+ # Gets the language_root page for page
400
+ def get_language_root
401
+ return self if self.language_root
402
+ page = self
403
+ while page.parent do
404
+ page = page.parent
405
+ break if page.language_root?
406
+ end
407
+ return page
408
+ end
409
+
410
+ def self.layout_root_for(language_id)
411
+ where({:parent_id => Page.root.id, :layoutpage => true, :language_id => language_id}).limit(1).first
412
+ end
413
+
414
+ def self.find_or_create_layout_root_for(language_id)
415
+ layoutroot = layout_root_for(language_id)
416
+ return layoutroot if layoutroot
417
+ language = Language.find(language_id)
418
+ layoutroot = Page.new({
419
+ :name => "Layoutroot for #{language.name}",
420
+ :layoutpage => true,
421
+ :language => language,
422
+ :do_not_autogenerate => true
423
+ })
424
+ if layoutroot.save(:validate => false)
425
+ layoutroot.move_to_child_of(Page.root)
426
+ return layoutroot
427
+ else
428
+ raise "Layout root for #{language.name} could not be created"
429
+ end
430
+ end
431
+
432
+ def self.all_from_clipboard(clipboard)
433
+ return [] if clipboard.blank?
434
+ self.find_all_by_id(clipboard.collect { |i| i[:id] })
435
+ end
436
+
437
+ def self.all_from_clipboard_for_select(clipboard, language_id, layoutpage = false)
438
+ return [] if clipboard.blank?
439
+ clipboard_pages = self.all_from_clipboard(clipboard)
440
+ allowed_page_layouts = Alchemy::PageLayout.selectable_layouts(language_id, layoutpage)
441
+ allowed_page_layout_names = allowed_page_layouts.collect{ |p| p['name'] }
442
+ clipboard_pages.select { |cp| allowed_page_layout_names.include?(cp.page_layout) }
443
+ end
444
+
445
+ def copy_children_to(new_parent)
446
+ self.children.each do |child|
447
+ next if child == new_parent
448
+ new_child = Page.copy(child, {
449
+ :language_id => new_parent.language_id,
450
+ :language_code => new_parent.language_code,
451
+ :name => child.name + ' (' + Alchemy::I18n.t('Copy') + ')',
452
+ :urlname => '',
453
+ :title => ''
454
+ })
455
+ new_child.move_to_child_of(new_parent)
456
+ child.copy_children_to(new_child) unless child.children.blank?
457
+ end
458
+ end
459
+
460
+ # Returns true or false if the page has a page_layout that has cells.
461
+ def can_have_cells?
462
+ !definition['cells'].blank?
463
+ end
464
+
465
+ def has_cells?
466
+ cells.any?
467
+ end
468
+
469
+ def self.link_target_options
470
+ options = [
471
+ [Alchemy::I18n.t('default', :scope => :link_target_options), '']
472
+ ]
473
+ link_target_options = Alchemy::Config.get(:link_target_options)
474
+ link_target_options.each do |option|
475
+ options << [Alchemy::I18n.t(option, :scope => :link_target_options), option]
476
+ end
477
+ options
478
+ end
479
+
480
+ def locker_name
481
+ return Alchemy::I18n.t('unknown') if self.locker.nil?
482
+ self.locker.name
483
+ end
484
+
485
+ # is the curent object the main rootpage?
486
+ def rootpage?
487
+ (self.page_layout == "rootpage") && self.parent_id.blank?
488
+ end
489
+
490
+ def self.rootpage
491
+ where(:page_layout => 'rootpage').where(:parent_id => nil).first
492
+ end
493
+
494
+ private
495
+
496
+ def find_next_or_previous_page(direction = "next", options = {})
497
+ if direction == "previous"
498
+ step_direction = ["pages.lft < ?", self.lft]
499
+ order_direction = "lft DESC"
500
+ else
501
+ step_direction = ["pages.lft > ?", self.lft]
502
+ order_direction = "lft"
503
+ end
504
+ conditions = Page.merge_conditions(
505
+ {:parent_id => self.parent_id},
506
+ {:public => options[:public]},
507
+ step_direction
508
+ )
509
+ if !options[:restricted].nil?
510
+ conditions = Page.merge_conditions(conditions, {:restricted => options[:restricted]})
511
+ end
512
+ return Page.where(conditions).order(order_direction).limit(1)
513
+ end
514
+
515
+ # Converts the given nbame into an url friendly string
516
+ # Names shorter than 3 will be filled with dashes, so it does not collidate with the language code.
517
+ def convert_url_name(name)
518
+ url_name = name.gsub(/[äÄ]/, 'ae').gsub(/[üÜ]/, 'ue').gsub(/[öÖ]/, 'oe').parameterize
519
+ url_name = ('-' * (3 - url_name.length)) + url_name if url_name.length < 3
520
+ return url_name
521
+ end
522
+
523
+ # Looks in the layout_descripion, if there are elements to autogenerate.
524
+ # If so, it generates them.
525
+ def autogenerate_elements
526
+ elements = self.layout_description["autogenerate"]
527
+ unless (elements.blank?)
528
+ elements.each do |element|
529
+ element = Element.create_from_scratch({'page_id' => self.id, 'name' => element})
530
+ element.move_to_bottom if element
531
+ end
532
+ end
533
+ end
534
+
535
+ def set_language_code
536
+ return false if self.language.blank?
537
+ self.language_code = self.language.code
538
+ end
539
+
540
+ def create_cells
541
+ return false if !can_have_cells?
542
+ definition['cells'].each do |cellname|
543
+ cells.create({:name => cellname})
544
+ end
545
+ end
546
+
547
+ end
548
+ end