alchemy_cms 2.6.3 → 2.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (246) hide show
  1. checksums.yaml +4 -4
  2. data/.simplecov +14 -0
  3. data/.travis.yml +1 -1
  4. data/Gemfile +7 -6
  5. data/README.md +15 -5
  6. data/alchemy_cms.gemspec +3 -2
  7. data/app/assets/javascripts/alchemy/alchemy.base.js.coffee +9 -17
  8. data/app/assets/javascripts/alchemy/alchemy.dirty.js.coffee +70 -0
  9. data/app/assets/javascripts/alchemy/alchemy.dragndrop.js.coffee +80 -0
  10. data/app/assets/javascripts/alchemy/alchemy.element_editors.js.coffee +43 -19
  11. data/app/assets/javascripts/alchemy/alchemy.gui.js.coffee +3 -1
  12. data/app/assets/javascripts/alchemy/alchemy.js +4 -2
  13. data/app/assets/javascripts/alchemy/alchemy.onload.js.coffee +1 -1
  14. data/app/assets/javascripts/alchemy/alchemy.spinner.js.coffee +14 -0
  15. data/app/assets/javascripts/alchemy/alchemy.tinymce.js.coffee.erb +96 -0
  16. data/app/assets/javascripts/alchemy/alchemy.translations.js.coffee +22 -0
  17. data/app/assets/javascripts/alchemy/alchemy.windows.js.coffee +28 -17
  18. data/app/assets/stylesheets/alchemy/base.scss +6 -0
  19. data/app/assets/stylesheets/alchemy/elements.scss +2 -28
  20. data/app/assets/stylesheets/alchemy/errors.scss +1 -1
  21. data/app/assets/stylesheets/alchemy/menubar.css.scss +2 -0
  22. data/app/assets/stylesheets/alchemy/sitemap.scss +21 -34
  23. data/app/assets/stylesheets/alchemy/tables.scss +13 -3
  24. data/app/controllers/alchemy/admin/attachments_controller.rb +10 -5
  25. data/app/controllers/alchemy/admin/base_controller.rb +19 -0
  26. data/app/controllers/alchemy/admin/contents_controller.rb +1 -4
  27. data/app/controllers/alchemy/admin/dashboard_controller.rb +2 -1
  28. data/app/controllers/alchemy/admin/elements_controller.rb +1 -1
  29. data/app/controllers/alchemy/admin/essence_files_controller.rb +1 -1
  30. data/app/controllers/alchemy/admin/essence_pictures_controller.rb +70 -56
  31. data/app/controllers/alchemy/admin/pages_controller.rb +37 -114
  32. data/app/controllers/alchemy/admin/pictures_controller.rb +5 -12
  33. data/app/controllers/alchemy/admin/resources_controller.rb +3 -1
  34. data/app/controllers/alchemy/admin/trash_controller.rb +1 -1
  35. data/app/controllers/alchemy/attachments_controller.rb +1 -1
  36. data/app/controllers/alchemy/base_controller.rb +3 -15
  37. data/app/controllers/alchemy/messages_controller.rb +4 -10
  38. data/app/controllers/alchemy/pages_controller.rb +6 -6
  39. data/app/controllers/alchemy/passwords_controller.rb +1 -1
  40. data/app/controllers/alchemy/user_sessions_controller.rb +1 -1
  41. data/app/helpers/alchemy/admin/base_helper.rb +49 -230
  42. data/app/helpers/alchemy/admin/contents_helper.rb +5 -1
  43. data/app/helpers/alchemy/admin/elements_helper.rb +19 -47
  44. data/app/helpers/alchemy/admin/essences_helper.rb +59 -17
  45. data/app/helpers/alchemy/admin/navigation_helper.rb +204 -0
  46. data/app/helpers/alchemy/admin/pages_helper.rb +22 -79
  47. data/app/helpers/alchemy/admin/pictures_helper.rb +1 -1
  48. data/app/helpers/alchemy/admin/tags_helper.rb +42 -0
  49. data/app/helpers/alchemy/base_helper.rb +0 -11
  50. data/app/helpers/alchemy/elements_helper.rb +48 -25
  51. data/app/helpers/alchemy/essences_helper.rb +0 -20
  52. data/app/helpers/alchemy/pages_helper.rb +18 -14
  53. data/app/helpers/alchemy/url_helper.rb +1 -0
  54. data/app/mailers/alchemy/messages.rb +4 -6
  55. data/app/models/alchemy/attachment.rb +3 -0
  56. data/app/models/alchemy/cell.rb +33 -35
  57. data/app/models/alchemy/content.rb +20 -111
  58. data/app/models/alchemy/content/factory.rb +188 -0
  59. data/app/models/alchemy/element.rb +51 -200
  60. data/app/models/alchemy/element/definitions.rb +52 -0
  61. data/app/models/alchemy/element/presenters.rb +87 -0
  62. data/app/models/alchemy/essence_date.rb +1 -1
  63. data/app/models/alchemy/essence_file.rb +6 -7
  64. data/app/models/alchemy/essence_picture.rb +19 -4
  65. data/app/models/alchemy/message.rb +18 -14
  66. data/app/models/alchemy/page.rb +120 -214
  67. data/app/models/alchemy/page/elements.rb +145 -36
  68. data/app/models/alchemy/page/natures.rb +90 -0
  69. data/app/models/alchemy/page/scopes.rb +93 -0
  70. data/app/models/alchemy/page/users.rb +25 -0
  71. data/app/models/alchemy/picture.rb +15 -0
  72. data/app/models/alchemy/site.rb +15 -1
  73. data/app/models/alchemy/site/layout.rb +38 -0
  74. data/app/models/alchemy/user.rb +13 -3
  75. data/app/views/alchemy/admin/attachments/_archive_overlay.html.erb +7 -7
  76. data/app/views/alchemy/admin/attachments/_file_to_assign.html.erb +8 -8
  77. data/app/views/alchemy/admin/attachments/_tag_list.html.erb +1 -16
  78. data/app/views/alchemy/admin/attachments/destroy.js.erb +1 -4
  79. data/app/views/alchemy/admin/contents/create.js.erb +1 -1
  80. data/app/views/alchemy/admin/dashboard/index.html.erb +14 -13
  81. data/app/views/alchemy/admin/elements/_element_head.html.erb +7 -7
  82. data/app/views/alchemy/admin/elements/_refresh_editor.js.erb +10 -0
  83. data/app/views/alchemy/admin/elements/create.js.erb +44 -44
  84. data/app/views/alchemy/admin/elements/fold.js.erb +22 -26
  85. data/app/views/alchemy/admin/elements/trash.js.erb +1 -1
  86. data/app/views/alchemy/admin/elements/update.js.erb +22 -25
  87. data/app/views/alchemy/admin/essence_files/assign.js.erb +8 -3
  88. data/app/views/alchemy/admin/essence_pictures/crop.html.erb +14 -12
  89. data/app/views/alchemy/admin/essence_pictures/edit.html.erb +22 -39
  90. data/app/views/alchemy/admin/pages/_page.html.erb +73 -80
  91. data/app/views/alchemy/admin/pages/destroy.js.erb +2 -2
  92. data/app/views/alchemy/admin/pages/edit.html.erb +21 -18
  93. data/app/views/alchemy/admin/pages/fold.js.erb +1 -0
  94. data/app/views/alchemy/admin/pages/info.html.erb +32 -0
  95. data/app/views/alchemy/admin/partials/_main_navigation_entry.html.erb +11 -13
  96. data/app/views/alchemy/admin/partials/_remote_search_form.html.erb +20 -20
  97. data/app/views/alchemy/admin/partials/_sub_navigation.html.erb +8 -0
  98. data/app/views/alchemy/admin/partials/_toolbar_button.html.erb +25 -0
  99. data/app/views/alchemy/admin/partials/_upload_form.html.erb +15 -15
  100. data/app/views/alchemy/admin/pictures/_filter_and_size_bar.html.erb +39 -39
  101. data/app/views/alchemy/admin/pictures/_picture_to_assign.html.erb +10 -10
  102. data/app/views/alchemy/admin/pictures/_tag_list.html.erb +1 -16
  103. data/app/views/alchemy/admin/resources/destroy.js.erb +1 -1
  104. data/app/views/alchemy/base/500.html.erb +1 -1
  105. data/app/views/alchemy/base/permission_denied.js.erb +1 -1
  106. data/app/views/alchemy/base/redirect.js.erb +1 -1
  107. data/app/views/alchemy/essences/_essence_link_editor.html.erb +1 -1
  108. data/app/views/alchemy/essences/_essence_picture_editor.html.erb +1 -1
  109. data/app/views/alchemy/essences/_essence_richtext_editor.html.erb +1 -1
  110. data/app/views/alchemy/essences/_essence_text_editor.html.erb +1 -1
  111. data/app/views/alchemy/essences/{_essence_picture_tools.html.erb → shared/_essence_picture_tools.html.erb} +5 -5
  112. data/app/views/alchemy/essences/{_linkable_essence_tools.html.erb → shared/_linkable_essence_tools.html.erb} +0 -0
  113. data/app/views/alchemy/messages/contact_form_mail.de.text.erb +12 -0
  114. data/app/views/alchemy/messages/contact_form_mail.en.text.erb +12 -0
  115. data/app/views/alchemy/notifications/reset_password_instructions.de.text.erb +1 -1
  116. data/app/views/alchemy/notifications/reset_password_instructions.en.text.erb +2 -2
  117. data/app/views/alchemy/pages/sitemap.xml.erb +3 -5
  118. data/app/views/alchemy/user_sessions/leave.html.erb +1 -1
  119. data/app/views/layouts/alchemy/admin.html.erb +4 -2
  120. data/app/views/layouts/alchemy/sitemap.xml.erb +1 -1
  121. data/bin/alchemy +7 -13
  122. data/config/alchemy/config.yml +1 -0
  123. data/config/authorization_rules.rb +2 -3
  124. data/config/initializers/dragonfly.rb +2 -0
  125. data/config/locales/alchemy.de.yml +8 -9
  126. data/config/locales/alchemy.en.yml +7 -4
  127. data/config/routes.rb +3 -0
  128. data/db/migrate/{20130214233001_alchemy_two_point_five.rb → 20130827094554_alchemy_two_point_six.rb} +29 -6
  129. data/lib/alchemy/auth/engine.rb +9 -0
  130. data/lib/alchemy/capistrano.rb +37 -12
  131. data/lib/alchemy/config.rb +48 -35
  132. data/lib/alchemy/engine.rb +35 -6
  133. data/lib/alchemy/essence.rb +25 -29
  134. data/lib/alchemy/ferret/search.rb +86 -0
  135. data/lib/alchemy/{scoped_pagination_url_helper.rb → kaminari/scoped_pagination_url_helper.rb} +0 -0
  136. data/lib/alchemy/logger.rb +3 -4
  137. data/lib/alchemy/page_layout.rb +124 -55
  138. data/lib/alchemy/resource.rb +0 -10
  139. data/lib/alchemy/resources_helper.rb +0 -5
  140. data/lib/alchemy/seeder.rb +1 -32
  141. data/lib/alchemy/shell.rb +6 -1
  142. data/lib/alchemy/tinymce.rb +41 -32
  143. data/lib/alchemy/upgrader.rb +3 -1
  144. data/lib/alchemy/upgrader/two_point_five.rb +15 -8
  145. data/lib/alchemy/upgrader/two_point_one.rb +10 -10
  146. data/lib/alchemy/upgrader/two_point_two.rb +96 -51
  147. data/lib/alchemy/version.rb +1 -1
  148. data/lib/alchemy_cms.rb +5 -46
  149. data/lib/rails/generators/alchemy/deploy_script/templates/deploy.rb.tt +1 -1
  150. data/lib/rails/generators/alchemy/devise/devise_generator.rb +9 -4
  151. data/lib/rails/generators/alchemy/essence/essence_generator.rb +7 -6
  152. data/lib/rails/generators/alchemy/essence/templates/editor.html.erb +1 -1
  153. data/lib/rails/generators/alchemy/scaffold/files/_standard.html.erb +1 -0
  154. data/lib/rails/generators/alchemy/scaffold/scaffold_generator.rb +1 -0
  155. data/lib/rails/generators/alchemy/site_layouts/site_layouts_generator.rb +23 -0
  156. data/lib/rails/generators/alchemy/site_layouts/templates/layout.html.erb +1 -0
  157. data/lib/rails/generators/alchemy/site_layouts/templates/layout.html.haml +1 -0
  158. data/lib/rails/generators/alchemy/site_layouts/templates/layout.html.slim +1 -0
  159. data/lib/rails/templates/alchemy.rb +2 -2
  160. data/lib/tasks/alchemy/db.rake +3 -1
  161. data/lib/tasks/alchemy/tidy.rake +82 -0
  162. data/lib/tasks/alchemy/upgrade.rake +2 -1
  163. data/spec/controllers/admin/attachments_controller_spec.rb +124 -0
  164. data/spec/controllers/admin/base_controller_spec.rb +35 -0
  165. data/spec/controllers/admin/clipboard_controller_spec.rb +1 -1
  166. data/spec/controllers/admin/contents_controller_spec.rb +17 -26
  167. data/spec/controllers/admin/dashboard_controller_spec.rb +121 -0
  168. data/spec/controllers/admin/elements_controller_spec.rb +1 -1
  169. data/spec/controllers/admin/essence_files_controller_spec.rb +67 -0
  170. data/spec/controllers/admin/essence_pictures_controller_spec.rb +161 -0
  171. data/spec/controllers/admin/languages_controller_spec.rb +1 -1
  172. data/spec/controllers/admin/layoutpages_controller_spec.rb +28 -0
  173. data/spec/controllers/admin/pages_controller_spec.rb +164 -118
  174. data/spec/controllers/admin/pictures_controller_spec.rb +89 -0
  175. data/spec/controllers/admin/trash_controller_spec.rb +21 -31
  176. data/spec/controllers/admin/users_controller_spec.rb +114 -85
  177. data/spec/controllers/attachments_controller_spec.rb +6 -2
  178. data/spec/controllers/base_controller_spec.rb +22 -0
  179. data/spec/controllers/elements_controller_spec.rb +1 -1
  180. data/spec/controllers/messages_controller_spec.rb +200 -0
  181. data/spec/controllers/pictures_controller_spec.rb +1 -1
  182. data/spec/controllers/user_sessions_controller_spec.rb +7 -6
  183. data/spec/controllers/users_controller_spec.rb +2 -2
  184. data/spec/dummy/config/alchemy/cells.yml +2 -0
  185. data/spec/dummy/config/application.rb +19 -8
  186. data/spec/dummy/db/migrate/{20130214233001_alchemy_two_point_five.rb → 20130827094554_alchemy_two_point_six.rb} +29 -6
  187. data/spec/dummy/db/schema.rb +1 -1
  188. data/spec/fast_specs.rb +15 -0
  189. data/spec/helpers/admin/base_helper_spec.rb +53 -34
  190. data/spec/helpers/admin/contents_helper_spec.rb +15 -7
  191. data/spec/helpers/admin/elements_helper_spec.rb +79 -34
  192. data/spec/helpers/admin/essences_helper_spec.rb +45 -31
  193. data/spec/helpers/admin/navigation_helper_spec.rb +204 -0
  194. data/spec/helpers/admin/pages_helper_spec.rb +25 -15
  195. data/spec/helpers/admin/tags_helper_spec.rb +62 -2
  196. data/spec/helpers/elements_helper_spec.rb +202 -138
  197. data/spec/helpers/pages_helper_spec.rb +48 -0
  198. data/spec/helpers/url_helper_spec.rb +7 -0
  199. data/spec/libraries/config_spec.rb +110 -3
  200. data/spec/libraries/essence_spec.rb +29 -9
  201. data/spec/libraries/page_layout_spec.rb +134 -0
  202. data/spec/libraries/resource_spec.rb +3 -16
  203. data/spec/libraries/resources_helper_spec.rb +4 -8
  204. data/spec/libraries/shell_spec.rb +1 -0
  205. data/spec/libraries/tinymce_spec.rb +61 -0
  206. data/spec/mailers/messages_spec.rb +23 -0
  207. data/spec/models/attachment_spec.rb +45 -0
  208. data/spec/models/cell_spec.rb +62 -9
  209. data/spec/models/content_spec.rb +110 -28
  210. data/spec/models/element_spec.rb +275 -253
  211. data/spec/models/essence_date_spec.rb +25 -0
  212. data/spec/models/essence_file_spec.rb +23 -0
  213. data/spec/models/essence_html_spec.rb +13 -0
  214. data/spec/models/essence_picture_spec.rb +16 -0
  215. data/spec/models/essence_text_spec.rb +29 -0
  216. data/spec/models/language_spec.rb +34 -0
  217. data/spec/models/message_spec.rb +43 -0
  218. data/spec/models/page_spec.rb +726 -567
  219. data/spec/models/picture_spec.rb +98 -0
  220. data/spec/models/site_spec.rb +60 -2
  221. data/spec/models/tag_spec.rb +31 -0
  222. data/spec/models/user_spec.rb +4 -4
  223. data/spec/spec_helper.rb +49 -58
  224. data/spec/support/alchemy/controller_helpers.rb +35 -0
  225. data/spec/support/alchemy/{specs_helpers.rb → integration_helpers.rb} +4 -8
  226. data/spec/{factories.rb → support/factories.rb} +11 -1
  227. data/vendor/assets/javascripts/jquery_plugins/jquery.ui.nestedSortable.js +2 -8
  228. metadata +166 -106
  229. data/Guardfile +0 -16
  230. data/app/assets/javascripts/alchemy/alchemy.dirty.js +0 -93
  231. data/app/assets/javascripts/alchemy/alchemy.dragndrop.js +0 -122
  232. data/app/models/alchemy/tree_node.rb +0 -4
  233. data/app/views/alchemy/admin/pages/_page_infos.html.erb +0 -3
  234. data/app/views/alchemy/admin/partials/_sub_navigation_tab.html.erb +0 -8
  235. data/app/views/alchemy/messages/contact_form_mail.text.erb +0 -12
  236. data/config/initializers/kaminari_config.rb +0 -9
  237. data/db/migrate/20130221200514_migrate_attachments_to_dragonfly.rb +0 -21
  238. data/db/migrate/20130312205327_change_alchemy_users_role_to_roles.rb +0 -11
  239. data/lib/alchemy/auth_engine.rb +0 -7
  240. data/lib/alchemy/authentication_helpers.rb +0 -9
  241. data/lib/alchemy/ferret_search.rb +0 -84
  242. data/lib/extensions/array.rb +0 -25
  243. data/lib/extensions/hash.rb +0 -34
  244. data/spec/dummy/db/migrate/20130221200514_migrate_attachments_to_dragonfly.rb +0 -21
  245. data/spec/dummy/db/migrate/20130312205327_change_alchemy_users_role_to_roles.rb +0 -11
  246. data/spec/models/page_layout_spec.rb +0 -60
@@ -0,0 +1,9 @@
1
+ module Alchemy
2
+ module Auth
3
+ module Engine
4
+ def self.get_instance
5
+ ::Authorization::Engine.instance
6
+ end
7
+ end
8
+ end
9
+ end
@@ -83,9 +83,10 @@ EOF
83
83
  run "cd #{current_path} && #{rake} RAILS_ENV=#{fetch(:rails_env, 'production')} alchemy:db:seed"
84
84
  end
85
85
 
86
- desc "Dumps the database into 'db/dumps'"
86
+ desc "Dumps the database into 'db/dumps' on the server."
87
87
  task :dump, :roles => :db do
88
- run "cd #{current_path} && #{rake} RAILS_ENV=#{fetch(:rails_env, 'production')} alchemy:db:dump"
88
+ timestamp = Time.now.strftime('%Y-%m-%d-%H-%M')
89
+ run "cd #{current_path} && mkdir -p db/dumps && #{rake} RAILS_ENV=#{fetch(:rails_env, 'production')} DUMP_FILENAME=db/dumps/#{timestamp}.sql alchemy:db:dump"
89
90
  end
90
91
 
91
92
  end
@@ -101,17 +102,14 @@ EOF
101
102
 
102
103
  desc "Imports the database into your local development machine."
103
104
  task :database, :roles => [:db], :only => {:primary => true} do
105
+ require 'spinner'
104
106
  server = find_servers_for_task(current_task).first
105
- dump_cmd = "cd #{current_path} && #{rake} RAILS_ENV=#{fetch(:rails_env, 'production')} alchemy:db:dump"
106
- sql_stream = "ssh -p #{fetch(:port, 22)} #{user}@#{server} '#{dump_cmd}'"
107
- mysql_credentials = ["--user='#{database_config['username']}'"]
108
- if database_config['password']
109
- mysql_credentials << "--password='#{database_config['password']}'"
110
- end
111
- if host = database_config['host'] && host != 'localhost'
112
- mysql_credentials << "--host='#{host}'"
107
+ spinner = Spinner.new
108
+ print "\n"
109
+ spinner.task("Importing the database. Please wait...") do
110
+ system db_import_cmd(server)
113
111
  end
114
- system "#{sql_stream} | mysql #{mysql_credentials.join(' ')} #{database_config['database']}"
112
+ spinner.spin!
115
113
  end
116
114
 
117
115
  desc "Imports attachments into your local machine using rsync."
@@ -136,7 +134,34 @@ EOF
136
134
 
137
135
  def database_config
138
136
  raise "database.yml not found!" if !File.exists?("./config/database.yml")
139
- YAML.load_file("./config/database.yml").fetch(ENV['RAILS_ENV'] || 'development')
137
+ @database_config ||= begin
138
+ config_file = YAML.load_file("./config/database.yml")
139
+ if config = config_file.fetch(ENV['RAILS_ENV'] || 'development')
140
+ config
141
+ else
142
+ raise "Database configuration for #{ENV['RAILS_ENV'] || 'development'} not found!"
143
+ end
144
+ end
145
+ end
146
+
147
+ def db_import_cmd(server)
148
+ dump_cmd = "cd #{current_path} && #{rake} RAILS_ENV=#{fetch(:rails_env, 'production')} alchemy:db:dump"
149
+ sql_stream = "ssh -p #{fetch(:port, 22)} #{user}@#{server} '#{dump_cmd}'"
150
+ "#{sql_stream} | mysql #{mysql_credentials} #{database_config['database']}"
151
+ end
152
+
153
+ def mysql_credentials
154
+ mysql_credentials = []
155
+ if database_config['username']
156
+ mysql_credentials << "--user='#{database_config['username']}'"
157
+ end
158
+ if database_config['password']
159
+ mysql_credentials << "--password='#{database_config['password']}'"
160
+ end
161
+ if (host = database_config['host']) && (host != 'localhost')
162
+ mysql_credentials << "--host='#{host}'"
163
+ end
164
+ mysql_credentials.join(' ')
140
165
  end
141
166
 
142
167
  end
@@ -1,51 +1,64 @@
1
+ # encoding: utf-8
2
+
1
3
  module Alchemy
2
4
  class Config
3
5
 
4
6
  class << self
5
7
 
6
- # Returns the configuration for given parameter name from +config/alchemy/config.yml+ file.
8
+ # Returns the configuration for given parameter name.
9
+ #
10
+ # @param name [String]
11
+ #
7
12
  def get(name)
8
13
  show[name.to_s]
9
14
  end
10
-
11
15
  alias_method :parameter, :get
12
16
 
13
- # Returns the complete configuration from +config/alchemy/config.yml+ file.
17
+ # Returns a merged configuration of the following files
18
+ #
19
+ # Alchemy´s default config: +gems/../alchemy_cms/config/alchemy/config.yml+
20
+ # Your apps default config: +your_app/config/alchemy/config.yml+
21
+ # Environment specific config: +your_app/config/alchemy/development.config.yml+
22
+ #
23
+ # An environment specific config overwrites the settings of your apps default config,
24
+ # while your apps default config has precedence over Alchemy´s default config.
25
+ #
14
26
  def show
15
- @@config ||= read_files
27
+ @config ||= merge_configs!(alchemy_config, main_app_config, env_specific_config)
28
+ end
29
+
30
+ private
31
+
32
+ # Alchemy default configuration
33
+ def alchemy_config
34
+ read_file(File.join(File.dirname(__FILE__), '..', '..', 'config/alchemy/config.yml'))
35
+ end
36
+
37
+ # Application specific configuration
38
+ def main_app_config
39
+ read_file("#{Rails.root}/config/alchemy/config.yml")
40
+ end
41
+
42
+ # Rails Environment specific configuration
43
+ def env_specific_config
44
+ read_file("#{Rails.root}/config/alchemy/#{Rails.env}.config.yml")
45
+ end
46
+
47
+ # Tries to load yaml file from given path.
48
+ # If it does not exist, or its empty, it returns an empty Hash.
49
+ #
50
+ def read_file(file)
51
+ return YAML.load_file(file) || {} if File.exists?(file) # YAML.load_file returns false if file is empty.
52
+ {}
16
53
  end
17
54
 
18
- private
19
-
20
- def read_files
21
- # Looking for any Rails Environment specific configuration
22
- if File.exists? "#{Rails.root.to_s}/config/alchemy/config_#{Rails.env}.yml"
23
- config_1 = YAML.load_file("#{Rails.root.to_s}/config/alchemy/config_#{Rails.env}.yml")
24
- else
25
- config_1 = {}
26
- end
27
-
28
- # Looking for Application specific configuration
29
- if File.exists? "#{Rails.root.to_s}/config/alchemy/config.yml"
30
- config_2 = YAML.load_file("#{Rails.root.to_s}/config/alchemy/config.yml")
31
- else
32
- config_2 = {}
33
- end
34
-
35
- # Reading Alchemy standard configuration
36
- if File.exists? File.join(File.dirname(__FILE__), '..', '..', 'config/alchemy/config.yml')
37
- config_3 = YAML.load_file(File.join(File.dirname(__FILE__), '..', '..', 'config/alchemy/config.yml'))
38
- else
39
- config_3 = {}
40
- end
41
-
42
- # Mergin all together
43
- if config_1.blank? && config_3.blank? && config_3.blank?
44
- raise LoadError, 'No Alchemy config file found!'
45
- else
46
- [config_1, config_2, config_3].map(&:stringify_keys!)
47
- return config_3.merge(config_2.merge(config_1))
48
- end
55
+ # Merges all given configs together
56
+ #
57
+ def merge_configs!(*config_files)
58
+ raise LoadError, 'No Alchemy config file found!' if config_files.map(&:blank?).all?
59
+ config = {}
60
+ config_files.each {|h| config.merge!(h.stringify_keys!) }
61
+ config
49
62
  end
50
63
 
51
64
  end
@@ -1,5 +1,38 @@
1
+ # Require globally used external libraries
2
+ require 'coffee-rails'
3
+ require 'compass-rails'
4
+ require 'declarative_authorization'
5
+ require 'devise'
6
+ require 'dynamic_form'
7
+ require 'jquery-rails'
8
+ require 'jquery-ui-rails'
9
+ require 'kaminari'
10
+ require 'rails3-jquery-autocomplete'
11
+ require 'sass-rails'
12
+ require 'sassy-buttons'
13
+
14
+ # Require globally used Alchemy mixins
15
+ require 'alchemy/auth/engine'
16
+ require 'alchemy/config'
17
+ require 'alchemy/errors'
18
+ require 'alchemy/essence'
19
+ require 'alchemy/ferret/search'
20
+ require 'alchemy/filetypes'
21
+ require 'alchemy/i18n'
22
+ require 'alchemy/logger'
23
+ require 'alchemy/modules'
24
+ require 'alchemy/mount_point'
25
+ require 'alchemy/name_conversions'
26
+ require 'alchemy/page_layout'
27
+ require 'alchemy/picture_attributes'
28
+ require 'alchemy/tinymce'
29
+
30
+ # Require hacks
31
+ require 'alchemy/kaminari/scoped_pagination_url_helper'
32
+ require File.join(File.dirname(__FILE__), '../extensions/action_view')
33
+
34
+ # Require middleware
1
35
  require File.join(File.dirname(__FILE__), '../middleware/flash_session_cookie')
2
- require File.join(File.dirname(__FILE__), 'authentication_helpers')
3
36
 
4
37
  module Alchemy
5
38
  class Engine < Rails::Engine
@@ -37,11 +70,7 @@ module Alchemy
37
70
  end
38
71
 
39
72
  initializer "alchemy.add_authorization_rules" do
40
- Alchemy::AuthEngine.get_instance.load(File.join(File.dirname(__FILE__), '../..', 'config/authorization_rules.rb'))
41
- end
42
-
43
- config.after_initialize do
44
- #ApplicationController.send :include, Alchemy::AuthenticationHelpers
73
+ Alchemy::Auth::Engine.get_instance.load(File.join(File.dirname(__FILE__), '../..', 'config/authorization_rules.rb'))
45
74
  end
46
75
 
47
76
  end
@@ -7,23 +7,26 @@ module Alchemy #:nodoc:
7
7
  end
8
8
 
9
9
  # Delivers various methods we need for Essences in Alchemy.
10
+ #
10
11
  # To turn a model into an essence call acts_as_essence inside your model and you will get:
11
12
  # * validations
12
13
  # * several getters (ie: page, element, content, ingredient, preview_text)
14
+ #
13
15
  module ClassMethods
14
16
 
15
- # Configuration options are:
17
+ # Turn any active record model into an essence by calling this class method
18
+ #
19
+ # @option options [String || Symbol] ingredient_column ('body')
20
+ # specifies the column name you use for storing the content in the database (default: +body+)
21
+ # @option options [String || Symbol] validate_column (ingredient_column)
22
+ # The column the the validations run against.
23
+ # @option options [String || Symbol] preview_text_column (ingredient_column)
24
+ # Specify the column for the preview_text method.
16
25
  #
17
- # * +ingredient_column+ - specifies the column name you use for storing the content in the database (default: +body+)
18
- # * +validate_column+ - which column should be validated. (default: ingredient_column)
19
- # * +preview_text_column+ - specifies the column for the preview_text method. (default: ingredient_column)
20
- # * +preview_text_method+ - a method called on ingredient to get the preview text. (default: ingredient_column)
21
26
  def acts_as_essence(options={})
22
- configuration = {}
23
- configuration.update(options) if options.is_a?(Hash)
24
- ingredient_column = configuration[:ingredient_column].blank? ? 'body' : configuration[:ingredient_column]
25
- preview_text_column = configuration[:preview_text_column].blank? ? ingredient_column : configuration[:preview_text_column]
26
- validate_column = configuration[:validate_column].blank? ? ingredient_column : configuration[:validate_column]
27
+ configuration = {
28
+ ingredient_column: 'body'
29
+ }.update(options)
27
30
 
28
31
  class_eval <<-EOV
29
32
  attr_accessor :validation_errors
@@ -39,22 +42,17 @@ module Alchemy #:nodoc:
39
42
  #{self.name}
40
43
  end
41
44
 
42
- def validation_column
43
- '#{validate_column}'
44
- end
45
-
46
45
  def ingredient_column
47
- '#{ingredient_column}'
46
+ '#{configuration[:ingredient_column]}'
48
47
  end
49
48
 
50
- def preview_text_column
51
- '#{preview_text_column}'
49
+ def validation_column
50
+ '#{configuration[:validate_column] || configuration[:ingredient_column]}'
52
51
  end
53
52
 
54
- def preview_text_method
55
- '#{configuration[:preview_text_method]}'
53
+ def preview_text_column
54
+ '#{configuration[:preview_text_column] || configuration[:ingredient_column]}'
56
55
  end
57
-
58
56
  EOV
59
57
  end
60
58
 
@@ -65,10 +63,12 @@ module Alchemy #:nodoc:
65
63
  # Essence Validations:
66
64
  #
67
65
  # Essence validations can be set inside the config/elements.yml file.
66
+ #
68
67
  # Currently supported validations are:
69
- # * presence
70
- # * format
71
- # * uniqueness
68
+ #
69
+ # * presence
70
+ # * format
71
+ # * uniqueness
72
72
  #
73
73
  # If you want to validate the format you must additionally pass validate_format_as or validate_format_with:
74
74
  #
@@ -171,13 +171,9 @@ module Alchemy #:nodoc:
171
171
  end
172
172
 
173
173
  # Returns the first x (default 30) characters of ingredient for the Element#preview_text method.
174
+ #
174
175
  def preview_text(maxlength = 30)
175
- if preview_text_method.blank?
176
- self.send(preview_text_column).to_s[0..maxlength]
177
- else
178
- return "" if ingredient.blank?
179
- ingredient.send(preview_text_method).to_s[0..maxlength]
180
- end
176
+ self.send(preview_text_column).to_s[0..maxlength-1]
181
177
  end
182
178
 
183
179
  def open_link_in_new_window?
@@ -0,0 +1,86 @@
1
+ module Alchemy
2
+ # Provides full text search methods in your controller
3
+ #
4
+ # === Usage
5
+ #
6
+ # include Alchemy::Ferret::Search
7
+ #
8
+ module Ferret
9
+ module Search
10
+
11
+ # Adds a +before_filter+ to your controller
12
+ #
13
+ def self.included(controller)
14
+ controller.send(:before_filter, :perform_search, :only => :show)
15
+ controller.send(:helper_method, :find_search_result_page)
16
+ end
17
+
18
+ # Performs a full text search with +Ferret+.
19
+ #
20
+ # Gets invoked everytime 'query' is given in params.
21
+ #
22
+ # This method only sets the +@search_results+ instance variable.
23
+ #
24
+ # You have to redirect to the search result page within a search form.
25
+ #
26
+ # === Alchemy provides a handy helper for rendering the search form:
27
+ #
28
+ # render_search_form
29
+ #
30
+ # === Note
31
+ #
32
+ # If in preview mode a fake search value "lorem" will be set.
33
+ #
34
+ # @see Alchemy::PagesHelper#render_search_form
35
+ #
36
+ def perform_search
37
+ if @preview_mode && params[:query].blank?
38
+ params[:query] = 'lorem'
39
+ end
40
+ return if params[:query].blank?
41
+ @search_results = get_search_results
42
+ end
43
+
44
+ # Finds what is provided in "query" param with Ferret on EssenceText and EssenceRichtext
45
+ #
46
+ # @return [Array]
47
+ #
48
+ def get_search_results
49
+ search_results = []
50
+ %w(Alchemy::EssenceText Alchemy::EssenceRichtext).each do |e|
51
+ search_results += e.constantize.includes(:contents => {:element => :page}).find_with_ferret(
52
+ "*#{params[:query]}*",
53
+ {:limit => :all},
54
+ {:conditions => [
55
+ 'alchemy_pages.public = ? AND alchemy_pages.layoutpage = ? AND alchemy_pages.restricted = ? AND alchemy_pages.language_id = ?',
56
+ true, false, false, session[:language_id]
57
+ ]}
58
+ )
59
+ end
60
+ if search_results.any?
61
+ search_results.sort { |y, x| x.ferret_score <=> y.ferret_score }
62
+ end
63
+ end
64
+
65
+ # A view helper that loads the search result page.
66
+ #
67
+ # === Raises a ActiveRecord::RecordNotFound error, if the page could not be found or is not published.
68
+ #
69
+ # @return [Alchemy::Page]
70
+ #
71
+ def find_search_result_page
72
+ if searchresult_page_layout = PageLayout.get_all_by_attributes(:searchresults => true).first
73
+ search_result_page = Page.published.where(
74
+ :page_layout => searchresult_page_layout["name"],
75
+ :language_id => session[:language_id]
76
+ ).limit(1).first
77
+ end
78
+ if search_result_page.nil?
79
+ logger.warn "\n++++++\nNo published search result page found. Please create one or publish your search result page.\n++++++\n"
80
+ end
81
+ search_result_page
82
+ end
83
+
84
+ end
85
+ end
86
+ end
@@ -1,16 +1,15 @@
1
1
  module Alchemy
2
2
  module Logger
3
3
 
4
- # Logs a warning to the Rails standard logger and adds some nicer formatting
4
+ # Logs a debug message to the Rails standard logger and adds some nicer formatting
5
5
  def self.warn(message, caller_string)
6
- Rails.logger.warn %(\n++++ WARNING: #{message}\nCalled from: #{caller_string}\n)
6
+ Rails.logger.debug %(\n++++ WARNING: #{message}\nCalled from: #{caller_string}\n)
7
7
  return nil
8
8
  end
9
9
 
10
- def warn(message)
10
+ def log_warning(message)
11
11
  Alchemy::Logger.warn(message, caller.first)
12
12
  end
13
- alias_method :warning, :warn
14
13
 
15
14
  end
16
15
  end
@@ -2,40 +2,41 @@ module Alchemy
2
2
  class PageLayout
3
3
  class << self
4
4
 
5
- def element_names_for(page_layout)
6
- layout_description = get(page_layout)
7
- if layout_description.blank?
8
- puts "\n+++ Warning: No Layout Description for #{page_layout} found! in page_layouts.yml\n"
9
- return []
10
- else
11
- layout_description["elements"] || []
12
- end
13
- end
14
-
15
- # Returns all layouts defined in +config/alchemy/page_layout.yml+.
5
+ # Returns all page layouts.
6
+ #
7
+ # They are defined in +config/alchemy/page_layout.yml+ file.
8
+ #
16
9
  def all
17
- @@definitions = read_layouts_file
10
+ @definitions ||= read_layouts_file
18
11
  end
19
12
 
20
- # Add additional pagelayout definitions. I.E. from your module.
21
- # Call +Alchemy::PageLayout.add(your_layout_definition)+ in your engine.rb file.
22
- # You can pass a single layout definition as Hash, or a collection of pagelayouts as Array.
23
- # Example Pagelayout definitions can be found in the +page_layouts.yml+ from the standard set.
13
+ # Add additional page layout definitions to collection.
14
+ #
15
+ # Useful for extending the page layouts from an Alchemy module.
16
+ #
17
+ # === Usage Example
18
+ #
19
+ # Call +Alchemy::PageLayout.add(your_layout_definition)+ in your engine.rb file.
20
+ #
21
+ # @param [Array || Hash]
22
+ # You can pass a single layout definition as Hash, or a collection of page layouts as Array.
23
+ #
24
24
  def add(page_layout)
25
25
  all
26
26
  if page_layout.is_a?(Array)
27
- @@definitions += page_layout
27
+ @definitions += page_layout
28
28
  elsif page_layout.is_a?(Hash)
29
- @@definitions << page_layout
29
+ @definitions << page_layout
30
30
  else
31
31
  raise TypeError
32
32
  end
33
33
  end
34
34
 
35
- # Returns the page_layout description found by name in page_layouts.yml
35
+ # Returns one page layout description by given name.
36
+ #
36
37
  def get(name)
37
38
  return {} if name.blank?
38
- all.detect { |a| a["name"].downcase == name.downcase }
39
+ all.detect { |a| a['name'].downcase == name.downcase }
39
40
  end
40
41
 
41
42
  def get_all_by_attributes(attributes)
@@ -53,60 +54,128 @@ module Alchemy
53
54
  end
54
55
 
55
56
  # Returns page layouts ready for Rails' select form helper.
56
- def layouts_for_select(language_id, layoutpage = false)
57
- map_layouts(selectable_layouts(language_id, layoutpage), [[I18n.t('Please choose'), '']])
57
+ #
58
+ def layouts_for_select(language_id, only_layoutpages = false)
59
+ @map_array = [[I18n.t('Please choose'), '']]
60
+ mapped_layouts_for_select(selectable_layouts(language_id, only_layoutpages))
58
61
  end
59
62
 
60
- def layouts_with_own_for_select(own_layout, language_id, layoutpage)
61
- layouts = selectable_layouts(language_id, layoutpage)
62
- if layouts.detect { |l| l['name'] == own_layout } == nil
63
- map_array = [
64
- [I18n.t(own_layout, scope: 'page_layout_names', default: own_layout.to_s.humanize), own_layout]
65
- ]
63
+ # Returns page layouts including given layout ready for Rails' select form helper.
64
+ #
65
+ def layouts_with_own_for_select(page_layout_name, language_id, only_layoutpages = false)
66
+ layouts = selectable_layouts(language_id, only_layoutpages)
67
+ if layouts.detect { |l| l['name'] == page_layout_name }.nil?
68
+ @map_array = [[human_layout_name(page_layout_name), page_layout_name]]
66
69
  else
67
- map_array = []
68
- end
69
- map_layouts(layouts, map_array)
70
- end
71
-
72
- # Maps given layouts for Rails select form helper.
73
- def map_layouts(layouts, map_array = [])
74
- layouts.each do |layout|
75
- map_array << [
76
- I18n.t(layout['name'], scope: 'page_layout_names', default: layout['name'].to_s.humanize),
77
- layout["name"]
78
- ]
70
+ @map_array = []
79
71
  end
80
- map_array
72
+ mapped_layouts_for_select(layouts)
81
73
  end
82
74
 
83
- def selectable_layouts(language_id, layoutpage = false)
84
- all.select do |layout|
85
- next if layout["hide"]
86
- used = layout["unique"] && has_a_page_this_layout?(layout["name"], language_id)
87
- if layoutpage
88
- layout["layoutpage"] == true && !used
75
+ # Returns all layouts that can be used for creating a new page.
76
+ #
77
+ # It removes all layouts from available layouts that are unique and already taken and that are marked as hide.
78
+ #
79
+ # @param [Fixnum]
80
+ # language_id of current used Language.
81
+ # @param [Boolean] (false)
82
+ # Pass true to only select layouts for global/layout pages.
83
+ #
84
+ def selectable_layouts(language_id, only_layoutpages = false)
85
+ @language_id = language_id
86
+ all.select { |layout|
87
+ if only_layoutpages
88
+ layout['layoutpage'] && layout_available?(layout)
89
89
  else
90
- layout["layoutpage"] != true && !used
90
+ !layout['layoutpage'] && layout_available?(layout)
91
91
  end
92
+ }
93
+ end
94
+
95
+ # Returns all names of elements defined in given page layout.
96
+ #
97
+ def element_names_for(page_layout)
98
+ if layout_description = get(page_layout)
99
+ layout_description.fetch('elements', [])
100
+ else
101
+ Rails.logger.warn "\n+++ Warning: No Layout Description for #{page_layout} found! in page_layouts.yml\n"
102
+ return []
92
103
  end
93
104
  end
94
105
 
95
- def has_a_page_this_layout?(layout, language_id)
96
- Page.where({:page_layout => layout, :language_id => language_id}).any?
106
+ # Translates name for given layout
107
+ #
108
+ # === Translation example
109
+ #
110
+ # de:
111
+ # alchemy:
112
+ # page_layout_names:
113
+ # products_overview: Produktübersicht
114
+ #
115
+ # @param [String]
116
+ # The layout name
117
+ #
118
+ def human_layout_name(layout)
119
+ I18n.t(layout, scope: 'page_layout_names', default: layout.to_s.humanize)
97
120
  end
98
121
 
99
122
  private
100
123
 
124
+ # Returns true if the given layout is unique and not already taken or it should be hidden.
125
+ #
126
+ def layout_available?(layout)
127
+ !layout['hide'] && !already_taken?(layout) && available_on_site?(layout)
128
+ end
129
+
130
+ # Returns true if this layout is unique and already taken by another page.
131
+ #
132
+ def already_taken?(layout)
133
+ layout['unique'] && page_with_layout_existing?(layout['name'])
134
+ end
135
+
136
+ # Returns true if one page already has the given layout
137
+ #
138
+ def page_with_layout_existing?(layout)
139
+ Page.where(page_layout: layout, language_id: @language_id).pluck(:id).any?
140
+ end
141
+
142
+ # Returns true if given layout is available for current site.
143
+ #
144
+ # If no site layouts are defined it always returns true.
145
+ #
146
+ # == Example
147
+ #
148
+ # # config/alchemy/site_layouts.yml
149
+ # - name: default_site
150
+ # page_layouts: [default_intro]
151
+ #
152
+ def available_on_site?(layout)
153
+ Site.current.layout_definition.blank? || Site.current.layout_definition.fetch('page_layouts', []).include?(layout['name'])
154
+ end
155
+
101
156
  # Reads the layout definitions from +config/alchemy/page_layouts.yml+.
157
+ #
102
158
  def read_layouts_file
103
- if File.exists? "#{Rails.root}/config/alchemy/page_layouts.yml"
104
- layouts = YAML.load_file "#{Rails.root}/config/alchemy/page_layouts.yml"
105
- # Since YAML returns false for an empty file, we have to normalize it here.
106
- layouts || []
159
+ if File.exists?(layouts_file_path)
160
+ YAML.load_file(layouts_file_path) || []
107
161
  else
108
- raise LoadError, "Could not find page_layouts.yml file! Please run: rails generate alchemy:scaffold"
162
+ raise LoadError, "Could not find page_layouts.yml file! Please run `rails generate alchemy:scaffold`"
163
+ end
164
+ end
165
+
166
+ # Returns the page_layouts.yml file path
167
+ #
168
+ def layouts_file_path
169
+ Rails.root.join 'config/alchemy/page_layouts.yml'
170
+ end
171
+
172
+ # Maps given layouts for Rails select form helper.
173
+ #
174
+ def mapped_layouts_for_select(layouts)
175
+ layouts.each do |layout|
176
+ @map_array << [human_layout_name(layout['name']), layout["name"]]
109
177
  end
178
+ @map_array
110
179
  end
111
180
 
112
181
  end