refinerycms-pages 2.1.5 → 3.0.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.
- checksums.yaml +4 -4
- data/app/controllers/refinery/admin/page_parts_controller.rb +6 -1
- data/app/controllers/refinery/admin/pages_controller.rb +53 -45
- data/app/controllers/refinery/pages/admin/preview_controller.rb +12 -3
- data/app/controllers/refinery/pages_controller.rb +12 -12
- data/app/helpers/refinery/admin/pages_helper.rb +5 -4
- data/app/helpers/refinery/pages/content_pages_helper.rb +6 -1
- data/app/models/refinery/page.rb +115 -141
- data/app/models/refinery/page_part.rb +32 -7
- data/app/presenters/refinery/pages/content_presenter.rb +7 -5
- data/app/presenters/refinery/pages/menu_presenter.rb +41 -15
- data/app/presenters/refinery/pages/page_part_section_presenter.rb +1 -7
- data/app/presenters/refinery/pages/section_presenter.rb +2 -6
- data/app/views/refinery/admin/pages/_actions.html.erb +4 -13
- data/app/views/refinery/admin/pages/_form.html.erb +7 -10
- data/app/views/refinery/admin/pages/_form_advanced_options.html.erb +5 -3
- data/app/views/refinery/admin/pages/_form_extra_fields_for_more_options.html.erb +1 -0
- data/app/views/refinery/admin/pages/_form_new_page_parts.html.erb +8 -0
- data/app/views/refinery/admin/pages/_form_page_parts.html.erb +10 -21
- data/app/views/refinery/admin/pages/_page.html.erb +31 -31
- data/app/views/refinery/admin/pages/_page_part_field.html.erb +2 -1
- data/app/views/refinery/admin/pages/_records.html.erb +3 -3
- data/app/views/refinery/admin/pages/_save_and_continue_callback.html.erb +1 -0
- data/app/views/refinery/admin/pages/index.html.erb +2 -4
- data/app/views/refinery/admin/pages_dialogs/link_to.html.erb +1 -1
- data/config/locales/bg.yml +1 -2
- data/config/locales/ca.yml +85 -0
- data/config/locales/cs.yml +13 -3
- data/config/locales/da.yml +1 -2
- data/config/locales/de.yml +0 -1
- data/config/locales/el.yml +41 -29
- data/config/locales/en.yml +2 -2
- data/config/locales/es.yml +2 -4
- data/config/locales/fi.yml +1 -4
- data/config/locales/fr.yml +2 -2
- data/config/locales/hu.yml +1 -2
- data/config/locales/it.yml +15 -16
- data/config/locales/ja.yml +1 -3
- data/config/locales/ko.yml +1 -4
- data/config/locales/lt.yml +1 -3
- data/config/locales/lv.yml +0 -2
- data/config/locales/nb.yml +1 -4
- data/config/locales/nl.yml +1 -2
- data/config/locales/pl.yml +1 -13
- data/config/locales/pt-BR.yml +1 -3
- data/config/locales/pt.yml +1 -2
- data/config/locales/rs.yml +1 -3
- data/config/locales/ru.yml +8 -5
- data/config/locales/sk.yml +1 -2
- data/config/locales/sl.yml +1 -3
- data/config/locales/sv.yml +1 -3
- data/config/locales/tr.yml +1 -2
- data/config/locales/uk.yml +1 -5
- data/config/locales/vi.yml +1 -3
- data/config/locales/zh-CN.yml +1 -4
- data/config/locales/zh-TW.yml +1 -3
- data/config/routes.rb +16 -16
- data/db/migrate/20100913234708_create_refinerycms_pages_schema.rb +28 -11
- data/db/migrate/20140105190324_add_custom_slug_to_refinery_pages.rb +20 -0
- data/db/migrate/20150130044643_add_slug_to_refinery_page_parts.rb +6 -0
- data/db/migrate/20150720155305_update_slug_and_title_in_refinery_page_parts.rb +13 -0
- data/db/seeds.rb +42 -36
- data/lib/generators/refinery/pages/templates/config/initializers/refinery/pages.rb.erb +12 -0
- data/lib/refinery/pages.rb +4 -3
- data/lib/refinery/pages/admin/instance_methods.rb +3 -3
- data/lib/refinery/pages/configuration.rb +7 -1
- data/lib/refinery/pages/engine.rb +19 -18
- data/lib/refinery/pages/finder.rb +179 -0
- data/lib/refinery/pages/instance_methods.rb +3 -14
- data/lib/refinery/pages/tab.rb +2 -2
- data/lib/refinery/pages/types.rb +1 -1
- data/lib/refinery/pages/url.rb +15 -3
- data/license.md +1 -1
- data/refinerycms-pages.gemspec +8 -5
- data/spec/controllers/refinery/admin/pages_controller_spec.rb +53 -0
- data/spec/controllers/refinery/pages_controller_spec.rb +1 -1
- data/spec/factories/pages.rb +1 -1
- data/spec/features/refinery/admin/pages_spec.rb +274 -290
- data/spec/features/refinery/pages_spec.rb +123 -138
- data/spec/helpers/refinery/pages/admin/pages_helper_spec.rb +15 -11
- data/spec/helpers/refinery/pages/content_pages_helper_spec.rb +11 -11
- data/spec/lib/generators/refinery/pages/pages_generator_spec.rb +1 -1
- data/spec/lib/pages_spec.rb +2 -2
- data/spec/lib/refinery/pages/tab_spec.rb +9 -9
- data/spec/lib/refinery/pages/url_spec.rb +12 -12
- data/spec/models/refinery/page_finder_spec.rb +72 -0
- data/spec/models/refinery/page_menu_spec.rb +107 -0
- data/spec/models/refinery/page_meta_data_spec.rb +49 -0
- data/spec/models/refinery/page_part_spec.rb +67 -0
- data/spec/models/refinery/page_spec.rb +16 -534
- data/spec/models/refinery/page_url_spec.rb +320 -0
- data/spec/presenters/refinery/pages/content_page_presenter_spec.rb +9 -9
- data/spec/presenters/refinery/pages/content_presenter_spec.rb +20 -20
- data/spec/presenters/refinery/pages/menu_presenter_spec.rb +44 -6
- data/spec/presenters/refinery/pages/page_part_section_presenter_spec.rb +12 -12
- data/spec/presenters/refinery/pages/section_presenter_spec.rb +22 -22
- data/spec/presenters/refinery/pages/title_section_presenter_spec.rb +4 -4
- data/spec/support/refinery/pages/caching_helpers.rb +2 -2
- metadata +55 -25
- data/app/helpers/refinery/admin/page_parts_helper.rb +0 -6
- data/app/helpers/refinery/admin/pages_dialogs_helper.rb +0 -6
- data/app/sweepers/refinery/pages/page_sweeper.rb +0 -29
- data/lib/refinery/pages/caching.rb +0 -60
- data/spec/lib/refinery/pages/caching_spec.rb +0 -90
- data/spec/support/refinery/pages/caching.rb +0 -19
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 2bdcbfb6ced22f015c509108b4cdf43b28a2fb99
|
|
4
|
+
data.tar.gz: f1c3faf991e0c23fa346ed0461d5cf3759139bb0
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 7dbd0c97774895a794dd88fd3114f8d601ebfca7de61771b9b60714b7614a4482511bf4e123da675eac832802c222a1539013c46806dd86ea575e7cbebfe102b
|
|
7
|
+
data.tar.gz: fd285907905d48ccbeaaacbebe163f5d101d25b5198c347ba2a427ee9c123d1541f362afeb8d2eb42ab0a6c97ca1baf6aa8511adababa9e0bdddf42522b63f54
|
|
@@ -4,7 +4,7 @@ module Refinery
|
|
|
4
4
|
|
|
5
5
|
def new
|
|
6
6
|
render :partial => '/refinery/admin/pages/page_part_field', :locals => {
|
|
7
|
-
:part => ::Refinery::PagePart.new(
|
|
7
|
+
:part => ::Refinery::PagePart.new(new_page_part_params),
|
|
8
8
|
:new_part => true,
|
|
9
9
|
:part_index => params[:part_index]
|
|
10
10
|
}
|
|
@@ -21,6 +21,11 @@ module Refinery
|
|
|
21
21
|
end
|
|
22
22
|
end
|
|
23
23
|
|
|
24
|
+
protected
|
|
25
|
+
def new_page_part_params
|
|
26
|
+
params.permit(:title, :slug, :body)
|
|
27
|
+
end
|
|
28
|
+
|
|
24
29
|
end
|
|
25
30
|
end
|
|
26
31
|
end
|
|
@@ -1,22 +1,18 @@
|
|
|
1
1
|
module Refinery
|
|
2
2
|
module Admin
|
|
3
3
|
class PagesController < Refinery::AdminController
|
|
4
|
-
|
|
5
|
-
cache_sweeper Pages::PageSweeper
|
|
4
|
+
prepend Pages::InstanceMethods
|
|
6
5
|
|
|
7
6
|
crudify :'refinery/page',
|
|
8
|
-
:order => "lft ASC",
|
|
9
7
|
:include => [:translations, :children],
|
|
10
8
|
:paging => false
|
|
11
9
|
|
|
12
|
-
|
|
13
|
-
before_filter :restrict_access, :only => [:create, :update, :update_positions, :destroy]
|
|
14
|
-
after_filter proc { Pages::Caching.new().expire! }, :only => :update_positions
|
|
10
|
+
helper_method :valid_layout_templates, :valid_view_templates
|
|
15
11
|
|
|
16
12
|
def new
|
|
17
|
-
@page = Page.new(
|
|
13
|
+
@page = Page.new(new_page_params)
|
|
18
14
|
Pages.default_parts_for(@page).each_with_index do |page_part, index|
|
|
19
|
-
@page.parts << PagePart.new(:title => page_part, :position => index)
|
|
15
|
+
@page.parts << PagePart.new(:title => page_part, :slug => page_part, :position => index)
|
|
20
16
|
end
|
|
21
17
|
end
|
|
22
18
|
|
|
@@ -26,43 +22,38 @@ module Refinery
|
|
|
26
22
|
end
|
|
27
23
|
|
|
28
24
|
def update
|
|
29
|
-
if @page.update_attributes(
|
|
30
|
-
flash.notice = t(
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
)
|
|
34
|
-
|
|
35
|
-
unless from_dialog?
|
|
36
|
-
unless params[:continue_editing] =~ /true|on|1/
|
|
37
|
-
redirect_back_or_default(refinery.admin_pages_path)
|
|
38
|
-
else
|
|
39
|
-
unless request.xhr?
|
|
40
|
-
redirect_to :back
|
|
41
|
-
else
|
|
42
|
-
render :partial => 'save_and_continue_callback', :locals => {
|
|
43
|
-
:new_refinery_page_path => refinery.admin_page_path(@page.nested_url),
|
|
44
|
-
:new_page_path => refinery.pages_admin_preview_page_path(@page.nested_url)
|
|
45
|
-
}
|
|
46
|
-
end
|
|
47
|
-
end
|
|
48
|
-
else
|
|
25
|
+
if @page.update_attributes(page_params)
|
|
26
|
+
flash.notice = t('refinery.crudify.updated', what: "'#{@page.title}'")
|
|
27
|
+
|
|
28
|
+
if from_dialog?
|
|
49
29
|
self.index
|
|
50
30
|
@dialog_successful = true
|
|
51
31
|
render :index
|
|
32
|
+
else
|
|
33
|
+
if params[:continue_editing] =~ /true|on|1/
|
|
34
|
+
if request.xhr?
|
|
35
|
+
render partial: 'save_and_continue_callback',
|
|
36
|
+
locals: save_and_continue_locals(@page)
|
|
37
|
+
else
|
|
38
|
+
redirect_to :back
|
|
39
|
+
end
|
|
40
|
+
else
|
|
41
|
+
redirect_back_or_default(refinery.admin_pages_path)
|
|
42
|
+
end
|
|
52
43
|
end
|
|
53
44
|
else
|
|
54
|
-
|
|
55
|
-
render :action => 'edit'
|
|
56
|
-
else
|
|
45
|
+
if request.xhr?
|
|
57
46
|
render :partial => '/refinery/admin/error_messages', :locals => {
|
|
58
47
|
:object => @page,
|
|
59
48
|
:include_object_name => true
|
|
60
49
|
}
|
|
50
|
+
else
|
|
51
|
+
render 'edit'
|
|
61
52
|
end
|
|
62
53
|
end
|
|
63
54
|
end
|
|
64
55
|
|
|
65
|
-
|
|
56
|
+
protected
|
|
66
57
|
|
|
67
58
|
def after_update_positions
|
|
68
59
|
find_all_pages
|
|
@@ -70,12 +61,12 @@ module Refinery
|
|
|
70
61
|
end
|
|
71
62
|
|
|
72
63
|
def find_page
|
|
73
|
-
@page = Page.find_by_path_or_id(params[:path], params[:id])
|
|
64
|
+
@page = Page.find_by_path_or_id!(params[:path], params[:id])
|
|
74
65
|
end
|
|
75
66
|
alias_method :page, :find_page
|
|
76
67
|
|
|
77
68
|
# We can safely assume ::Refinery::I18n is defined because this method only gets
|
|
78
|
-
# Invoked when the
|
|
69
|
+
# Invoked when the before_action from the plugin is run.
|
|
79
70
|
def globalize!
|
|
80
71
|
return super unless action_name.to_s == 'index'
|
|
81
72
|
|
|
@@ -87,23 +78,40 @@ module Refinery
|
|
|
87
78
|
end
|
|
88
79
|
end
|
|
89
80
|
|
|
90
|
-
def
|
|
91
|
-
|
|
92
|
-
|
|
81
|
+
def valid_layout_templates
|
|
82
|
+
Pages.layout_template_whitelist & Pages.valid_templates(*Pages.layout_templates_pattern)
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def valid_view_templates
|
|
86
|
+
Pages.valid_templates(*Pages.view_templates_pattern)
|
|
87
|
+
end
|
|
93
88
|
|
|
94
|
-
|
|
89
|
+
def page_params
|
|
90
|
+
params.require(:page).permit(permitted_page_params)
|
|
95
91
|
end
|
|
96
92
|
|
|
97
|
-
def
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
end
|
|
93
|
+
def new_page_params
|
|
94
|
+
params.permit(:parent_id, :view_template, :layout_template)
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
private
|
|
103
98
|
|
|
104
|
-
|
|
99
|
+
def permitted_page_params
|
|
100
|
+
[
|
|
101
|
+
:browser_title, :draft, :link_url, :menu_title, :meta_description,
|
|
102
|
+
:parent_id, :skip_to_first_child, :show_in_menu, :title, :view_template,
|
|
103
|
+
:layout_template, :custom_slug, parts_attributes: [:id, :title, :slug, :body, :position]
|
|
104
|
+
]
|
|
105
105
|
end
|
|
106
106
|
|
|
107
|
+
def save_and_continue_locals(page)
|
|
108
|
+
nested_url = page.nested_url
|
|
109
|
+
{
|
|
110
|
+
new_refinery_edit_page_path: refinery.admin_edit_page_path(nested_url),
|
|
111
|
+
new_refinery_page_path: refinery.admin_page_path(nested_url),
|
|
112
|
+
new_page_path: refinery.pages_admin_preview_page_path(nested_url)
|
|
113
|
+
}
|
|
114
|
+
end
|
|
107
115
|
end
|
|
108
116
|
end
|
|
109
117
|
end
|
|
@@ -8,7 +8,7 @@ module Refinery
|
|
|
8
8
|
include Refinery::Admin::BaseController
|
|
9
9
|
include Pages::RenderOptions
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
skip_before_action :error_404, :set_canonical
|
|
12
12
|
|
|
13
13
|
layout :layout
|
|
14
14
|
|
|
@@ -17,6 +17,7 @@ module Refinery
|
|
|
17
17
|
end
|
|
18
18
|
|
|
19
19
|
protected
|
|
20
|
+
|
|
20
21
|
def admin?
|
|
21
22
|
false
|
|
22
23
|
end
|
|
@@ -24,10 +25,10 @@ module Refinery
|
|
|
24
25
|
def find_page
|
|
25
26
|
if @page = Refinery::Page.find_by_path_or_id(params[:path], params[:id])
|
|
26
27
|
# Preview existing pages
|
|
27
|
-
@page.attributes =
|
|
28
|
+
@page.attributes = page_params
|
|
28
29
|
elsif params[:page]
|
|
29
30
|
# Preview a non-persisted page
|
|
30
|
-
@page = Page.new
|
|
31
|
+
@page = Page.new page_params
|
|
31
32
|
end
|
|
32
33
|
end
|
|
33
34
|
alias_method :page, :find_page
|
|
@@ -35,6 +36,14 @@ module Refinery
|
|
|
35
36
|
def layout
|
|
36
37
|
'application'
|
|
37
38
|
end
|
|
39
|
+
|
|
40
|
+
def page_params
|
|
41
|
+
params.require(:page).permit(
|
|
42
|
+
:browser_title, :draft, :link_url, :menu_title, :meta_description,
|
|
43
|
+
:parent_id, :skip_to_first_child, :show_in_menu, :title, :view_template,
|
|
44
|
+
:layout_template, parts_attributes: [:id, :title, :body, :position]
|
|
45
|
+
)
|
|
46
|
+
end
|
|
38
47
|
end
|
|
39
48
|
end
|
|
40
49
|
end
|
|
@@ -2,11 +2,11 @@ module Refinery
|
|
|
2
2
|
class PagesController < ::ApplicationController
|
|
3
3
|
include Pages::RenderOptions
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
before_action :find_page, :set_canonical
|
|
6
|
+
before_action :error_404, :unless => :current_user_can_view_page?
|
|
7
7
|
|
|
8
8
|
# Save whole Page after delivery
|
|
9
|
-
|
|
9
|
+
after_action :write_cache?
|
|
10
10
|
|
|
11
11
|
# This action is usually accessed with the root path, normally '/'
|
|
12
12
|
def home
|
|
@@ -53,15 +53,14 @@ module Refinery
|
|
|
53
53
|
end
|
|
54
54
|
|
|
55
55
|
def should_redirect_to_friendly_url?
|
|
56
|
-
requested_friendly_id != page.friendly_id ||
|
|
56
|
+
requested_friendly_id != page.friendly_id || (
|
|
57
|
+
::Refinery::Pages.scope_slug_by_parent &&
|
|
58
|
+
params[:path].present? && params[:path].match(page.root.slug).nil?
|
|
59
|
+
)
|
|
57
60
|
end
|
|
58
61
|
|
|
59
62
|
def current_user_can_view_page?
|
|
60
|
-
page.live? ||
|
|
61
|
-
end
|
|
62
|
-
|
|
63
|
-
def current_refinery_user_can_access?(plugin)
|
|
64
|
-
refinery_user? && current_refinery_user.authorized_plugins.include?(plugin)
|
|
63
|
+
page.live? || authorisation_manager.allow?(:plugin, "refinery_pages")
|
|
65
64
|
end
|
|
66
65
|
|
|
67
66
|
def first_live_child
|
|
@@ -71,9 +70,9 @@ module Refinery
|
|
|
71
70
|
def find_page(fallback_to_404 = true)
|
|
72
71
|
@page ||= case action_name
|
|
73
72
|
when "home"
|
|
74
|
-
Refinery::Page.
|
|
73
|
+
Refinery::Page.find_by(link_url: '/')
|
|
75
74
|
when "show"
|
|
76
|
-
Refinery::Page.find_by_path_or_id(params[:path], params[:id])
|
|
75
|
+
Refinery::Page.friendly.find_by_path_or_id(params[:path], params[:id])
|
|
77
76
|
end
|
|
78
77
|
@page || (error_404 if fallback_to_404)
|
|
79
78
|
end
|
|
@@ -85,7 +84,8 @@ module Refinery
|
|
|
85
84
|
end
|
|
86
85
|
|
|
87
86
|
def write_cache?
|
|
88
|
-
|
|
87
|
+
# Don't cache the page with the site bar showing.
|
|
88
|
+
if Refinery::Pages.cache_pages_full && !authorisation_manager.allow?(:read, :site_bar)
|
|
89
89
|
cache_page(response.body, File.join('', 'refinery', 'cache', 'pages', request.path).to_s)
|
|
90
90
|
end
|
|
91
91
|
end
|
|
@@ -3,12 +3,12 @@ module Refinery
|
|
|
3
3
|
module PagesHelper
|
|
4
4
|
def parent_id_nested_set_options(current_page)
|
|
5
5
|
pages = []
|
|
6
|
-
nested_set_options(::Refinery::Page, current_page) {|page| pages << page}
|
|
6
|
+
nested_set_options(::Refinery::Page, current_page) { |page| pages << page}
|
|
7
7
|
# page.title needs the :translations association, doing something like
|
|
8
8
|
# nested_set_options(::Refinery::Page.includes(:translations), page) doesn't work, yet.
|
|
9
9
|
# See https://github.com/collectiveidea/awesome_nested_set/pull/123
|
|
10
|
-
ActiveRecord::Associations::Preloader.new(pages, :translations)
|
|
11
|
-
pages.map {|page| ["#{'-' * page.level} #{page.title}", page.id]}
|
|
10
|
+
ActiveRecord::Associations::Preloader.new.preload(pages, :translations)
|
|
11
|
+
pages.map { |page| ["#{'-' * page.level} #{page.title}", page.id]}
|
|
12
12
|
end
|
|
13
13
|
|
|
14
14
|
def template_options(template_type, current_page)
|
|
@@ -50,8 +50,9 @@ module Refinery
|
|
|
50
50
|
# We show the title from the next available locale
|
|
51
51
|
# if there is no title for the current locale
|
|
52
52
|
def page_title_with_translations(page)
|
|
53
|
-
page.title.presence || page.translations.detect {|t| t.title.present?}.title
|
|
53
|
+
page.title.presence || page.translations.detect { |t| t.title.present?}.title
|
|
54
54
|
end
|
|
55
|
+
|
|
55
56
|
end
|
|
56
57
|
end
|
|
57
58
|
end
|
|
@@ -18,9 +18,14 @@ module Refinery
|
|
|
18
18
|
# so avoid common layout names such as :header, :footer, etc.
|
|
19
19
|
def render_content_presenter(content_page, options = {})
|
|
20
20
|
content_page.hide_sections(options[:hide_sections]) if options[:hide_sections]
|
|
21
|
-
content_page.fetch_template_overrides {|section_id| content_for(section_id)}
|
|
21
|
+
content_page.fetch_template_overrides { |section_id| content_for(section_id)}
|
|
22
22
|
content_page.to_html(options[:can_use_fallback])
|
|
23
23
|
end
|
|
24
|
+
|
|
25
|
+
# Compiles the default menu.
|
|
26
|
+
def refinery_menu_pages
|
|
27
|
+
Refinery::Menu.new Refinery::Page.fast_menu
|
|
28
|
+
end
|
|
24
29
|
end
|
|
25
30
|
end
|
|
26
31
|
end
|
data/app/models/refinery/page.rb
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
require 'friendly_id'
|
|
3
3
|
require 'refinery/core/base_model'
|
|
4
4
|
require 'refinery/pages/url'
|
|
5
|
+
require 'refinery/pages/finder'
|
|
5
6
|
|
|
6
7
|
module Refinery
|
|
7
8
|
class Page < Core::BaseModel
|
|
@@ -11,18 +12,35 @@ module Refinery
|
|
|
11
12
|
|
|
12
13
|
class Translation
|
|
13
14
|
is_seo_meta
|
|
14
|
-
|
|
15
|
+
|
|
16
|
+
def self.seo_fields
|
|
17
|
+
::SeoMeta.attributes.keys.map{ |a| [a, :"#{a}="]}.flatten
|
|
18
|
+
end
|
|
15
19
|
end
|
|
16
20
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
21
|
+
class FriendlyIdOptions
|
|
22
|
+
def self.options
|
|
23
|
+
# Docs for friendly_id https://github.com/norman/friendly_id
|
|
24
|
+
friendly_id_options = {
|
|
25
|
+
use: [:reserved],
|
|
26
|
+
reserved_words: Refinery::Pages.friendly_id_reserved_words
|
|
27
|
+
}
|
|
28
|
+
if ::Refinery::Pages.scope_slug_by_parent
|
|
29
|
+
friendly_id_options[:use] << :scoped
|
|
30
|
+
friendly_id_options.merge!(scope: :parent)
|
|
31
|
+
end
|
|
32
|
+
friendly_id_options[:use] << :globalize
|
|
33
|
+
friendly_id_options
|
|
34
|
+
end
|
|
35
|
+
end
|
|
20
36
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
37
|
+
# If title changes tell friendly_id to regenerate slug when saving record
|
|
38
|
+
def should_generate_new_friendly_id?
|
|
39
|
+
changes.keys.include?("title") || changes.keys.include?("custom_slug")
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# Delegate SEO Attributes to globalize translation
|
|
43
|
+
delegate(*(Translation.seo_fields << {:to => :translation}))
|
|
26
44
|
|
|
27
45
|
validates :title, :presence => true
|
|
28
46
|
|
|
@@ -32,30 +50,19 @@ module Refinery
|
|
|
32
50
|
# rather than :delete_all we want :destroy
|
|
33
51
|
acts_as_nested_set :dependent => :destroy
|
|
34
52
|
|
|
35
|
-
|
|
36
|
-
friendly_id_options = {:use => [:reserved, :globalize], :reserved_words => %w(index new session login logout users refinery admin images wymiframe)}
|
|
37
|
-
if ::Refinery::Pages.scope_slug_by_parent
|
|
38
|
-
friendly_id_options[:use] << :scoped
|
|
39
|
-
friendly_id_options.merge!(:scope => :parent)
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
friendly_id :custom_slug_or_title, friendly_id_options
|
|
53
|
+
friendly_id :custom_slug_or_title, FriendlyIdOptions.options
|
|
43
54
|
|
|
44
|
-
has_many :parts,
|
|
45
|
-
|
|
55
|
+
has_many :parts, -> {
|
|
56
|
+
scope = order('position ASC')
|
|
57
|
+
scope = scope.includes(:translations) if ::Refinery::PagePart.respond_to?(:translation_class)
|
|
58
|
+
scope
|
|
59
|
+
}, :foreign_key => :refinery_page_id,
|
|
46
60
|
:class_name => '::Refinery::PagePart',
|
|
47
|
-
:order => 'position ASC',
|
|
48
61
|
:inverse_of => :page,
|
|
49
|
-
:dependent => :destroy
|
|
50
|
-
:include => ((:translations) if ::Refinery::PagePart.respond_to?(:translation_class))
|
|
62
|
+
:dependent => :destroy
|
|
51
63
|
|
|
52
64
|
accepts_nested_attributes_for :parts, :allow_destroy => true
|
|
53
65
|
|
|
54
|
-
before_save do |m|
|
|
55
|
-
m.translation.globalized_model = self
|
|
56
|
-
m.translation.save if m.translation.new_record?
|
|
57
|
-
end
|
|
58
|
-
before_create :ensure_locale!
|
|
59
66
|
before_destroy :deletable?
|
|
60
67
|
after_save :reposition_parts!
|
|
61
68
|
|
|
@@ -68,36 +75,27 @@ module Refinery
|
|
|
68
75
|
|
|
69
76
|
# Find page by path, checking for scoping rules
|
|
70
77
|
def find_by_path(path)
|
|
71
|
-
|
|
72
|
-
# With slugs scoped to the parent page we need to find a page by its full path.
|
|
73
|
-
# For example with about/example we would need to find 'about' and then its child
|
|
74
|
-
# called 'example' otherwise it may clash with another page called /example.
|
|
75
|
-
path = path.split('/').select(&:present?)
|
|
76
|
-
page = by_slug(path.shift, :parent_id => nil).first
|
|
77
|
-
while page && path.any? do
|
|
78
|
-
slug_or_id = path.shift
|
|
79
|
-
page = page.children.by_slug(slug_or_id).first || page.children.find(slug_or_id)
|
|
80
|
-
end
|
|
81
|
-
else
|
|
82
|
-
page = by_slug(path).first
|
|
83
|
-
end
|
|
84
|
-
|
|
85
|
-
page
|
|
78
|
+
Pages::Finder.by_path(path)
|
|
86
79
|
end
|
|
87
80
|
|
|
88
81
|
# Helps to resolve the situation where you have a path and an id
|
|
89
82
|
# and if the path is unfriendly then a different finder method is required
|
|
90
83
|
# than find_by_path.
|
|
91
84
|
def find_by_path_or_id(path, id)
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
85
|
+
Pages::Finder.by_path_or_id(path, id)
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
# Helps to resolve the situation where you have a path and an id
|
|
89
|
+
# and if the path is unfriendly then a different finder method is required
|
|
90
|
+
# than find_by_path.
|
|
91
|
+
#
|
|
92
|
+
# raise ActiveRecord::RecordNotFound if not found.
|
|
93
|
+
def find_by_path_or_id!(path, id)
|
|
94
|
+
page = find_by_path_or_id(path, id)
|
|
95
|
+
|
|
96
|
+
raise ActiveRecord::RecordNotFound unless page
|
|
97
|
+
|
|
98
|
+
page
|
|
101
99
|
end
|
|
102
100
|
|
|
103
101
|
# Finds pages by their title. This method is necessary because pages
|
|
@@ -105,18 +103,15 @@ module Refinery
|
|
|
105
103
|
# pages table thus requiring us to find the attribute on the translations table
|
|
106
104
|
# and then join to the pages table again to return the associated record.
|
|
107
105
|
def by_title(title)
|
|
108
|
-
|
|
106
|
+
Pages::Finder.by_title(title)
|
|
109
107
|
end
|
|
110
108
|
|
|
111
109
|
# Finds pages by their slug. This method is necessary because pages
|
|
112
110
|
# are translated which means the slug attribute does not exist on the
|
|
113
111
|
# pages table thus requiring us to find the attribute on the translations table
|
|
114
112
|
# and then join to the pages table again to return the associated record.
|
|
115
|
-
def by_slug(slug, conditions={})
|
|
116
|
-
|
|
117
|
-
:locale => Refinery::I18n.frontend_locales.map(&:to_s),
|
|
118
|
-
:slug => slug
|
|
119
|
-
}.merge(conditions))
|
|
113
|
+
def by_slug(slug, conditions = {})
|
|
114
|
+
Pages::Finder.by_slug(slug, conditions)
|
|
120
115
|
end
|
|
121
116
|
|
|
122
117
|
# Shows all pages with :show_in_menu set to true, but it also
|
|
@@ -134,19 +129,7 @@ module Refinery
|
|
|
134
129
|
|
|
135
130
|
# Wrap up the logic of finding the pages based on the translations table.
|
|
136
131
|
def with_globalize(conditions = {})
|
|
137
|
-
|
|
138
|
-
translations_conditions = {}
|
|
139
|
-
translated_attrs = translated_attribute_names.map(&:to_s) | %w(locale)
|
|
140
|
-
|
|
141
|
-
conditions.keys.each do |key|
|
|
142
|
-
if translated_attrs.include? key.to_s
|
|
143
|
-
translations_conditions["#{self.translation_class.table_name}.#{key}"] = conditions.delete(key)
|
|
144
|
-
end
|
|
145
|
-
end
|
|
146
|
-
|
|
147
|
-
# A join implies readonly which we don't really want.
|
|
148
|
-
where(conditions).joins(:translations).where(translations_conditions).
|
|
149
|
-
readonly(false)
|
|
132
|
+
Pages::Finder.with_globalize(conditions)
|
|
150
133
|
end
|
|
151
134
|
|
|
152
135
|
# Returns how many pages per page should there be when paginating pages
|
|
@@ -161,6 +144,7 @@ module Refinery
|
|
|
161
144
|
alias_method_chain :rebuild!, :slug_nullification
|
|
162
145
|
|
|
163
146
|
protected
|
|
147
|
+
|
|
164
148
|
def nullify_duplicate_slugs_under_the_same_parent!
|
|
165
149
|
t_slug = translation_class.arel_table[:slug]
|
|
166
150
|
joins(:translations).group(:locale, :parent_id, t_slug).having(t_slug.count.gt(1)).count.
|
|
@@ -174,7 +158,7 @@ module Refinery
|
|
|
174
158
|
end
|
|
175
159
|
|
|
176
160
|
def translated_to_default_locale?
|
|
177
|
-
persisted? && translations.
|
|
161
|
+
persisted? && translations.any?{ |t| t.locale == Refinery::I18n.default_frontend_locale}
|
|
178
162
|
end
|
|
179
163
|
|
|
180
164
|
# The canonical page for this particular page.
|
|
@@ -193,7 +177,8 @@ module Refinery
|
|
|
193
177
|
# Returns in cascading order: custom_slug or menu_title or title depending on
|
|
194
178
|
# which attribute is first found to be present for this page.
|
|
195
179
|
def custom_slug_or_title
|
|
196
|
-
|
|
180
|
+
(Refinery::Pages.use_custom_slugs && custom_slug.presence) ||
|
|
181
|
+
menu_title.presence || title.presence
|
|
197
182
|
end
|
|
198
183
|
|
|
199
184
|
# Am I allowed to delete this page?
|
|
@@ -207,7 +192,7 @@ module Refinery
|
|
|
207
192
|
# This ensures that they are in the correct 0,1,2,3,4... etc order.
|
|
208
193
|
def reposition_parts!
|
|
209
194
|
reload.parts.each_with_index do |part, index|
|
|
210
|
-
part.
|
|
195
|
+
part.update_columns position: index
|
|
211
196
|
end
|
|
212
197
|
end
|
|
213
198
|
|
|
@@ -223,56 +208,32 @@ module Refinery
|
|
|
223
208
|
|
|
224
209
|
# If you want to destroy a page that is set to be not deletable this is the way to do it.
|
|
225
210
|
def destroy!
|
|
226
|
-
self.menu_match
|
|
227
|
-
self.link_url = nil
|
|
228
|
-
self.deletable = true
|
|
211
|
+
self.update_attributes(:menu_match => nil, :link_url => nil, :deletable => true)
|
|
229
212
|
|
|
230
|
-
destroy
|
|
213
|
+
self.destroy
|
|
231
214
|
end
|
|
232
215
|
|
|
233
|
-
#
|
|
234
|
-
#
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
216
|
+
# Returns the full path to this page.
|
|
217
|
+
# This automatically prints out this page title and all parent page titles.
|
|
218
|
+
# The result is joined by the path_separator argument.
|
|
219
|
+
def path(path_separator: ' - ', ancestors_first: true)
|
|
220
|
+
return title if root?
|
|
238
221
|
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
parts.reverse! if options[:reversed]
|
|
242
|
-
parts.join(' - ')
|
|
243
|
-
else
|
|
244
|
-
title
|
|
245
|
-
end
|
|
222
|
+
chain = ancestors_first ? self_and_ancestors : self_and_ancestors.reverse
|
|
223
|
+
chain.map(&:title).join(path_separator)
|
|
246
224
|
end
|
|
247
225
|
|
|
248
226
|
def url
|
|
249
227
|
Pages::Url.build(self)
|
|
250
228
|
end
|
|
251
229
|
|
|
252
|
-
def link_url_localised?
|
|
253
|
-
Refinery.deprecate "Refinery::Page#link_url_localised?", :when => '2.2',
|
|
254
|
-
:replacement => "Refinery::Pages::Url::Localised#url"
|
|
255
|
-
Pages::Url::Localised.new(self).url
|
|
256
|
-
end
|
|
257
|
-
|
|
258
|
-
def url_normal
|
|
259
|
-
Refinery.deprecate "Refinery::Page#url_normal", :when => '2.2',
|
|
260
|
-
:replacement => "Refinery::Pages::Url::Normal#url"
|
|
261
|
-
Pages::Url::Normal.new(self).url
|
|
262
|
-
end
|
|
263
|
-
|
|
264
|
-
def url_marketable
|
|
265
|
-
Refinery.deprecate "Refinery::Page#url_marketable", :when => '2.2',
|
|
266
|
-
:replacement => "Refinery::Pages::Url::Marketable#url"
|
|
267
|
-
Pages::Url::Marketable.new(self).url
|
|
268
|
-
end
|
|
269
|
-
|
|
270
230
|
def nested_url
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
231
|
+
Globalize.with_locale(slug_locale) do
|
|
232
|
+
if ::Refinery::Pages.scope_slug_by_parent && !root?
|
|
233
|
+
self_and_ancestors.includes(:translations).map(&:to_param)
|
|
234
|
+
else
|
|
235
|
+
[to_param.to_s]
|
|
236
|
+
end
|
|
276
237
|
end
|
|
277
238
|
end
|
|
278
239
|
|
|
@@ -330,8 +291,8 @@ module Refinery
|
|
|
330
291
|
# ::Refinery::Page.first.content_for(:body)
|
|
331
292
|
#
|
|
332
293
|
# Will return the body page part of the first page.
|
|
333
|
-
def content_for(
|
|
334
|
-
|
|
294
|
+
def content_for(part_slug)
|
|
295
|
+
part_with_slug(part_slug).try(:body)
|
|
335
296
|
end
|
|
336
297
|
|
|
337
298
|
# Accessor method to test whether a page part
|
|
@@ -341,34 +302,27 @@ module Refinery
|
|
|
341
302
|
# ::Refinery::Page.first.content_for?(:body)
|
|
342
303
|
#
|
|
343
304
|
# Will return true if the page has a body page part and it is not blank.
|
|
344
|
-
def content_for?(
|
|
345
|
-
content_for(
|
|
305
|
+
def content_for?(part_slug)
|
|
306
|
+
content_for(part_slug).present?
|
|
346
307
|
end
|
|
347
308
|
|
|
348
309
|
# Accessor method to get a page part object from a page.
|
|
349
310
|
# Example:
|
|
350
311
|
#
|
|
351
|
-
# ::Refinery::Page.first.
|
|
312
|
+
# ::Refinery::Page.first.part_with_slug(:body)
|
|
352
313
|
#
|
|
353
|
-
# Will return the Refinery::PagePart object with that
|
|
354
|
-
def
|
|
314
|
+
# Will return the Refinery::PagePart object with that slug using the first page.
|
|
315
|
+
def part_with_slug(part_slug)
|
|
355
316
|
# self.parts is usually already eager loaded so we can now just grab
|
|
356
317
|
# the first element matching the title we specified.
|
|
357
318
|
self.parts.detect do |part|
|
|
358
|
-
part.
|
|
359
|
-
part.title == part_title.to_s or
|
|
360
|
-
part.title.downcase.gsub(" ", "_") == part_title.to_s.downcase.gsub(" ", "_")
|
|
319
|
+
part.slug_matches?(part_slug)
|
|
361
320
|
end
|
|
362
321
|
end
|
|
363
322
|
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
# The translation is set to the default frontend locale.
|
|
368
|
-
def ensure_locale!
|
|
369
|
-
if self.translations.empty?
|
|
370
|
-
self.translations.build(:locale => Refinery::I18n.default_frontend_locale)
|
|
371
|
-
end
|
|
323
|
+
def part_with_title(part_title)
|
|
324
|
+
Refinery.deprecate("Refinery::Page#part_with_title", when: "3.1", replacement: "part_with_slug")
|
|
325
|
+
part_with_slug(part_title.to_s.parameterize.underscore)
|
|
372
326
|
end
|
|
373
327
|
|
|
374
328
|
# Protects generated slugs from title if they are in the list of reserved words
|
|
@@ -377,21 +331,41 @@ module Refinery
|
|
|
377
331
|
# Also check for global scoping, and if enabled, allow slashes in slug.
|
|
378
332
|
#
|
|
379
333
|
# Returns the sluggified string
|
|
380
|
-
def
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
334
|
+
def normalize_friendly_id(slug_string)
|
|
335
|
+
FriendlyIdPath.normalize_friendly_id(slug_string)
|
|
336
|
+
end
|
|
337
|
+
|
|
338
|
+
private
|
|
339
|
+
|
|
340
|
+
class FriendlyIdPath
|
|
341
|
+
def self.normalize_friendly_id_path(slug_string)
|
|
342
|
+
# Remove leading and trailing slashes, but allow internal
|
|
343
|
+
slug_string
|
|
344
|
+
.sub(%r{^/*}, '')
|
|
345
|
+
.sub(%r{/*$}, '')
|
|
346
|
+
.split('/')
|
|
347
|
+
.select(&:present?)
|
|
348
|
+
.map { |slug| self.normalize_friendly_id(slug) }.join('/')
|
|
349
|
+
end
|
|
350
|
+
|
|
351
|
+
def self.normalize_friendly_id(slug_string)
|
|
352
|
+
# If we are scoping by parent, no slashes are allowed. Otherwise, slug is
|
|
353
|
+
# potentially a custom slug that contains a custom route to the page.
|
|
354
|
+
if !Pages.scope_slug_by_parent && slug_string.include?('/')
|
|
355
|
+
self.normalize_friendly_id_path(slug_string)
|
|
356
|
+
else
|
|
357
|
+
self.protected_slug_string(slug_string)
|
|
358
|
+
end
|
|
359
|
+
end
|
|
360
|
+
|
|
361
|
+
def self.protected_slug_string(slug_string)
|
|
387
362
|
sluggified = slug_string.to_slug.normalize!
|
|
388
|
-
if Pages.marketable_urls &&
|
|
363
|
+
if Pages.marketable_urls && Refinery::Pages.friendly_id_reserved_words.include?(sluggified)
|
|
389
364
|
sluggified << "-page"
|
|
390
365
|
end
|
|
391
366
|
sluggified
|
|
392
367
|
end
|
|
393
368
|
end
|
|
394
|
-
alias_method_chain :normalize_friendly_id, :marketable_urls
|
|
395
369
|
|
|
396
370
|
def puts_destroy_help
|
|
397
371
|
puts "This page is not deletable. Please use .destroy! if you really want it deleted "
|
|
@@ -401,9 +375,9 @@ module Refinery
|
|
|
401
375
|
end
|
|
402
376
|
|
|
403
377
|
def slug_locale
|
|
404
|
-
return Globalize.locale if translation_for(Globalize.locale).try(:slug).present?
|
|
378
|
+
return Globalize.locale if translation_for(Globalize.locale, false).try(:slug).present?
|
|
405
379
|
|
|
406
|
-
if translations.empty? || translation_for(Refinery::I18n.default_frontend_locale).present?
|
|
380
|
+
if translations.empty? || translation_for(Refinery::I18n.default_frontend_locale, false).present?
|
|
407
381
|
Refinery::I18n.default_frontend_locale
|
|
408
382
|
else
|
|
409
383
|
translations.first.locale
|