alchemy_cms 2.1.12 → 2.2.rc1

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 (405) hide show
  1. data/.travis.yml +1 -1
  2. data/Gemfile +20 -16
  3. data/README.md +11 -7
  4. data/alchemy_cms.gemspec +31 -29
  5. data/app/assets/javascripts/alchemy/alchemy.base.js +234 -233
  6. data/app/assets/javascripts/alchemy/alchemy.buttons.js +26 -26
  7. data/app/assets/javascripts/alchemy/alchemy.datepicker.js +32 -32
  8. data/app/assets/javascripts/alchemy/alchemy.dirty.js +78 -78
  9. data/app/assets/javascripts/alchemy/alchemy.dragndrop.js +103 -103
  10. data/app/assets/javascripts/alchemy/alchemy.element_editor_selector.js +84 -84
  11. data/app/assets/javascripts/alchemy/alchemy.elements_window.js +88 -88
  12. data/app/assets/javascripts/alchemy/alchemy.file_progress.js +92 -0
  13. data/app/assets/javascripts/alchemy/alchemy.growler.js +23 -23
  14. data/app/assets/javascripts/alchemy/alchemy.html5.js +23 -0
  15. data/app/assets/javascripts/alchemy/alchemy.image_cropper.js +53 -52
  16. data/app/assets/javascripts/alchemy/alchemy.jquery_loader.js +33 -30
  17. data/app/assets/javascripts/alchemy/alchemy.js +2 -0
  18. data/app/assets/javascripts/alchemy/alchemy.js_extensions.js +14 -14
  19. data/app/assets/javascripts/alchemy/alchemy.link_overlay.js.coffee +181 -0
  20. data/app/assets/javascripts/alchemy/alchemy.menubar.js +48 -48
  21. data/app/assets/javascripts/alchemy/alchemy.page_sorter.js +39 -39
  22. data/app/assets/javascripts/alchemy/alchemy.preview.js +81 -83
  23. data/app/assets/javascripts/alchemy/alchemy.preview_window.js +86 -86
  24. data/app/assets/javascripts/alchemy/alchemy.routes.js.erb +23 -23
  25. data/app/assets/javascripts/alchemy/alchemy.swf_upload.js +208 -353
  26. data/app/assets/javascripts/alchemy/alchemy.uploader.js +279 -0
  27. data/app/assets/javascripts/alchemy/alchemy.windows.js +268 -268
  28. data/app/assets/javascripts/tiny_mce/plugins/alchemy_link/editor_plugin.js +42 -42
  29. data/app/assets/stylesheets/alchemy/_defaults.scss +89 -89
  30. data/app/assets/stylesheets/alchemy/base.css.scss +790 -804
  31. data/app/assets/stylesheets/alchemy/buttons.css.scss +263 -264
  32. data/app/assets/stylesheets/alchemy/dashboard.css.scss +66 -66
  33. data/app/assets/stylesheets/alchemy/elements.css.scss +575 -564
  34. data/app/assets/stylesheets/alchemy/flash.css.scss +45 -45
  35. data/app/assets/stylesheets/alchemy/frame.css.scss +262 -262
  36. data/app/assets/stylesheets/alchemy/icons.css.scss +86 -86
  37. data/app/assets/stylesheets/alchemy/jquery-ui.alchemy.css.scss +706 -707
  38. data/app/assets/stylesheets/alchemy/jquery.Jcrop.css.scss +46 -27
  39. data/app/assets/stylesheets/alchemy/jquery.sb.css.scss +107 -107
  40. data/app/assets/stylesheets/alchemy/login.css.scss +40 -38
  41. data/app/assets/stylesheets/alchemy/menubar.css.scss +84 -82
  42. data/app/assets/stylesheets/alchemy/modules.css.scss +9 -9
  43. data/app/assets/stylesheets/alchemy/pagination.css.scss +49 -49
  44. data/app/assets/stylesheets/alchemy/print.css +7 -7
  45. data/app/assets/stylesheets/alchemy/sitemap.css.scss +185 -154
  46. data/app/assets/stylesheets/alchemy/standard_set.css +205 -206
  47. data/app/assets/stylesheets/alchemy/tables.css.scss +94 -60
  48. data/app/assets/stylesheets/alchemy/tinymce_content.css.scss +34 -34
  49. data/app/assets/stylesheets/alchemy/tinymce_dialog.css.scss +177 -177
  50. data/app/assets/stylesheets/alchemy/upload.css.scss +68 -45
  51. data/app/assets/stylesheets/tiny_mce/plugins/inlinepopups/skins/alchemy/window.css.scss +222 -221
  52. data/app/controllers/alchemy/admin/attachments_controller.rb +100 -100
  53. data/app/controllers/alchemy/admin/base_controller.rb +116 -116
  54. data/app/controllers/alchemy/admin/clipboard_controller.rb +44 -44
  55. data/app/controllers/alchemy/admin/contents_controller.rb +55 -55
  56. data/app/controllers/alchemy/admin/dashboard_controller.rb +12 -11
  57. data/app/controllers/alchemy/admin/elements_controller.rb +109 -109
  58. data/app/controllers/alchemy/admin/essence_audios_controller.rb +8 -8
  59. data/app/controllers/alchemy/admin/essence_files_controller.rb +20 -20
  60. data/app/controllers/alchemy/admin/essence_flashes_controller.rb +8 -8
  61. data/app/controllers/alchemy/admin/essence_pictures_controller.rb +81 -81
  62. data/app/controllers/alchemy/admin/essence_videos_controller.rb +8 -8
  63. data/app/controllers/alchemy/admin/languages_controller.rb +16 -4
  64. data/app/controllers/alchemy/admin/layoutpages_controller.rb +9 -9
  65. data/app/controllers/alchemy/admin/pages_controller.rb +249 -248
  66. data/app/controllers/alchemy/admin/pictures_controller.rb +105 -105
  67. data/app/controllers/alchemy/admin/resources_controller.rb +111 -166
  68. data/app/controllers/alchemy/admin/trash_controller.rb +18 -18
  69. data/app/controllers/alchemy/admin/users_controller.rb +69 -69
  70. data/app/controllers/alchemy/attachments_controller.rb +27 -27
  71. data/app/controllers/alchemy/base_controller.rb +159 -155
  72. data/app/controllers/alchemy/elements_controller.rb +16 -16
  73. data/app/controllers/alchemy/messages_controller.rb +59 -59
  74. data/app/controllers/alchemy/pages_controller.rb +194 -198
  75. data/app/controllers/alchemy/pictures_controller.rb +57 -57
  76. data/app/controllers/alchemy/user_sessions_controller.rb +70 -70
  77. data/app/helpers/alchemy/admin/attachments_helper.rb +7 -7
  78. data/app/helpers/alchemy/admin/base_helper.rb +425 -425
  79. data/app/helpers/alchemy/admin/contents_helper.rb +72 -72
  80. data/app/helpers/alchemy/admin/elements_helper.rb +108 -107
  81. data/app/helpers/alchemy/admin/essences_helper.rb +108 -108
  82. data/app/helpers/alchemy/admin/pages_helper.rb +42 -42
  83. data/app/helpers/alchemy/admin/pictures_helper.rb +26 -26
  84. data/app/helpers/alchemy/base_helper.rb +90 -90
  85. data/app/helpers/alchemy/elements_helper.rb +167 -168
  86. data/app/helpers/alchemy/essences_helper.rb +133 -133
  87. data/app/helpers/alchemy/pages_helper.rb +515 -526
  88. data/app/helpers/alchemy/pictures_helper.rb +19 -0
  89. data/app/mailers/alchemy/messages.rb +13 -13
  90. data/app/mailers/alchemy/notifications.rb +19 -19
  91. data/app/models/alchemy.rb +3 -3
  92. data/app/models/alchemy/attachment.rb +52 -78
  93. data/app/models/alchemy/cell.rb +48 -48
  94. data/app/models/alchemy/content.rb +196 -196
  95. data/app/models/alchemy/element.rb +500 -490
  96. data/app/models/alchemy/essence_audio.rb +7 -7
  97. data/app/models/alchemy/essence_date.rb +10 -10
  98. data/app/models/alchemy/essence_file.rb +7 -7
  99. data/app/models/alchemy/essence_flash.rb +6 -6
  100. data/app/models/alchemy/essence_html.rb +9 -9
  101. data/app/models/alchemy/essence_picture.rb +17 -17
  102. data/app/models/alchemy/essence_richtext.rb +53 -53
  103. data/app/models/alchemy/essence_text.rb +21 -21
  104. data/app/models/alchemy/essence_video.rb +7 -7
  105. data/app/models/alchemy/folded_page.rb +3 -3
  106. data/app/models/alchemy/language.rb +91 -91
  107. data/app/models/alchemy/language/code.rb +14 -14
  108. data/app/models/alchemy/message.rb +48 -45
  109. data/app/models/alchemy/page.rb +555 -558
  110. data/app/models/alchemy/picture.rb +100 -99
  111. data/app/models/alchemy/user.rb +76 -74
  112. data/app/models/alchemy/user_session.rb +8 -8
  113. data/app/sweepers/alchemy/content_sweeper.rb +15 -15
  114. data/app/sweepers/alchemy/pages_sweeper.rb +50 -50
  115. data/app/sweepers/alchemy/pictures_sweeper.rb +14 -14
  116. data/app/views/alchemy/admin/attachments/_archive_overlay.html.erb +23 -23
  117. data/app/views/alchemy/admin/attachments/_attachment.html.erb +56 -56
  118. data/app/views/alchemy/admin/attachments/_file_to_assign.html.erb +15 -15
  119. data/app/views/alchemy/admin/attachments/_files_list.html.erb +16 -16
  120. data/app/views/alchemy/admin/attachments/create.js.erb +2 -2
  121. data/app/views/alchemy/admin/attachments/destroy.js.erb +3 -3
  122. data/app/views/alchemy/admin/attachments/edit.html.erb +10 -10
  123. data/app/views/alchemy/admin/attachments/index.html.erb +14 -14
  124. data/app/views/alchemy/admin/attachments/new.html.erb +9 -9
  125. data/app/views/alchemy/admin/clipboard/index.html.erb +21 -21
  126. data/app/views/alchemy/admin/clipboard/insert.js.erb +5 -5
  127. data/app/views/alchemy/admin/contents/_missing.html.erb +1 -1
  128. data/app/views/alchemy/admin/contents/create.js.erb +33 -33
  129. data/app/views/alchemy/admin/contents/destroy.js.erb +5 -5
  130. data/app/views/alchemy/admin/contents/new.html.erb +13 -13
  131. data/app/views/alchemy/admin/contents/order.js.erb +2 -2
  132. data/app/views/alchemy/admin/dashboard/index.html.erb +96 -92
  133. data/app/views/alchemy/admin/elements/_add_content.html.erb +12 -12
  134. data/app/views/alchemy/admin/elements/_element.html.erb +3 -3
  135. data/app/views/alchemy/admin/elements/_new_element_form.html.erb +28 -28
  136. data/app/views/alchemy/admin/elements/_picture_editor.html.erb +21 -21
  137. data/app/views/alchemy/admin/elements/create.js.erb +32 -32
  138. data/app/views/alchemy/admin/elements/index.html.erb +2 -2
  139. data/app/views/alchemy/admin/elements/new.html.erb +31 -31
  140. data/app/views/alchemy/admin/elements/order.js.erb +3 -3
  141. data/app/views/alchemy/admin/elements/trash.js.erb +13 -13
  142. data/app/views/alchemy/admin/elements/update.js.erb +6 -6
  143. data/app/views/alchemy/admin/essence_files/assign.js.erb +6 -6
  144. data/app/views/alchemy/admin/essence_pictures/crop.html.erb +32 -32
  145. data/app/views/alchemy/admin/essence_pictures/destroy.js.erb +1 -1
  146. data/app/views/alchemy/admin/essence_pictures/edit.html.erb +1 -1
  147. data/app/views/alchemy/admin/essence_pictures/update.js.erb +11 -11
  148. data/app/views/alchemy/admin/languages/_form.html.erb +51 -45
  149. data/app/views/alchemy/admin/languages/_language.html.erb +45 -45
  150. data/app/views/alchemy/admin/languages/_table.html.erb +25 -25
  151. data/app/views/alchemy/admin/layoutpages/index.html.erb +35 -35
  152. data/app/views/alchemy/admin/pages/_create_language_form.html.erb +42 -42
  153. data/app/views/alchemy/admin/pages/_external_link.html.erb +1 -1
  154. data/app/views/alchemy/admin/pages/_new_page_form.html.erb +27 -27
  155. data/app/views/alchemy/admin/pages/_page.html.erb +112 -112
  156. data/app/views/alchemy/admin/pages/_sitemap.html.erb +1 -1
  157. data/app/views/alchemy/admin/pages/configure.html.erb +71 -69
  158. data/app/views/alchemy/admin/pages/configure_external.html.erb +38 -38
  159. data/app/views/alchemy/admin/pages/destroy.js.erb +10 -10
  160. data/app/views/alchemy/admin/pages/edit.html.erb +165 -165
  161. data/app/views/alchemy/admin/pages/fold.js.erb +2 -2
  162. data/app/views/alchemy/admin/pages/index.html.erb +66 -66
  163. data/app/views/alchemy/admin/pages/locked.html.erb +1 -1
  164. data/app/views/alchemy/admin/pages/new.html.erb +40 -40
  165. data/app/views/alchemy/admin/pages/sort.js.erb +4 -4
  166. data/app/views/alchemy/admin/pages/unlock.js.erb +6 -6
  167. data/app/views/alchemy/admin/pages/update.js.erb +19 -19
  168. data/app/views/alchemy/admin/partials/_flash.html.erb +2 -2
  169. data/app/views/alchemy/admin/partials/_flash_notices.html.erb +1 -1
  170. data/app/views/alchemy/admin/partials/_flash_upload.html.erb +38 -0
  171. data/app/views/alchemy/admin/partials/_language_tree_select.html.erb +15 -15
  172. data/app/views/alchemy/admin/partials/_main_navigation_entry.html.erb +8 -8
  173. data/app/views/alchemy/admin/partials/_remote_search_form.html.erb +35 -35
  174. data/app/views/alchemy/admin/partials/_search_form.html.erb +14 -14
  175. data/app/views/alchemy/admin/partials/_sub_navigation_tab.html.erb +6 -6
  176. data/app/views/alchemy/admin/partials/_upload_form.html.erb +56 -118
  177. data/app/views/alchemy/admin/pictures/_archive_overlay.html.erb +11 -11
  178. data/app/views/alchemy/admin/pictures/_filter_and_size_bar.html.erb +71 -71
  179. data/app/views/alchemy/admin/pictures/_picture.html.erb +32 -32
  180. data/app/views/alchemy/admin/pictures/_picture_to_assign.html.erb +26 -26
  181. data/app/views/alchemy/admin/pictures/_pictures_list.html.erb +6 -6
  182. data/app/views/alchemy/admin/pictures/create.js.erb +7 -7
  183. data/app/views/alchemy/admin/pictures/index.html.erb +67 -67
  184. data/app/views/alchemy/admin/pictures/show_in_window.html.erb +5 -4
  185. data/app/views/alchemy/admin/resources/_form.html.erb +25 -19
  186. data/app/views/alchemy/admin/resources/_resource.html.erb +37 -36
  187. data/app/views/alchemy/admin/resources/_table.html.erb +17 -17
  188. data/app/views/alchemy/admin/resources/destroy.js.erb +1 -1
  189. data/app/views/alchemy/admin/resources/index.html.erb +14 -14
  190. data/app/views/alchemy/admin/trash/index.html.erb +20 -20
  191. data/app/views/alchemy/admin/users/_table.html.erb +52 -52
  192. data/app/views/alchemy/admin/users/_user.html.erb +35 -36
  193. data/app/views/alchemy/admin/users/index.html.erb +26 -27
  194. data/app/views/alchemy/base/error_notice.html.erb +2 -2
  195. data/app/views/alchemy/base/update.js.erb +1 -1
  196. data/app/views/alchemy/elements/_contactform_view.html.erb +76 -76
  197. data/app/views/alchemy/elements/_download_view.html.erb +1 -1
  198. data/app/views/alchemy/elements/_editor_not_found.html.erb +3 -3
  199. data/app/views/alchemy/elements/_searchresult_view.html.erb +2 -2
  200. data/app/views/alchemy/elements/_sitemap_editor.html.erb +1 -1
  201. data/app/views/alchemy/essences/_essence_audio_view.html.erb +13 -13
  202. data/app/views/alchemy/essences/_essence_date_editor.html.erb +10 -10
  203. data/app/views/alchemy/essences/_essence_file_editor.html.erb +62 -62
  204. data/app/views/alchemy/essences/_essence_file_view.html.erb +8 -8
  205. data/app/views/alchemy/essences/_essence_flash_view.html.erb +19 -19
  206. data/app/views/alchemy/essences/_essence_html_editor.html.erb +6 -6
  207. data/app/views/alchemy/essences/_essence_picture_editor.html.erb +73 -73
  208. data/app/views/alchemy/essences/_essence_picture_view.html.erb +34 -34
  209. data/app/views/alchemy/essences/_essence_richtext_editor.html.erb +7 -7
  210. data/app/views/alchemy/essences/_essence_text_editor.html.erb +8 -8
  211. data/app/views/alchemy/navigation/_image_link.html.erb +12 -12
  212. data/app/views/alchemy/navigation/_link.html.erb +13 -13
  213. data/app/views/alchemy/navigation/_renderer.html.erb +17 -17
  214. data/app/views/alchemy/page_layouts/_layout_footer.html.erb +1 -1
  215. data/app/views/alchemy/page_layouts/_layout_header.html.erb +1 -1
  216. data/app/views/alchemy/pages/show.rss.builder +14 -14
  217. data/app/views/alchemy/search/_result.html.erb +7 -7
  218. data/app/views/alchemy/user_sessions/leave.html.erb +9 -9
  219. data/app/views/alchemy/user_sessions/login.html.erb +39 -39
  220. data/app/views/alchemy/user_sessions/logout.html.erb +1 -1
  221. data/app/views/layouts/alchemy/admin.html.erb +81 -81
  222. data/app/views/layouts/alchemy/login.html.erb +36 -36
  223. data/app/views/layouts/alchemy/pages.html.erb +48 -27
  224. data/bin/alchemy +136 -134
  225. data/config/alchemy/config.yml +13 -9
  226. data/config/locales/alchemy.de.yml +24 -30
  227. data/config/locales/alchemy.en.yml +11 -28
  228. data/config/routes.rb +146 -146
  229. data/db/migrate/20100607193638_create_essence_pictures.rb +3 -3
  230. data/db/migrate/20101109150312_alter_pages_visible_column_default.rb +1 -1
  231. data/db/migrate/20101109151812_create_languages.rb +3 -3
  232. data/db/migrate/20110115123343_remove_css_class_default_from_essence_pictures.rb +3 -3
  233. data/db/migrate/20110224105120_change_pages_visible_default.rb +3 -3
  234. data/db/migrate/20110228182659_remove_default_page_layout_from_pages.rb +2 -2
  235. data/db/migrate/20110414163140_remove_display_name_from_elements.rb +3 -3
  236. data/db/migrate/20110511100516_rename_essence_texts_title_to_link_title.rb +2 -2
  237. data/db/migrate/20110529130500_add_cell_id_to_elements.rb +3 -3
  238. data/db/migrate/20110530102804_change_pages_page_layout_column.rb +3 -3
  239. data/db/migrate/20110711142057_change_open_link_in_new_window_to_link_target.rb +1 -1
  240. data/db/migrate/20111116125112_namespace_alchemy_models.rb +21 -21
  241. data/lib/alchemy/auth_engine.rb +5 -5
  242. data/lib/alchemy/capistrano.rb +64 -64
  243. data/lib/alchemy/config.rb +47 -44
  244. data/lib/alchemy/engine.rb +41 -41
  245. data/lib/alchemy/essence.rb +50 -51
  246. data/lib/alchemy/i18n.rb +48 -48
  247. data/lib/alchemy/modules.rb +30 -30
  248. data/lib/alchemy/mount_point.rb +6 -6
  249. data/lib/alchemy/page_layout.rb +94 -93
  250. data/lib/alchemy/resource.rb +82 -0
  251. data/lib/alchemy/resources_helper.rb +56 -0
  252. data/lib/alchemy/scoped_pagination_url_helper.rb +8 -8
  253. data/lib/alchemy/seeder.rb +88 -88
  254. data/lib/alchemy/tinymce.rb +49 -49
  255. data/lib/alchemy/upgrader.rb +103 -103
  256. data/lib/alchemy/version.rb +1 -1
  257. data/lib/alchemy_cms.rb +26 -27
  258. data/lib/extensions/action_view.rb +1 -1
  259. data/lib/extensions/array.rb +3 -3
  260. data/lib/extensions/hash.rb +3 -3
  261. data/lib/middleware/flash_session_cookie.rb +1 -1
  262. data/lib/rails/generators/alchemy/deploy_script/deploy_script_generator.rb +24 -24
  263. data/lib/rails/generators/alchemy/elements/elements_generator.rb +7 -7
  264. data/lib/rails/generators/alchemy/elements/templates/view.html.erb +17 -17
  265. data/lib/rails/generators/alchemy/page_layouts/page_layouts_generator.rb +6 -6
  266. data/lib/rails/generators/alchemy/plugin/templates/authorization_rules.rb +8 -8
  267. data/lib/rails/generators/alchemy/scaffold/files/pages.html.erb +7 -7
  268. data/lib/rails/generators/alchemy/scaffold/scaffold_generator.rb +36 -36
  269. data/lib/rails/templates/alchemy.rb +1 -1
  270. data/lib/tasks/ferret.rake +2 -2
  271. data/lib/tasks/fleximage.rake +32 -32
  272. data/lib/tasks/install.rake +12 -12
  273. data/lib/tasks/upgrade.rake +4 -4
  274. data/spec/controllers/admin/clipboard_controller_spec.rb +43 -43
  275. data/spec/controllers/admin/contents_controller_spec.rb +22 -22
  276. data/spec/controllers/admin/elements_controller_spec.rb +13 -13
  277. data/spec/controllers/admin/languages_controller_spec.rb +31 -0
  278. data/spec/controllers/admin/pages_controller_spec.rb +10 -41
  279. data/spec/controllers/admin/resources_controller_spec.rb +19 -0
  280. data/spec/controllers/admin/trash_controller_spec.rb +11 -11
  281. data/spec/controllers/base_controller_spec.rb +46 -46
  282. data/spec/controllers/pages_controller_spec.rb +102 -92
  283. data/spec/dummy/app/controllers/admin/events_controller.rb +3 -0
  284. data/spec/dummy/app/controllers/errors_controller.rb +5 -0
  285. data/spec/dummy/app/models/event.rb +3 -0
  286. data/spec/dummy/config.ru +1 -1
  287. data/spec/dummy/config/application.rb +3 -0
  288. data/spec/dummy/config/authorization_rules.rb +7 -0
  289. data/spec/dummy/config/environments/development.rb +8 -1
  290. data/spec/dummy/config/environments/production.rb +1 -1
  291. data/spec/dummy/config/environments/test.rb +5 -2
  292. data/spec/dummy/config/routes.rb +9 -1
  293. data/spec/dummy/db/schema.rb +47 -35
  294. data/spec/dummy/public/404.html +19 -7
  295. data/spec/dummy/public/404.html.bak +26 -0
  296. data/spec/dummy/public/422.html +19 -7
  297. data/spec/dummy/public/500.html +19 -7
  298. data/spec/dummy/script/rails +2 -2
  299. data/spec/factories.rb +76 -76
  300. data/spec/helpers/admin/base_helper_spec.rb +21 -21
  301. data/spec/helpers/admin/contents_helper_spec.rb +14 -14
  302. data/spec/helpers/admin/elements_helper_spec.rb +40 -40
  303. data/spec/helpers/admin/essences_helper_spec.rb +7 -7
  304. data/spec/helpers/elements_helper_spec.rb +154 -154
  305. data/spec/helpers/essences_helper_spec.rb +10 -10
  306. data/spec/helpers/pages_helper_spec.rb +369 -372
  307. data/spec/helpers/pictures_helper_spec.rb +14 -0
  308. data/spec/helpers/url_helpers_spec.rb +29 -34
  309. data/spec/integration/admin/pages_controller_spec.rb +50 -50
  310. data/spec/integration/admin/resources_integration_spec.rb +100 -0
  311. data/spec/integration/navigation_spec.rb +1 -1
  312. data/spec/integration/pages_controller_spec.rb +205 -207
  313. data/spec/integration/security_spec.rb +47 -47
  314. data/spec/javascripts/alchemy/link_overlay_spec.js.coffee +42 -0
  315. data/spec/javascripts/alchemy_integration_spec.coffee +12 -0
  316. data/spec/javascripts/fixtures/select.html +3 -0
  317. data/spec/javascripts/helpers/.gitkeep +0 -0
  318. data/spec/javascripts/helpers/jasmine-jquery-1.3.1.js +289 -0
  319. data/spec/javascripts/helpers/mock-ajax.js +207 -0
  320. data/spec/javascripts/helpers/test_responses/test_responses.js +1 -0
  321. data/spec/javascripts/spec.css +3 -0
  322. data/spec/javascripts/spec.js +2 -0
  323. data/spec/libraries/resource_spec.rb +122 -0
  324. data/spec/libraries/resources_helper_spec.rb +105 -0
  325. data/spec/models/content_spec.rb +67 -67
  326. data/spec/models/element_spec.rb +133 -133
  327. data/spec/models/essence_picture_spec.rb +5 -5
  328. data/spec/models/essence_richtext_spec.rb +4 -4
  329. data/spec/models/language_spec.rb +89 -89
  330. data/spec/models/page_spec.rb +436 -506
  331. data/spec/models/picture_spec.rb +34 -34
  332. data/spec/models/user_spec.rb +2 -2
  333. data/spec/page_layout_spec.rb +24 -20
  334. data/spec/routing_spec.rb +253 -253
  335. data/spec/spec_helper.rb +51 -50
  336. data/spec/support/alchemy/controller_hacks.rb +25 -25
  337. data/spec/support/alchemy/specs_helpers.rb +25 -25
  338. data/spec/support/integration_spec_helper.rb +24 -0
  339. data/vendor/assets/javascripts/jquery_plugins/jquery.html5uploader.js +271 -0
  340. data/vendor/assets/javascripts/jquery_plugins/jquery.in-place-edit.js +86 -85
  341. data/vendor/assets/javascripts/jquery_plugins/jquery.ui.nestedSortable.js +380 -377
  342. data/vendor/assets/javascripts/jquery_plugins/jquery.ui.tabspaging.js +285 -279
  343. data/vendor/assets/javascripts/swfupload/SWFObject License.txt +3 -3
  344. data/vendor/assets/javascripts/swfupload/swfupload.cookies.js +47 -47
  345. data/vendor/assets/javascripts/swfupload/swfupload.js +612 -612
  346. data/vendor/assets/javascripts/swfupload/swfupload.queue.js +93 -93
  347. data/vendor/assets/javascripts/swfupload/swfupload.speed.js +337 -337
  348. data/vendor/assets/javascripts/swfupload/swfupload.swfobject.js +706 -102
  349. data/vendor/assets/javascripts/tiny_mce/license.txt +6 -6
  350. data/vendor/assets/javascripts/tiny_mce/plugins/fullscreen/fullscreen.htm +97 -97
  351. data/vendor/assets/javascripts/tiny_mce/plugins/inlinepopups/template.htm +386 -376
  352. data/vendor/assets/javascripts/tiny_mce/plugins/paste/js/pastetext.js +30 -30
  353. data/vendor/assets/javascripts/tiny_mce/plugins/paste/js/pasteword.js +45 -45
  354. data/vendor/assets/javascripts/tiny_mce/plugins/paste/pastetext.htm +20 -17
  355. data/vendor/assets/javascripts/tiny_mce/plugins/paste/pasteword.htm +12 -12
  356. data/vendor/assets/javascripts/tiny_mce/plugins/table/cell.htm +183 -173
  357. data/vendor/assets/javascripts/tiny_mce/plugins/table/css/cell.css +4 -4
  358. data/vendor/assets/javascripts/tiny_mce/plugins/table/css/row.css +7 -7
  359. data/vendor/assets/javascripts/tiny_mce/plugins/table/css/table.css +3 -3
  360. data/vendor/assets/javascripts/tiny_mce/plugins/table/js/cell.js +282 -280
  361. data/vendor/assets/javascripts/tiny_mce/plugins/table/js/merge_cells.js +15 -15
  362. data/vendor/assets/javascripts/tiny_mce/plugins/table/js/row.js +204 -204
  363. data/vendor/assets/javascripts/tiny_mce/plugins/table/js/table.js +435 -435
  364. data/vendor/assets/javascripts/tiny_mce/plugins/table/merge_cells.htm +24 -22
  365. data/vendor/assets/javascripts/tiny_mce/plugins/table/row.htm +144 -136
  366. data/vendor/assets/javascripts/tiny_mce/plugins/table/table.htm +184 -168
  367. data/vendor/assets/javascripts/tiny_mce/themes/advanced/about.htm +62 -46
  368. data/vendor/assets/javascripts/tiny_mce/themes/advanced/anchor.htm +17 -16
  369. data/vendor/assets/javascripts/tiny_mce/themes/advanced/charmap.htm +56 -47
  370. data/vendor/assets/javascripts/tiny_mce/themes/advanced/color_picker.htm +67 -54
  371. data/vendor/assets/javascripts/tiny_mce/themes/advanced/editor_template.js +852 -1
  372. data/vendor/assets/javascripts/tiny_mce/themes/advanced/image.htm +79 -69
  373. data/vendor/assets/javascripts/tiny_mce/themes/advanced/js/about.js +48 -48
  374. data/vendor/assets/javascripts/tiny_mce/themes/advanced/js/anchor.js +28 -28
  375. data/vendor/assets/javascripts/tiny_mce/themes/advanced/js/charmap.js +317 -317
  376. data/vendor/assets/javascripts/tiny_mce/themes/advanced/js/color_picker.js +248 -246
  377. data/vendor/assets/javascripts/tiny_mce/themes/advanced/js/image.js +246 -246
  378. data/vendor/assets/javascripts/tiny_mce/themes/advanced/js/link.js +146 -146
  379. data/vendor/assets/javascripts/tiny_mce/themes/advanced/js/source_editor.js +31 -31
  380. data/vendor/assets/javascripts/tiny_mce/themes/advanced/langs/de.js +1 -1
  381. data/vendor/assets/javascripts/tiny_mce/themes/advanced/langs/de_dlg.js +1 -1
  382. data/vendor/assets/javascripts/tiny_mce/themes/advanced/langs/en.js +1 -1
  383. data/vendor/assets/javascripts/tiny_mce/themes/advanced/langs/en_dlg.js +1 -1
  384. data/vendor/assets/javascripts/tiny_mce/themes/advanced/link.htm +53 -46
  385. data/vendor/assets/javascripts/tiny_mce/themes/advanced/shortcuts.htm +57 -45
  386. data/vendor/assets/javascripts/tiny_mce/themes/advanced/skins/default/content.css +182 -47
  387. data/vendor/assets/javascripts/tiny_mce/themes/advanced/skins/default/dialog.css +399 -92
  388. data/vendor/assets/javascripts/tiny_mce/themes/advanced/skins/default/ui.css +891 -187
  389. data/vendor/assets/javascripts/tiny_mce/themes/advanced/skins/highcontrast/content.css +102 -24
  390. data/vendor/assets/javascripts/tiny_mce/themes/advanced/skins/highcontrast/dialog.css +377 -78
  391. data/vendor/assets/javascripts/tiny_mce/themes/advanced/skins/highcontrast/ui.css +452 -77
  392. data/vendor/assets/javascripts/tiny_mce/themes/advanced/skins/o2k7/content.css +167 -45
  393. data/vendor/assets/javascripts/tiny_mce/themes/advanced/skins/o2k7/dialog.css +399 -92
  394. data/vendor/assets/javascripts/tiny_mce/themes/advanced/skins/o2k7/ui.css +890 -190
  395. data/vendor/assets/javascripts/tiny_mce/themes/advanced/skins/o2k7/ui_black.css +33 -7
  396. data/vendor/assets/javascripts/tiny_mce/themes/advanced/skins/o2k7/ui_silver.css +15 -4
  397. data/vendor/assets/javascripts/tiny_mce/themes/advanced/source_editor.htm +18 -15
  398. data/vendor/assets/javascripts/tiny_mce/utils/editable_selects.js +46 -46
  399. data/vendor/assets/javascripts/tiny_mce/utils/form_utils.js +124 -124
  400. data/vendor/assets/javascripts/tiny_mce/utils/mctabs.js +112 -112
  401. data/vendor/assets/javascripts/tiny_mce/utils/validate.js +213 -213
  402. metadata +102 -115
  403. data/app/assets/javascripts/alchemy/alchemy.link_overlay.js +0 -216
  404. data/lib/tasks/routes.rake +0 -29
  405. data/spec/integration/admin/resources_spec.rb +0 -19
@@ -0,0 +1,19 @@
1
+ module Alchemy
2
+ module PicturesHelper
3
+
4
+ # This helper returns a path to picture for use inside a image_tag helper.
5
+ #
6
+ # Any additional options are passed to the url_helper, so you can add arguments to your url.
7
+ #
8
+ # Example:
9
+ #
10
+ # <%= image_tag alchemy_picture_path(picture, :size => '320x200', :format => :png) %>
11
+ #
12
+ def alchemy_picture_path(picture, options={})
13
+ defaults = {:format => Alchemy::Config.get(:image_output_format)}
14
+ options = defaults.update(options)
15
+ alchemy.show_picture_path({:id => picture.id, :name => picture.urlname}.merge(options))
16
+ end
17
+
18
+ end
19
+ end
@@ -1,17 +1,17 @@
1
1
  module Alchemy
2
- class Messages < ActionMailer::Base
2
+ class Messages < ActionMailer::Base
3
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
4
+ default :from => Alchemy::Config.get(:mailer)[:mail_from]
15
5
 
16
- end
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
17
  end
@@ -1,25 +1,25 @@
1
1
  module Alchemy
2
- class Notifications < ActionMailer::Base
2
+ class Notifications < ActionMailer::Base
3
3
 
4
- default :from => Alchemy::Config.get(:mailer)[:mail_from]
4
+ default :from => Alchemy::Config.get(:mailer)[:mail_from]
5
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
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
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
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
23
 
24
- end
24
+ end
25
25
  end
@@ -1,7 +1,7 @@
1
1
  module Alchemy
2
2
 
3
- def self.table_name_prefix
4
- 'alchemy_'
5
- end
3
+ def self.table_name_prefix
4
+ 'alchemy_'
5
+ end
6
6
 
7
7
  end
@@ -1,87 +1,61 @@
1
1
  module Alchemy
2
- class Attachment < ActiveRecord::Base
2
+ class Attachment < ActiveRecord::Base
3
3
 
4
- stampable
4
+ stampable
5
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
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
12
 
13
- def self.find_paginated(params, per_page)
14
- cond = "name LIKE '%#{params[:query]}%' OR filename LIKE '%#{params[:query]}%'"
15
- self.where(cond).page(params[:page] || 1).per(per_page).order(:name)
16
- end
13
+ def self.find_paginated(params, per_page)
14
+ cond = "name LIKE '%#{params[:query]}%' OR filename LIKE '%#{params[:query]}%'"
15
+ self.where(cond).page(params[:page] || 1).per(per_page).order(:name)
16
+ end
17
17
 
18
- def urlname
19
- ::CGI.escape(read_attribute(:filename).split('.').first)
20
- end
18
+ def urlname
19
+ ::CGI.escape(read_attribute(:filename).split('.').first)
20
+ end
21
21
 
22
- def extension
23
- filename.split(".").last
24
- end
25
- alias_method :suffix, :extension
22
+ def extension
23
+ filename.split(".").last
24
+ end
26
25
 
27
- def icon_css_class
28
- case content_type
29
- when "application/x-flash-video"
30
- then "video"
31
- when "video/x-flv"
32
- then "video"
33
- when "video/mp4"
34
- then "video"
35
- when "video/mpeg"
36
- then "video"
37
- when "video/quicktime"
38
- then "video"
39
- when "video/x-msvideo"
40
- then "video"
41
- when "video/x-ms-wmv"
42
- then "video"
43
- when "application/zip"
44
- then "archive"
45
- when "application/x-rar"
46
- then "archive"
47
- when "audio/mpeg"
48
- then "audio"
49
- when "audio/mp4"
50
- then "audio"
51
- when "audio/wav"
52
- then "audio"
53
- when "audio/x-wav"
54
- then "audio"
55
- when "application/x-shockwave-flash"
56
- then "flash"
57
- when "image/gif"
58
- then "image"
59
- when "image/jpeg"
60
- then "image"
61
- when "image/png"
62
- then "image"
63
- when "image/tiff"
64
- then "image"
65
- when "image/x-psd"
66
- then "psd"
67
- when "text/plain"
68
- then "text"
69
- when "application/rtf"
70
- then "rtf"
71
- when "application/pdf"
72
- then "pdf"
73
- when "application/msword"
74
- then "word"
75
- when "application/vnd.ms-excel"
76
- then "excel"
77
- when "text/x-vcard"
78
- then "vcard"
79
- when "application/vcard"
80
- then "vcard"
81
- else
82
- "file"
83
- end
84
- end
26
+ alias_method :suffix, :extension
85
27
 
86
- end
28
+ def icon_css_class
29
+ case content_type
30
+ when "application/x-flash-video" then "video"
31
+ when "video/x-flv" then "video"
32
+ when "video/mp4" then "video"
33
+ when "video/mpeg" then "video"
34
+ when "video/quicktime" then "video"
35
+ when "video/x-msvideo" then "video"
36
+ when "video/x-ms-wmv" then "video"
37
+ when "application/zip" then "archive"
38
+ when "application/x-rar" then "archive"
39
+ when "audio/mpeg" then "audio"
40
+ when "audio/mp4" then "audio"
41
+ when "audio/wav" then "audio"
42
+ when "audio/x-wav" then "audio"
43
+ when "application/x-shockwave-flash" then "flash"
44
+ when "image/gif" then "image"
45
+ when "image/jpeg" then "image"
46
+ when "image/png" then "image"
47
+ when "image/tiff" then "image"
48
+ when "image/x-psd" then "psd"
49
+ when "text/plain" then "text"
50
+ when "application/rtf" then "rtf"
51
+ when "application/pdf" then "pdf"
52
+ when "application/msword" then "word"
53
+ when "application/vnd.ms-excel" then "excel"
54
+ when "text/x-vcard" then "vcard"
55
+ when "application/vcard" then "vcard"
56
+ else "file"
57
+ end
58
+ end
59
+
60
+ end
87
61
  end
@@ -11,52 +11,52 @@
11
11
  # Views for cells are inside the +app/views/cells+ folder in you project.
12
12
  #
13
13
  module Alchemy
14
- class Cell < ActiveRecord::Base
15
-
16
- belongs_to :page
17
- validates_uniqueness_of :name, :scope => :page_id
18
- has_many :elements, :dependent => :destroy, :order => :position
19
-
20
- def self.definitions
21
- cell_yml = ::File.join(::Rails.root, 'config', 'alchemy', 'cells.yml')
22
- ::YAML.load_file(cell_yml) if ::File.exist?(cell_yml)
23
- end
24
-
25
- def self.definition_for(cellname)
26
- return nil if cellname.blank?
27
- definitions.detect { |c| c['name'] == cellname }
28
- end
29
-
30
- def self.all_definitions_for(cellnames)
31
- definitions.select { |c| cellnames.include? c['name'] }
32
- end
33
-
34
- def self.all_element_definitions_for(cellnames)
35
- element_names = []
36
- all_definitions_for(cellnames).each do |cell|
37
- element_names += cell['elements']
38
- end
39
- Element.all_definitions_for(element_names.uniq)
40
- end
41
-
42
- def self.definitions_for_element(element_name)
43
- return [] if definitions.blank?
44
- definitions.select { |d| d['elements'].include?(element_name) }
45
- end
46
-
47
- def self.names_for_element(element_name)
48
- definitions = definitions_for_element(element_name)
49
- return nil if definitions.blank?
50
- definitions.collect { |d| d['name'] }
51
- end
52
-
53
- def name_for_label
54
- self.class.translated_label_for(self.name)
55
- end
56
-
57
- def self.translated_label_for(cell_name)
58
- I18n.t(cell_name, :scope => :cell_names)
59
- end
60
-
61
- end
14
+ class Cell < ActiveRecord::Base
15
+
16
+ belongs_to :page
17
+ validates_uniqueness_of :name, :scope => :page_id
18
+ has_many :elements, :dependent => :destroy, :order => :position
19
+
20
+ def self.definitions
21
+ cell_yml = ::File.join(::Rails.root, 'config', 'alchemy', 'cells.yml')
22
+ ::YAML.load_file(cell_yml) if ::File.exist?(cell_yml)
23
+ end
24
+
25
+ def self.definition_for(cellname)
26
+ return nil if cellname.blank?
27
+ definitions.detect { |c| c['name'] == cellname }
28
+ end
29
+
30
+ def self.all_definitions_for(cellnames)
31
+ definitions.select { |c| cellnames.include? c['name'] }
32
+ end
33
+
34
+ def self.all_element_definitions_for(cellnames)
35
+ element_names = []
36
+ all_definitions_for(cellnames).each do |cell|
37
+ element_names += cell['elements']
38
+ end
39
+ Element.all_definitions_for(element_names.uniq)
40
+ end
41
+
42
+ def self.definitions_for_element(element_name)
43
+ return [] if definitions.blank?
44
+ definitions.select { |d| d['elements'].include?(element_name) }
45
+ end
46
+
47
+ def self.names_for_element(element_name)
48
+ definitions = definitions_for_element(element_name)
49
+ return nil if definitions.blank?
50
+ definitions.collect { |d| d['name'] }
51
+ end
52
+
53
+ def name_for_label
54
+ self.class.translated_label_for(self.name)
55
+ end
56
+
57
+ def self.translated_label_for(cell_name)
58
+ I18n.t(cell_name, :scope => :cell_names)
59
+ end
60
+
61
+ end
62
62
  end
@@ -1,198 +1,198 @@
1
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 :name, :scope => :element_id
16
- validates_uniqueness_of :position, :scope => [:element_id, :essence_type]
17
-
18
- scope :essence_pictures, where(:essence_type => "Alchemy::EssencePicture")
19
- scope :essence_texts, where(:essence_type => "Alchemy::EssenceText")
20
- scope :essence_richtexts, where(:essence_type => "Alchemy::EssenceRichtext")
21
-
22
- # Creates a new Content as descriped in the elements.yml file
23
- def self.create_from_scratch(element, essences_hash)
24
- if essences_hash[:name].blank? && !essences_hash[:essence_type].blank?
25
- essences_of_same_type = element.contents.where(
26
- :essence_type => Content.normalize_essence_type(essences_hash[:essence_type])
27
- )
28
- description = {
29
- 'type' => essences_hash[:essence_type],
30
- 'name' => "#{essences_hash[:essence_type].classify.demodulize.underscore}_#{essences_of_same_type.count + 1}"
31
- }
32
- else
33
- description = element.content_description_for(essences_hash[:name])
34
- description = element.available_content_description_for(essences_hash[:name]) if description.blank?
35
- end
36
- raise "No description found in elements.yml for #{essences_hash.inspect} and #{element.inspect}" if description.blank?
37
- essence_class = Content.normalize_essence_type(description['type']).constantize
38
- content = self.new(:name => description['name'], :element_id => element.id)
39
- if description['type'] == "EssenceRichtext" || description['type'] == "EssenceText"
40
- essence = essence_class.create(:do_not_index => !description['do_not_index'].nil?)
41
- else
42
- essence = essence_class.create
43
- end
44
- if essence
45
- content.essence = essence
46
- content.save!
47
- else
48
- content = nil
49
- end
50
- return content
51
- end
52
-
53
- # Settings from the elements.yml definition
54
- def settings
55
- return {} if description.blank?
56
- settings = description['settings']
57
- return {} if settings.blank?
58
- settings.symbolize_keys
59
- end
60
-
61
- def siblings
62
- return [] if !element
63
- self.element.contents
64
- end
65
-
66
- # Makes a copy of source and also copies the associated essence.
67
- #
68
- # You can pass a differences hash to update the attributes of the copy.
69
- #
70
- # === Example
71
- #
72
- # @copy = Alchemy::Content.copy(@content, {:element_id => 3})
73
- # @copy.element_id # => 3
74
- #
75
- def self.copy(source, differences = {})
76
- differences[:position] = nil
77
- differences[:id] = nil
78
- attributes = source.attributes.except("id").merge(differences)
79
- content = self.create!(attributes)
80
- new_essence = content.essence.class.new(content.essence.attributes.except('id'))
81
- new_essence.save!
82
- raise "Essence not cloned" if new_essence.id == content.essence_id
83
- content.update_attribute(:essence_id, new_essence.id)
84
- content
85
- end
86
-
87
- # Returns my description hash from elements.yml
88
- # Returns the description from available_contents if my own description is blank
89
- def description
90
- if self.element.blank?
91
- logger.warn("\n+++++++++++ Warning: Content with id #{self.id} is missing its Element\n")
92
- return nil
93
- else
94
- desc = self.element.content_description_for(self.name)
95
- if desc.blank?
96
- desc = self.element.available_content_description_for(self.name)
97
- else
98
- return desc
99
- end
100
- end
101
- end
102
-
103
- # Gets the ingredient from essence
104
- def ingredient
105
- return nil if self.essence.nil?
106
- self.essence.ingredient
107
- end
108
-
109
- # Calls essence.update_attributes. Called from +Alchemy::Element#save_contents+
110
- # Ads errors to self.base if essence validation fails.
111
- def update_essence(params={})
112
- raise "Essence not found" if essence.nil?
113
- if essence.update_attributes(params)
114
- return true
115
- else
116
- errors.add(:essence, :validation_failed)
117
- return false
118
- end
119
- end
120
-
121
- def essence_validation_failed?
122
- essence.errors.any?
123
- end
124
-
125
- def has_validations?
126
- return false if description.blank?
127
- !description['validate'].blank?
128
- end
129
-
130
- # Returns a string to be passed to Rails form field tags to ensure we have same params layout everywhere.
131
- #
132
- # === Example:
133
- #
134
- # <%= text_field_tag content.form_field_name, content.ingredient %>
135
- #
136
- # === Options:
137
- #
138
- # You can pass an Essence column_name. Default is self.essence.ingredient_column
139
- #
140
- # ==== Example:
141
- #
142
- # <%= text_field_tag content.form_field_name(:link), content.ingredient %>
143
- #
144
- def form_field_name(essence_column = self.essence.ingredient_column)
145
- "contents[content_#{self.id}][#{essence_column}]"
146
- end
147
-
148
- def form_field_id(essence_column = self.essence.ingredient_column)
149
- "contents_content_#{self.id}_#{essence_column}"
150
- end
151
-
152
- # Returns the translated name for displaying in labels, etc.
153
- def name_for_label
154
- self.class.translated_label_for(self.name, self.element.name)
155
- end
156
-
157
- # Returns the translated label for a content name.
158
- #
159
- # Translate it in your locale yml file:
160
- #
161
- # alchemy:
162
- # content_names:
163
- # foo: Bar
164
- #
165
- # Optionally you can scope your content name to an element:
166
- #
167
- # alchemy:
168
- # content_names:
169
- # article:
170
- # foo: Baz
171
- #
172
- def self.translated_label_for(content_name, element_name = nil)
173
- Alchemy::I18n.t("content_names.#{element_name}.#{content_name}", :default => ["content_names.#{content_name}".to_sym, content_name.capitalize])
174
- end
175
-
176
- def linked?
177
- essence && !essence.link.blank?
178
- end
179
-
180
- def essence_partial_name
181
- essence.partial_name
182
- end
183
-
184
- def normalized_essence_type
185
- self.class.normalize_essence_type(self.essence_type)
186
- end
187
-
188
- def self.normalize_essence_type(essence_type)
189
- essence_type = essence_type.classify
190
- if not essence_type.match(/^Alchemy::/)
191
- essence_type.gsub!(/^Essence/, 'Alchemy::Essence')
192
- else
193
- essence_type
194
- end
195
- end
196
-
197
- end
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 :name, :scope => :element_id
16
+ validates_uniqueness_of :position, :scope => [:element_id, :essence_type]
17
+
18
+ scope :essence_pictures, where(:essence_type => "Alchemy::EssencePicture")
19
+ scope :essence_texts, where(:essence_type => "Alchemy::EssenceText")
20
+ scope :essence_richtexts, where(:essence_type => "Alchemy::EssenceRichtext")
21
+
22
+ # Creates a new Content as descriped in the elements.yml file
23
+ def self.create_from_scratch(element, essences_hash)
24
+ if essences_hash[:name].blank? && !essences_hash[:essence_type].blank?
25
+ essences_of_same_type = element.contents.where(
26
+ :essence_type => Content.normalize_essence_type(essences_hash[:essence_type])
27
+ )
28
+ description = {
29
+ 'type' => essences_hash[:essence_type],
30
+ 'name' => "#{essences_hash[:essence_type].classify.demodulize.underscore}_#{essences_of_same_type.count + 1}"
31
+ }
32
+ else
33
+ description = element.content_description_for(essences_hash[:name])
34
+ description = element.available_content_description_for(essences_hash[:name]) if description.blank?
35
+ end
36
+ raise "No description found in elements.yml for #{essences_hash.inspect} and #{element.inspect}" if description.blank?
37
+ essence_class = Content.normalize_essence_type(description['type']).constantize
38
+ content = self.new(:name => description['name'], :element_id => element.id)
39
+ if description['type'] == "EssenceRichtext" || description['type'] == "EssenceText"
40
+ essence = essence_class.create(:do_not_index => !description['do_not_index'].nil?)
41
+ else
42
+ essence = essence_class.create
43
+ end
44
+ if essence
45
+ content.essence = essence
46
+ content.save!
47
+ else
48
+ content = nil
49
+ end
50
+ return content
51
+ end
52
+
53
+ # Settings from the elements.yml definition
54
+ def settings
55
+ return {} if description.blank?
56
+ settings = description['settings']
57
+ return {} if settings.blank?
58
+ settings.symbolize_keys
59
+ end
60
+
61
+ def siblings
62
+ return [] if !element
63
+ self.element.contents
64
+ end
65
+
66
+ # Makes a copy of source and also copies the associated essence.
67
+ #
68
+ # You can pass a differences hash to update the attributes of the copy.
69
+ #
70
+ # === Example
71
+ #
72
+ # @copy = Alchemy::Content.copy(@content, {:element_id => 3})
73
+ # @copy.element_id # => 3
74
+ #
75
+ def self.copy(source, differences = {})
76
+ differences[:position] = nil
77
+ differences[:id] = nil
78
+ attributes = source.attributes.except("id").merge(differences)
79
+ content = self.create!(attributes)
80
+ new_essence = content.essence.class.new(content.essence.attributes.except('id'))
81
+ new_essence.save!
82
+ raise "Essence not cloned" if new_essence.id == content.essence_id
83
+ content.update_attribute(:essence_id, new_essence.id)
84
+ content
85
+ end
86
+
87
+ # Returns my description hash from elements.yml
88
+ # Returns the description from available_contents if my own description is blank
89
+ def description
90
+ if self.element.blank?
91
+ logger.warn("\n+++++++++++ Warning: Content with id #{self.id} is missing its Element\n")
92
+ return nil
93
+ else
94
+ desc = self.element.content_description_for(self.name)
95
+ if desc.blank?
96
+ desc = self.element.available_content_description_for(self.name)
97
+ else
98
+ return desc
99
+ end
100
+ end
101
+ end
102
+
103
+ # Gets the ingredient from essence
104
+ def ingredient
105
+ return nil if self.essence.nil?
106
+ self.essence.ingredient
107
+ end
108
+
109
+ # Calls essence.update_attributes. Called from +Alchemy::Element#save_contents+
110
+ # Ads errors to self.base if essence validation fails.
111
+ def update_essence(params={})
112
+ raise "Essence not found" if essence.nil?
113
+ if essence.update_attributes(params)
114
+ return true
115
+ else
116
+ errors.add(:essence, :validation_failed)
117
+ return false
118
+ end
119
+ end
120
+
121
+ def essence_validation_failed?
122
+ essence.errors.any?
123
+ end
124
+
125
+ def has_validations?
126
+ return false if description.blank?
127
+ !description['validate'].blank?
128
+ end
129
+
130
+ # Returns a string to be passed to Rails form field tags to ensure we have same params layout everywhere.
131
+ #
132
+ # === Example:
133
+ #
134
+ # <%= text_field_tag content.form_field_name, content.ingredient %>
135
+ #
136
+ # === Options:
137
+ #
138
+ # You can pass an Essence column_name. Default is self.essence.ingredient_column
139
+ #
140
+ # ==== Example:
141
+ #
142
+ # <%= text_field_tag content.form_field_name(:link), content.ingredient %>
143
+ #
144
+ def form_field_name(essence_column = self.essence.ingredient_column)
145
+ "contents[content_#{self.id}][#{essence_column}]"
146
+ end
147
+
148
+ def form_field_id(essence_column = self.essence.ingredient_column)
149
+ "contents_content_#{self.id}_#{essence_column}"
150
+ end
151
+
152
+ # Returns the translated name for displaying in labels, etc.
153
+ def name_for_label
154
+ self.class.translated_label_for(self.name, self.element.name)
155
+ end
156
+
157
+ # Returns the translated label for a content name.
158
+ #
159
+ # Translate it in your locale yml file:
160
+ #
161
+ # alchemy:
162
+ # content_names:
163
+ # foo: Bar
164
+ #
165
+ # Optionally you can scope your content name to an element:
166
+ #
167
+ # alchemy:
168
+ # content_names:
169
+ # article:
170
+ # foo: Baz
171
+ #
172
+ def self.translated_label_for(content_name, element_name = nil)
173
+ Alchemy::I18n.t("content_names.#{element_name}.#{content_name}", :default => ["content_names.#{content_name}".to_sym, content_name.capitalize])
174
+ end
175
+
176
+ def linked?
177
+ essence && !essence.link.blank?
178
+ end
179
+
180
+ def essence_partial_name
181
+ essence.partial_name
182
+ end
183
+
184
+ def normalized_essence_type
185
+ self.class.normalize_essence_type(self.essence_type)
186
+ end
187
+
188
+ def self.normalize_essence_type(essence_type)
189
+ essence_type = essence_type.classify
190
+ if not essence_type.match(/^Alchemy::/)
191
+ essence_type.gsub!(/^Essence/, 'Alchemy::Essence')
192
+ else
193
+ essence_type
194
+ end
195
+ end
196
+
197
+ end
198
198
  end