alchemy_cms 6.1.2 → 7.0.0.pre.a

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 (243) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yml +0 -3
  3. data/.gitignore +1 -6
  4. data/CHANGELOG.md +22 -8
  5. data/Gemfile +1 -0
  6. data/Rakefile +13 -8
  7. data/alchemy_cms.gemspec +1 -3
  8. data/app/assets/javascripts/alchemy/alchemy.dirty.js.coffee +1 -1
  9. data/app/assets/javascripts/alchemy/alchemy.element_editors.js.coffee +18 -32
  10. data/app/assets/javascripts/alchemy/alchemy.elements_window.js.coffee +2 -2
  11. data/app/assets/javascripts/alchemy/alchemy.gui.js.coffee +2 -2
  12. data/app/assets/javascripts/alchemy/alchemy.link_dialog.js.coffee +27 -29
  13. data/app/assets/stylesheets/alchemy/elements.scss +16 -35
  14. data/app/assets/stylesheets/alchemy/forms.scss +0 -4
  15. data/app/assets/stylesheets/alchemy/node-select.scss +2 -2
  16. data/app/controllers/alchemy/admin/attachments_controller.rb +0 -1
  17. data/app/controllers/alchemy/admin/elements_controller.rb +7 -32
  18. data/app/controllers/alchemy/admin/pages_controller.rb +1 -1
  19. data/app/controllers/alchemy/admin/pictures_controller.rb +1 -1
  20. data/app/controllers/alchemy/admin/resources_controller.rb +1 -18
  21. data/app/controllers/alchemy/api/elements_controller.rb +0 -2
  22. data/app/controllers/alchemy/api/pages_controller.rb +6 -4
  23. data/app/controllers/alchemy/messages_controller.rb +9 -9
  24. data/app/controllers/alchemy/pages_controller.rb +19 -28
  25. data/app/decorators/alchemy/element_editor.rb +10 -30
  26. data/app/helpers/alchemy/admin/elements_helper.rb +0 -2
  27. data/app/helpers/alchemy/elements_block_helper.rb +5 -42
  28. data/app/helpers/alchemy/elements_helper.rb +3 -11
  29. data/app/helpers/alchemy/pages_helper.rb +0 -4
  30. data/app/models/alchemy/attachment.rb +6 -3
  31. data/app/models/alchemy/base_record.rb +2 -0
  32. data/app/models/alchemy/eager_loading.rb +0 -1
  33. data/app/models/alchemy/element/element_ingredients.rb +1 -8
  34. data/app/models/alchemy/element/presenters.rb +9 -25
  35. data/app/models/alchemy/element.rb +2 -16
  36. data/app/models/alchemy/ingredient.rb +17 -6
  37. data/app/models/alchemy/ingredients/audio.rb +2 -0
  38. data/app/models/alchemy/ingredients/datetime.rb +3 -1
  39. data/app/models/alchemy/ingredients/file.rb +7 -0
  40. data/app/models/alchemy/ingredients/headline.rb +6 -0
  41. data/app/models/alchemy/ingredients/link.rb +2 -0
  42. data/app/models/alchemy/ingredients/node.rb +2 -0
  43. data/app/models/alchemy/ingredients/page.rb +2 -0
  44. data/app/models/alchemy/ingredients/picture.rb +11 -0
  45. data/app/models/alchemy/ingredients/richtext.rb +6 -0
  46. data/app/models/alchemy/ingredients/select.rb +1 -0
  47. data/app/models/alchemy/ingredients/text.rb +8 -0
  48. data/app/models/alchemy/ingredients/video.rb +2 -0
  49. data/app/models/alchemy/node.rb +9 -6
  50. data/app/models/alchemy/page/page_elements.rb +5 -26
  51. data/app/models/alchemy/page/page_layouts.rb +0 -14
  52. data/app/models/alchemy/page/page_natures.rb +0 -10
  53. data/app/models/alchemy/page.rb +0 -8
  54. data/app/models/alchemy/picture/transformations.rb +0 -30
  55. data/app/models/alchemy/picture/url.rb +1 -1
  56. data/app/models/alchemy/picture.rb +12 -10
  57. data/app/models/alchemy/picture_thumb/create.rb +7 -18
  58. data/app/models/alchemy/picture_thumb/file_store.rb +33 -0
  59. data/app/models/alchemy/picture_thumb.rb +10 -10
  60. data/app/models/concerns/alchemy/picture_thumbnails.rb +2 -2
  61. data/app/serializers/alchemy/element_serializer.rb +1 -6
  62. data/app/services/alchemy/delete_elements.rb +1 -7
  63. data/app/services/alchemy/duplicate_element.rb +1 -6
  64. data/app/views/alchemy/admin/elements/_element.html.erb +5 -22
  65. data/app/views/alchemy/admin/elements/create.js.erb +1 -1
  66. data/app/views/alchemy/admin/elements/fold.js.erb +2 -2
  67. data/app/views/alchemy/admin/elements/order.js.erb +1 -1
  68. data/app/views/alchemy/admin/elements/update.js.erb +1 -2
  69. data/app/views/alchemy/admin/pages/_external_link.html.erb +2 -2
  70. data/app/views/alchemy/admin/pages/_file_link.html.erb +2 -2
  71. data/app/views/alchemy/admin/pages/_internal_link.html.erb +2 -2
  72. data/app/views/alchemy/admin/pages/_tinymce_custom_config.html.erb +3 -6
  73. data/app/views/alchemy/admin/pages/edit.html.erb +1 -1
  74. data/app/views/alchemy/admin/pictures/_filter_and_size_bar.html.erb +1 -3
  75. data/app/views/alchemy/admin/pictures/_infos.html.erb +4 -6
  76. data/app/views/alchemy/ingredients/_boolean_editor.html.erb +1 -1
  77. data/app/views/alchemy/ingredients/_headline_editor.html.erb +1 -1
  78. data/app/views/alchemy/ingredients/_html_editor.html.erb +1 -1
  79. data/app/views/alchemy/ingredients/_node_editor.html.erb +1 -1
  80. data/app/views/alchemy/ingredients/_picture_editor.html.erb +4 -4
  81. data/app/views/alchemy/ingredients/_select_editor.html.erb +2 -2
  82. data/app/views/alchemy/ingredients/_text_editor.html.erb +1 -1
  83. data/app/views/alchemy/ingredients/shared/_link_tools.html.erb +3 -3
  84. data/app/views/alchemy/pages/_meta_data.html.erb +0 -1
  85. data/app/views/layouts/alchemy/admin.html.erb +5 -1
  86. data/config/alchemy/config.yml +6 -6
  87. data/config/brakeman.ignore +56 -57
  88. data/config/locales/alchemy.en.yml +98 -112
  89. data/config/routes.rb +1 -16
  90. data/db/migrate/20230121212637_alchemy_six_point_one.rb +248 -0
  91. data/lib/alchemy/cache_digests/template_tracker.rb +6 -7
  92. data/lib/alchemy/config.rb +2 -2
  93. data/lib/alchemy/deprecation.rb +1 -1
  94. data/lib/alchemy/errors.rb +0 -11
  95. data/lib/alchemy/hints.rb +10 -10
  96. data/lib/alchemy/install/tasks.rb +7 -1
  97. data/lib/alchemy/permissions.rb +0 -13
  98. data/lib/alchemy/routing_constraints.rb +3 -3
  99. data/lib/alchemy/searchable_resource.rb +38 -0
  100. data/lib/alchemy/tasks/tidy.rb +0 -38
  101. data/lib/alchemy/test_support/capybara_helpers.rb +69 -0
  102. data/lib/alchemy/test_support/factories/element_factory.rb +0 -6
  103. data/lib/alchemy/test_support/factories/ingredient_factory.rb +1 -1
  104. data/lib/alchemy/test_support/factories/page_factory.rb +4 -2
  105. data/lib/alchemy/test_support/shared_dom_ids_examples.rb +1 -1
  106. data/lib/alchemy/test_support/shared_ingredient_examples.rb +1 -1
  107. data/lib/alchemy/tinymce.rb +1 -18
  108. data/lib/alchemy/upgrader/seven_point_zero.rb +45 -0
  109. data/lib/alchemy/upgrader/tasks/.keep +0 -0
  110. data/lib/alchemy/upgrader.rb +8 -3
  111. data/lib/alchemy/version.rb +1 -1
  112. data/lib/alchemy.rb +0 -19
  113. data/lib/alchemy_cms.rb +2 -3
  114. data/lib/generators/alchemy/elements/elements_generator.rb +0 -1
  115. data/lib/generators/alchemy/elements/templates/view.html.erb +1 -10
  116. data/lib/generators/alchemy/elements/templates/view.html.haml +1 -9
  117. data/lib/generators/alchemy/elements/templates/view.html.slim +1 -9
  118. data/lib/generators/alchemy/install/files/alchemy.en.yml +7 -8
  119. data/lib/generators/alchemy/install/files/application.html.erb +1 -1
  120. data/lib/generators/alchemy/install/install_generator.rb +18 -22
  121. data/lib/generators/alchemy/install/templates/elements.yml.tt +12 -12
  122. data/lib/non_stupid_digest_assets.rb +55 -0
  123. data/lib/tasks/alchemy/thumbnails.rake +2 -21
  124. data/lib/tasks/alchemy/tidy.rake +1 -12
  125. data/lib/tasks/alchemy/upgrade.rake +10 -47
  126. data/package/dist/admin.js +16 -0
  127. data/package/dist/admin.js.map +7 -0
  128. data/package.json +5 -3
  129. metadata +15 -154
  130. data/app/controllers/alchemy/admin/contents_controller.rb +0 -21
  131. data/app/controllers/alchemy/admin/essence_audios_controller.rb +0 -30
  132. data/app/controllers/alchemy/admin/essence_files_controller.rb +0 -31
  133. data/app/controllers/alchemy/admin/essence_pictures_controller.rb +0 -43
  134. data/app/controllers/alchemy/admin/essence_videos_controller.rb +0 -34
  135. data/app/controllers/alchemy/api/contents_controller.rb +0 -52
  136. data/app/decorators/alchemy/content_editor.rb +0 -119
  137. data/app/helpers/alchemy/admin/contents_helper.rb +0 -42
  138. data/app/helpers/alchemy/admin/essences_helper.rb +0 -31
  139. data/app/models/alchemy/content/factory.rb +0 -143
  140. data/app/models/alchemy/content.rb +0 -247
  141. data/app/models/alchemy/element/element_contents.rb +0 -200
  142. data/app/models/alchemy/element/element_essences.rb +0 -133
  143. data/app/models/alchemy/essence_audio.rb +0 -13
  144. data/app/models/alchemy/essence_boolean.rb +0 -20
  145. data/app/models/alchemy/essence_date.rb +0 -25
  146. data/app/models/alchemy/essence_file.rb +0 -49
  147. data/app/models/alchemy/essence_headline.rb +0 -41
  148. data/app/models/alchemy/essence_html.rb +0 -23
  149. data/app/models/alchemy/essence_link.rb +0 -21
  150. data/app/models/alchemy/essence_node.rb +0 -19
  151. data/app/models/alchemy/essence_page.rb +0 -17
  152. data/app/models/alchemy/essence_picture.rb +0 -67
  153. data/app/models/alchemy/essence_picture_view.rb +0 -90
  154. data/app/models/alchemy/essence_richtext.rb +0 -44
  155. data/app/models/alchemy/essence_select.rb +0 -19
  156. data/app/models/alchemy/essence_text.rb +0 -23
  157. data/app/models/alchemy/essence_video.rb +0 -13
  158. data/app/serializers/alchemy/content_serializer.rb +0 -17
  159. data/app/serializers/alchemy/essence_boolean_serializer.rb +0 -10
  160. data/app/serializers/alchemy/essence_date_serializer.rb +0 -10
  161. data/app/serializers/alchemy/essence_file_serializer.rb +0 -13
  162. data/app/serializers/alchemy/essence_html_serializer.rb +0 -10
  163. data/app/serializers/alchemy/essence_link_serializer.rb +0 -13
  164. data/app/serializers/alchemy/essence_picture_serializer.rb +0 -28
  165. data/app/serializers/alchemy/essence_richtext_serializer.rb +0 -11
  166. data/app/serializers/alchemy/essence_select_serializer.rb +0 -10
  167. data/app/serializers/alchemy/essence_text_serializer.rb +0 -22
  168. data/app/views/alchemy/admin/contents/create.js.erb +0 -21
  169. data/app/views/alchemy/admin/essence_audios/edit.html.erb +0 -7
  170. data/app/views/alchemy/admin/essence_files/edit.html.erb +0 -21
  171. data/app/views/alchemy/admin/essence_pictures/destroy.js.erb +0 -5
  172. data/app/views/alchemy/admin/essence_pictures/edit.html.erb +0 -30
  173. data/app/views/alchemy/admin/essence_pictures/save_link.js.erb +0 -3
  174. data/app/views/alchemy/admin/essence_pictures/update.js.erb +0 -8
  175. data/app/views/alchemy/admin/essence_videos/edit.html.erb +0 -12
  176. data/app/views/alchemy/essences/_essence_audio_editor.html.erb +0 -4
  177. data/app/views/alchemy/essences/_essence_audio_view.html.erb +0 -15
  178. data/app/views/alchemy/essences/_essence_boolean_editor.html.erb +0 -11
  179. data/app/views/alchemy/essences/_essence_boolean_view.html.erb +0 -2
  180. data/app/views/alchemy/essences/_essence_date_editor.html.erb +0 -16
  181. data/app/views/alchemy/essences/_essence_date_view.html.erb +0 -10
  182. data/app/views/alchemy/essences/_essence_file_editor.html.erb +0 -54
  183. data/app/views/alchemy/essences/_essence_file_view.html.erb +0 -18
  184. data/app/views/alchemy/essences/_essence_headline_editor.html.erb +0 -36
  185. data/app/views/alchemy/essences/_essence_headline_view.html.erb +0 -10
  186. data/app/views/alchemy/essences/_essence_html_editor.html.erb +0 -10
  187. data/app/views/alchemy/essences/_essence_html_view.html.erb +0 -2
  188. data/app/views/alchemy/essences/_essence_link_editor.html.erb +0 -30
  189. data/app/views/alchemy/essences/_essence_link_view.html.erb +0 -10
  190. data/app/views/alchemy/essences/_essence_node_editor.html.erb +0 -27
  191. data/app/views/alchemy/essences/_essence_node_view.html.erb +0 -1
  192. data/app/views/alchemy/essences/_essence_page_editor.html.erb +0 -26
  193. data/app/views/alchemy/essences/_essence_page_view.html.erb +0 -5
  194. data/app/views/alchemy/essences/_essence_picture_editor.html.erb +0 -59
  195. data/app/views/alchemy/essences/_essence_picture_view.html.erb +0 -6
  196. data/app/views/alchemy/essences/_essence_richtext_editor.html.erb +0 -14
  197. data/app/views/alchemy/essences/_essence_richtext_view.html.erb +0 -4
  198. data/app/views/alchemy/essences/_essence_select_editor.html.erb +0 -28
  199. data/app/views/alchemy/essences/_essence_select_view.html.erb +0 -2
  200. data/app/views/alchemy/essences/_essence_text_editor.html.erb +0 -29
  201. data/app/views/alchemy/essences/_essence_text_view.html.erb +0 -17
  202. data/app/views/alchemy/essences/_essence_video_editor.html.erb +0 -4
  203. data/app/views/alchemy/essences/_essence_video_view.html.erb +0 -19
  204. data/app/views/alchemy/essences/shared/_essence_picture_tools.html.erb +0 -59
  205. data/app/views/alchemy/essences/shared/_linkable_essence_tools.html.erb +0 -20
  206. data/app/views/alchemy/pages/show.rss.builder +0 -21
  207. data/db/migrate/20200226213334_alchemy_four_point_four.rb +0 -313
  208. data/db/migrate/20200423073425_create_alchemy_essence_nodes.rb +0 -11
  209. data/db/migrate/20200504210159_remove_site_id_from_nodes.rb +0 -28
  210. data/db/migrate/20200505215518_add_language_id_foreign_key_to_alchemy_pages.rb +0 -8
  211. data/db/migrate/20200511113603_add_menu_type_to_alchemy_nodes.rb +0 -27
  212. data/db/migrate/20200514091507_make_page_layoutpage_null_false.rb +0 -6
  213. data/db/migrate/20200519073500_remove_visible_from_alchemy_pages.rb +0 -24
  214. data/db/migrate/20200617110713_create_alchemy_picture_thumbs.rb +0 -22
  215. data/db/migrate/20200907111332_remove_tri_state_booleans.rb +0 -33
  216. data/db/migrate/20201207131309_create_page_versions.rb +0 -19
  217. data/db/migrate/20201207135820_add_page_version_id_to_alchemy_elements.rb +0 -76
  218. data/db/migrate/20210205143548_rename_public_on_and_public_until_on_alchemy_pages.rb +0 -10
  219. data/db/migrate/20210326105046_add_sanitized_body_to_alchemy_essence_richtexts.rb +0 -7
  220. data/db/migrate/20210406093436_add_alchemy_essence_headlines.rb +0 -12
  221. data/db/migrate/20210506135919_create_essence_audios.rb +0 -19
  222. data/db/migrate/20210506140258_create_essence_videos.rb +0 -23
  223. data/db/migrate/20210508091432_create_alchemy_ingredients.rb +0 -22
  224. data/db/migrate/20220514072456_restrict_on_delete_page_id_foreign_key_from_alchemy_nodes.rb +0 -13
  225. data/db/migrate/20220622130905_add_playsinline_to_alchemy_essence_videos.rb +0 -9
  226. data/lib/alchemy/essence.rb +0 -250
  227. data/lib/alchemy/test_support/essence_shared_examples.rb +0 -271
  228. data/lib/alchemy/test_support/factories/content_factory.rb +0 -20
  229. data/lib/alchemy/test_support/factories/essence_audio_factory.rb +0 -7
  230. data/lib/alchemy/test_support/factories/essence_file_factory.rb +0 -7
  231. data/lib/alchemy/test_support/factories/essence_page_factory.rb +0 -7
  232. data/lib/alchemy/test_support/factories/essence_picture_factory.rb +0 -11
  233. data/lib/alchemy/test_support/factories/essence_text_factory.rb +0 -7
  234. data/lib/alchemy/test_support/factories/essence_video_factory.rb +0 -7
  235. data/lib/alchemy/upgrader/five_point_zero.rb +0 -41
  236. data/lib/alchemy/upgrader/six_point_zero.rb +0 -21
  237. data/lib/alchemy/upgrader/tasks/add_page_versions.rb +0 -33
  238. data/lib/alchemy/upgrader/tasks/element_views_updater.rb +0 -34
  239. data/lib/alchemy/upgrader/tasks/harden_gutentag_migrations.rb +0 -29
  240. data/lib/alchemy/upgrader/tasks/ingredients_migrator.rb +0 -74
  241. data/lib/generators/alchemy/essence/essence_generator.rb +0 -49
  242. data/lib/generators/alchemy/essence/templates/editor.html.erb +0 -17
  243. data/lib/generators/alchemy/essence/templates/view.html.erb +0 -2
@@ -21,9 +21,7 @@
21
21
  #
22
22
 
23
23
  require_dependency "alchemy/element/definitions"
24
- require_dependency "alchemy/element/element_contents"
25
24
  require_dependency "alchemy/element/element_ingredients"
26
- require_dependency "alchemy/element/element_essences"
27
25
  require_dependency "alchemy/element/presenters"
28
26
 
29
27
  module Alchemy
@@ -38,7 +36,6 @@ module Alchemy
38
36
  "amount",
39
37
  "autogenerate",
40
38
  "nestable_elements",
41
- "contents",
42
39
  "hint",
43
40
  "ingredients",
44
41
  "taggable",
@@ -59,10 +56,6 @@ module Alchemy
59
56
 
60
57
  stampable stamper_class_name: Alchemy.user_class.name
61
58
 
62
- has_many :contents, dependent: :destroy, inverse_of: :element
63
-
64
- deprecate contents: :ingredients, deprecator: Alchemy::Deprecation
65
-
66
59
  before_destroy :delete_all_nested_elements
67
60
 
68
61
  has_many :all_nested_elements,
@@ -95,9 +88,7 @@ module Alchemy
95
88
  validates_presence_of :name, on: :create
96
89
  validates_format_of :name, on: :create, with: NAME_REGEXP
97
90
 
98
- attr_accessor :autogenerate_contents
99
91
  attr_accessor :autogenerate_nested_elements
100
- after_create :create_contents, unless: -> { autogenerate_contents == false }
101
92
  after_create :generate_nested_elements, unless: -> { autogenerate_nested_elements == false }
102
93
 
103
94
  after_update :touch_touchable_pages
@@ -105,7 +96,6 @@ module Alchemy
105
96
  scope :published, -> { where(public: true) }
106
97
  scope :hidden, -> { where(public: false) }
107
98
  scope :not_restricted, -> { joins(:page).merge(Page.not_restricted) }
108
- scope :available, -> { published }
109
99
  scope :named, ->(names) { where(name: names) }
110
100
  scope :excluded, ->(names) { where.not(name: names) }
111
101
  scope :fixed, -> { where(fixed: true) }
@@ -119,8 +109,6 @@ module Alchemy
119
109
 
120
110
  # Concerns
121
111
  include Definitions
122
- include ElementContents
123
- include ElementEssences
124
112
  include ElementIngredients
125
113
  include Presenters
126
114
 
@@ -157,7 +145,7 @@ module Alchemy
157
145
  @_dom_id_class = klass
158
146
  end
159
147
 
160
- # This methods does a copy of source and all depending contents and all of their depending essences.
148
+ # This methods does a copy of source and all its ingredients.
161
149
  #
162
150
  # == Options
163
151
  #
@@ -192,8 +180,6 @@ module Alchemy
192
180
 
193
181
  all_from_clipboard(clipboard).where(name: parent_element.definition["nestable_elements"])
194
182
  end
195
-
196
- deprecate available: :published, deprecator: Alchemy::Deprecation
197
183
  end
198
184
 
199
185
  # Returns next public element from same page.
@@ -277,7 +263,7 @@ module Alchemy
277
263
  # Elements are defined in the +config/alchemy/elements.yml+ file
278
264
  #
279
265
  # - name: article
280
- # contents:
266
+ # ingredients:
281
267
  # ...
282
268
  #
283
269
  # == Override the view
@@ -13,11 +13,13 @@ module Alchemy
13
13
  belongs_to :element, touch: true, class_name: "Alchemy::Element", inverse_of: :ingredients
14
14
  belongs_to :related_object, polymorphic: true, optional: true
15
15
 
16
+ has_one :page, through: :element, class_name: "Alchemy::Page"
17
+
16
18
  after_initialize :set_default_value,
17
19
  if: -> { definition.key?(:default) && value.nil? }
18
20
 
19
21
  validates :type, presence: true
20
- validates :role, presence: true
22
+ validates :role, presence: true, uniqueness: { scope: :element_id, case_sensitive: false }
21
23
 
22
24
  validates_with Alchemy::IngredientValidator, on: :update, if: :has_validations?
23
25
 
@@ -76,11 +78,16 @@ module Alchemy
76
78
  default: Alchemy.t("ingredient_roles.#{role}", default: role.humanize),
77
79
  )
78
80
  end
79
- end
80
81
 
81
- # Compatibility method for access from element
82
- def essence
83
- self
82
+ # Allow to define settings on the ingredient definition
83
+ def allow_settings(settings)
84
+ @allowed_settings = Array(settings)
85
+ end
86
+
87
+ # Allowed settings on the ingredient
88
+ def allowed_settings
89
+ @allowed_settings ||= []
90
+ end
84
91
  end
85
92
 
86
93
  # The value or the related object if present
@@ -97,7 +104,7 @@ module Alchemy
97
104
  #
98
105
  # @param key [Symbol] - The hash key you want to fetch the value from
99
106
  # @param options [Hash] - An optional Hash that can override the settings.
100
- # Normally passed as options hash into the content
107
+ # Normally passed as options hash into the ingredient
101
108
  # editor view.
102
109
  def settings_value(key, options = {})
103
110
  settings.merge(options || {})[key.to_sym]
@@ -164,6 +171,10 @@ module Alchemy
164
171
  role
165
172
  end
166
173
 
174
+ def hint_translation_scope
175
+ "ingredient_hints"
176
+ end
177
+
167
178
  def set_default_value
168
179
  self.value = default_value
169
180
  end
@@ -11,6 +11,8 @@ module Alchemy
11
11
  :muted,
12
12
  :loop
13
13
 
14
+ allow_settings %i[except only]
15
+
14
16
  related_object_alias :attachment, class_name: "Alchemy::Attachment"
15
17
 
16
18
  delegate :name, to: :attachment, allow_nil: true
@@ -5,6 +5,8 @@ module Alchemy
5
5
  # A datetime value
6
6
  #
7
7
  class Datetime < Alchemy::Ingredient
8
+ allow_settings %i[date_format]
9
+
8
10
  def value
9
11
  ActiveRecord::Type::DateTime.new.cast(self[:value])
10
12
  end
@@ -13,7 +15,7 @@ module Alchemy
13
15
  def preview_text(_maxlength = nil)
14
16
  return "" unless value
15
17
 
16
- ::I18n.l(value, format: :'alchemy.essence_date')
18
+ ::I18n.l(value, format: :'alchemy.ingredient_date')
17
19
  end
18
20
  end
19
21
  end
@@ -12,6 +12,13 @@ module Alchemy
12
12
  :link_text,
13
13
  :title
14
14
 
15
+ allow_settings %i[
16
+ css_classes
17
+ except
18
+ link_text
19
+ only
20
+ ]
21
+
15
22
  related_object_alias :attachment, class_name: "Alchemy::Attachment"
16
23
 
17
24
  delegate :name, to: :attachment, allow_nil: true
@@ -12,6 +12,12 @@ module Alchemy
12
12
  :level,
13
13
  :size
14
14
 
15
+ allow_settings %i[
16
+ anchor
17
+ levels
18
+ sizes
19
+ ]
20
+
15
21
  before_create :set_level_and_size
16
22
 
17
23
  def preview_text(maxlength = 30)
@@ -10,6 +10,8 @@ module Alchemy
10
10
  :link_target,
11
11
  :link_title
12
12
 
13
+ allow_settings %i[text]
14
+
13
15
  alias_method :link, :value
14
16
  end
15
17
  end
@@ -9,6 +9,8 @@ module Alchemy
9
9
  class Node < Alchemy::Ingredient
10
10
  related_object_alias :node, class_name: "Alchemy::Node"
11
11
 
12
+ allow_settings %i[query_params]
13
+
12
14
  # The first 30 characters of node name
13
15
  #
14
16
  # Used by the Element#preview_text method.
@@ -9,6 +9,8 @@ module Alchemy
9
9
  class Page < Alchemy::Ingredient
10
10
  related_object_alias :page, class_name: "Alchemy::Page"
11
11
 
12
+ allow_settings %i[query_params]
13
+
12
14
  # The first 30 characters of page name
13
15
  #
14
16
  # Used by the Element#preview_text method.
@@ -27,6 +27,17 @@ module Alchemy
27
27
 
28
28
  related_object_alias :picture, class_name: "Alchemy::Picture"
29
29
 
30
+ allow_settings %i[
31
+ crop
32
+ css_classes
33
+ fixed_ratio
34
+ linkable
35
+ size
36
+ sizes
37
+ srcset
38
+ upsample
39
+ ]
40
+
30
41
  # The first 30 characters of the pictures name
31
42
  #
32
43
  # Used by the Element#preview_text method.
@@ -9,6 +9,12 @@ module Alchemy
9
9
  :stripped_body,
10
10
  :sanitized_body
11
11
 
12
+ allow_settings %i[
13
+ plain_text
14
+ sanitizer
15
+ tinymce
16
+ ]
17
+
12
18
  before_save :strip_content
13
19
  before_save :sanitize_content
14
20
 
@@ -5,6 +5,7 @@ module Alchemy
5
5
  # A text value from a select box
6
6
  #
7
7
  class Select < Alchemy::Ingredient
8
+ allow_settings %i[display_inline select_values]
8
9
  end
9
10
  end
10
11
  end
@@ -15,6 +15,14 @@ module Alchemy
15
15
  :link_target,
16
16
  :link_title,
17
17
  :link_class_name
18
+
19
+ allow_settings %i[
20
+ anchor
21
+ disable_link
22
+ display_inline
23
+ input_type
24
+ linkable
25
+ ]
18
26
  end
19
27
  end
20
28
  end
@@ -16,6 +16,8 @@ module Alchemy
16
16
  :preload,
17
17
  :width
18
18
 
19
+ allow_settings %i[except only]
20
+
19
21
  related_object_alias :attachment, class_name: "Alchemy::Attachment"
20
22
 
21
23
  delegate :name, to: :attachment, allow_nil: true
@@ -4,7 +4,7 @@ module Alchemy
4
4
  class Node < BaseRecord
5
5
  VALID_URL_REGEX = /\A(\/|\D[a-z\+\d\.\-]+:)/
6
6
 
7
- before_destroy :check_if_related_essence_nodes_present
7
+ before_destroy :check_if_related_node_ingredients_present
8
8
 
9
9
  acts_as_nested_set scope: "language_id", touch: true
10
10
  stampable stamper_class_name: Alchemy.user_class.name
@@ -14,7 +14,10 @@ module Alchemy
14
14
 
15
15
  has_one :site, through: :language
16
16
 
17
- has_many :essence_nodes, class_name: "Alchemy::EssenceNode", foreign_key: :node_id, inverse_of: :ingredient_association
17
+ has_many :node_ingredients,
18
+ class_name: "Alchemy::Ingredients::Node",
19
+ foreign_key: :related_object_id,
20
+ inverse_of: :related_object
18
21
 
19
22
  before_validation :translate_root_menu_name, if: -> { root? }
20
23
  before_validation :set_menu_type_from_root, unless: -> { root? }
@@ -76,10 +79,10 @@ module Alchemy
76
79
 
77
80
  private
78
81
 
79
- def check_if_related_essence_nodes_present
80
- dependent_essence_nodes = self_and_descendants.flat_map(&:essence_nodes)
81
- if dependent_essence_nodes.any?
82
- errors.add(:base, :essence_nodes_present, page_names: dependent_essence_nodes.map(&:page).map(&:name).to_sentence)
82
+ def check_if_related_node_ingredients_present
83
+ dependent_node_ingredients = self_and_descendants.flat_map(&:node_ingredients)
84
+ if dependent_node_ingredients.any?
85
+ errors.add(:base, :node_ingredients_present, page_names: dependent_node_ingredients.map { |i| i.element&.page&.name }.to_sentence)
83
86
  throw(:abort)
84
87
  end
85
88
  end
@@ -19,7 +19,7 @@ module Alchemy
19
19
  has_many :fixed_elements, -> { fixed.published }
20
20
  end
21
21
 
22
- has_many :contents, through: :elements
22
+ has_many :ingredients, through: :elements
23
23
  has_and_belongs_to_many :to_be_swept_elements, -> { distinct },
24
24
  class_name: "Alchemy::Element",
25
25
  join_table: ElementToPage.table_name
@@ -58,17 +58,17 @@ module Alchemy
58
58
  #
59
59
  # - name: headline
60
60
  # unique: true
61
- # contents:
61
+ # ingredients:
62
62
  # - name: headline
63
- # type: EssenceText
63
+ # type: Text
64
64
  #
65
65
  # == Example of limited element:
66
66
  #
67
67
  # - name: article
68
68
  # amount: 2
69
- # contents:
69
+ # ingredients:
70
70
  # - name: text
71
- # type: EssenceRichtext
71
+ # type: Richtext
72
72
  #
73
73
  def available_element_definitions(only_element_named = nil)
74
74
  @_element_definitions ||= if only_element_named
@@ -156,27 +156,6 @@ module Alchemy
156
156
  end
157
157
  end
158
158
 
159
- # Returns all elements that should be feeded via rss.
160
- #
161
- # Define feedable elements in your +page_layouts.yml+:
162
- #
163
- # - name: news
164
- # feed: true
165
- # feed_elements: [element_name, element_2_name]
166
- #
167
- def feed_elements
168
- elements.named(definition["feed_elements"])
169
- end
170
-
171
- # Returns an array of all EssenceRichtext contents ids from not folded elements
172
- #
173
- def richtext_contents_ids
174
- Alchemy::Content.joins(:element)
175
- .where(Element.table_name => { page_version_id: draft_version.id, folded: false })
176
- .select(&:has_tinymce?)
177
- .collect(&:id)
178
- end
179
-
180
159
  # Returns an array of all Richtext ingredients ids from not folded elements
181
160
  #
182
161
  def richtext_ingredients_ids
@@ -23,20 +23,6 @@ module Alchemy
23
23
  mapped_layouts_for_select(selectable_layouts(language_id, layoutpages: layoutpages))
24
24
  end
25
25
 
26
- # Returns page layouts including given layout ready for Rails' select form helper.
27
- #
28
- def layouts_with_own_for_select(page_layout_name, language_id, layoutpages: false)
29
- layouts = selectable_layouts(language_id, layoutpages: layoutpages)
30
- if layouts.detect { |l| l["name"] == page_layout_name }.nil?
31
- @map_array = [[human_layout_name(page_layout_name), page_layout_name]]
32
- else
33
- @map_array = []
34
- end
35
- mapped_layouts_for_select(layouts)
36
- end
37
-
38
- deprecate :layouts_with_own_for_select, deprecator: Alchemy::Deprecation
39
-
40
26
  # Returns all layouts that can be used for creating a new page.
41
27
  #
42
28
  # It removes all layouts from available layouts that are unique and already taken and that are marked as hide.
@@ -17,12 +17,6 @@ module Alchemy
17
17
  public_until ? public_until - Time.current : nil
18
18
  end
19
19
 
20
- def taggable?
21
- definition["taggable"] == true
22
- end
23
-
24
- deprecate :taggable?, deprecator: Alchemy::Deprecation
25
-
26
20
  def rootpage?
27
21
  !new_record? && parent_id.blank?
28
22
  end
@@ -33,10 +27,6 @@ module Alchemy
33
27
  folded_pages.where(user_id: user_id, folded: true).any?
34
28
  end
35
29
 
36
- def contains_feed?
37
- definition["feed"]
38
- end
39
-
40
30
  # Returns an Array of Alchemy roles which are able to edit this template
41
31
  #
42
32
  # # config/alchemy/page_layouts.yml
@@ -163,14 +163,6 @@ module Alchemy
163
163
  # site_name accessor
164
164
  delegate :name, to: :site, prefix: true, allow_nil: true
165
165
 
166
- # Old public_on and public_until attributes for historical reasons
167
- #
168
- # These attributes now exist on the page versions
169
- #
170
- attr_readonly :legacy_public_on, :legacy_public_until
171
- deprecate :legacy_public_on, deprecator: Alchemy::Deprecation
172
- deprecate :legacy_public_until, deprecator: Alchemy::Deprecation
173
-
174
166
  # Class methods
175
167
  #
176
168
  class << self
@@ -33,36 +33,6 @@ module Alchemy
33
33
  image_file.thumbnail(upsample ? size : "#{size}>")
34
34
  end
35
35
 
36
- # Returns true if picture's width is greater than it's height
37
- #
38
- def landscape_format?
39
- image_file.landscape?
40
- end
41
-
42
- alias_method :landscape?, :landscape_format?
43
- deprecate landscape_format?: "Use image_file.landscape? instead", deprecator: Alchemy::Deprecation
44
- deprecate landscape?: "Use image_file.landscape? instead", deprecator: Alchemy::Deprecation
45
-
46
- # Returns true if picture's width is smaller than it's height
47
- #
48
- def portrait_format?
49
- image_file.portrait?
50
- end
51
-
52
- alias_method :portrait?, :portrait_format?
53
- deprecate portrait_format?: "Use image_file.portrait? instead", deprecator: Alchemy::Deprecation
54
- deprecate portrait?: "Use image_file.portrait? instead", deprecator: Alchemy::Deprecation
55
-
56
- # Returns true if picture's width and height is equal
57
- #
58
- def square_format?
59
- image_file.aspect_ratio == 1.0
60
- end
61
-
62
- alias_method :square?, :square_format?
63
- deprecate square_format?: "Use image_file.aspect_ratio instead", deprecator: Alchemy::Deprecation
64
- deprecate square?: "Use image_file.aspect_ratio instead", deprecator: Alchemy::Deprecation
65
-
66
36
  # Returns true if the class we're included in has a meaningful render_size attribute
67
37
  #
68
38
  def render_size?
@@ -36,7 +36,7 @@ module Alchemy
36
36
  else
37
37
  uid = PictureThumb::Uid.call(signature, variant)
38
38
  ActiveRecord::Base.connected_to(role: ActiveRecord::Base.writing_role) do
39
- PictureThumb.generator_class.call(variant, signature, uid)
39
+ PictureThumb::Create.call(variant, signature, uid)
40
40
  end
41
41
  uid
42
42
  end
@@ -47,17 +47,16 @@ module Alchemy
47
47
  include Alchemy::TouchElements
48
48
  include Calculations
49
49
 
50
- has_many :essence_pictures,
51
- class_name: "Alchemy::EssencePicture",
52
- foreign_key: "picture_id",
53
- inverse_of: :ingredient_association
50
+ has_many :picture_ingredients,
51
+ class_name: "Alchemy::Ingredients::Picture",
52
+ foreign_key: "related_object_id",
53
+ inverse_of: :related_object
54
54
 
55
- has_many :contents, through: :essence_pictures
56
- has_many :elements, through: :contents
55
+ has_many :elements, through: :picture_ingredients
57
56
  has_many :pages, through: :elements
58
57
  has_many :thumbs, class_name: "Alchemy::PictureThumb", dependent: :destroy
59
58
 
60
- # Raise error, if picture is in use (aka. assigned to an EssencePicture)
59
+ # Raise error, if picture is in use (aka. assigned to an Picture ingredient)
61
60
  #
62
61
  # === CAUTION
63
62
  #
@@ -114,7 +113,10 @@ module Alchemy
114
113
 
115
114
  scope :named, ->(name) { where("#{table_name}.name LIKE ?", "%#{name}%") }
116
115
  scope :recent, -> { where("#{table_name}.created_at > ?", Time.current - 24.hours).order(:created_at) }
117
- scope :deletable, -> { where("#{table_name}.id NOT IN (SELECT picture_id FROM #{EssencePicture.table_name})") }
116
+ scope :deletable,
117
+ -> {
118
+ where("#{table_name}.id NOT IN (SELECT related_object_id FROM alchemy_ingredients WHERE related_object_type = 'Alchemy::Picture')")
119
+ }
118
120
  scope :without_tag, -> { left_outer_joins(:taggings).where(gutentag_taggings: { id: nil }) }
119
121
  scope :by_file_format, ->(format) { where(image_file_format: format) }
120
122
 
@@ -279,10 +281,10 @@ module Alchemy
279
281
  pages.any? && pages.not_restricted.blank?
280
282
  end
281
283
 
282
- # Returns true if picture is not assigned to any EssencePicture.
284
+ # Returns true if picture is not assigned to any Picture ingredient.
283
285
  #
284
286
  def deletable?
285
- essence_pictures.empty?
287
+ picture_ingredients.empty?
286
288
  end
287
289
 
288
290
  # A size String from original image file values.
@@ -2,9 +2,11 @@
2
2
 
3
3
  module Alchemy
4
4
  class PictureThumb < BaseRecord
5
- # Stores the render result of a Alchemy::PictureVariant
6
- # in the configured Dragonfly datastore
7
- # (Default: Dragonfly::FileDataStore)
5
+ # Creates a Alchemy::PictureThumb
6
+ #
7
+ # Stores the processes result of a Alchemy::PictureVariant
8
+ # in the configured +Alchemy::PictureThumb.storage_class+
9
+ # (Default: {Alchemy::PictureThumb::FileStore})
8
10
  #
9
11
  class Create
10
12
  class << self
@@ -24,26 +26,13 @@ module Alchemy
24
26
  thumb.uid = uid
25
27
  end
26
28
  begin
27
- # process the image
28
- image = variant.image
29
- # store the processed image
30
- image.to_file(server_path(uid)).close
31
- rescue RuntimeError => e
29
+ Alchemy::PictureThumb.storage_class.call(variant, uid)
30
+ rescue StandardError => e
32
31
  ErrorTracking.notification_handler.call(e)
33
32
  # destroy the thumb if processing or storing fails
34
33
  @thumb&.destroy
35
34
  end
36
35
  end
37
-
38
- private
39
-
40
- # Alchemys dragonfly datastore config seperates the storage path from the public server
41
- # path for security reasons. The Dragonfly FileDataStorage does not support that,
42
- # so we need to build the path on our own.
43
- def server_path(uid)
44
- dragonfly_app = ::Dragonfly.app(:alchemy_pictures)
45
- "#{dragonfly_app.datastore.server_root}/#{uid}"
46
- end
47
36
  end
48
37
  end
49
38
  end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Alchemy
4
+ class PictureThumb < BaseRecord
5
+ # Stores the render result of a Alchemy::PictureVariant
6
+ # in the configured Dragonfly datastore
7
+ # (Default: Dragonfly::FileDataStore)
8
+ #
9
+ class FileStore
10
+ class << self
11
+ # @param [Alchemy::PictureVariant] variant the to be rendered image
12
+ # @param [String] uid The Unique Image Identifier the image is stored at
13
+ #
14
+ def call(variant, uid)
15
+ # process the image
16
+ image = variant.image
17
+ # store the processed image
18
+ image.to_file(server_path(uid)).close
19
+ end
20
+
21
+ private
22
+
23
+ # Alchemys dragonfly datastore config seperates the storage path from the public server
24
+ # path for security reasons. The Dragonfly FileDataStorage does not support that,
25
+ # so we need to build the path on our own.
26
+ def server_path(uid)
27
+ dragonfly_app = ::Dragonfly.app(:alchemy_pictures)
28
+ "#{dragonfly_app.datastore.server_root}/#{uid}"
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -7,7 +7,7 @@ module Alchemy
7
7
  # different thumbnail store (ie. a remote file storage).
8
8
  #
9
9
  # config/initializers/alchemy.rb
10
- # Alchemy::PictureThumb.generator_class = My::ThumbnailGenerator
10
+ # Alchemy::PictureThumb.storage_class = My::ThumbnailStore
11
11
  #
12
12
  class PictureThumb < BaseRecord
13
13
  belongs_to :picture, class_name: "Alchemy::Picture"
@@ -16,18 +16,18 @@ module Alchemy
16
16
  validates :uid, presence: true
17
17
 
18
18
  class << self
19
- # Thumbnail generator class
19
+ # Thumbnail storage class
20
20
  #
21
- # @see Alchemy::PictureThumb::Create
22
- def generator_class
23
- @_generator_class ||= Alchemy::PictureThumb::Create
21
+ # @see Alchemy::PictureThumb::FileStore
22
+ def storage_class
23
+ @_storage_class ||= Alchemy::PictureThumb::FileStore
24
24
  end
25
25
 
26
- # Set a thumbnail generator class
26
+ # Set a thumbnail storage class
27
27
  #
28
- # @see Alchemy::PictureThumb::Create
29
- def generator_class=(klass)
30
- @_generator_class = klass
28
+ # @see Alchemy::PictureThumb::FileStore
29
+ def storage_class=(klass)
30
+ @_storage_class = klass
31
31
  end
32
32
 
33
33
  # Upfront generation of picture thumbnails
@@ -49,7 +49,7 @@ module Alchemy
49
49
  next if thumb
50
50
 
51
51
  uid = Alchemy::PictureThumb::Uid.call(signature, variant)
52
- generator_class.call(variant, signature, uid)
52
+ Alchemy::PictureThumb::Create.call(variant, signature, uid)
53
53
  end
54
54
  end
55
55
  end