alchemy_cms 2.1.beta1 → 2.1.beta5

Sign up to get free protection for your applications and to get access to all the features.
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