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,17 @@
1
+ module Alchemy
2
+ class Messages < ActionMailer::Base
3
+
4
+ default :from => Alchemy::Config.get(:mailer)[:mail_from]
5
+
6
+ def contact_form_mail(message, mail_to, mail_from, subject)
7
+ @message = message
8
+ mail(
9
+ :from => mail_from,
10
+ :to => mail_to,
11
+ :reply_to => message.email,
12
+ :subject => subject
13
+ )
14
+ end
15
+
16
+ end
17
+ end
@@ -0,0 +1,25 @@
1
+ module Alchemy
2
+ class Notifications < ActionMailer::Base
3
+
4
+ default :from => Alchemy::Config.get(:mailer)[:mail_from]
5
+
6
+ def registered_user_created(user)
7
+ @user = user
8
+ @url = login_url
9
+ mail(
10
+ :to => user.email,
11
+ :subject => Alchemy::I18n.t("alchemy.mailer.new_user_mail.subject")
12
+ )
13
+ end
14
+
15
+ def admin_user_created(user)
16
+ @user = user
17
+ @url = admin_url
18
+ mail(
19
+ :to => user.email,
20
+ :subject => Alchemy::I18n.t("Your Alchemy Login")
21
+ )
22
+ end
23
+
24
+ end
25
+ end
@@ -0,0 +1,7 @@
1
+ module Alchemy
2
+
3
+ def self.table_name_prefix
4
+ 'alchemy_'
5
+ end
6
+
7
+ end
@@ -0,0 +1,82 @@
1
+ module Alchemy
2
+ class Attachment < ActiveRecord::Base
3
+
4
+ stampable
5
+
6
+ has_attachment(
7
+ :storage => :file_system,
8
+ :file_system_path => 'uploads/attachments',
9
+ :size => 0.kilobytes..1000.megabytes
10
+ )
11
+ validates_as_attachment
12
+
13
+ def name
14
+ read_attribute(:name).split('.').first
15
+ end
16
+
17
+ def extension
18
+ filename.split(".").last
19
+ end
20
+ alias_method :suffix, :extension
21
+
22
+ def icon_css_class
23
+ case content_type
24
+ when "application/x-flash-video"
25
+ then "video"
26
+ when "video/x-flv"
27
+ then "video"
28
+ when "video/mp4"
29
+ then "video"
30
+ when "video/mpeg"
31
+ then "video"
32
+ when "video/quicktime"
33
+ then "video"
34
+ when "video/x-msvideo"
35
+ then "video"
36
+ when "video/x-ms-wmv"
37
+ then "video"
38
+ when "application/zip"
39
+ then "archive"
40
+ when "application/x-rar"
41
+ then "archive"
42
+ when "audio/mpeg"
43
+ then "audio"
44
+ when "audio/mp4"
45
+ then "audio"
46
+ when "audio/wav"
47
+ then "audio"
48
+ when "audio/x-wav"
49
+ then "audio"
50
+ when "application/x-shockwave-flash"
51
+ then "flash"
52
+ when "image/gif"
53
+ then "image"
54
+ when "image/jpeg"
55
+ then "image"
56
+ when "image/png"
57
+ then "image"
58
+ when "image/tiff"
59
+ then "image"
60
+ when "image/x-psd"
61
+ then "psd"
62
+ when "text/plain"
63
+ then "text"
64
+ when "application/rtf"
65
+ then "rtf"
66
+ when "application/pdf"
67
+ then "pdf"
68
+ when "application/msword"
69
+ then "word"
70
+ when "application/vnd.ms-excel"
71
+ then "excel"
72
+ when "text/x-vcard"
73
+ then "vcard"
74
+ when "application/vcard"
75
+ then "vcard"
76
+ else
77
+ "file"
78
+ end
79
+ end
80
+
81
+ end
82
+ end
@@ -0,0 +1,61 @@
1
+ # A cell is a group of elements that are rendered inside a specific area on your page_layout.
2
+ # Think of it like a column, or section in your layout. I.e. a header or right column.
3
+ #
4
+ # Elements are displayed in tabs inside the elements window in page edit view.
5
+ # Every cell is a list of elements with the position scoped to +cell_id+ and +page_id+.
6
+ #
7
+ # Define cells inside a +cells.yml+ file located in the +config/alchermy+ folder of your project.
8
+ #
9
+ # Render cells with the +render_cell+ helper
10
+ #
11
+ # Views for cells are inside the +app/views/cells+ folder in you project.
12
+ #
13
+ module Alchemy
14
+ class Cell < ActiveRecord::Base
15
+
16
+ belongs_to :page
17
+ has_many :elements, :dependent => :destroy, :order => :position
18
+
19
+ def self.definitions
20
+ cell_yml = File.join(Rails.root, 'config', 'alchemy', 'cells.yml')
21
+ YAML.load_file(cell_yml) if File.exist?(cell_yml)
22
+ end
23
+
24
+ def self.definition_for(cellname)
25
+ return nil if cellname.blank?
26
+ definitions.detect { |c| c['name'] == cellname }
27
+ end
28
+
29
+ def self.all_definitions_for(cellnames)
30
+ definitions.select { |c| cellnames.include? c['name'] }
31
+ end
32
+
33
+ def self.all_element_definitions_for(cellnames)
34
+ element_names = []
35
+ all_definitions_for(cellnames).each do |cell|
36
+ element_names += cell['elements']
37
+ end
38
+ Element.all_definitions_for(element_names.uniq)
39
+ end
40
+
41
+ def self.definitions_for_element(element_name)
42
+ return [] if definitions.blank?
43
+ definitions.select { |d| d['elements'].include?(element_name) }
44
+ end
45
+
46
+ def self.names_for_element(element_name)
47
+ definitions = definitions_for_element(element_name)
48
+ return nil if definitions.blank?
49
+ definitions.collect { |d| d['name'] }
50
+ end
51
+
52
+ def name_for_label
53
+ self.class.translated_label_for(self.name)
54
+ end
55
+
56
+ def self.translated_label_for(cell_name)
57
+ Alchemy::I18n.t("alchemy.cell_names.#{cell_name}", :default => cell_name.camelcase)
58
+ end
59
+
60
+ end
61
+ end
@@ -0,0 +1,163 @@
1
+ module Alchemy
2
+ class Content < ActiveRecord::Base
3
+
4
+ belongs_to :essence, :polymorphic => true, :dependent => :destroy
5
+ belongs_to :element
6
+
7
+ stampable :stamper_class_name => :user
8
+
9
+ acts_as_list
10
+
11
+ def scope_condition
12
+ "element_id = '#{element_id}' AND essence_type = '#{essence_type}'"
13
+ end
14
+
15
+ validates_uniqueness_of :position, :scope => [:element_id, :essence_type]
16
+
17
+ # Creates a new Content as descriped in the elements.yml file
18
+ def self.create_from_scratch(element, essences_hash)
19
+ if essences_hash[:name].blank? && !essences_hash[:essence_type].blank?
20
+ essences_of_same_type = element.contents.find_all_by_essence_type(essences_hash[:essence_type])
21
+ description = {
22
+ 'type' => essences_hash[:essence_type],
23
+ 'name' => "#{essences_hash[:essence_type].underscore}_#{essences_of_same_type.length + 1}"
24
+ }
25
+ else
26
+ description = element.content_description_for(essences_hash[:name])
27
+ description = element.available_content_description_for(essences_hash[:name]) if description.blank?
28
+ end
29
+ raise "No description found in elements.yml for #{essences_hash.inspect} and #{element.inspect}" if description.blank?
30
+ essence_class = "alchemy/#{description['type']}".classify.constantize
31
+ content = self.new(:name => description['name'], :element_id => element.id)
32
+ if description['type'] == "EssenceRichtext" || description['type'] == "EssenceText"
33
+ essence = essence_class.create(:do_not_index => !description['do_not_index'].nil?)
34
+ else
35
+ essence = essence_class.create
36
+ end
37
+ if essence
38
+ content.essence = essence
39
+ content.save
40
+ else
41
+ content = nil
42
+ end
43
+ return content
44
+ end
45
+
46
+ # Settings from the elements.yml definition
47
+ def settings
48
+ return {} if description.blank?
49
+ settings = description['settings']
50
+ return {} if settings.blank?
51
+ settings.symbolize_keys
52
+ end
53
+
54
+ # makes a copy of source and copies the polymorphic associated essence
55
+ def self.copy(source, differences = {})
56
+ differences[:position] = nil
57
+ differences[:id] = nil
58
+ attributes = source.attributes.merge(differences)
59
+ content = self.create!(attributes.except("id"))
60
+ new_essence = content.essence.clone
61
+ new_essence.save
62
+ content.essence_id = new_essence.id
63
+ content
64
+ end
65
+
66
+ # Returns my description hash from elements.yml
67
+ # Returns the description from available_contents if my own description is blank
68
+ def description
69
+ if self.element.blank?
70
+ logger.warn("\n+++++++++++ Warning: Content with id #{self.id} is missing its Element\n")
71
+ return nil
72
+ else
73
+ desc = self.element.content_description_for(self.name)
74
+ if desc.blank?
75
+ desc = self.element.available_content_description_for(self.name)
76
+ else
77
+ return desc
78
+ end
79
+ end
80
+ end
81
+
82
+ # Gets the ingredient from essence
83
+ def ingredient
84
+ return nil if self.essence.nil?
85
+ self.essence.ingredient
86
+ end
87
+
88
+ # Calls essence.save_ingredient. Called from ElementController#update for each content in element.
89
+ # Adding errors if essence validation fails.
90
+ def save_essence(params, options = {})
91
+ if essence.save_ingredient(params, options)
92
+ return true
93
+ else
94
+ errors.add(:base, :essence_validation_failed)
95
+ return false
96
+ end
97
+ end
98
+
99
+ def essence_validation_failed?
100
+ !essence.essence_errors.blank?
101
+ end
102
+
103
+ def has_validations?
104
+ return false if description.blank?
105
+ !description['validate'].blank?
106
+ end
107
+
108
+ # Returns a string to be passed to Rails form field tags to ensure we have same params layout everywhere.
109
+ #
110
+ # Example:
111
+ # ========
112
+ # <%= text_field_tag content.form_field_name, content.ingredient %>
113
+ #
114
+ # Options:
115
+ # ========
116
+ # You can pass an Essence column_name. Default is self.essence.ingredient_column
117
+ #
118
+ # Example:
119
+ # =======
120
+ # <%= text_field_tag content.form_field_name(:link), content.ingredient %>
121
+ #
122
+ def form_field_name(essence_column = self.essence.ingredient_column)
123
+ "contents[content_#{self.id}][#{essence_column}]"
124
+ end
125
+
126
+ def form_field_id(essence_column = self.essence.ingredient_column)
127
+ "contents_content_#{self.id}_#{essence_column}"
128
+ end
129
+
130
+ # Returns the translated name for displaying in labels, etc.
131
+ def name_for_label
132
+ self.class.translated_label_for(self.name, self.element.name)
133
+ end
134
+
135
+ # Returns the translated label for a content name.
136
+ #
137
+ # Translate it in your locale yml file:
138
+ #
139
+ # alchemy:
140
+ # content_names:
141
+ # foo: Bar
142
+ #
143
+ # Optionally you can scope your content name to an element:
144
+ #
145
+ # alchemy:
146
+ # content_names:
147
+ # article:
148
+ # foo: Baz
149
+ #
150
+ def self.translated_label_for(content_name, element_name = nil)
151
+ Alchemy::I18n.t("content_names.#{element_name}.#{content_name}", :default => ["content_names.#{content_name}".to_sym, content_name.capitalize])
152
+ end
153
+
154
+ def linked?
155
+ essence && !essence.link.blank?
156
+ end
157
+
158
+ def essence_partial_name
159
+ essence.partial_name
160
+ end
161
+
162
+ end
163
+ end
@@ -0,0 +1,479 @@
1
+ module Alchemy
2
+ class Element < ActiveRecord::Base
3
+
4
+ # All Elements inside a cell are a list. All Elements not in cell are in the cell_id.nil list.
5
+ acts_as_list :scope => [:page_id, :cell_id]
6
+ stampable :stamper_class_name => :user
7
+
8
+ has_many :contents, :order => :position, :dependent => :destroy
9
+ belongs_to :cell
10
+ belongs_to :page
11
+ has_and_belongs_to_many :to_be_sweeped_pages, :class_name => 'Alchemy::Page', :uniq => true, :join_table => 'alchemy_elements_alchemy_pages'
12
+
13
+ validates_uniqueness_of :position, :scope => [:page_id, :cell_id]
14
+ validates_presence_of :name, :on => :create, :message => '^'+Alchemy::I18n.t("Please choose an element.")
15
+
16
+ attr_accessor :create_contents_after_create
17
+
18
+ after_create :create_contents, :unless => Proc.new { |m| m.create_contents_after_create == false }
19
+
20
+ # TODO: add a trashed column to elements table
21
+ scope :trashed, where(:page_id => nil).order('updated_at DESC')
22
+ scope :not_trashed, where('`alchemy_elements`.`page_id` IS NOT NULL')
23
+ scope :published, where(:public => true)
24
+ scope :named, lambda { |names| where(arel_table[:name].in(names)) }
25
+ scope :excluded, lambda { |names| where(arel_table[:name].not_in(names)) }
26
+ scope :not_in_cell, where(:cell_id => nil)
27
+
28
+ # Returns next Element on self.page or nil. Pass a Element.name to get next of this kind.
29
+ def next(name = nil)
30
+ if name.nil?
31
+ find_conditions = ["public = 1 AND page_id = ? AND position > ?", self.page.id, self.position]
32
+ else
33
+ find_conditions = ["public = 1 AND page_id = ? AND name = ? AND position > ?", self.page.id, name, self.position]
34
+ end
35
+ self.class.where(find_conditions).order("position ASC").limit(1)
36
+ end
37
+
38
+ # Returns previous Element on self.page or nil. Pass a Element.name to get previous of this kind.
39
+ def prev(name = nil)
40
+ if name.nil?
41
+ find_conditions = ["public = 1 AND page_id = ? AND position < ?", self.page.id, self.position]
42
+ else
43
+ find_conditions = ["public = 1 AND page_id = ? AND name = ? AND position < ?", self.page.id, name, self.position]
44
+ end
45
+ self.class.where(find_conditions).order("position DESC").limit(1)
46
+ end
47
+
48
+ # Stores the page into `to_be_sweeped_pages` (Pages that have to be sweeped after updating element).
49
+ def store_page(page)
50
+ return true if page.nil?
51
+ unless self.to_be_sweeped_pages.include? page
52
+ self.to_be_sweeped_pages << page
53
+ self.save
54
+ end
55
+ end
56
+
57
+ # Nullifies the page_id and cell_id, fold the element, set it to unpublic and removes its position.
58
+ def trash
59
+ self.attributes = {
60
+ :page_id => nil,
61
+ :cell_id => nil,
62
+ :folded => true,
63
+ :public => false
64
+ }
65
+ self.remove_from_list
66
+ end
67
+
68
+ def trashed?
69
+ page_id.nil?
70
+ end
71
+
72
+ def content_by_name(name)
73
+ self.contents.find_by_name(name)
74
+ end
75
+
76
+ def content_by_type(essence_type)
77
+ self.contents.find_by_essence_type(essence_type)
78
+ end
79
+
80
+ def all_contents_by_name(name)
81
+ self.contents.find_all_by_name(name)
82
+ end
83
+
84
+ def all_contents_by_type(essence_type)
85
+ self.contents.find_all_by_essence_type(essence_type)
86
+ end
87
+
88
+ # Returns the content that is marked as rss title.
89
+ #
90
+ # Mark a content as rss title in your +elements.yml+ file:
91
+ #
92
+ # - name: news
93
+ # contents:
94
+ # - name: headline
95
+ # type: EssenceText
96
+ # rss_title: true
97
+ #
98
+ def content_for_rss_title
99
+ rss_title = content_descriptions.detect { |c| c['rss_title'] }
100
+ contents.find_by_name(rss_title['name'])
101
+ end
102
+
103
+ # Returns the content that is marked as rss description.
104
+ #
105
+ # Mark a content as rss description in your +elements.yml+ file:
106
+ #
107
+ # - name: news
108
+ # contents:
109
+ # - name: body
110
+ # type: EssenceRichtext
111
+ # rss_description: true
112
+ #
113
+ def content_for_rss_description
114
+ rss_title = content_descriptions.detect { |c| c['rss_description'] }
115
+ contents.find_by_name(rss_title['name'])
116
+ end
117
+
118
+ # Inits a new element for page as described in /config/alchemy/elements.yml from element_name
119
+ def self.new_from_scratch(attributes)
120
+ attributes.stringify_keys!
121
+ return Element.new if attributes['name'].blank?
122
+ element_descriptions = Element.descriptions
123
+ return if element_descriptions.blank?
124
+ element_scratch = element_descriptions.select{ |m| m["name"] == attributes['name'].split('#').first }.first
125
+ element = Element.new(
126
+ element_scratch.except('contents', 'available_contents', 'display_name').merge({
127
+ :page_id => attributes['page_id']
128
+ })
129
+ )
130
+ element
131
+ end
132
+
133
+ # Inits a new element for page as described in /config/alchemy/elements.yml from element_name and saves it
134
+ def self.create_from_scratch(attributes)
135
+ element = Element.new_from_scratch(attributes)
136
+ element.save if element
137
+ return element
138
+ end
139
+
140
+ # pastes a element from the clipboard in the session to page
141
+ def self.paste_from_clipboard(page_id, element, method, position)
142
+ copy = self.copy(element, :page_id => page_id)
143
+ copy.insert_at(position)
144
+ if method == "move" && copy.valid?
145
+ element.destroy
146
+ end
147
+ copy
148
+ end
149
+
150
+ # Returns the descriptions from elements.yml file.
151
+ # Alchemy comes with its own elements.yml file. As so called standard set.
152
+ # Place a elements.yml file inside your apps config/alchemy folder to define
153
+ # your own set of elements
154
+ def self.descriptions
155
+ if File.exists? "#{Rails.root}/config/alchemy/elements.yml"
156
+ element_definitions = YAML.load_file( "#{Rails.root}/config/alchemy/elements.yml" )
157
+ end
158
+ if !element_definitions
159
+ if File.exists?(File.join(File.dirname(__FILE__), "../../../config/alchemy/elements.yml"))
160
+ element_definitions = YAML.load_file( File.join(File.dirname(__FILE__), "../../../config/alchemy/elements.yml") )
161
+ end
162
+ end
163
+ if !element_definitions
164
+ raise LoadError, "Could not find elements.yml file! Please run: rails generate alchemy:scaffold"
165
+ end
166
+ element_definitions
167
+ end
168
+
169
+ def self.definitions
170
+ self.descriptions
171
+ end
172
+
173
+ # Returns the array with the hashes for all element contents in the elements.yml file
174
+ def content_descriptions
175
+ return nil if description.blank?
176
+ description['contents']
177
+ end
178
+
179
+ # Returns the array with the hashes for all element available_contents in the elements.yml file
180
+ def available_content_descriptions
181
+ return nil if description.blank?
182
+ description['available_contents']
183
+ end
184
+
185
+ # Returns the description for given content_name
186
+ def content_description_for(content_name)
187
+ if content_descriptions.blank?
188
+ logger.warn("\n+++++++++++ Warning: Element #{self.name} is missing the content description for #{content_name}\n")
189
+ return nil
190
+ else
191
+ content_descriptions.detect { |d| d['name'] == content_name }
192
+ end
193
+ end
194
+
195
+ # Returns the description for given content_name inside the available_contents
196
+ def available_content_description_for(content_name)
197
+ return nil if available_content_descriptions.blank?
198
+ available_content_descriptions.detect { |d| d['name'] == content_name }
199
+ end
200
+
201
+ # returns the description of the element with my name in element.yml
202
+ def description
203
+ self.class.descriptions.detect{ |d| d['name'] == self.name }
204
+ end
205
+ alias_method :definition, :description
206
+
207
+ # Human name for displaying in selectboxes and element editor views.
208
+ # The name is beeing translated from elements name value as described in config/alchemy/elements.yml
209
+ #
210
+ # Translate the name in your config/locales language file. Example:
211
+ #
212
+ # de:
213
+ # element_names:
214
+ # contactform: 'Kontakt Formular'
215
+ #
216
+ # If no translation is found the capitalized name is used!
217
+ #
218
+ def display_name
219
+ return name.capitalize if description.blank?
220
+ Alchemy::I18n.t(description['name'], :scope => :element_names)
221
+ end
222
+
223
+ # Gets the preview text from the first Content found in the +elements.yml+ Element description file.
224
+ # You can flag a Content as +take_me_for_preview+ to take this as preview.
225
+ def preview_text(maxlength = 30)
226
+ return "" if description.blank?
227
+ my_contents = description["contents"]
228
+ return "" if my_contents.blank?
229
+ content_flagged_as_preview = my_contents.select{ |a| a["take_me_for_preview"] }.first
230
+ if content_flagged_as_preview.blank?
231
+ content_to_take_as_preview = my_contents.first
232
+ else
233
+ content_to_take_as_preview = content_flagged_as_preview
234
+ end
235
+ preview_content = self.contents.select{ |content| content.name == content_to_take_as_preview["name"] }.first
236
+ return "" if preview_content.blank? || preview_content.essence.blank?
237
+ text = preview_content.essence.preview_text(maxlength)
238
+ text.size > maxlength ? "#{text[0..maxlength]}..." : text
239
+ end
240
+
241
+ # Generates a preview text containing Element#display_name and Element#preview_text.
242
+ # It is displayed inside the head of the Element in the Elements.list overlay window from the Alchemy Admin::Page#edit view.
243
+ #
244
+ # === Example
245
+ #
246
+ # A Element described as:
247
+ #
248
+ # - name: funky_element
249
+ # display_name: Funky Element
250
+ # contents:
251
+ # - name: headline
252
+ # type: EssenceText
253
+ # - name: text
254
+ # type EssenceRichtext
255
+ # take_me_for_preview: true
256
+ #
257
+ # With "I want to tell you a funky story" as stripped_body for the EssenceRichtext Content produces:
258
+ #
259
+ # Funky Element: I want to tell ...
260
+ #
261
+ # Options:
262
+ #
263
+ # maxlength(integer). [Default 30] : Length of characters after the text will be cut off.
264
+ #
265
+ def display_name_with_preview_text(maxlength = 30)
266
+ "#{display_name}: #{preview_text(maxlength)}"
267
+ end
268
+
269
+ def dom_id
270
+ "#{name}_#{id}"
271
+ end
272
+
273
+ # List all elements by from page_layout
274
+ def self.elements_for_layout(layout)
275
+ element_descriptions = Element.descriptions
276
+ elements = []
277
+ page_layout = PageLayout.get(layout)
278
+ layout_elements = page_layout["elements"]
279
+ return element_descriptions if layout_elements == "all"
280
+ element_descriptions.each do |element|
281
+ if layout_elements.include?(element["name"])
282
+ elements << element
283
+ end
284
+ end
285
+ return elements
286
+ end
287
+
288
+ def self.get_from_clipboard(clipboard)
289
+ return nil if clipboard.blank?
290
+ self.find_by_id(clipboard[:element_id])
291
+ end
292
+
293
+ def self.all_from_clipboard(clipboard)
294
+ return [] if clipboard.nil?
295
+ self.find_all_by_id(clipboard.collect { |i| i[:id] })
296
+ end
297
+
298
+ def self.all_from_clipboard_for_page(clipboard, page)
299
+ return [] if clipboard.nil? || page.nil?
300
+ allowed_elements = self.all_for_page(page)
301
+ clipboard_elements = self.all_from_clipboard(clipboard)
302
+ allowed_element_names = allowed_elements.collect { |e| e['name'] }
303
+ clipboard_elements.select { |ce| allowed_element_names.include?(ce.name) }
304
+ end
305
+
306
+ # returns the collection of available essence_types that can be created for this element depending on its description in elements.yml
307
+ def available_contents
308
+ description['available_contents']
309
+ end
310
+
311
+ # Returns the contents ingredient for passed content name.
312
+ def ingredient(name)
313
+ content = content_by_name(name)
314
+ return nil if content.blank?
315
+ content.ingredient
316
+ end
317
+
318
+ def has_ingredient?(name)
319
+ !self.ingredient(name).blank?
320
+ end
321
+
322
+ def save_contents(params)
323
+ contents.each do |content|
324
+ unless content.save_essence(params[:contents]["content_#{content.id}"], :public => !params["public"].nil?)
325
+ errors.add(:base, :essence_validation_failed)
326
+ end
327
+ end
328
+ return errors.blank?
329
+ end
330
+
331
+ def essences
332
+ return [] if contents.blank?
333
+ contents.collect(&:essence)
334
+ end
335
+
336
+ # Returns all essence_errors in the format:
337
+ #
338
+ # {
339
+ # essence.content.name => [error_message_for_validation_1, error_message_for_validation_2]
340
+ # }
341
+ #
342
+ # Get translated error messages with Element#essence_error_messages
343
+ #
344
+ def essence_errors
345
+ essence_errors = {}
346
+ essences.each do |essence|
347
+ unless essence.essence_errors.blank?
348
+ essence_errors[essence.content.name] = essence.essence_errors
349
+ end
350
+ end
351
+ essence_errors
352
+ end
353
+
354
+ # Essence validation errors messages are translated via ::I18n.
355
+ # Inside your translation file add translations like:
356
+ #
357
+ # alchemy:
358
+ # content_validations:
359
+ # name_of_the_element:
360
+ # name_of_the_content:
361
+ # validation_error_type: Error Message
362
+ #
363
+ # validation_error_type has to be one of:
364
+ #
365
+ # * blank
366
+ # * taken
367
+ # * wrong_format
368
+ #
369
+ # Example:
370
+ #
371
+ # de:
372
+ # alchemy:
373
+ # content_validations:
374
+ # contact:
375
+ # email:
376
+ # wrong_format: 'Die Email hat nicht das richtige Format'
377
+ #
378
+ def essence_error_messages
379
+ messages = []
380
+ essence_errors.each do |content_name, errors|
381
+ errors.each do |error|
382
+ messages << Alchemy::I18n.t(
383
+ "content_validations.#{self.name}.#{content_name}.#{error}",
384
+ :default => [
385
+ "content_validations.fields.#{content_name}.#{error}".to_sym,
386
+ "content_validations.errors.#{error}".to_sym
387
+ ],
388
+ :field => Content.translated_label_for(content_name)
389
+ )
390
+ end
391
+ end
392
+ messages
393
+ end
394
+
395
+ def contents_with_errors
396
+ contents.select(&:essence_validation_failed?)
397
+ end
398
+
399
+ def has_validations?
400
+ !contents.detect(&:has_validations?).blank?
401
+ end
402
+
403
+ def rtf_contents
404
+ contents.select { |content| content.essence_type == 'Alchemy::EssenceRichtext' }
405
+ end
406
+ alias_method :richtext_contents, :rtf_contents
407
+
408
+ # The name of the cell the element could be placed in.
409
+ def belonging_cellnames(page)
410
+ cellnames = Cell.names_for_element(name)
411
+ if cellnames.blank? || !page.has_cells?
412
+ return ['for_other_elements']
413
+ else
414
+ return cellnames
415
+ end
416
+ end
417
+
418
+ private
419
+
420
+ # List all elements for page_layout
421
+ def self.all_for_page(page)
422
+ raise TypeError if page.class.name != "Alchemy::Page"
423
+ # if page_layout has cells, collect elements from cells and group them by cellname
424
+ page_layout = Alchemy::PageLayout.get(page.page_layout)
425
+ if page_layout.blank?
426
+ logger.warn "\n++++++\nWARNING! Could not find page_layout description for page: #{page.name}\n++++++++\n"
427
+ return []
428
+ end
429
+ elements_for_layout = []
430
+ elements_for_layout += all_definitions_for(page_layout['elements'])
431
+ return [] if elements_for_layout.blank?
432
+ # all unique elements from this layout
433
+ unique_elements = elements_for_layout.select{ |m| m["unique"] == true }
434
+ elements_already_on_the_page = page.elements
435
+ # delete all elements from the elements that could be placed that are unique and already and the page
436
+ unique_elements.each do |unique_element|
437
+ elements_already_on_the_page.each do |already_placed_element|
438
+ if already_placed_element.name == unique_element["name"]
439
+ elements_for_layout.delete(unique_element)
440
+ end
441
+ end
442
+ end
443
+ return elements_for_layout
444
+ end
445
+
446
+ def self.all_definitions_for(element_names)
447
+ return [] if element_names.blank?
448
+ if element_names.to_s == "all"
449
+ return element_descriptions
450
+ else
451
+ return definitions.select { |e| element_names.include? e['name'] }
452
+ end
453
+ end
454
+
455
+ # makes a copy of source and makes copies of the contents from source
456
+ def self.copy(source, differences = {})
457
+ attributes = source.attributes.except("id").merge(differences)
458
+ element = self.create!(attributes.merge(:create_contents_after_create => false, :id => nil, :position => nil))
459
+ source.contents.each do |content|
460
+ new_content = Content.copy(content, :element_id => element.id)
461
+ new_content.move_to_bottom
462
+ end
463
+ element
464
+ end
465
+
466
+ # creates the contents for this element as described in the elements.yml
467
+ def create_contents
468
+ contents = []
469
+ if description["contents"].blank?
470
+ logger.warn "\n++++++\nWARNING! Could not find any content descriptions for element: #{self.name}\n++++++++\n"
471
+ else
472
+ description["contents"].each do |content_hash|
473
+ contents << Content.create_from_scratch(self, content_hash.symbolize_keys)
474
+ end
475
+ end
476
+ end
477
+
478
+ end
479
+ end