refinerycms-pages 2.1.5 → 3.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|