refinerycms-pages 2.0.10 → 2.1.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/pages_controller.rb +23 -17
- data/app/controllers/refinery/admin/pages_dialogs_controller.rb +8 -45
- data/app/controllers/refinery/pages/admin/preview_controller.rb +38 -0
- data/app/controllers/refinery/pages_controller.rb +26 -43
- data/app/helpers/refinery/admin/pages_helper.rb +19 -14
- data/app/models/refinery/page.rb +133 -194
- data/app/models/refinery/page_part.rb +1 -1
- data/{lib → app/presenters}/refinery/pages/content_page_presenter.rb +1 -5
- data/{lib → app/presenters}/refinery/pages/content_presenter.rb +1 -15
- data/app/presenters/refinery/pages/menu_presenter.rb +118 -0
- data/{lib → app/presenters}/refinery/pages/page_part_section_presenter.rb +0 -0
- data/{lib → app/presenters}/refinery/pages/section_presenter.rb +0 -0
- data/{lib → app/presenters}/refinery/pages/title_section_presenter.rb +0 -0
- data/app/sweepers/refinery/pages/page_sweeper.rb +29 -0
- data/app/views/refinery/admin/pages/_form.html.erb +4 -4
- data/app/views/refinery/admin/pages/_form_advanced_options.html.erb +3 -18
- data/app/views/refinery/admin/pages/_form_page_parts.html.erb +2 -2
- data/app/views/refinery/admin/pages/_page.html.erb +5 -5
- data/app/views/refinery/admin/pages/_records.html.erb +1 -3
- data/app/views/refinery/admin/pages/_sortable_list.html.erb +1 -1
- data/app/views/refinery/admin/pages/index.html.erb +1 -1
- data/app/views/refinery/admin/pages_dialogs/link_to.html.erb +0 -2
- data/config/locales/bg.yml +0 -11
- data/config/locales/cs.yml +1 -3
- data/config/locales/da.yml +15 -5
- data/config/locales/de.yml +16 -5
- data/config/locales/el.yml +0 -3
- data/config/locales/en.yml +1 -12
- data/config/locales/es.yml +0 -3
- data/config/locales/fi.yml +0 -3
- data/config/locales/fr.yml +0 -11
- data/config/locales/hu.yml +85 -0
- data/config/locales/it.yml +0 -10
- data/config/locales/ja.yml +0 -3
- data/config/locales/ko.yml +0 -11
- data/config/locales/lt.yml +0 -3
- data/config/locales/lv.yml +0 -3
- data/config/locales/nb.yml +0 -3
- data/config/locales/nl.yml +51 -40
- data/config/locales/pl.yml +23 -4
- data/config/locales/pt-BR.yml +0 -3
- data/config/locales/pt.yml +85 -0
- data/config/locales/rs.yml +0 -3
- data/config/locales/ru.yml +0 -3
- data/config/locales/sk.yml +0 -11
- data/config/locales/sl.yml +0 -3
- data/config/locales/sv.yml +0 -3
- data/config/locales/tr.yml +85 -0
- data/config/locales/uk.yml +82 -0
- data/config/locales/vi.yml +0 -3
- data/config/locales/zh-CN.yml +8 -11
- data/config/locales/zh-TW.yml +0 -3
- data/config/routes.rb +11 -5
- data/db/seeds.rb +16 -14
- data/lib/generators/refinery/pages/templates/config/initializers/refinery/pages.rb.erb +8 -4
- data/lib/refinery/pages.rb +5 -9
- data/lib/refinery/pages/caching.rb +60 -0
- data/lib/refinery/pages/configuration.rb +11 -7
- data/lib/refinery/pages/engine.rb +7 -8
- data/lib/refinery/pages/instance_methods.rb +4 -11
- data/lib/refinery/pages/render_options.rb +27 -0
- data/lib/refinery/pages/tab.rb +15 -4
- data/lib/refinery/pages/url.rb +74 -0
- data/refinerycms-pages.gemspec +4 -3
- data/spec/controllers/refinery/pages_controller_spec.rb +24 -0
- data/spec/factories/pages.rb +1 -1
- data/spec/{requests → features}/refinery/admin/pages_spec.rb +125 -42
- data/spec/{requests → features}/refinery/pages_spec.rb +139 -23
- data/spec/helpers/refinery/pages/admin/pages_helper_spec.rb +25 -25
- data/spec/lib/refinery/pages/caching_spec.rb +90 -0
- data/spec/lib/refinery/pages/tab_spec.rb +89 -0
- data/spec/lib/refinery/pages/url_spec.rb +74 -0
- data/spec/models/refinery/page_spec.rb +196 -71
- data/spec/{lib → presenters/refinery}/pages/content_page_presenter_spec.rb +0 -0
- data/spec/{lib → presenters/refinery}/pages/content_presenter_spec.rb +0 -0
- data/spec/presenters/refinery/pages/menu_presenter_spec.rb +58 -0
- data/spec/{lib → presenters/refinery}/pages/page_part_section_presenter_spec.rb +0 -0
- data/spec/{lib → presenters/refinery}/pages/section_presenter_spec.rb +0 -0
- data/spec/{lib → presenters/refinery}/pages/title_section_presenter_spec.rb +0 -0
- data/spec/support/refinery/pages/caching.rb +19 -0
- data/spec/support/refinery/pages/caching_helpers.rb +22 -0
- metadata +77 -33
- data/app/controllers/refinery/page_sweeper.rb +0 -34
- data/app/helpers/refinery/pages_helper.rb +0 -20
- data/app/views/refinery/admin/pages/_locale_picker.html.erb +0 -11
- data/config/locales/pt-PT.yml +0 -75
- data/spec/controllers/refinery/admin/pages_controller_spec.rb +0 -17
- data/spec/helpers/refinery/pages/pages_helper_spec.rb +0 -30
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4780e7414495d270398ae05f97f184a229536571
|
4
|
+
data.tar.gz: 570c24e94417d1eec341292220e105a8ee162261
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 69fd5760bf9f85414fe6fbc03bb099b0a48009add74178c43fba435e5264ef2a1234d1b29608a2d7a32dd7a82c2710df35c46d526d907db3c0849542d91c0ce5
|
7
|
+
data.tar.gz: f99adadf7d2ee66c289f89789a2d0b54c1a80d1511f6a1a026dc085330b0872cdd2e4e07e91ff42eebfafb5057464cf3bf65c89b2d0926590c603c22432ec1df
|
@@ -1,24 +1,22 @@
|
|
1
1
|
module Refinery
|
2
2
|
module Admin
|
3
3
|
class PagesController < Refinery::AdminController
|
4
|
-
|
4
|
+
include Pages::InstanceMethods
|
5
|
+
cache_sweeper Pages::PageSweeper
|
5
6
|
|
6
7
|
crudify :'refinery/page',
|
7
8
|
:order => "lft ASC",
|
8
9
|
:include => [:translations, :children],
|
9
10
|
:paging => false
|
10
11
|
|
11
|
-
after_filter lambda{::Refinery::Page.expire_page_caching}, :only => [:update_positions]
|
12
|
-
|
13
12
|
before_filter :load_valid_templates, :only => [:edit, :new]
|
14
|
-
|
15
|
-
|
16
|
-
:if => proc { Refinery.i18n_enabled? }
|
13
|
+
before_filter :restrict_access, :only => [:create, :update, :update_positions, :destroy]
|
14
|
+
after_filter proc { Pages::Caching.new().expire! }, :only => :update_positions
|
17
15
|
|
18
16
|
def new
|
19
|
-
@page =
|
20
|
-
|
21
|
-
@page.parts <<
|
17
|
+
@page = Page.new(params.except(:controller, :action, :switch_locale))
|
18
|
+
Pages.default_parts_for(@page).each_with_index do |page_part, index|
|
19
|
+
@page.parts << PagePart.new(:title => page_part, :position => index)
|
22
20
|
end
|
23
21
|
end
|
24
22
|
|
@@ -42,8 +40,8 @@ module Refinery
|
|
42
40
|
redirect_to :back
|
43
41
|
else
|
44
42
|
render :partial => 'save_and_continue_callback', :locals => {
|
45
|
-
:new_refinery_page_path => refinery.admin_page_path(@page.
|
46
|
-
:new_page_path => refinery.
|
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)
|
47
45
|
}
|
48
46
|
end
|
49
47
|
end
|
@@ -66,8 +64,13 @@ module Refinery
|
|
66
64
|
|
67
65
|
protected
|
68
66
|
|
67
|
+
def after_update_positions
|
68
|
+
find_all_pages
|
69
|
+
render :partial => '/refinery/admin/pages/sortable_list' and return
|
70
|
+
end
|
71
|
+
|
69
72
|
def find_page
|
70
|
-
@page =
|
73
|
+
@page = Page.find_by_path_or_id(params[:path], params[:id])
|
71
74
|
end
|
72
75
|
alias_method :page, :find_page
|
73
76
|
|
@@ -77,15 +80,18 @@ module Refinery
|
|
77
80
|
return super unless action_name.to_s == 'index'
|
78
81
|
|
79
82
|
# Always display the tree of pages from the default frontend locale.
|
80
|
-
|
83
|
+
if Refinery::I18n.built_in_locales.keys.map(&:to_s).include?(params[:switch_locale])
|
84
|
+
Globalize.locale = params[:switch_locale].try(:to_sym)
|
85
|
+
else
|
86
|
+
Globalize.locale = Refinery::I18n.default_frontend_locale
|
87
|
+
end
|
81
88
|
end
|
82
89
|
|
83
90
|
def load_valid_templates
|
84
|
-
@valid_layout_templates =
|
85
|
-
|
91
|
+
@valid_layout_templates = Pages.layout_template_whitelist &
|
92
|
+
Pages.valid_templates('app', 'views', '{layouts,refinery/layouts}', '*html*')
|
86
93
|
|
87
|
-
@valid_view_templates =
|
88
|
-
Refinery::Pages.valid_templates('app', 'views', '{pages,refinery/pages}', '*html*')
|
94
|
+
@valid_view_templates = Pages.valid_templates('app', 'views', '{pages,refinery/pages}', '*html*')
|
89
95
|
end
|
90
96
|
|
91
97
|
def restrict_access
|
@@ -1,5 +1,3 @@
|
|
1
|
-
require 'net/http'
|
2
|
-
|
3
1
|
module Refinery
|
4
2
|
module Admin
|
5
3
|
class PagesDialogsController < ::Refinery::Admin::DialogsController
|
@@ -9,21 +7,23 @@ module Refinery
|
|
9
7
|
def link_to
|
10
8
|
# Get the switch_local variable to determine the locale we're currently editing
|
11
9
|
# Set up Globalize with our current locale
|
12
|
-
if ::
|
13
|
-
|
10
|
+
Globalize.locale = if params[:switch_locale].present? && Refinery::I18n.built_in_locales.keys.map(&:to_s).include?(params[:switch_locale])
|
11
|
+
Globalize.locale = params[:switch_locale]
|
12
|
+
else
|
13
|
+
Refinery::I18n.default_locale
|
14
14
|
end
|
15
15
|
|
16
16
|
@pages = ::Refinery::Page.roots.paginate(:page => params[:page], :per_page => ::Refinery::Page.per_page(true))
|
17
17
|
|
18
|
-
@pages = @pages.with_globalize
|
18
|
+
@pages = @pages.with_globalize
|
19
19
|
|
20
20
|
if ::Refinery::Plugins.registered.names.include?('refinery_files')
|
21
|
-
|
22
|
-
|
21
|
+
@resources = Resource.paginate(:page => params[:resource_page], :per_page => Resource.per_page(true)).
|
22
|
+
order('created_at DESC')
|
23
23
|
|
24
24
|
# resource link
|
25
25
|
if params[:current_link].present?
|
26
|
-
|
26
|
+
is_resource_link = params[:current_link].include?("/system/resources")
|
27
27
|
end
|
28
28
|
end
|
29
29
|
|
@@ -52,43 +52,6 @@ module Refinery
|
|
52
52
|
end
|
53
53
|
end
|
54
54
|
|
55
|
-
def test_url
|
56
|
-
result = 'failure'
|
57
|
-
begin
|
58
|
-
timeout(5) do
|
59
|
-
unless params[:url].blank?
|
60
|
-
url = URI.parse(params[:url])
|
61
|
-
if url.host.nil? && params[:url].start_with?('/')
|
62
|
-
url.host = URI.parse(request.url).host
|
63
|
-
end
|
64
|
-
|
65
|
-
result = case Net::HTTP.get_response(url)
|
66
|
-
when Net::HTTPSuccess, Net::HTTPRedirection
|
67
|
-
'success'
|
68
|
-
end
|
69
|
-
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
73
|
-
rescue
|
74
|
-
# be quiet
|
75
|
-
end
|
76
|
-
|
77
|
-
render :json => {:result => result}
|
78
|
-
end
|
79
|
-
|
80
|
-
def test_email
|
81
|
-
if params[:email].present?
|
82
|
-
valid = params[:email] =~ /^([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})$/i
|
83
|
-
|
84
|
-
render :json => if valid
|
85
|
-
{:result => 'success'}
|
86
|
-
else
|
87
|
-
{:result => 'failure'}
|
88
|
-
end
|
89
|
-
end
|
90
|
-
end
|
91
|
-
|
92
55
|
end
|
93
56
|
end
|
94
57
|
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module Refinery
|
2
|
+
module Pages
|
3
|
+
module Admin
|
4
|
+
class PreviewController < AdminController
|
5
|
+
include Pages::InstanceMethods
|
6
|
+
include Pages::RenderOptions
|
7
|
+
|
8
|
+
before_filter :find_page
|
9
|
+
|
10
|
+
layout :layout
|
11
|
+
|
12
|
+
def show
|
13
|
+
render_with_templates?
|
14
|
+
end
|
15
|
+
|
16
|
+
protected
|
17
|
+
def admin?
|
18
|
+
false
|
19
|
+
end
|
20
|
+
|
21
|
+
def find_page
|
22
|
+
if @page = Refinery::Page.find_by_path_or_id(params[:path], params[:id])
|
23
|
+
# Preview existing pages
|
24
|
+
@page.attributes = params[:page]
|
25
|
+
elsif params[:page]
|
26
|
+
# Preview a non-persisted page
|
27
|
+
@page = Page.new params[:page]
|
28
|
+
end
|
29
|
+
end
|
30
|
+
alias_method :page, :find_page
|
31
|
+
|
32
|
+
def layout
|
33
|
+
'application'
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -1,10 +1,12 @@
|
|
1
1
|
module Refinery
|
2
2
|
class PagesController < ::ApplicationController
|
3
|
-
|
4
|
-
|
3
|
+
include Pages::RenderOptions
|
4
|
+
|
5
|
+
before_filter :find_page, :set_canonical
|
6
|
+
before_filter :error_404, :unless => :current_user_can_view_page?
|
5
7
|
|
6
8
|
# Save whole Page after delivery
|
7
|
-
after_filter
|
9
|
+
after_filter :write_cache?
|
8
10
|
|
9
11
|
# This action is usually accessed with the root path, normally '/'
|
10
12
|
def home
|
@@ -22,37 +24,38 @@ module Refinery
|
|
22
24
|
# GET /about/mission
|
23
25
|
#
|
24
26
|
def show
|
25
|
-
if
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
if requested_friendly_id != page.friendly_id
|
32
|
-
redirect_to refinery.url_for(page.url), :status => 301
|
33
|
-
else
|
34
|
-
render_with_templates?
|
35
|
-
end
|
36
|
-
end
|
37
|
-
else
|
38
|
-
error_404
|
27
|
+
if should_skip_to_first_child?
|
28
|
+
redirect_to refinery.url_for(first_live_child.url) and return
|
29
|
+
elsif page.link_url.present?
|
30
|
+
redirect_to page.link_url and return
|
31
|
+
elsif should_redirect_to_friendly_url?
|
32
|
+
redirect_to refinery.url_for(page.url), :status => 301 and return
|
39
33
|
end
|
40
|
-
end
|
41
34
|
|
42
|
-
|
43
|
-
render_with_templates?(:action => :show)
|
35
|
+
render_with_templates?
|
44
36
|
end
|
45
37
|
|
46
38
|
protected
|
47
39
|
|
48
40
|
def requested_friendly_id
|
49
|
-
|
41
|
+
if ::Refinery::Pages.scope_slug_by_parent
|
42
|
+
# Pick out last path component, or id if present
|
43
|
+
"#{params[:path]}/#{params[:id]}".split('/').last
|
44
|
+
else
|
45
|
+
# Remove leading and trailing slashes in path, but leave internal
|
46
|
+
# ones for global slug scoping
|
47
|
+
params[:path].to_s.gsub(%r{\A/+}, '').presence || params[:id]
|
48
|
+
end
|
50
49
|
end
|
51
50
|
|
52
51
|
def should_skip_to_first_child?
|
53
52
|
page.skip_to_first_child && first_live_child
|
54
53
|
end
|
55
54
|
|
55
|
+
def should_redirect_to_friendly_url?
|
56
|
+
requested_friendly_id != page.friendly_id || ::Refinery::Pages.scope_slug_by_parent && params[:path].present? && params[:path].match(page.root.slug).nil?
|
57
|
+
end
|
58
|
+
|
56
59
|
def current_user_can_view_page?
|
57
60
|
page.live? || current_refinery_user_can_access?("refinery_pages")
|
58
61
|
end
|
@@ -65,21 +68,11 @@ module Refinery
|
|
65
68
|
page.children.order('lft ASC').live.first
|
66
69
|
end
|
67
70
|
|
68
|
-
def find_page_for_preview
|
69
|
-
if page(fallback_to_404 = false)
|
70
|
-
# Preview existing pages
|
71
|
-
@page.attributes = view_context.sanitize_hash params[:page]
|
72
|
-
elsif params[:page]
|
73
|
-
# Preview a non-persisted page
|
74
|
-
@page = Page.new params[:page]
|
75
|
-
end
|
76
|
-
end
|
77
|
-
|
78
71
|
def find_page(fallback_to_404 = true)
|
79
72
|
@page ||= case action_name
|
80
73
|
when "home"
|
81
74
|
Refinery::Page.where(:link_url => '/').first
|
82
|
-
when "show"
|
75
|
+
when "show"
|
83
76
|
Refinery::Page.find_by_path_or_id(params[:path], params[:id])
|
84
77
|
end
|
85
78
|
@page || (error_404 if fallback_to_404)
|
@@ -87,23 +80,13 @@ module Refinery
|
|
87
80
|
|
88
81
|
alias_method :page, :find_page
|
89
82
|
|
90
|
-
def render_with_templates?(render_options = {})
|
91
|
-
if Refinery::Pages.use_layout_templates && page.layout_template.present?
|
92
|
-
render_options[:layout] = page.layout_template
|
93
|
-
end
|
94
|
-
if Refinery::Pages.use_view_templates && page.view_template.present?
|
95
|
-
render_options[:action] = page.view_template
|
96
|
-
end
|
97
|
-
render render_options if render_options.any?
|
98
|
-
end
|
99
|
-
|
100
83
|
def set_canonical
|
101
84
|
@canonical = refinery.url_for @page.canonical if @page.present?
|
102
85
|
end
|
103
86
|
|
104
87
|
def write_cache?
|
105
88
|
if Refinery::Pages.cache_pages_full && !refinery_user?
|
106
|
-
cache_page(response.body, File.join('', 'refinery', 'cache', 'pages', request.path
|
89
|
+
cache_page(response.body, File.join('', 'refinery', 'cache', 'pages', request.path).to_s)
|
107
90
|
end
|
108
91
|
end
|
109
92
|
end
|
@@ -12,15 +12,24 @@ module Refinery
|
|
12
12
|
end
|
13
13
|
|
14
14
|
def template_options(template_type, current_page)
|
15
|
-
|
16
|
-
|
17
|
-
if current_page.
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
{ :selected => Refinery::Pages.send("#{template_type}_whitelist").first }
|
15
|
+
html_options = { :selected => send("default_#{template_type}", current_page) }
|
16
|
+
|
17
|
+
if (template = current_page.send(template_type).presence)
|
18
|
+
html_options.update :selected => template
|
19
|
+
elsif current_page.parent_id? && !current_page.send(template_type).presence
|
20
|
+
template = current_page.parent.send(template_type).presence
|
21
|
+
html_options.update :selected => template if template
|
23
22
|
end
|
23
|
+
|
24
|
+
html_options
|
25
|
+
end
|
26
|
+
|
27
|
+
def default_view_template(current_page)
|
28
|
+
current_page.link_url == "/" ? "home" : "show"
|
29
|
+
end
|
30
|
+
|
31
|
+
def default_layout_template(current_page)
|
32
|
+
"application"
|
24
33
|
end
|
25
34
|
|
26
35
|
# In the admin area we use a slightly different title
|
@@ -35,17 +44,13 @@ module Refinery
|
|
35
44
|
::I18n.t('draft', :scope => 'refinery.admin.pages.page')
|
36
45
|
end if page.draft?
|
37
46
|
|
38
|
-
meta_information
|
47
|
+
meta_information
|
39
48
|
end
|
40
49
|
|
41
50
|
# We show the title from the next available locale
|
42
51
|
# if there is no title for the current locale
|
43
52
|
def page_title_with_translations(page)
|
44
|
-
|
45
|
-
page.title
|
46
|
-
else
|
47
|
-
page.translations.detect {|t| t.title.present?}.title
|
48
|
-
end
|
53
|
+
page.title.presence || page.translations.detect {|t| t.title.present?}.title
|
49
54
|
end
|
50
55
|
end
|
51
56
|
end
|
data/app/models/refinery/page.rb
CHANGED
@@ -1,49 +1,44 @@
|
|
1
1
|
# Encoding: utf-8
|
2
|
-
require 'refinerycms-core'
|
3
|
-
require 'acts_as_indexed'
|
4
2
|
require 'friendly_id'
|
3
|
+
require 'refinery/core/base_model'
|
5
4
|
|
6
5
|
module Refinery
|
7
6
|
class Page < Core::BaseModel
|
8
7
|
extend FriendlyId
|
9
8
|
|
10
|
-
# when collecting the pages path how is each of the pages seperated?
|
11
|
-
PATH_SEPARATOR = " - "
|
12
|
-
|
13
9
|
translates :title, :menu_title, :custom_slug, :slug, :include => :seo_meta
|
14
10
|
|
15
11
|
class Translation
|
16
12
|
is_seo_meta
|
17
|
-
attr_accessible
|
13
|
+
attr_accessible *::SeoMeta.attributes.keys, :locale
|
18
14
|
end
|
19
15
|
|
20
|
-
attr_accessible :title
|
21
|
-
|
22
16
|
# Delegate SEO Attributes to globalize3 translation
|
23
17
|
seo_fields = ::SeoMeta.attributes.keys.map{|a| [a, :"#{a}="]}.flatten
|
24
18
|
delegate(*(seo_fields << {:to => :translation}))
|
25
19
|
|
26
|
-
attr_accessible :id, :deletable, :link_url, :menu_match,
|
20
|
+
attr_accessible :id, :deletable, :link_url, :menu_match,
|
27
21
|
:skip_to_first_child, :position, :show_in_menu, :draft,
|
28
|
-
:parts_attributes, :
|
29
|
-
:
|
30
|
-
:
|
22
|
+
:parts_attributes, :parent_id, :menu_title, :page_id,
|
23
|
+
:layout_template, :view_template, :custom_slug, :slug,
|
24
|
+
:title, *::SeoMeta.attributes.keys
|
31
25
|
|
32
|
-
attr_accessor :locale, :page_title, :page_menu_title # to hold temporarily
|
33
26
|
validates :title, :presence => true
|
34
27
|
|
28
|
+
validates :custom_slug, :uniqueness => true, :allow_blank => true
|
29
|
+
|
35
30
|
# Docs for acts_as_nested_set https://github.com/collectiveidea/awesome_nested_set
|
36
31
|
# rather than :delete_all we want :destroy
|
37
32
|
acts_as_nested_set :dependent => :destroy
|
38
33
|
|
39
34
|
# Docs for friendly_id http://github.com/norman/friendly_id
|
40
|
-
|
41
|
-
|
42
|
-
|
35
|
+
friendly_id_options = {:use => [:reserved, :globalize], :reserved_words => %w(index new session login logout users refinery admin images wymiframe)}
|
36
|
+
if ::Refinery::Pages.scope_slug_by_parent
|
37
|
+
friendly_id_options[:use] << :scoped
|
38
|
+
friendly_id_options.merge!(:scope => :parent)
|
39
|
+
end
|
43
40
|
|
44
|
-
|
45
|
-
acts_as_indexed :fields => [:title, :meta_keywords, :meta_description,
|
46
|
-
:menu_title, :browser_title, :all_page_part_content]
|
41
|
+
friendly_id :custom_slug_or_title, friendly_id_options
|
47
42
|
|
48
43
|
has_many :parts,
|
49
44
|
:foreign_key => :refinery_page_id,
|
@@ -56,10 +51,9 @@ module Refinery
|
|
56
51
|
accepts_nested_attributes_for :parts, :allow_destroy => true
|
57
52
|
|
58
53
|
before_save { |m| m.translation.save }
|
59
|
-
before_create :ensure_locale
|
54
|
+
before_create :ensure_locale!
|
60
55
|
before_destroy :deletable?
|
61
|
-
after_save :reposition_parts
|
62
|
-
after_destroy :expire_page_caching
|
56
|
+
after_save :reposition_parts!
|
63
57
|
|
64
58
|
class << self
|
65
59
|
# Live pages are 'allowed' to be shown in the frontend of your website.
|
@@ -68,13 +62,18 @@ module Refinery
|
|
68
62
|
where(:draft => false)
|
69
63
|
end
|
70
64
|
|
71
|
-
#
|
72
|
-
# For example with about/example we would need to find 'about' and then its child
|
73
|
-
# called 'example' otherwise it may clash with another page called /example.
|
65
|
+
# Find page by path, checking for scoping rules
|
74
66
|
def find_by_path(path)
|
75
|
-
|
76
|
-
|
77
|
-
|
67
|
+
if ::Refinery::Pages.scope_slug_by_parent
|
68
|
+
# With slugs scoped to the parent page we need to find a page by its full path.
|
69
|
+
# For example with about/example we would need to find 'about' and then its child
|
70
|
+
# called 'example' otherwise it may clash with another page called /example.
|
71
|
+
path = path.split('/').select(&:present?)
|
72
|
+
page = by_slug(path.shift, :parent_id => nil).first
|
73
|
+
page = page.children.by_slug(path.shift).first while page && path.any?
|
74
|
+
else
|
75
|
+
page = by_slug(path).first
|
76
|
+
end
|
78
77
|
|
79
78
|
page
|
80
79
|
end
|
@@ -83,7 +82,7 @@ module Refinery
|
|
83
82
|
# and if the path is unfriendly then a different finder method is required
|
84
83
|
# than find_by_path.
|
85
84
|
def find_by_path_or_id(path, id)
|
86
|
-
if
|
85
|
+
if path.present?
|
87
86
|
if path.friendly_id?
|
88
87
|
find_by_path(path)
|
89
88
|
else
|
@@ -102,10 +101,15 @@ module Refinery
|
|
102
101
|
with_globalize(:title => title)
|
103
102
|
end
|
104
103
|
|
105
|
-
# Finds pages by their slug.
|
104
|
+
# Finds pages by their slug. This method is necessary because pages
|
105
|
+
# are translated which means the slug attribute does not exist on the
|
106
|
+
# pages table thus requiring us to find the attribute on the translations table
|
107
|
+
# and then join to the pages table again to return the associated record.
|
106
108
|
def by_slug(slug, conditions={})
|
107
|
-
|
108
|
-
|
109
|
+
with_globalize({
|
110
|
+
:locale => Refinery::I18n.frontend_locales.map(&:to_s),
|
111
|
+
:slug => slug
|
112
|
+
}.merge(conditions))
|
109
113
|
end
|
110
114
|
|
111
115
|
# Shows all pages with :show_in_menu set to true, but it also
|
@@ -116,59 +120,26 @@ module Refinery
|
|
116
120
|
where(:show_in_menu => true).with_globalize
|
117
121
|
end
|
118
122
|
|
119
|
-
#
|
120
|
-
|
121
|
-
|
122
|
-
# using only one SQL query. This has limitations, including not being able
|
123
|
-
# to access any other attributes of the pages but you can specify more columns
|
124
|
-
# by passing in an array e.g. fast_menu([:column1, :column2])
|
125
|
-
def fast_menu(columns = [])
|
126
|
-
# First, apply a filter to determine which pages to show.
|
127
|
-
pages = live.in_menu.order('lft ASC').includes(:translations)
|
128
|
-
|
129
|
-
# Now we only want to select particular columns to avoid any further queries.
|
130
|
-
# Title and menu_title are retrieved in the next block below so they are not here.
|
131
|
-
(menu_columns | columns).each do |column|
|
132
|
-
pages = pages.select(arel_table[column.to_sym])
|
133
|
-
end
|
134
|
-
|
135
|
-
# We have to get title and menu_title from the translations table.
|
136
|
-
# To avoid calling globalize3 an extra time, we get title as page_title
|
137
|
-
# and we get menu_title as page_menu_title.
|
138
|
-
# These is used in 'to_refinery_menu_item' in the Page model.
|
139
|
-
%w(title menu_title).each do |column|
|
140
|
-
pages = pages.joins(:translations).select(
|
141
|
-
"#{translation_class.table_name}.#{column} as page_#{column}"
|
142
|
-
)
|
143
|
-
end
|
144
|
-
|
145
|
-
pages
|
123
|
+
# An optimised scope containing only live pages ordered for display in a menu.
|
124
|
+
def fast_menu
|
125
|
+
live.in_menu.order(arel_table[:lft]).includes(:parent, :translations)
|
146
126
|
end
|
147
127
|
|
148
128
|
# Wrap up the logic of finding the pages based on the translations table.
|
149
129
|
def with_globalize(conditions = {})
|
150
130
|
conditions = {:locale => ::Globalize.locale.to_s}.merge(conditions)
|
151
|
-
|
131
|
+
translations_conditions = {}
|
132
|
+
translated_attrs = translated_attribute_names.map(&:to_s) | %w(locale)
|
133
|
+
|
152
134
|
conditions.keys.each do |key|
|
153
|
-
if
|
154
|
-
|
135
|
+
if translated_attrs.include? key.to_s
|
136
|
+
translations_conditions["#{self.translation_class.table_name}.#{key}"] = conditions.delete(key)
|
155
137
|
end
|
156
138
|
end
|
157
|
-
# A join implies readonly which we don't really want.
|
158
|
-
joins(:translations).where(globalized_conditions).where(conditions).readonly(false)
|
159
|
-
end
|
160
|
-
|
161
|
-
# Wraps up all the checks that we need to do to figure out whether
|
162
|
-
# the current frontend locale is different to the current one set by ::I18n.locale.
|
163
|
-
# This terminates in a false if i18n extension is not defined or enabled.
|
164
|
-
def different_frontend_locale?
|
165
|
-
::Refinery.i18n_enabled? && ::Refinery::I18n.current_frontend_locale != ::I18n.locale
|
166
|
-
end
|
167
139
|
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
%w(id depth parent_id lft rgt link_url menu_match slug)
|
140
|
+
# A join implies readonly which we don't really want.
|
141
|
+
where(conditions).joins(:translations).where(translations_conditions).
|
142
|
+
readonly(false)
|
172
143
|
end
|
173
144
|
|
174
145
|
# Returns how many pages per page should there be when paginating pages
|
@@ -176,46 +147,53 @@ module Refinery
|
|
176
147
|
dialog ? Pages.pages_per_dialog : Pages.pages_per_admin_index
|
177
148
|
end
|
178
149
|
|
179
|
-
def
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
150
|
+
def rebuild_with_slug_nullification!
|
151
|
+
rebuild_without_slug_nullification!
|
152
|
+
nullify_duplicate_slugs_under_the_same_parent!
|
153
|
+
end
|
154
|
+
alias_method_chain :rebuild!, :slug_nullification
|
155
|
+
|
156
|
+
protected
|
157
|
+
def nullify_duplicate_slugs_under_the_same_parent!
|
158
|
+
t_slug = translation_class.arel_table[:slug]
|
159
|
+
joins(:translations).group(:locale, :parent_id, t_slug).having(t_slug.count.gt(1)).count.
|
160
|
+
each do |(locale, parent_id, slug), count|
|
161
|
+
by_slug(slug, :locale => locale).where(:parent_id => parent_id).drop(1).each do |page|
|
162
|
+
page.slug = nil # kill the duplicate slug
|
163
|
+
page.save # regenerate the slug
|
164
|
+
end
|
187
165
|
end
|
188
166
|
end
|
189
167
|
end
|
190
168
|
|
191
169
|
def translated_to_default_locale?
|
192
|
-
persisted? &&
|
170
|
+
persisted? && translations.where(:locale => Refinery::I18n.default_frontend_locale).any?
|
193
171
|
end
|
194
172
|
|
195
173
|
# The canonical page for this particular page.
|
196
174
|
# Consists of:
|
197
175
|
# * The default locale's translated slug
|
198
176
|
def canonical
|
199
|
-
Globalize.with_locale(Refinery
|
177
|
+
Globalize.with_locale(::Refinery::I18n.default_frontend_locale) { url }
|
200
178
|
end
|
201
179
|
|
202
180
|
# The canonical slug for this particular page.
|
203
181
|
# This is the slug for the default frontend locale.
|
204
182
|
def canonical_slug
|
205
|
-
Globalize.with_locale(Refinery
|
183
|
+
Globalize.with_locale(::Refinery::I18n.default_frontend_locale) { slug }
|
206
184
|
end
|
207
185
|
|
208
186
|
# Returns in cascading order: custom_slug or menu_title or title depending on
|
209
187
|
# which attribute is first found to be present for this page.
|
210
188
|
def custom_slug_or_title
|
211
|
-
custom_slug.presence || menu_title.presence || title
|
189
|
+
custom_slug.presence || menu_title.presence || title.presence
|
212
190
|
end
|
213
191
|
|
214
192
|
# Am I allowed to delete this page?
|
215
193
|
# If a link_url is set we don't want to break the link so we don't allow them to delete
|
216
194
|
# If deletable is set to false then we don't allow this page to be deleted. These are often Refinery system pages
|
217
195
|
def deletable?
|
218
|
-
deletable && link_url.blank?
|
196
|
+
deletable && link_url.blank? && menu_match.blank?
|
219
197
|
end
|
220
198
|
|
221
199
|
# Repositions the child page_parts that belong to this page.
|
@@ -231,13 +209,7 @@ module Refinery
|
|
231
209
|
def destroy
|
232
210
|
return super if deletable?
|
233
211
|
|
234
|
-
|
235
|
-
# give useful feedback when trying to delete from console
|
236
|
-
puts "This page is not deletable. Please use .destroy! if you really want it deleted "
|
237
|
-
puts "unset .link_url," if link_url.present?
|
238
|
-
puts "unset .menu_match," if menu_match.present?
|
239
|
-
puts "set .deletable to true" unless deletable
|
240
|
-
end
|
212
|
+
puts_destroy_help
|
241
213
|
|
242
214
|
false
|
243
215
|
end
|
@@ -257,73 +229,44 @@ module Refinery
|
|
257
229
|
# Override default options with any supplied.
|
258
230
|
options = {:reversed => true}.merge(options)
|
259
231
|
|
260
|
-
|
232
|
+
if parent_id
|
261
233
|
parts = [title, parent.path(options)]
|
262
234
|
parts.reverse! if options[:reversed]
|
263
|
-
parts.join(
|
235
|
+
parts.join(' - ')
|
264
236
|
else
|
265
237
|
title
|
266
238
|
end
|
267
239
|
end
|
268
240
|
|
269
|
-
# When this page is rendered in the navigation, where should it link?
|
270
|
-
# If a custom "link_url" is set, it uses that otherwise it defaults to a normal page URL.
|
271
|
-
# The "link_url" is often used to link to a plugin rather than a page.
|
272
|
-
#
|
273
|
-
# For example if I had a "Contact" page I don't want it to just render a contact us page
|
274
|
-
# I want it to show the Inquiries form so I can collect inquiries. So I would set the "link_url"
|
275
|
-
# to "/contact"
|
276
241
|
def url
|
277
|
-
|
278
|
-
link_url_localised?
|
279
|
-
elsif Refinery::Pages.marketable_urls
|
280
|
-
with_locale_param url_marketable
|
281
|
-
elsif to_param.present?
|
282
|
-
with_locale_param url_normal
|
283
|
-
end
|
242
|
+
Pages::Url.build(self)
|
284
243
|
end
|
285
244
|
|
286
|
-
# Adds the locale key into the URI for this page's link_url attribute, unless
|
287
|
-
# the current locale is set as the default locale.
|
288
245
|
def link_url_localised?
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
if current_url =~ %r{^/} && ::Refinery::I18n.current_frontend_locale != ::Refinery::I18n.default_frontend_locale
|
294
|
-
current_url = "/#{::Refinery::I18n.current_frontend_locale}#{current_url}"
|
295
|
-
end
|
296
|
-
|
297
|
-
current_url
|
246
|
+
Refinery.deprecate "Refinery::Page#link_url_localised?", :when => '2.2',
|
247
|
+
:replacement => "Refinery::Pages::Url::Localised#url"
|
248
|
+
Pages::Url::Localised.new(self).url
|
298
249
|
end
|
299
250
|
|
300
|
-
# Add 'marketable url' attributes into this page's url.
|
301
|
-
# This sets 'path' as the nested_url value and sets 'id' to nil.
|
302
|
-
# For example, this might evaluate to /about for the "About" page.
|
303
|
-
def url_marketable
|
304
|
-
# :id => nil is important to prevent any other params[:id] from interfering with this route.
|
305
|
-
url_normal.merge :path => nested_url, :id => nil
|
306
|
-
end
|
307
|
-
|
308
|
-
# Returns a url suitable to be used in url_for in Rails (such as link_to).
|
309
|
-
# For example, this might evaluate to /pages/about for the "About" page.
|
310
251
|
def url_normal
|
311
|
-
|
252
|
+
Refinery.deprecate "Refinery::Page#url_normal", :when => '2.2',
|
253
|
+
:replacement => "Refinery::Pages::Url::Normal#url"
|
254
|
+
Pages::Url::Normal.new(self).url
|
312
255
|
end
|
313
256
|
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
url_hash.update :locale => locale if locale
|
319
|
-
url_hash
|
257
|
+
def url_marketable
|
258
|
+
Refinery.deprecate "Refinery::Page#url_marketable", :when => '2.2',
|
259
|
+
:replacement => "Refinery::Pages::Url::Marketable#url"
|
260
|
+
Pages::Url::Marketable.new(self).url
|
320
261
|
end
|
321
262
|
|
322
|
-
def
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
263
|
+
def nested_url
|
264
|
+
globalized_slug = Globalize.with_locale(slug_locale) { to_param.to_s }
|
265
|
+
if ::Refinery::Pages.scope_slug_by_parent
|
266
|
+
[parent.try(:nested_url), globalized_slug].compact.flatten
|
267
|
+
else
|
268
|
+
[globalized_slug]
|
269
|
+
end
|
327
270
|
end
|
328
271
|
|
329
272
|
# Returns an array with all ancestors to_param, allow with its own
|
@@ -332,29 +275,17 @@ module Refinery
|
|
332
275
|
#
|
333
276
|
# ['about', 'mission']
|
334
277
|
#
|
335
|
-
alias_method :
|
278
|
+
alias_method :uncached_nested_url, :nested_url
|
336
279
|
|
337
|
-
# Returns the string version of nested_url, i.e., the path that should be
|
338
|
-
# by the router
|
280
|
+
# Returns the string version of nested_url, i.e., the path that should be
|
281
|
+
# generated by the router
|
339
282
|
def nested_path
|
340
|
-
|
341
|
-
end
|
342
|
-
|
343
|
-
def path_cache_key(locale = Globalize.locale)
|
344
|
-
[cache_key(locale), 'nested_path'].join('#')
|
345
|
-
end
|
346
|
-
|
347
|
-
def url_cache_key(locale = Globalize.locale)
|
348
|
-
[cache_key(locale), 'nested_url'].join('#')
|
349
|
-
end
|
350
|
-
|
351
|
-
def cache_key(locale)
|
352
|
-
[Refinery::Core.base_cache_key, 'page', locale, id].compact.join('/')
|
283
|
+
['', nested_url].join('/')
|
353
284
|
end
|
354
285
|
|
355
286
|
# Returns true if this page is "published"
|
356
287
|
def live?
|
357
|
-
|
288
|
+
!draft?
|
358
289
|
end
|
359
290
|
|
360
291
|
# Return true if this page can be shown in the navigation.
|
@@ -364,12 +295,7 @@ module Refinery
|
|
364
295
|
end
|
365
296
|
|
366
297
|
def not_in_menu?
|
367
|
-
|
368
|
-
end
|
369
|
-
|
370
|
-
# Returns true if this page is the home page or links to it.
|
371
|
-
def home?
|
372
|
-
link_url == '/'
|
298
|
+
!in_menu?
|
373
299
|
end
|
374
300
|
|
375
301
|
# Returns all visible sibling pages that can be rendered for the menu
|
@@ -377,18 +303,15 @@ module Refinery
|
|
377
303
|
siblings.reject(&:not_in_menu?)
|
378
304
|
end
|
379
305
|
|
380
|
-
def refinery_menu_title
|
381
|
-
[page_menu_title, page_title, menu_title, title].detect(&:present?)
|
382
|
-
end
|
383
|
-
|
384
306
|
def to_refinery_menu_item
|
385
307
|
{
|
386
308
|
:id => id,
|
387
309
|
:lft => lft,
|
310
|
+
:depth => depth,
|
388
311
|
:menu_match => menu_match,
|
389
312
|
:parent_id => parent_id,
|
390
313
|
:rgt => rgt,
|
391
|
-
:title =>
|
314
|
+
:title => menu_title.presence || title.presence,
|
392
315
|
:type => self.class.name,
|
393
316
|
:url => url
|
394
317
|
}
|
@@ -404,6 +327,17 @@ module Refinery
|
|
404
327
|
part_with_title(part_title).try(:body)
|
405
328
|
end
|
406
329
|
|
330
|
+
# Accessor method to test whether a page part
|
331
|
+
# exists and has content for this page.
|
332
|
+
# Example:
|
333
|
+
#
|
334
|
+
# ::Refinery::Page.first.content_for?(:body)
|
335
|
+
#
|
336
|
+
# Will return true if the page has a body page part and it is not blank.
|
337
|
+
def content_for?(part_title)
|
338
|
+
content_for(part_title).present?
|
339
|
+
end
|
340
|
+
|
407
341
|
# Accessor method to get a page part object from a page.
|
408
342
|
# Example:
|
409
343
|
#
|
@@ -420,44 +354,49 @@ module Refinery
|
|
420
354
|
end
|
421
355
|
end
|
422
356
|
|
423
|
-
|
424
|
-
|
425
|
-
|
357
|
+
private
|
358
|
+
|
359
|
+
# Make sures that a translation exists for this page.
|
360
|
+
# The translation is set to the default frontend locale.
|
361
|
+
def ensure_locale!
|
362
|
+
if self.translations.empty?
|
363
|
+
self.translations.build(:locale => Refinery::I18n.default_frontend_locale)
|
364
|
+
end
|
426
365
|
end
|
427
366
|
|
428
|
-
##
|
429
367
|
# Protects generated slugs from title if they are in the list of reserved words
|
430
368
|
# This applies mostly to plugin-generated pages.
|
431
369
|
# This only kicks in when Refinery::Pages.marketable_urls is enabled.
|
370
|
+
# Also check for global scoping, and if enabled, allow slashes in slug.
|
432
371
|
#
|
433
372
|
# Returns the sluggified string
|
434
373
|
def normalize_friendly_id_with_marketable_urls(slug_string)
|
435
|
-
|
436
|
-
|
437
|
-
|
374
|
+
# If we are scoping by parent, no slashes are allowed. Otherwise, slug is potentially
|
375
|
+
# a custom slug that contains a custom route to the page.
|
376
|
+
if !Pages.scope_slug_by_parent && slug_string.include?('/')
|
377
|
+
slug_string.sub!(%r{^/*}, '').sub!(%r{/*$}, '') # Remove leading and trailing slashes, but allow internal
|
378
|
+
slug_string.split('/').select(&:present?).map {|s| normalize_friendly_id_with_marketable_urls(s) }.join('/')
|
379
|
+
else
|
380
|
+
sluggified = slug_string.to_slug.normalize!
|
381
|
+
if Pages.marketable_urls && self.class.friendly_id_config.reserved_words.include?(sluggified)
|
382
|
+
sluggified << "-page"
|
383
|
+
end
|
384
|
+
sluggified
|
438
385
|
end
|
439
|
-
sluggified
|
440
386
|
end
|
441
387
|
alias_method_chain :normalize_friendly_id, :marketable_urls
|
442
388
|
|
443
|
-
|
444
|
-
|
445
|
-
|
446
|
-
|
447
|
-
|
448
|
-
if self.translations.empty?
|
449
|
-
self.translations.build :locale => ::Refinery::I18n.default_frontend_locale
|
450
|
-
end
|
451
|
-
end
|
452
|
-
|
453
|
-
def expire_page_caching
|
454
|
-
self.class.expire_page_caching
|
389
|
+
def puts_destroy_help
|
390
|
+
puts "This page is not deletable. Please use .destroy! if you really want it deleted "
|
391
|
+
puts "unset .link_url," if link_url.present?
|
392
|
+
puts "unset .menu_match," if menu_match.present?
|
393
|
+
puts "set .deletable to true" unless deletable
|
455
394
|
end
|
456
395
|
|
457
396
|
def slug_locale
|
458
397
|
return Globalize.locale if translation_for(Globalize.locale).try(:slug).present?
|
459
398
|
|
460
|
-
if
|
399
|
+
if translations.empty? || translation_for(Refinery::I18n.default_frontend_locale).present?
|
461
400
|
Refinery::I18n.default_frontend_locale
|
462
401
|
else
|
463
402
|
translations.first.locale
|