alchemy_cms 4.5.1 → 4.6.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.

Potentially problematic release.


This version of alchemy_cms might be problematic. Click here for more details.

Files changed (49) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yml +11 -14
  3. data/.rubocop.yml +7 -15
  4. data/CHANGELOG.md +18 -8
  5. data/app/assets/javascripts/alchemy/alchemy.link_dialog.js.coffee +5 -5
  6. data/app/assets/javascripts/alchemy/templates/page.hbs +1 -1
  7. data/app/assets/stylesheets/alchemy/_mixins.scss +2 -3
  8. data/app/assets/stylesheets/alchemy/_variables.scss +2 -2
  9. data/app/assets/stylesheets/alchemy/lists.scss +0 -8
  10. data/app/assets/stylesheets/alchemy/nodes.scss +1 -1
  11. data/app/assets/stylesheets/alchemy/sitemap.scss +59 -21
  12. data/app/assets/stylesheets/tinymce/skins/alchemy/skin.min.css.scss +6 -6
  13. data/app/controllers/alchemy/admin/pages_controller.rb +0 -1
  14. data/app/controllers/alchemy/api/pages_controller.rb +2 -0
  15. data/app/decorators/alchemy/content_editor.rb +55 -0
  16. data/app/helpers/alchemy/admin/pages_helper.rb +16 -16
  17. data/app/models/alchemy/attachment.rb +1 -1
  18. data/app/models/alchemy/content.rb +9 -23
  19. data/app/models/alchemy/element.rb +1 -1
  20. data/app/models/alchemy/node.rb +9 -8
  21. data/app/models/alchemy/page/url_path.rb +66 -0
  22. data/app/models/alchemy/page.rb +12 -1
  23. data/app/models/alchemy/picture.rb +1 -1
  24. data/app/serializers/alchemy/page_serializer.rb +2 -1
  25. data/app/serializers/alchemy/page_tree_serializer.rb +4 -3
  26. data/app/views/alchemy/admin/layoutpages/index.html.erb +5 -1
  27. data/app/views/alchemy/admin/nodes/_form.html.erb +2 -2
  28. data/app/views/alchemy/admin/pages/_form.html.erb +1 -1
  29. data/app/views/alchemy/admin/pages/_menu_fields.html.erb +33 -29
  30. data/app/views/alchemy/admin/pages/_page.html.erb +3 -6
  31. data/app/views/alchemy/admin/pages/_sitemap.html.erb +6 -0
  32. data/app/views/alchemy/admin/pages/info.html.erb +1 -1
  33. data/config/alchemy/config.yml +0 -6
  34. data/config/locales/alchemy.en.yml +6 -6
  35. data/lib/alchemy/config.rb +30 -2
  36. data/lib/alchemy/essence.rb +1 -1
  37. data/lib/alchemy/resource.rb +4 -6
  38. data/lib/alchemy/ssl_protection.rb +3 -1
  39. data/lib/alchemy/upgrader/four_point_six.rb +50 -0
  40. data/lib/alchemy/upgrader/four_point_two.rb +0 -1
  41. data/lib/alchemy/upgrader/tasks/cells_migration.rb +1 -2
  42. data/lib/alchemy/upgrader/tasks/cells_upgrader.rb +3 -21
  43. data/lib/alchemy/upgrader/tasks/element_partial_name_variable_updater.rb +4 -8
  44. data/lib/alchemy/userstamp.rb +1 -1
  45. data/lib/alchemy/version.rb +1 -1
  46. data/lib/tasks/alchemy/convert.rake +2 -0
  47. data/lib/tasks/alchemy/upgrade.rake +67 -46
  48. metadata +8 -6
  49. data/lib/alchemy/upgrader/tasks/fixed_element_name_finder.rb +0 -31
@@ -4,12 +4,12 @@ module Alchemy
4
4
  class Node < BaseRecord
5
5
  VALID_URL_REGEX = /\A(\/|\D[a-z\+\d\.\-]+:)/
6
6
 
7
- acts_as_nested_set scope: 'language_id', touch: true
8
- stampable stamper_class_name: Alchemy.user_class.name
7
+ acts_as_nested_set scope: "language_id", touch: true
8
+ stampable stamper_class_name: Alchemy.user_class_name
9
9
 
10
- belongs_to :site, class_name: 'Alchemy::Site'
11
- belongs_to :language, class_name: 'Alchemy::Language'
12
- belongs_to :page, class_name: 'Alchemy::Page', optional: true, inverse_of: :nodes
10
+ belongs_to :site, class_name: "Alchemy::Site"
11
+ belongs_to :language, class_name: "Alchemy::Language"
12
+ belongs_to :page, class_name: "Alchemy::Page", optional: true, inverse_of: :nodes
13
13
 
14
14
  validates :name, presence: true, if: -> { page.nil? }
15
15
  validates :url, format: { with: VALID_URL_REGEX }, unless: -> { url.nil? }
@@ -25,7 +25,8 @@ module Alchemy
25
25
  class << self
26
26
  # Returns all root nodes for current language
27
27
  def language_root_nodes
28
- raise 'No language found' if Language.current.nil?
28
+ raise "No language found" if Language.current.nil?
29
+
29
30
  roots.where(language_id: Language.current.id)
30
31
  end
31
32
 
@@ -48,7 +49,7 @@ module Alchemy
48
49
  # Returns the +menus.yml+ file path
49
50
  #
50
51
  def definitions_file_path
51
- Rails.root.join 'config/alchemy/menus.yml'
52
+ Rails.root.join "config/alchemy/menus.yml"
52
53
  end
53
54
  end
54
55
 
@@ -57,7 +58,7 @@ module Alchemy
57
58
  # Either the value is stored in the database, aka. an external url.
58
59
  # Or, if attached, the values comes from a page.
59
60
  def url
60
- page && "/#{page.urlname}" || read_attribute(:url).presence
61
+ page&.url_path || read_attribute(:url).presence
61
62
  end
62
63
 
63
64
  def to_partial_path
@@ -0,0 +1,66 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Alchemy
4
+ class Page
5
+ # = The url_path for this page
6
+ #
7
+ # Use this to build relative links to this page
8
+ #
9
+ # It takes several circumstances into account:
10
+ #
11
+ # 1. It returns just a slash for language root pages of the default langauge
12
+ # 2. It returns a url path with a leading slash for regular pages
13
+ # 3. It returns a url path with a leading slash and language code prefix for pages not having the default language
14
+ # 4. It returns a url path with a leading slash and the language code for language root pages of a non-default language
15
+ #
16
+ # == Examples
17
+ #
18
+ # Using Rails' link_to helper
19
+ #
20
+ # link_to page.url
21
+ #
22
+ class UrlPath
23
+ ROOT_PATH = "/"
24
+
25
+ def initialize(page)
26
+ @page = page
27
+ @language = @page.language
28
+ @site = @language.site
29
+ end
30
+
31
+ def call
32
+ return @page.urlname if @page.definition["redirects_to_external"]
33
+
34
+ if @page.language_root?
35
+ language_root_path
36
+ elsif @site.languages.select(&:public?).length > 1
37
+ page_path_with_language_prefix
38
+ else
39
+ page_path_with_leading_slash
40
+ end
41
+ end
42
+
43
+ private
44
+
45
+ def language_root_path
46
+ @language.default? ? ROOT_PATH : language_path
47
+ end
48
+
49
+ def page_path_with_language_prefix
50
+ @language.default? ? page_path : language_path + page_path
51
+ end
52
+
53
+ def page_path_with_leading_slash
54
+ @page.language_root? ? ROOT_PATH : page_path
55
+ end
56
+
57
+ def language_path
58
+ "/#{@page.language_code}"
59
+ end
60
+
61
+ def page_path
62
+ "/#{@page.urlname}"
63
+ end
64
+ end
65
+ end
66
+ end
@@ -85,7 +85,7 @@ module Alchemy
85
85
 
86
86
  acts_as_nested_set(dependent: :destroy)
87
87
 
88
- stampable stamper_class_name: Alchemy.user_class.name
88
+ stampable stamper_class_name: Alchemy.user_class_name
89
89
 
90
90
  belongs_to :language, optional: true
91
91
 
@@ -161,6 +161,10 @@ module Alchemy
161
161
 
162
162
  attr_accessor :menu_id
163
163
 
164
+ deprecate visible: "Page slugs will be visible in URLs of child pages all the time. " \
165
+ "Please use Menus and Tags instead to re-organize your pages if your page tree does not reflect the URL hierarchy.",
166
+ deprecator: Alchemy::Deprecation
167
+
164
168
  # Class methods
165
169
  #
166
170
  class << self
@@ -347,6 +351,13 @@ module Alchemy
347
351
  finder.elements(page: self)
348
352
  end
349
353
 
354
+ # = The url_path for this page
355
+ #
356
+ # @see Alchemy::Page::UrlPath#call
357
+ def url_path
358
+ Alchemy::Page::UrlPath.new(self).call
359
+ end
360
+
350
361
  # The page's view partial is dependent from its page layout
351
362
  #
352
363
  # == Define page layouts
@@ -74,7 +74,7 @@ module Alchemy
74
74
  case_sensitive: false,
75
75
  message: Alchemy.t("not a valid image")
76
76
 
77
- stampable stamper_class_name: Alchemy.user_class.name
77
+ stampable stamper_class_name: Alchemy.user_class_name
78
78
 
79
79
  scope :named, ->(name) {
80
80
  where("#{table_name}.name LIKE ?", "%#{name}%")
@@ -13,7 +13,8 @@ module Alchemy
13
13
  :tag_list,
14
14
  :created_at,
15
15
  :updated_at,
16
- :status
16
+ :status,
17
+ :url_path
17
18
 
18
19
  has_many :elements
19
20
  end
@@ -9,7 +9,7 @@ module Alchemy
9
9
  def pages
10
10
  tree = []
11
11
  path = [{id: object.parent_id, children: tree}]
12
- page_list = object.self_and_descendants
12
+ page_list = object.self_and_descendants.includes({ language: :site }, :locker)
13
13
  base_level = object.level - 1
14
14
  # Load folded pages in advance
15
15
  folded_user_pages = FoldedPage.folded_for_user(opts[:user]).pluck(:page_id)
@@ -60,9 +60,10 @@ module Alchemy
60
60
  redirects_to_external: page.definition['redirects_to_external'],
61
61
  urlname: page.urlname,
62
62
  external_urlname: page.definition['redirects_to_external'] ? page.external_urlname : nil,
63
+ url_path: page.url_path,
63
64
  level: level,
64
- root: level == 1,
65
- root_or_leaf: level == 1 || !has_children,
65
+ root: page.depth == 1,
66
+ root_or_leaf: page.depth == 1 || !has_children,
66
67
  children: []
67
68
  }
68
69
 
@@ -30,6 +30,10 @@
30
30
  </div>
31
31
  <% end %>
32
32
 
33
- <ul class="list" id="layoutpages">
33
+ <h4 id="sitemap_heading">
34
+ <span class="page_name"><%= Alchemy::Page.human_attribute_name(:name) %></span>
35
+ </h4>
36
+
37
+ <ul class="list" id="sitemap">
34
38
  <%= render partial: "layoutpage", collection: @layout_root.children %>
35
39
  </ul>
@@ -30,7 +30,7 @@
30
30
  initialSelection: {
31
31
  id: <%= node.page_id %>,
32
32
  text: "<%= node.page.name %>",
33
- url: "/<%= node.page.urlname %>"
33
+ url_path: "<%= node.page.url_path %>"
34
34
  }
35
35
  <% end %>
36
36
  }).on('change', function(e) {
@@ -39,7 +39,7 @@
39
39
  $('#node_url').val('').prop('disabled', false)
40
40
  } else {
41
41
  $('#node_name').attr('placeholder', e.added.name)
42
- $('#node_url').val('/' + e.added.urlname).prop('disabled', true)
42
+ $('#node_url').val(e.added.url_path).prop('disabled', true)
43
43
  }
44
44
  })
45
45
  </script>
@@ -18,7 +18,7 @@
18
18
  </div>
19
19
 
20
20
  <%= f.input :name, autofocus: true %>
21
- <%= f.input :urlname, as: 'string', input_html: {value: @page.slug} %>
21
+ <%= f.input :urlname, as: 'string', input_html: {value: @page.slug}, label: Alchemy::Page.human_attribute_name(:slug) %>
22
22
  <%= f.input :title,
23
23
  input_html: {'data-alchemy-char-counter' => 60} %>
24
24
 
@@ -1,33 +1,37 @@
1
- <% if @page.menus.any? %>
2
- <label class="checkbox">
3
- <input type="checkbox" disabled checked>
4
- <%= Alchemy.t(:attached_to) %>
5
- </label>
6
- <% @page.menus.each do |menu| %>
7
- <span class="page-menu-name label">
8
- <%= menu.name %>
9
- </span>
1
+ <% if Alchemy::Node.roots.where(language: @page.language).any? %>
2
+ <% unless @page.language_root %>
3
+ <%= page_status_checkbox(@page, :visible, label: Alchemy.t("show in url of child pages")) %>
4
+ <% end %>
5
+ <% if @page.menus.any? %>
6
+ <label style="vertical-align: middle">
7
+ <%= Alchemy.t(:attached_to) %>
8
+ </label>
9
+ <% @page.menus.each do |menu| %>
10
+ <span class="page-menu-name label">
11
+ <%= I18n.t(menu.name, scope: [:alchemy, :menu_names]) %>
12
+ </span>
13
+ <% end %>
14
+ <% else %>
15
+ <a class="button small" id="attach-page"><%= Alchemy.t("attach to a menu") %></a>
16
+ <%= f.input :menu_id, collection: Alchemy::Node.roots.map { |n|
17
+ [I18n.t(n.name, scope: [:alchemy, :menu_names]), n.id]
18
+ },
19
+ prompt: Alchemy.t("Please choose a menu"),
20
+ input_html: { class: "alchemy_selectbox" },
21
+ wrapper_html: { class: "hidden" },
22
+ label: false %>
23
+ <script>
24
+ (function() {
25
+ var wrapper = document.querySelector(".input.page_menu_id")
26
+ document.querySelector("#attach-page").addEventListener("click", function() {
27
+ var select = wrapper.querySelector("select")
28
+ this.classList.toggle("active")
29
+ wrapper.classList.toggle("hidden")
30
+ $(select).select2("val", "")
31
+ })
32
+ })()
33
+ </script>
10
34
  <% end %>
11
- <% elsif Alchemy::Node.roots.any? %>
12
- <%= page_status_checkbox(@page, :visible) %>
13
- <%= f.input :menu_id, collection: Alchemy::Node.roots.map { |n| [n.name, n.id] },
14
- prompt: Alchemy.t('Please choose a menu'),
15
- input_html: { class: 'alchemy_selectbox' },
16
- wrapper_html: { style: @page.visible? ? 'display: block' : 'display: none' },
17
- label: false %>
18
- <script>
19
- (function() {
20
- var $wrapper = $('.input.page_menu_id')
21
- $('#page_visible').click(function() {
22
- if ($(this).is(':checked')) {
23
- $wrapper.show()
24
- } else {
25
- $wrapper.find('select').val('')
26
- $wrapper.hide()
27
- }
28
- })
29
- })()
30
- </script>
31
35
  <% else %>
32
36
  <%= page_status_checkbox(@page, :visible) %>
33
37
  <% end %>
@@ -159,12 +159,9 @@
159
159
  <span class="hint-bubble">{{status_titles.restricted}}</span>
160
160
  </span>
161
161
  </div>
162
- {{#if redirects_to_external}}
163
- <div class="redirect_url" title="{{urlname}}">
164
- &raquo; <%= Alchemy.t('Redirects to') %>:
165
- {{ external_urlname }}
166
- </div>
167
- {{/if}}
162
+ <div class="sitemap_url" title="{{url_path}}">
163
+ {{ url_path }}
164
+ </div>
168
165
  <div class="sitemap_sitename">
169
166
  {{#if redirects_to_external}}
170
167
  <span class="sitemap_pagename_link inactive">{{ name }}</span>
@@ -1,4 +1,10 @@
1
1
  <div id="sitemap-wrapper">
2
+ <h4 id="sitemap_heading">
3
+ <span class="page_name"><%= Alchemy::Page.human_attribute_name(:name) %></span>
4
+ <span class="page_urlname"><%= Alchemy::Page.human_attribute_name(:urlname) %></span>
5
+ <span class="page_status"><%= Alchemy.t(:page_status) %></span>
6
+ </h4>
7
+
2
8
  <p class="loading"></p>
3
9
  </div>
4
10
 
@@ -18,7 +18,7 @@
18
18
  <label><%= Alchemy::Page.human_attribute_name(:urlname) %></label>
19
19
  <p><%= @page.urlname %></p>
20
20
  <% else %>
21
- <label><%= Alchemy::LegacyPageUrl.human_attribute_name(:urlname) %></label>
21
+ <label><%= Alchemy::Page.human_attribute_name(:urlname) %></label>
22
22
  <p><%= "/#{@page.urlname}" %></p>
23
23
  <% end %>
24
24
  </div>
@@ -1,12 +1,6 @@
1
1
  # == This is the global Alchemy configuration file
2
2
  #
3
3
 
4
- # === Require SSL for login form and all admin modules
5
- #
6
- # NOTE: You have to create a SSL certificate on your server to make this work
7
- #
8
- require_ssl: false
9
-
10
4
  # === Auto Log Out Time
11
5
  #
12
6
  # The amount of time of inactivity in minutes after which the user is kicked out of his current session.
@@ -573,7 +573,6 @@ en:
573
573
  button_label: Upload image(s)
574
574
  upload_success: "Picture %{name} uploaded successfully"
575
575
  upload_failure: "Error while uploading %{name}: %{error}"
576
- url_name: "URL-Name"
577
576
  visible: "visible"
578
577
  want_to_create_new_language: "Do you want to create a new empty language tree?"
579
578
  want_to_make_copy_of_existing_language: "Do you want to copy an existing language tree?"
@@ -670,9 +669,9 @@ en:
670
669
  page_layout:
671
670
  blank: "^Please choose a page layout."
672
671
  urlname:
673
- too_short: "^The pages urlname is too short (minimum of 3 characters)."
674
- taken: "^URL-Name already taken."
675
- exclusion: "^URL-Name reserved."
672
+ too_short: "^URL-Path is too short (minimum of 3 characters)."
673
+ taken: "^URL-Path already taken."
674
+ exclusion: "^URL-Path reserved."
676
675
  alchemy/picture:
677
676
  attributes:
678
677
  image_file:
@@ -780,7 +779,7 @@ en:
780
779
  locale: Localization
781
780
  code: ISO Code
782
781
  alchemy/legacy_page_url:
783
- urlname: "URL path"
782
+ urlname: "URL-Path"
784
783
  alchemy/node:
785
784
  name: "Name"
786
785
  title: "Title"
@@ -805,7 +804,8 @@ en:
805
804
  tag_list: Tags
806
805
  title: "Title"
807
806
  updated_at: "Updated at"
808
- urlname: "Urlname"
807
+ urlname: "URL-Path"
808
+ slug: "Slug"
809
809
  visible: "visible in navigation"
810
810
  alchemy/picture:
811
811
  image_file_name: "Filename"
@@ -8,8 +8,10 @@ module Alchemy
8
8
  # @param name [String]
9
9
  #
10
10
  def get(name)
11
+ check_deprecation(name)
11
12
  show[name.to_s]
12
13
  end
14
+
13
15
  alias_method :parameter, :get
14
16
 
15
17
  # Returns a merged configuration of the following files
@@ -25,11 +27,22 @@ module Alchemy
25
27
  @config ||= merge_configs!(alchemy_config, main_app_config, env_specific_config)
26
28
  end
27
29
 
30
+ # A list of deprecated configurations
31
+ # a value of nil means there is no new default
32
+ # any not nil value is the new default
33
+ def deprecated_configs
34
+ {
35
+ url_nesting: true,
36
+ require_ssl: nil,
37
+ auto_logout_time: nil,
38
+ }
39
+ end
40
+
28
41
  private
29
42
 
30
43
  # Alchemy default configuration
31
44
  def alchemy_config
32
- read_file(File.join(File.dirname(__FILE__), '..', '..', 'config/alchemy/config.yml'))
45
+ read_file(File.join(File.dirname(__FILE__), "..", "..", "config/alchemy/config.yml"))
33
46
  end
34
47
 
35
48
  # Application specific configuration
@@ -54,11 +67,26 @@ module Alchemy
54
67
  # Merges all given configs together
55
68
  #
56
69
  def merge_configs!(*config_files)
57
- raise LoadError, 'No Alchemy config file found!' if config_files.map(&:blank?).all?
70
+ raise LoadError, "No Alchemy config file found!" if config_files.map(&:blank?).all?
71
+
58
72
  config = {}
59
73
  config_files.each { |h| config.merge!(h.stringify_keys!) }
60
74
  config
61
75
  end
76
+
77
+ def check_deprecation(name)
78
+ if deprecated_configs.key?(name.to_sym)
79
+ config = deprecated_configs[name.to_sym]
80
+ if config.nil?
81
+ Alchemy::Deprecation.warn("#{name} configuration is deprecated and will be removed from Alchemy 5.0")
82
+ else
83
+ value = show[name.to_s]
84
+ if value != config
85
+ Alchemy::Deprecation.warn("Setting #{name} configuration to #{value} is deprecated and will be always #{config} in Alchemy 5.0")
86
+ end
87
+ end
88
+ end
89
+ end
62
90
  end
63
91
  end
64
92
  end
@@ -48,7 +48,7 @@ module Alchemy #:nodoc:
48
48
  class_eval <<-RUBY, __FILE__, __LINE__ + 1
49
49
  attr_writer :validation_errors
50
50
  include Alchemy::Essence::InstanceMethods
51
- stampable stamper_class_name: Alchemy.user_class.name
51
+ stampable stamper_class_name: Alchemy.user_class_name
52
52
  validate :validate_ingredient, on: :update, if: -> { validations.any? }
53
53
 
54
54
  has_one :content, as: :essence, class_name: "Alchemy::Content", inverse_of: :essence
@@ -131,23 +131,21 @@ module Alchemy
131
131
  end
132
132
 
133
133
  def namespaced_resource_name
134
- @_namespaced_resource_name ||= begin
135
- namespaced_resources_name.to_s.singularize
136
- end.to_sym # Rails >= 6.0.3.7 needs symbols in polymorphic routes
134
+ @_namespaced_resource_name ||= namespaced_resources_name.singularize
137
135
  end
138
136
 
139
137
  def namespaced_resources_name
140
138
  @_namespaced_resources_name ||= begin
141
139
  resource_name_array = resource_array.dup
142
140
  resource_name_array.delete(engine_name) if in_engine?
143
- resource_name_array.join("_")
144
- end.to_sym # Rails >= 6.0.3.7 needs symbols in polymorphic routes
141
+ resource_name_array.join('_')
142
+ end
145
143
  end
146
144
 
147
145
  def namespace_for_scope
148
146
  namespace_array = namespace_diff
149
147
  namespace_array.delete(engine_name) if in_engine?
150
- namespace_array.map(&:to_sym) # Rails >= 6.0.3.7 needs symbols in polymorphic routes
148
+ namespace_array
151
149
  end
152
150
 
153
151
  # Returns an array of underscored association names
@@ -26,7 +26,9 @@ module Alchemy
26
26
 
27
27
  # Redirects current request to https.
28
28
  def enforce_ssl
29
- redirect_to url_for(request.params.merge(protocol: 'https'))
29
+ redirect_to url_for(request.params.merge(protocol: "https"))
30
30
  end
31
+
32
+ deprecate :enforce_ssl, deprecator: Alchemy::Deprecation
31
33
  end
32
34
  end
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Alchemy
4
+ class Upgrader::FourPointSix < Upgrader
5
+ class << self
6
+ def todos
7
+ notice = <<-NOTE.strip_heredoc
8
+
9
+ ℹ️ Page visible attribute is deprecated
10
+ ----------------------------------------
11
+
12
+ Page slugs will be visible in URLs of child pages all the time in the future.
13
+ Please use Menus and Tags instead to re-organize your pages if your page tree does not reflect the URL hierarchy.
14
+
15
+ A rake task to help with the migration is available.
16
+
17
+ bin/rake alchemy:upgrade:4.6:restructure_page_tree
18
+
19
+ NOTE
20
+ todo notice, "Alchemy v4.6 TODO"
21
+ end
22
+
23
+ def restructure_page_tree
24
+ desc "Move child pages of invisible pages to visible parent."
25
+ Alchemy::Deprecation.silence do
26
+ # All leaves can safely be marked visible
27
+ Alchemy::Page.leaves.update_all(visible: true)
28
+ Alchemy::Page.language_roots.each do |root_page|
29
+ # Root pages are always visible
30
+ root_page.update!(visible: true)
31
+ remove_invisible_children(root_page)
32
+ end
33
+ Alchemy::Page.update_all(visible: true)
34
+ end
35
+ end
36
+
37
+ private
38
+
39
+ def remove_invisible_children(page)
40
+ page.children.each { |child| remove_invisible_children(child) }
41
+ if !page.visible
42
+ page.children.reload.reverse.each do |child|
43
+ puts "Moving #{child.urlname} to right of #{page.urlname}"
44
+ child.move_to_right_of(page)
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
@@ -1,6 +1,5 @@
1
1
  require_relative 'tasks/picture_gallery_upgrader'
2
2
  require_relative 'tasks/picture_gallery_migration'
3
- require_relative 'tasks/fixed_element_name_finder'
4
3
  require_relative 'tasks/cells_upgrader'
5
4
  require_relative 'tasks/cells_migration'
6
5
  require_relative 'tasks/element_partial_name_variable_updater'
@@ -8,7 +8,6 @@ module Alchemy::Upgrader::Tasks
8
8
  def migrate_cells
9
9
  if ActiveRecord::Base.connection.data_source_exists?('alchemy_cells')
10
10
  cells = Cell.all
11
- @fixed_element_name_finder = FixedElementNameFinder.new
12
11
 
13
12
  if cells.any?
14
13
  cells.each do |cell|
@@ -27,7 +26,7 @@ module Alchemy::Upgrader::Tasks
27
26
  def migrate_cell!(cell)
28
27
  # bust element definitions insta cache
29
28
  Alchemy::Element.instance_variable_set('@definitions', nil)
30
- fixed_element = Alchemy::Element.find_or_initialize_by(fixed: true, name: @fixed_element_name_finder.call(cell.name), page: cell.page)
29
+ fixed_element = Alchemy::Element.find_or_initialize_by(fixed: true, name: cell.name, page: cell.page)
31
30
  elements = Alchemy::Element.where(cell_id: cell.id).order(position: :asc)
32
31
 
33
32
  if fixed_element.new_record?
@@ -72,13 +72,12 @@ module Alchemy::Upgrader::Tasks
72
72
 
73
73
  def convert_cell_config
74
74
  puts '-- Converting cells into unique fixed nestable elements.'
75
- fixed_element_name_finder = FixedElementNameFinder.new
76
75
 
77
76
  YAML.load_file(cells_config_file).each do |cell|
78
77
  append_to_file Rails.root.join('config', 'alchemy', 'elements.yml') do
79
78
  <<-CELL.strip_heredoc
80
79
 
81
- - name: #{fixed_element_name_finder.call(cell['name'])}
80
+ - name: #{cell['name']}
82
81
  fixed: true
83
82
  unique: true
84
83
  nestable_elements: [#{cell['elements'].join(', ')}]
@@ -129,25 +128,8 @@ module Alchemy::Upgrader::Tasks
129
128
  puts "-- Update render_cell calls"
130
129
  Dir.glob("#{alchemy_views_folder}/**/*").each do |view|
131
130
  next if File.directory?(view)
132
- # <%= render_cell 'test' %>
133
- # <%= render_cell('test') %>
134
- # <%= render_cell("test", options: true) %>
135
- content = File.binread(view)
136
- content.gsub!(/render_cell([\s(]+)(['":])(\w+)([^\w])(.*?)/) do
137
- element_name = CellNameMigrator.call($3)
138
- "render_elements#{$1}only: #{$2}#{element_name}#{$4}, fixed: true#{$5}"
139
- end
140
-
141
- # <%= render_elements from_cell: 'page_intro' %>
142
- # <%= render_elements testing: 'blubb', from_cell: :page_intro %>
143
- # <%= render_elements from_cell: "page_intro", testing: 'blubb' %>
144
- # <%= render_elements(from_cell: "page_intro", testing: 'blubb') %>
145
- # <%= render_elements(testing: 'blubb', from_cell: "page_intro") %>
146
- content.gsub!(/render_elements(.*?)from_cell[:\s=>]+([:'"])(\w+)(['"]?)(.*)/) do
147
- element_name = CellNameMigrator.call($3)
148
- "render_elements#{$1}only: #{$2}#{element_name}#{$4}, fixed: true#{$5}"
149
- end
150
- File.open(view, "wb") { |file| file.write(content) }
131
+ gsub_file(view, /render_cell[\(\s]?([:'"]?[a-z_]+['"]?)\)?/, 'render_elements(only: \1, fixed: true)')
132
+ gsub_file(view, /render_elements[\(\s](.*):?from_cell:?\s?(=>)?\s?(['"][a-z_]+['"])\)?/, 'render_elements(\1only: \3, fixed: true)')
151
133
  end
152
134
  end
153
135
 
@@ -11,14 +11,10 @@ module Alchemy::Upgrader::Tasks
11
11
  puts "-- Update element views local variable to partial name"
12
12
  Dir.glob("#{elements_view_folder}/*_view.*").each do |view|
13
13
  variable_name = File.basename(view).gsub(/^_([\w-]*)\..*$/, '\1')
14
- %w[
15
- cache
16
- render_essence_view_by_name
17
- element_view_for
18
- ].each do |method_name|
19
- gsub_file(view, /#{method_name}([\s(]+)element([^\w])/, "#{method_name}\\1#{variable_name}\\2")
20
- end
21
- gsub_file(view, /([\s(%={]+)element([^\w:"'])/, "\\1#{variable_name}\\2")
14
+ gsub_file(view, /cache\(?element([,\s\w:\-,=>'"\?\/]*)\)?/, "cache(#{variable_name}\\1)")
15
+ gsub_file(view, /render_essence_view_by_name\(?element([,\s\w:\-,=>'"\?\/]*)\)?/, "render_essence_view_by_name(#{variable_name}\\1)")
16
+ gsub_file(view, /element_view_for\(?element([,\s\w:\-,=>'"\?\/]*)\)?/, "element_view_for(#{variable_name}\\1)")
17
+ gsub_file(view, /element\.([\w\?]+)/, "#{variable_name}.\\1")
22
18
  end
23
19
  end
24
20
  end
@@ -7,6 +7,6 @@
7
7
  if Alchemy.user_class < ActiveRecord::Base
8
8
  Alchemy.user_class.class_eval do
9
9
  model_stamper
10
- stampable stamper_class_name: Alchemy.user_class.name
10
+ stampable stamper_class_name: Alchemy.user_class_name
11
11
  end
12
12
  end