alchemy_cms 4.5.1 → 4.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/ci.yml +11 -14
- data/.rubocop.yml +7 -15
- data/CHANGELOG.md +18 -8
- data/app/assets/javascripts/alchemy/alchemy.link_dialog.js.coffee +5 -5
- data/app/assets/javascripts/alchemy/templates/page.hbs +1 -1
- data/app/assets/stylesheets/alchemy/_mixins.scss +2 -3
- data/app/assets/stylesheets/alchemy/_variables.scss +2 -2
- data/app/assets/stylesheets/alchemy/lists.scss +0 -8
- data/app/assets/stylesheets/alchemy/nodes.scss +1 -1
- data/app/assets/stylesheets/alchemy/sitemap.scss +59 -21
- data/app/assets/stylesheets/tinymce/skins/alchemy/skin.min.css.scss +6 -6
- data/app/controllers/alchemy/admin/pages_controller.rb +0 -1
- data/app/controllers/alchemy/api/pages_controller.rb +2 -0
- data/app/decorators/alchemy/content_editor.rb +55 -0
- data/app/helpers/alchemy/admin/pages_helper.rb +16 -16
- data/app/models/alchemy/attachment.rb +1 -1
- data/app/models/alchemy/content.rb +9 -23
- data/app/models/alchemy/element.rb +1 -1
- data/app/models/alchemy/node.rb +9 -8
- data/app/models/alchemy/page/url_path.rb +66 -0
- data/app/models/alchemy/page.rb +12 -1
- data/app/models/alchemy/picture.rb +1 -1
- data/app/serializers/alchemy/page_serializer.rb +2 -1
- data/app/serializers/alchemy/page_tree_serializer.rb +4 -3
- data/app/views/alchemy/admin/layoutpages/index.html.erb +5 -1
- data/app/views/alchemy/admin/nodes/_form.html.erb +2 -2
- data/app/views/alchemy/admin/pages/_form.html.erb +1 -1
- data/app/views/alchemy/admin/pages/_menu_fields.html.erb +33 -29
- data/app/views/alchemy/admin/pages/_page.html.erb +3 -6
- data/app/views/alchemy/admin/pages/_sitemap.html.erb +6 -0
- data/app/views/alchemy/admin/pages/info.html.erb +1 -1
- data/config/alchemy/config.yml +0 -6
- data/config/locales/alchemy.en.yml +6 -6
- data/lib/alchemy/config.rb +30 -2
- data/lib/alchemy/essence.rb +1 -1
- data/lib/alchemy/resource.rb +4 -6
- data/lib/alchemy/ssl_protection.rb +3 -1
- data/lib/alchemy/upgrader/four_point_six.rb +50 -0
- data/lib/alchemy/upgrader/four_point_two.rb +0 -1
- data/lib/alchemy/upgrader/tasks/cells_migration.rb +1 -2
- data/lib/alchemy/upgrader/tasks/cells_upgrader.rb +3 -21
- data/lib/alchemy/upgrader/tasks/element_partial_name_variable_updater.rb +4 -8
- data/lib/alchemy/userstamp.rb +1 -1
- data/lib/alchemy/version.rb +1 -1
- data/lib/tasks/alchemy/convert.rake +2 -0
- data/lib/tasks/alchemy/upgrade.rake +67 -46
- metadata +8 -6
- data/lib/alchemy/upgrader/tasks/fixed_element_name_finder.rb +0 -31
data/app/models/alchemy/node.rb
CHANGED
@@ -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:
|
8
|
-
stampable stamper_class_name: Alchemy.
|
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:
|
11
|
-
belongs_to :language, class_name:
|
12
|
-
belongs_to :page, class_name:
|
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
|
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
|
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
|
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
|
data/app/models/alchemy/page.rb
CHANGED
@@ -85,7 +85,7 @@ module Alchemy
|
|
85
85
|
|
86
86
|
acts_as_nested_set(dependent: :destroy)
|
87
87
|
|
88
|
-
stampable stamper_class_name: Alchemy.
|
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.
|
77
|
+
stampable stamper_class_name: Alchemy.user_class_name
|
78
78
|
|
79
79
|
scope :named, ->(name) {
|
80
80
|
where("#{table_name}.name LIKE ?", "%#{name}%")
|
@@ -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:
|
65
|
-
root_or_leaf:
|
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
|
-
<
|
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
|
-
|
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(
|
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.
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
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
|
-
{{
|
163
|
-
|
164
|
-
|
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::
|
21
|
+
<label><%= Alchemy::Page.human_attribute_name(:urlname) %></label>
|
22
22
|
<p><%= "/#{@page.urlname}" %></p>
|
23
23
|
<% end %>
|
24
24
|
</div>
|
data/config/alchemy/config.yml
CHANGED
@@ -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: "^
|
674
|
-
taken: "^URL-
|
675
|
-
exclusion: "^URL-
|
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
|
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: "
|
807
|
+
urlname: "URL-Path"
|
808
|
+
slug: "Slug"
|
809
809
|
visible: "visible in navigation"
|
810
810
|
alchemy/picture:
|
811
811
|
image_file_name: "Filename"
|
data/lib/alchemy/config.rb
CHANGED
@@ -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__),
|
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,
|
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
|
data/lib/alchemy/essence.rb
CHANGED
@@ -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.
|
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
|
data/lib/alchemy/resource.rb
CHANGED
@@ -131,23 +131,21 @@ module Alchemy
|
|
131
131
|
end
|
132
132
|
|
133
133
|
def namespaced_resource_name
|
134
|
-
@_namespaced_resource_name ||=
|
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
|
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
|
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:
|
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:
|
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: #{
|
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
|
-
|
133
|
-
|
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
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
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
|