alchemy_cms 2.6.3 → 2.7.0

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 (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
@@ -44,54 +44,115 @@ module Alchemy
44
44
 
45
45
  end
46
46
 
47
- # Finds selected elements from page.
47
+ # All available element definitions that can actually be placed on current page.
48
48
  #
49
- # Returns only public elements by default.
50
- # Pass true as second argument to get all elements.
49
+ # It extracts all definitions that are unique or limited and already on page.
51
50
  #
52
- # === Options are:
51
+ # == Example of unique element:
53
52
  #
54
- # :only => Array of element names # Returns only elements with given names
55
- # :except => Array of element names # Returns all elements except the ones with given names
56
- # :count => Integer # Limit the count of returned elements
57
- # :offset => Integer # Starts with an offset while returning elements
58
- # :random => Boolean # Return elements randomly shuffled
59
- # :from_cell => Cell or String # Return elements from given cell
53
+ # - name: headline
54
+ # unique: true
55
+ # contents:
56
+ # - name: headline
57
+ # type: EssenceText
60
58
  #
61
- def find_selected_elements(options = {}, show_non_public = false)
62
- if options[:from_cell].class.name == 'Alchemy::Cell'
63
- elements = options[:from_cell].elements
64
- elsif !options[:from_cell].blank? && options[:from_cell].class.name == 'String'
65
- cell = cells.find_by_name(options[:from_cell])
66
- if cell
67
- elements = cell.elements
68
- else
69
- warn("Cell with name `#{options[:from_cell]}` could not be found!")
70
- # Returns an empty relation. Can be removed with the release of Rails 4
71
- elements = self.elements.where('1 = 0')
72
- end
59
+ # == Example of limited element:
60
+ #
61
+ # - name: article
62
+ # amount: 2
63
+ # contents:
64
+ # - name: text
65
+ # type: EssenceRichtext
66
+ #
67
+ def available_element_definitions
68
+ @elements_for_layout ||= element_definitions
69
+ return [] if @elements_for_layout.blank?
70
+ @page_element_names = elements.not_trashed.pluck(:name)
71
+ delete_unique_element_definitions!
72
+ delete_outnumbered_element_definitions!
73
+ @elements_for_layout
74
+ end
75
+
76
+ # All names of elements that can actually be placed on current page.
77
+ #
78
+ def available_element_names
79
+ available_element_definitions.collect { |e| e['name'] }
80
+ end
81
+
82
+ # All element definitions defined for page's page layout
83
+ #
84
+ def element_definitions
85
+ element_definitions_by_name(element_definition_names)
86
+ end
87
+
88
+ # All names of elements that are defined in the page's page_layout definition.
89
+ #
90
+ # Define elements in +config/alchemy/page_layout.yml+ file
91
+ #
92
+ # == Example:
93
+ #
94
+ # - name: contact
95
+ # elements: [headline, contactform]
96
+ #
97
+ def element_definition_names
98
+ definition['elements'] || []
99
+ end
100
+
101
+ # Returns Element definitions with given name(s)
102
+ #
103
+ # @param [Array || String]
104
+ # one or many Alchemy::Element names. Pass +'all'+ to get all Element definitions
105
+ # @return [Array]
106
+ # An Array of element definitions
107
+ #
108
+ def element_definitions_by_name(names)
109
+ return [] if names.blank?
110
+ if names.to_s == "all"
111
+ Element.definitions
73
112
  else
74
- elements = self.elements.not_in_cell
113
+ Element.definitions.select { |e| names.include? e['name'] }
75
114
  end
76
- if !options[:only].blank?
115
+ end
116
+
117
+ # Finds elements of page.
118
+ #
119
+ # @param [Hash]
120
+ # options hash
121
+ # @param [Boolean] (false)
122
+ # Pass true, if you want to also have not published elements.
123
+ #
124
+ # @option options [Array] only
125
+ # Returns only elements with given names
126
+ # @option options [Array] except
127
+ # Returns all elements except the ones with given names
128
+ # @option options [Fixnum] count
129
+ # Limit the count of returned elements
130
+ # @option options [Fixnum] offset
131
+ # Starts with an offset while returning elements
132
+ # @option options [Boolean] random (false)
133
+ # Return elements randomly shuffled
134
+ # @option options [Alchemy::Cell || String] from_cell
135
+ # Return elements from given cell
136
+ #
137
+ # @return [ActiveRecord::Relation]
138
+ #
139
+ def find_elements(options = {}, show_non_public = false)
140
+ elements = elements_from_cell_or_self(options[:from_cell])
141
+ if options[:only].present?
77
142
  elements = elements.named(options[:only])
78
- elsif !options[:except].blank?
143
+ elsif options[:except].present?
79
144
  elements = elements.excluded(options[:except])
80
145
  end
81
- elements = elements.reverse_order if options[:reverse_sort] || options[:reverse]
146
+ if options[:reverse_sort] || options[:reverse]
147
+ elements = elements.reverse_order
148
+ end
82
149
  elements = elements.offset(options[:offset]).limit(options[:count])
83
- elements = elements.order("RAND()") if options[:random]
84
- show_non_public ? elements : elements.published
85
- end
86
-
87
- # What is this? A Kind of proxy method? Why not rendering the elements directly if you already have them????
88
- def find_elements(options = {}, show_non_public = false)
89
- if !options[:collection].blank? && options[:collection].is_a?(Array)
90
- return options[:collection]
91
- else
92
- find_selected_elements(options, show_non_public)
150
+ if options[:random]
151
+ elements = elements.order("RAND()")
93
152
  end
153
+ show_non_public ? elements : elements.published
94
154
  end
155
+ alias_method :find_selected_elements, :find_elements
95
156
 
96
157
  # Returns all elements that should be feeded via rss.
97
158
  #
@@ -105,6 +166,13 @@ module Alchemy
105
166
  elements.named(definition['feed_elements'])
106
167
  end
107
168
 
169
+ # Returns an array of selectors for all contents with custom tinymce config.
170
+ def custom_tinymce_contents_selectors
171
+ Tinymce.page_custom_config_contents(self).collect do |c|
172
+ "#{c['element']}_#{c['name']}"
173
+ end
174
+ end
175
+
108
176
  private
109
177
 
110
178
  # Looks in the page_layout descripion, if there are elements to autogenerate.
@@ -143,5 +211,46 @@ module Alchemy
143
211
  elements.select { |e| !definition['elements'].include?(e.name) }.map(&:trash)
144
212
  end
145
213
 
214
+ # Deletes unique and already present definitions from @elements_for_layout.
215
+ #
216
+ def delete_unique_element_definitions!
217
+ @elements_for_layout.delete_if { |element|
218
+ element['unique'] && @page_element_names.include?(element['name'])
219
+ }
220
+ end
221
+
222
+ # Deletes limited and outnumbered definitions from @elements_for_layout.
223
+ #
224
+ def delete_outnumbered_element_definitions!
225
+ @elements_for_layout.delete_if { |element|
226
+ element['amount'] && @page_element_names.select { |i| i == element['name'] }.count >= element['amount'].to_i
227
+ }
228
+ end
229
+
230
+ # Returns elements either from given cell or self
231
+ #
232
+ def elements_from_cell_or_self(cell)
233
+ case cell.class.name
234
+ when 'Alchemy::Cell'
235
+ cell.elements
236
+ when 'String'
237
+ cell_elements_by_name(cell)
238
+ else
239
+ self.elements.not_in_cell
240
+ end
241
+ end
242
+
243
+ # Returns all elements from given cell name
244
+ #
245
+ def cell_elements_by_name(name)
246
+ if cell = cells.find_by_name(name)
247
+ cell.elements
248
+ else
249
+ Alchemy::Logger.warn("Cell with name `#{name}` could not be found!", caller.first)
250
+ # Returns an empty relation. Can be removed with the release of Rails 4
251
+ self.elements.where('1 = 0')
252
+ end
253
+ end
254
+
146
255
  end
147
256
  end
@@ -0,0 +1,90 @@
1
+ module Alchemy
2
+ module Page::Natures
3
+
4
+ extend ActiveSupport::Concern
5
+
6
+ def taggable?
7
+ definition['taggable'] == true
8
+ end
9
+
10
+ def rootpage?
11
+ !self.new_record? && self.parent_id.blank?
12
+ end
13
+
14
+ def systempage?
15
+ return true if Page.root.nil?
16
+ rootpage? || (self.parent_id == Page.root.id && !self.language_root?)
17
+ end
18
+
19
+ def folded?(user_id)
20
+ folded_page = folded_pages.find_by_user_id(user_id)
21
+ folded_page.try(:folded) || false
22
+ end
23
+
24
+ def contains_feed?
25
+ definition["feed"]
26
+ end
27
+
28
+ # Returns true or false if the pages layout_description for config/alchemy/page_layouts.yml contains redirects_to_external: true
29
+ def redirects_to_external?
30
+ definition["redirects_to_external"]
31
+ end
32
+
33
+ def has_controller?
34
+ !PageLayout.get(self.page_layout).nil? && !PageLayout.get(self.page_layout)["controller"].blank?
35
+ end
36
+
37
+ def controller_and_action
38
+ if self.has_controller?
39
+ {
40
+ controller: self.layout_description["controller"].gsub(/(^\b)/, "/#{$1}"),
41
+ action: self.layout_description["action"]
42
+ }
43
+ end
44
+ end
45
+
46
+ # Returns a Hash describing the status of the Page.
47
+ #
48
+ def status
49
+ {
50
+ public: public?,
51
+ visible: visible?,
52
+ locked: locked?,
53
+ restricted: restricted?
54
+ }
55
+ end
56
+
57
+ # Returns the translated status for given status type.
58
+ #
59
+ # @param [Symbol] status_type
60
+ #
61
+ def status_title(status_type)
62
+ I18n.t(self.status[status_type].to_s, scope: "page_states.#{status_type}")
63
+ end
64
+
65
+ # Returns the self#page_layout description from config/alchemy/page_layouts.yml file.
66
+ def layout_description
67
+ return {} if self.systempage?
68
+ description = PageLayout.get(self.page_layout)
69
+ if description.nil?
70
+ raise PageLayoutDefinitionError, "Description could not be found for page layout named #{self.page_layout}. Please check page_layouts.yml file."
71
+ else
72
+ description
73
+ end
74
+ end
75
+ alias_method :definition, :layout_description
76
+
77
+ # Returns translated name of the pages page_layout value.
78
+ # Page layout names are defined inside the config/alchemy/page_layouts.yml file.
79
+ # Translate the name in your config/locales language yml file.
80
+ def layout_display_name
81
+ I18n.t(self.page_layout, :scope => :page_layout_names)
82
+ end
83
+
84
+ # Overwrites the cache_key method.
85
+ def cache_key(request = nil)
86
+ "alchemy/pages/#{id}"
87
+ end
88
+
89
+ end
90
+ end
@@ -0,0 +1,93 @@
1
+ module Alchemy
2
+
3
+ # ActiveRecord scopes for Alchemy::Page
4
+ #
5
+ module Page::Scopes
6
+ extend ActiveSupport::Concern
7
+
8
+ included do
9
+ # All language root pages
10
+ #
11
+ scope :language_roots, where(language_root: true)
12
+
13
+ # All layout pages
14
+ #
15
+ scope :layoutpages, where(layoutpage: true)
16
+
17
+ # All locked pages
18
+ #
19
+ scope :all_locked, where(locked: true)
20
+
21
+ # All pages locked by given +Alchemy::User+
22
+ #
23
+ scope :all_locked_by, ->(user) {
24
+ all_locked.where(locked_by: user.id)
25
+ }
26
+
27
+ # All not locked pages
28
+ #
29
+ scope :not_locked, where(locked: false)
30
+
31
+ # All visible pages
32
+ #
33
+ scope :visible, where(visible: true)
34
+
35
+ # All public pages
36
+ #
37
+ scope :published, where(public: true)
38
+
39
+ # All not restricted pages
40
+ #
41
+ scope :not_restricted, where(restricted: false)
42
+
43
+ # All restricted pages
44
+ #
45
+ scope :restricted, where(restricted: true)
46
+
47
+ # All pages that are a published language root
48
+ #
49
+ scope :public_language_roots, -> {
50
+ published.language_roots.where(
51
+ language_code: Language.all_codes_for_published
52
+ )
53
+ }
54
+
55
+ # Last 5 pages that where recently edited by given +Alchemy::User+
56
+ #
57
+ scope :all_last_edited_from, ->(user) {
58
+ where(updater_id: user.id).order('updated_at DESC').limit(5)
59
+ }
60
+
61
+ # Returns all pages that have the given +language_id+
62
+ #
63
+ scope :with_language, ->(language_id) {
64
+ where(language_id: language_id)
65
+ }
66
+
67
+ # Returns all content pages.
68
+ #
69
+ scope :contentpages, where(layoutpage: [false, nil]).where(Page.arel_table[:parent_id].not_eq(nil))
70
+
71
+ # Returns all public contentpages that are not locked.
72
+ #
73
+ # Used for flushing all pages caches at once.
74
+ #
75
+ scope :flushables, not_locked.published.contentpages
76
+
77
+ # All searchable pages
78
+ #
79
+ scope :searchables, not_restricted.published.contentpages
80
+
81
+ # All pages from +Alchemy::Site.current+
82
+ #
83
+ scope :from_current_site, -> {
84
+ where(alchemy_languages: {site_id: Site.current || Site.default}).joins(:language)
85
+ }
86
+
87
+ # All pages for xml sitemap
88
+ #
89
+ scope :sitemap, published.contentpages.where(sitemap: true)
90
+ end
91
+
92
+ end
93
+ end
@@ -0,0 +1,25 @@
1
+ module Alchemy
2
+ module Page::Users
3
+
4
+ extend ActiveSupport::Concern
5
+
6
+ # Returns the name of the creator of this page.
7
+ def creator_name
8
+ return I18n.t('unknown') if creator.nil?
9
+ creator.name
10
+ end
11
+
12
+ # Returns the name of the last updater of this page.
13
+ def updater_name
14
+ return I18n.t('unknown') if updater.nil?
15
+ updater.name
16
+ end
17
+
18
+ # Returns the name of the user currently editing this page.
19
+ def locker_name
20
+ return I18n.t('unknown') if locker.nil?
21
+ locker.name
22
+ end
23
+
24
+ end
25
+ end
@@ -1,3 +1,7 @@
1
+ require 'acts-as-taggable-on'
2
+ require 'dragonfly'
3
+ require 'userstamp'
4
+
1
5
  module Alchemy
2
6
  class Picture < ActiveRecord::Base
3
7
  include NameConversions
@@ -39,6 +43,7 @@ module Alchemy
39
43
 
40
44
  scope :recent, where("#{self.table_name}.created_at > ?", Time.now-24.hours).order(:created_at)
41
45
  scope :deletable, where("alchemy_pictures.id NOT IN (SELECT picture_id FROM alchemy_essence_pictures)")
46
+ scope :without_tag, where("cached_tag_list IS NULL OR cached_tag_list = ''")
42
47
 
43
48
  # Class methods
44
49
 
@@ -54,6 +59,16 @@ module Alchemy
54
59
  Picture.where(:upload_hash => last_picture.upload_hash)
55
60
  end
56
61
 
62
+ def filtered_by(filter = '')
63
+ case filter
64
+ when 'recent' then recent
65
+ when 'last_upload' then last_upload
66
+ when 'without_tag' then without_tag
67
+ else
68
+ scoped
69
+ end
70
+ end
71
+
57
72
  end
58
73
 
59
74
  # Instance methods