camaleon_cms 2.9.1 → 2.9.3
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/README.md +29 -9
- data/Rakefile +3 -16
- data/app/apps/plugins/attack/admin_controller.rb +9 -6
- data/app/apps/plugins/attack/attack_helper.rb +35 -25
- data/app/apps/plugins/authoring_post/authoring_post_helper.rb +23 -16
- data/app/apps/plugins/front_cache/admin_controller.rb +16 -10
- data/app/apps/plugins/front_cache/config/initializer.rb +1 -1
- data/app/apps/plugins/front_cache/front_cache_helper.rb +57 -24
- data/app/apps/plugins/visibility_post/config/config.json +1 -0
- data/app/apps/plugins/visibility_post/config/routes_front.txt +1 -0
- data/app/apps/plugins/visibility_post/front_controller.rb +23 -0
- data/app/apps/plugins/visibility_post/visibility_post_helper.rb +141 -70
- data/app/apps/themes/camaleon_first/main_helper.rb +18 -12
- data/app/apps/themes/default/assets/css/style.css.scss +24 -0
- data/app/apps/themes/default/assets/genericons/genericons.css +3 -8
- data/app/apps/themes/default/default_helper.rb +2 -1
- data/app/apps/themes/default/views/category.html.erb +1 -1
- data/app/apps/themes/default/views/layouts/index.html.erb +3 -1
- data/app/apps/themes/default/views/post_tag.html.erb +1 -1
- data/app/apps/themes/default/views/post_type.html.erb +1 -1
- data/app/apps/themes/default/views/search.html.erb +1 -1
- data/app/apps/themes/new/assets/css/styles.css.scss +24 -0
- data/app/apps/themes/new/custom_helper.rb +5 -9
- data/app/apps/themes/new/views/category.html.erb +1 -1
- data/app/apps/themes/new/views/layouts/_header.html.erb +3 -1
- data/app/apps/themes/new/views/post_tag.html.erb +1 -1
- data/app/apps/themes/new/views/post_type.html.erb +1 -1
- data/app/apps/themes/new/views/search.html.erb +1 -1
- data/app/assets/javascripts/camaleon_cms/admin/_data.js +16 -0
- data/app/assets/javascripts/camaleon_cms/admin/_post.js +5 -2
- data/app/assets/javascripts/camaleon_cms/admin/nav_menu.js +14 -3
- data/app/assets/javascripts/camaleon_cms/admin/uploader/_media_manager.js +5 -0
- data/app/controllers/camaleon_cms/admin/appearances/nav_menus_controller.rb +29 -10
- data/app/controllers/camaleon_cms/admin/appearances/themes_controller.rb +8 -5
- data/app/controllers/camaleon_cms/admin/appearances/widgets/assign_controller.rb +9 -2
- data/app/controllers/camaleon_cms/admin/appearances/widgets/main_controller.rb +4 -3
- data/app/controllers/camaleon_cms/admin/appearances/widgets/sidebar_controller.rb +2 -2
- data/app/controllers/camaleon_cms/admin/categories_controller.rb +27 -8
- data/app/controllers/camaleon_cms/admin/comments_controller.rb +0 -1
- data/app/controllers/camaleon_cms/admin/installers_controller.rb +32 -1
- data/app/controllers/camaleon_cms/admin/media_controller.rb +84 -19
- data/app/controllers/camaleon_cms/admin/plugins_controller.rb +1 -3
- data/app/controllers/camaleon_cms/admin/post_tags_controller.rb +15 -6
- data/app/controllers/camaleon_cms/admin/posts/drafts_controller.rb +40 -11
- data/app/controllers/camaleon_cms/admin/posts_controller.rb +58 -22
- data/app/controllers/camaleon_cms/admin/sessions_controller.rb +238 -45
- data/app/controllers/camaleon_cms/admin/settings/custom_fields_controller.rb +103 -18
- data/app/controllers/camaleon_cms/admin/settings/post_types_controller.rb +17 -5
- data/app/controllers/camaleon_cms/admin/settings/sites_controller.rb +33 -7
- data/app/controllers/camaleon_cms/admin/settings_controller.rb +11 -6
- data/app/controllers/camaleon_cms/admin/user_roles_controller.rb +9 -7
- data/app/controllers/camaleon_cms/admin/users_controller.rb +89 -18
- data/app/controllers/camaleon_cms/admin_controller.rb +144 -26
- data/app/controllers/camaleon_cms/apps/plugins_admin_controller.rb +5 -0
- data/app/controllers/camaleon_cms/camaleon_controller.rb +37 -92
- data/app/controllers/camaleon_cms/frontend_controller.rb +140 -70
- data/app/controllers/concerns/camaleon_cms/admin/custom_fields_concern.rb +44 -0
- data/app/controllers/concerns/camaleon_cms/frontend_concern.rb +46 -17
- data/app/controllers/concerns/camaleon_cms/frontend_visited_state_concern.rb +72 -0
- data/app/controllers/concerns/camaleon_cms/hook_lifecycle_concern.rb +104 -0
- data/app/controllers/concerns/camaleon_cms/request_context_concern.rb +113 -0
- data/app/controllers/concerns/camaleon_cms/runtime_admin_menu_concern.rb +237 -0
- data/app/controllers/concerns/camaleon_cms/runtime_captcha_image_concern.rb +13 -0
- data/app/controllers/concerns/camaleon_cms/runtime_html_content_concern.rb +143 -0
- data/app/controllers/concerns/camaleon_cms/runtime_shortcode_theme_concern.rb +246 -0
- data/app/controllers/concerns/camaleon_cms/runtime_state_concern.rb +13 -0
- data/app/controllers/concerns/camaleon_cms/runtime_uploader_concern.rb +54 -0
- data/app/controllers/concerns/camaleon_cms/session_captcha_runtime_concern.rb +19 -0
- data/app/controllers/concerns/camaleon_cms/session_runtime_concern.rb +40 -0
- data/app/decorators/camaleon_cms/application_decorator.rb +11 -8
- data/app/decorators/camaleon_cms/category_decorator.rb +3 -2
- data/app/decorators/camaleon_cms/post_comment_decorator.rb +13 -5
- data/app/decorators/camaleon_cms/post_decorator.rb +67 -51
- data/app/decorators/camaleon_cms/post_type_decorator.rb +1 -1
- data/app/decorators/camaleon_cms/site_decorator.rb +29 -23
- data/app/decorators/camaleon_cms/term_taxonomy_decorator.rb +21 -10
- data/app/decorators/camaleon_cms/theme_decorator.rb +3 -3
- data/app/decorators/camaleon_cms/user_decorator.rb +26 -5
- data/app/helpers/camaleon_cms/admin/application_helper.rb +21 -24
- data/app/helpers/camaleon_cms/admin/breadcrumb_helper.rb +1 -1
- data/app/helpers/camaleon_cms/admin/custom_fields_helper.rb +24 -23
- data/app/helpers/camaleon_cms/admin/menus_helper.rb +249 -139
- data/app/helpers/camaleon_cms/admin/post_type_helper.rb +51 -31
- data/app/helpers/camaleon_cms/camaleon_helper.rb +31 -39
- data/app/helpers/camaleon_cms/captcha_helper.rb +73 -53
- data/app/helpers/camaleon_cms/comment_helper.rb +87 -41
- data/app/helpers/camaleon_cms/content_helper.rb +13 -6
- data/app/helpers/camaleon_cms/email_helper.rb +7 -3
- data/app/helpers/camaleon_cms/frontend/content_select_helper.rb +34 -20
- data/app/helpers/camaleon_cms/frontend/nav_menu_helper.rb +144 -67
- data/app/helpers/camaleon_cms/frontend/seo_helper.rb +39 -28
- data/app/helpers/camaleon_cms/frontend/site_helper.rb +32 -12
- data/app/helpers/camaleon_cms/hooks_helper.rb +14 -4
- data/app/helpers/camaleon_cms/html_helper.rb +73 -38
- data/app/helpers/camaleon_cms/plugins_helper.rb +23 -24
- data/app/helpers/camaleon_cms/session_helper.rb +195 -39
- data/app/helpers/camaleon_cms/short_code_helper.rb +181 -85
- data/app/helpers/camaleon_cms/site_helper.rb +43 -9
- data/app/helpers/camaleon_cms/theme_helper.rb +35 -19
- data/app/helpers/camaleon_cms/uploader_helper.rb +19 -422
- data/app/helpers/camaleon_cms/user_roles_helper.rb +5 -4
- data/app/mailers/camaleon_cms/html_mailer.rb +4 -4
- data/app/models/camaleon_cms/ability.rb +65 -105
- data/app/models/camaleon_cms/category.rb +7 -5
- data/app/models/camaleon_cms/custom_field.rb +29 -6
- data/app/models/camaleon_cms/custom_field_group.rb +75 -21
- data/app/models/camaleon_cms/custom_fields_relationship.rb +133 -2
- data/app/models/camaleon_cms/media.rb +8 -2
- data/app/models/camaleon_cms/meta.rb +2 -2
- data/app/models/camaleon_cms/nav_menu.rb +6 -2
- data/app/models/camaleon_cms/nav_menu_item.rb +18 -8
- data/app/models/camaleon_cms/plugin.rb +4 -3
- data/app/models/camaleon_cms/post.rb +113 -27
- data/app/models/camaleon_cms/post_comment.rb +10 -6
- data/app/models/camaleon_cms/post_default.rb +42 -12
- data/app/models/camaleon_cms/post_relationship.rb +6 -4
- data/app/models/camaleon_cms/post_tag.rb +4 -3
- data/app/models/camaleon_cms/post_type.rb +22 -12
- data/app/models/camaleon_cms/site.rb +40 -28
- data/app/models/camaleon_cms/term_relationship.rb +10 -7
- data/app/models/camaleon_cms/term_taxonomy.rb +51 -5
- data/app/models/camaleon_cms/theme.rb +3 -3
- data/app/models/camaleon_cms/user.rb +17 -5
- data/app/models/camaleon_cms/user_role.rb +77 -4
- data/app/models/camaleon_cms/widget/assigned.rb +11 -6
- data/app/models/camaleon_cms/widget/main.rb +13 -7
- data/app/models/camaleon_cms/widget/sidebar.rb +3 -6
- data/app/models/camaleon_record.rb +123 -5
- data/app/models/concerns/camaleon_cms/categories_tags_for_posts.rb +20 -38
- data/app/models/concerns/camaleon_cms/common_relationships.rb +18 -5
- data/app/models/concerns/camaleon_cms/custom_fields_read.rb +115 -58
- data/app/models/concerns/camaleon_cms/metas.rb +32 -7
- data/app/models/concerns/camaleon_cms/normalize_attrs.rb +2 -8
- data/app/models/concerns/camaleon_cms/site_default_settings.rb +120 -16
- data/app/models/concerns/camaleon_cms/user_methods.rb +44 -19
- data/app/models/current_request.rb +23 -0
- data/app/uploaders/camaleon_cms_aws_uploader.rb +39 -11
- data/app/uploaders/camaleon_cms_local_uploader.rb +76 -19
- data/app/uploaders/camaleon_cms_uploader.rb +23 -10
- data/app/validators/camaleon_cms/post_uniq_validator.rb +21 -8
- data/app/validators/camaleon_cms/uniq_validator.rb +1 -1
- data/app/validators/camaleon_cms/user_url_validator.rb +215 -36
- data/app/views/camaleon_cms/admin/appearances/nav_menus/_left_menu_items.html.erb +2 -2
- data/app/views/camaleon_cms/admin/appearances/widgets/main/form.html.erb +1 -1
- data/app/views/camaleon_cms/admin/categories/index.html.erb +3 -3
- data/app/views/camaleon_cms/admin/comments/index.html.erb +2 -2
- data/app/views/camaleon_cms/admin/comments/list.html.erb +1 -1
- data/app/views/camaleon_cms/admin/installers/form.html.erb +5 -0
- data/app/views/camaleon_cms/admin/installers/welcome.html.erb +30 -6
- data/app/views/camaleon_cms/admin/plugins/_plugins_list.html.erb +2 -2
- data/app/views/camaleon_cms/admin/post_tags/index.html.erb +3 -3
- data/app/views/camaleon_cms/admin/posts/_sidebar.html.erb +2 -2
- data/app/views/camaleon_cms/admin/posts/form.html.erb +3 -2
- data/app/views/camaleon_cms/admin/posts/index.html.erb +6 -6
- data/app/views/camaleon_cms/admin/search.html.erb +1 -1
- data/app/views/camaleon_cms/admin/sessions/back_to_parent.html.erb +39 -0
- data/app/views/camaleon_cms/admin/sessions/logout_confirm.html.erb +27 -0
- data/app/views/camaleon_cms/admin/settings/_email_settings.html.erb +4 -1
- data/app/views/camaleon_cms/admin/settings/custom_fields/_get_items.html.erb +1 -1
- data/app/views/camaleon_cms/admin/settings/custom_fields/_render.html.erb +42 -6
- data/app/views/camaleon_cms/admin/settings/custom_fields/_render_category_simple.html.erb +1 -1
- data/app/views/camaleon_cms/admin/settings/custom_fields/fields/_select_eval.html.erb +1 -1
- data/app/views/camaleon_cms/admin/settings/custom_fields/form.html.erb +5 -4
- data/app/views/camaleon_cms/admin/settings/custom_fields/index.html.erb +1 -1
- data/app/views/camaleon_cms/admin/settings/post_types/index.html.erb +1 -1
- data/app/views/camaleon_cms/admin/settings/shortcodes.html.erb +4 -4
- data/app/views/camaleon_cms/admin/settings/site.html.erb +1 -1
- data/app/views/camaleon_cms/admin/settings/sites/form.html.erb +1 -1
- data/app/views/camaleon_cms/admin/settings/sites/index.html.erb +1 -1
- data/app/views/camaleon_cms/admin/user_roles/form.html.erb +102 -7
- data/app/views/camaleon_cms/admin/user_roles/index.html.erb +1 -1
- data/app/views/camaleon_cms/admin/users/form.html.erb +8 -4
- data/app/views/camaleon_cms/admin/users/index.html.erb +2 -2
- data/app/views/camaleon_cms/default_theme/partials/_render_custom_field.html.erb +8 -2
- data/app/views/camaleon_cms/default_theme/sitemap.html.erb +1 -1
- data/app/views/camaleon_cms/default_theme/sitemap.xml.builder +1 -1
- data/app/views/layouts/camaleon_cms/admin/_flash_messages.html.erb +2 -2
- data/app/views/layouts/camaleon_cms/admin/_header.html.erb +1 -1
- data/config/initializers/action_view.rb +42 -5
- data/config/initializers/active_record_extension.rb +13 -27
- data/config/initializers/assets.rb +52 -23
- data/config/initializers/custom_initializers.rb +3 -3
- data/config/locales/camaleon_cms/admin/ar.yml +7 -2
- data/config/locales/camaleon_cms/admin/de.yml +7 -2
- data/config/locales/camaleon_cms/admin/en.yml +39 -2
- data/config/locales/camaleon_cms/admin/es.yml +7 -2
- data/config/locales/camaleon_cms/admin/fr.yml +7 -2
- data/config/locales/camaleon_cms/admin/it.yml +7 -2
- data/config/locales/camaleon_cms/admin/nl.yml +8 -2
- data/config/locales/camaleon_cms/admin/pt-BR.yml +7 -2
- data/config/locales/camaleon_cms/admin/pt.yml +7 -2
- data/config/locales/camaleon_cms/admin/ru.yml +7 -2
- data/config/locales/camaleon_cms/admin/uk.yml +7 -2
- data/config/locales/camaleon_cms/admin/zh-CH.yml +7 -2
- data/config/routes/admin.rb +33 -15
- data/config/routes/frontend.rb +21 -15
- data/db/migrate/20150611161134_post_table_into_utf8.rb +14 -14
- data/db/migrate/20150926095310_rename_column_posts.rb +3 -3
- data/db/migrate/20151212095328_add_confirm_token_to_users.rb +3 -3
- data/db/migrate/20160504155652_add_feature_to_posts.rb +1 -1
- data/db/migrate/20160504155653_move_first_name_of_users.rb +2 -2
- data/db/migrate/20160609121449_add_group_to_custom_field_values.rb +1 -1
- data/db/migrate/20161215202255_drop_user_relationship_table.rb +1 -1
- data/db/migrate/20180124132318_create_media.rb +1 -1
- data/db/migrate/20180704211100_adjust_field_length.rb +1 -1
- data/lib/camaleon_cms/assets_precompile.rb +86 -0
- data/lib/camaleon_cms/captcha_image_generation.rb +65 -0
- data/lib/camaleon_cms/content_security.rb +158 -0
- data/lib/camaleon_cms/engine.rb +47 -9
- data/lib/camaleon_cms/media_security_headers.rb +27 -0
- data/lib/camaleon_cms/setup_token.rb +69 -0
- data/lib/camaleon_cms/svg_content_checker.rb +123 -0
- data/lib/camaleon_cms/task_reporter.rb +14 -0
- data/lib/camaleon_cms/unsafe_markup.rb +207 -0
- data/lib/camaleon_cms/uploader_content_security.rb +248 -0
- data/lib/camaleon_cms/uploader_image_processing.rb +166 -0
- data/lib/camaleon_cms/uploader_path_security.rb +146 -0
- data/lib/camaleon_cms/uploader_pipeline.rb +350 -0
- data/lib/camaleon_cms/uploader_support.rb +86 -0
- data/lib/camaleon_cms/version.rb +1 -1
- data/lib/camaleon_cms.rb +11 -0
- data/lib/ext/hash.rb +28 -2
- data/lib/ext/string.rb +13 -8
- data/lib/ext/translator.rb +10 -2
- data/lib/generators/camaleon_cms/gem_plugin_template/app/controllers/plugins/my_plugin/admin_controller.rb +5 -1
- data/lib/generators/camaleon_cms/install_generator.rb +7 -4
- data/lib/generators/camaleon_cms/install_template/plugin_routes.rb +5 -12
- data/lib/generators/camaleon_cms/theme_generator.rb +5 -10
- data/lib/generators/camaleon_cms/theme_template/views/layouts/index.html.erb +3 -1
- data/lib/plugin_routes.rb +412 -368
- data/lib/tasks/camaleon_cms/camaleon_tasks.rake +2 -1
- data/lib/tasks/cross_site_field_groups.rake +74 -0
- data/lib/tasks/custom_fields_roles.rake +58 -0
- data/lib/tasks/orphaned_comments.rake +42 -0
- data/lib/tasks/private_upload_acls.rake +31 -0
- data/lib/tasks/site_custom_field_groups.rake +36 -0
- data/lib/tasks/unsafe_stored_content.rake +42 -0
- data/lib/tasks/unsafe_stored_uploads.rake +70 -0
- data/lib/tasks/user_field_groups.rake +27 -0
- metadata +185 -7
|
@@ -1,22 +1,22 @@
|
|
|
1
1
|
module CamaleonCms
|
|
2
2
|
class FrontendController < CamaleonCms::CamaleonController
|
|
3
3
|
before_action :init_frontent
|
|
4
|
+
include CamaleonCms::FrontendVisitedStateConcern
|
|
4
5
|
include CamaleonCms::FrontendConcern
|
|
5
6
|
include CamaleonCms::Frontend::ApplicationHelper
|
|
6
7
|
layout proc { |controller|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
8
|
+
args = {
|
|
9
|
+
layout: (params[:cama_ajax_request].present? ? 'cama_ajax' : PluginRoutes.static_system_info['default_layout']),
|
|
10
|
+
controller: controller
|
|
11
|
+
}
|
|
12
|
+
hooks_run('front_default_layout', args)
|
|
13
|
+
args[:layout]
|
|
14
|
+
}
|
|
13
15
|
before_action :before_hooks
|
|
14
16
|
after_action :after_hooks
|
|
15
|
-
# rescue_from ActiveRecord::RecordNotFound, with: :page_not_found
|
|
16
|
-
|
|
17
17
|
# home page for frontend
|
|
18
18
|
def index
|
|
19
|
-
|
|
19
|
+
mark_frontend_home_visited
|
|
20
20
|
if @_site_options[:home_page].present?
|
|
21
21
|
render_post(@_site_options[:home_page].to_i)
|
|
22
22
|
else
|
|
@@ -29,28 +29,38 @@ module CamaleonCms
|
|
|
29
29
|
# render category list
|
|
30
30
|
def category
|
|
31
31
|
begin
|
|
32
|
-
|
|
32
|
+
if params[:category_slug].present?
|
|
33
|
+
@category ||= current_site.the_full_categories.find_by_slug(params[:category_slug]).decorate # rubocop:disable Rails/DynamicFindBy
|
|
34
|
+
end
|
|
33
35
|
@category ||= current_site.the_full_categories.find(params[:category_id]).decorate
|
|
34
36
|
@post_type = @category.the_post_type
|
|
35
37
|
rescue StandardError
|
|
36
38
|
return page_not_found
|
|
37
39
|
end
|
|
38
|
-
@
|
|
40
|
+
mark_frontend_category_visited(@category)
|
|
39
41
|
@children = @category.children.no_empty.decorate
|
|
40
42
|
@posts = @category.the_posts.paginate(page: params[:page],
|
|
41
43
|
per_page: current_site.front_per_page).eager_load(:metas)
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
44
|
+
category_slug = @category.the_slug
|
|
45
|
+
|
|
46
|
+
# specific template category with specific slug within a post-type
|
|
47
|
+
r_file = lookup_context.template_exists?("category_#{category_slug}") ? "category_#{category_slug}" : nil
|
|
48
|
+
post_type_slug = "post_types/#{@post_type.the_slug}"
|
|
49
|
+
if r_file.blank?
|
|
50
|
+
r_file = lookup_context.template_exists?("#{post_type_slug}/category") ? "#{post_type_slug}/category" : nil
|
|
45
51
|
end
|
|
46
|
-
|
|
47
|
-
r_file = lookup_context.template_exists?("categories/#{
|
|
52
|
+
if r_file.blank?
|
|
53
|
+
r_file = if lookup_context.template_exists?("categories/#{category_slug}")
|
|
54
|
+
"categories/#{category_slug}"
|
|
55
|
+
else
|
|
56
|
+
'category'
|
|
57
|
+
end
|
|
48
58
|
end
|
|
49
59
|
|
|
50
|
-
layout_ = if lookup_context.template_exists?("layouts
|
|
51
|
-
"
|
|
52
|
-
elsif lookup_context.template_exists?("layouts/categories/#{
|
|
53
|
-
"categories/#{
|
|
60
|
+
layout_ = if lookup_context.template_exists?("layouts/#{post_type_slug}/category")
|
|
61
|
+
"#{post_type_slug}/category"
|
|
62
|
+
elsif lookup_context.template_exists?("layouts/categories/#{category_slug}")
|
|
63
|
+
"categories/#{category_slug}"
|
|
54
64
|
end
|
|
55
65
|
r = { category: @category, layout: layout_, render: r_file }
|
|
56
66
|
hooks_run('on_render_category', r)
|
|
@@ -60,18 +70,20 @@ module CamaleonCms
|
|
|
60
70
|
# render contents from post type
|
|
61
71
|
def post_type
|
|
62
72
|
begin
|
|
63
|
-
@post_type = current_site.post_types.find_by_slug(params[:post_type_slug]).decorate
|
|
73
|
+
@post_type = current_site.post_types.find_by_slug(params[:post_type_slug]).decorate # rubocop:disable Rails/DynamicFindBy
|
|
64
74
|
rescue StandardError
|
|
65
75
|
return page_not_found
|
|
66
76
|
end
|
|
67
77
|
@object = @post_type
|
|
68
|
-
|
|
78
|
+
CurrentRequest.frontend_object = @object
|
|
79
|
+
mark_frontend_post_type_visited(@post_type)
|
|
69
80
|
@posts = @post_type.the_posts.paginate(page: params[:page],
|
|
70
81
|
per_page: current_site.front_per_page).eager_load(:metas)
|
|
71
82
|
@categories = @post_type.categories.no_empty.eager_load(:metas).decorate
|
|
72
83
|
@post_tags = @post_type.post_tags.eager_load(:metas)
|
|
73
|
-
|
|
74
|
-
|
|
84
|
+
post_type_slug = "post_types/#{@post_type.the_slug}"
|
|
85
|
+
r_file = lookup_context.template_exists?(post_type_slug) ? post_type_slug : 'post_type'
|
|
86
|
+
layout_ = lookup_context.template_exists?("layouts/#{post_type_slug}") ? post_type_slug : nil
|
|
75
87
|
r = { post_type: @post_type, layout: layout_, render: r_file }
|
|
76
88
|
hooks_run('on_render_post_type', r)
|
|
77
89
|
render r[:render], (!r[:layout].nil? ? { layout: r[:layout] } : {})
|
|
@@ -81,7 +93,7 @@ module CamaleonCms
|
|
|
81
93
|
def post_tag
|
|
82
94
|
begin
|
|
83
95
|
@post_tag = if params[:post_tag_slug].present?
|
|
84
|
-
current_site.post_tags.find_by_slug(params[:post_tag_slug]).decorate
|
|
96
|
+
current_site.post_tags.find_by_slug(params[:post_tag_slug]).decorate # rubocop:disable Rails/DynamicFindBy
|
|
85
97
|
else
|
|
86
98
|
current_site.post_tags.find(params[:post_tag_id]).decorate
|
|
87
99
|
end
|
|
@@ -90,10 +102,12 @@ module CamaleonCms
|
|
|
90
102
|
return page_not_found
|
|
91
103
|
end
|
|
92
104
|
@object = @post_tag
|
|
93
|
-
|
|
105
|
+
CurrentRequest.frontend_object = @object
|
|
106
|
+
mark_frontend_tag_visited(@post_tag)
|
|
94
107
|
@posts = @post_tag.the_posts.paginate(page: params[:page],
|
|
95
108
|
per_page: current_site.front_per_page).eager_load(:metas)
|
|
96
|
-
|
|
109
|
+
slug_post_tag = "post_types/#{@post_type.the_slug}/post_tag"
|
|
110
|
+
r_file = lookup_context.template_exists?(slug_post_tag) ? slug_post_tag : 'post_tag'
|
|
97
111
|
layout_ = lookup_context.template_exists?('layouts/post_tag') ? 'post_tag' : nil
|
|
98
112
|
r = { post_tag: @post_tag, layout: layout_, render: r_file }
|
|
99
113
|
hooks_run('on_render_post_tag', r)
|
|
@@ -103,19 +117,17 @@ module CamaleonCms
|
|
|
103
117
|
# search contents
|
|
104
118
|
def search
|
|
105
119
|
breadcrumb_add(ct('search'))
|
|
106
|
-
|
|
107
|
-
|
|
120
|
+
post_type_slugs = params[:post_type_slugs]
|
|
121
|
+
items = post_type_slugs.present? ? current_site.the_posts(post_type_slugs.split(',')) : current_site.the_posts
|
|
122
|
+
mark_frontend_search_visited
|
|
108
123
|
@param_search = params[:q]
|
|
109
124
|
layout_ = lookup_context.template_exists?('layouts/search') ? 'search' : nil
|
|
110
125
|
r = { layout: layout_, render: 'search', posts: nil }
|
|
111
126
|
hooks_run('on_render_search', r)
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
items.where('LOWER(title) LIKE ? OR LOWER(content_filtered) LIKE ?',
|
|
117
|
-
"%#{params[:q]}%", "%#{params[:q]}%")
|
|
118
|
-
end
|
|
127
|
+
q_params = params[:q].to_s.downcase
|
|
128
|
+
params[:q] = q_params
|
|
129
|
+
@posts = r[:posts] ||
|
|
130
|
+
items.where('LOWER(title) LIKE ? OR LOWER(content_filtered) LIKE ?', "%#{q_params}%", "%#{q_params}%")
|
|
119
131
|
@posts_size = @posts.size
|
|
120
132
|
@posts = @posts.paginate(page: params[:page], per_page: current_site.front_per_page)
|
|
121
133
|
render r[:render], (!r[:layout].nil? ? { layout: r[:layout] } : {})
|
|
@@ -124,7 +136,7 @@ module CamaleonCms
|
|
|
124
136
|
# ajax requests
|
|
125
137
|
def ajax
|
|
126
138
|
r = { render_file: nil, render_text: '', layout: nil }
|
|
127
|
-
|
|
139
|
+
mark_frontend_ajax_visited
|
|
128
140
|
hooks_run('on_ajax', r)
|
|
129
141
|
if r[:render_file]
|
|
130
142
|
render r[:render_file], (!r[:layout].nil? ? { layout: r[:layout] } : {})
|
|
@@ -150,7 +162,8 @@ module CamaleonCms
|
|
|
150
162
|
return page_not_found
|
|
151
163
|
end
|
|
152
164
|
@object = @user
|
|
153
|
-
|
|
165
|
+
CurrentRequest.frontend_object = @object
|
|
166
|
+
mark_frontend_profile_visited(@user)
|
|
154
167
|
layout_ = lookup_context.template_exists?('layouts/profile') ? 'profile' : nil
|
|
155
168
|
r = { user: @user, layout: layout_, render: 'profile' }
|
|
156
169
|
hooks_run('on_render_profile', r)
|
|
@@ -168,6 +181,7 @@ module CamaleonCms
|
|
|
168
181
|
def draft_render
|
|
169
182
|
post_draft = current_site.posts.drafts.find(params[:draft_id])
|
|
170
183
|
@object = post_draft
|
|
184
|
+
CurrentRequest.frontend_object = @object
|
|
171
185
|
|
|
172
186
|
# let a hook override the ability for certain roles see drafts
|
|
173
187
|
args = { permitted: false }
|
|
@@ -186,7 +200,9 @@ module CamaleonCms
|
|
|
186
200
|
def render_post(post_or_slug_or_id, from_url = false, status = nil, force_visit = false)
|
|
187
201
|
@post = case post_or_slug_or_id
|
|
188
202
|
when String # slug
|
|
189
|
-
|
|
203
|
+
# find_by_slug is multi-language aware (matches localized slugs like
|
|
204
|
+
# "<!--:en-->sample-post<!--:-->..."), unlike find_by(slug:)
|
|
205
|
+
current_site.the_posts.find_by_slug(post_or_slug_or_id) # rubocop:disable Rails/DynamicFindBy
|
|
190
206
|
when Integer # id
|
|
191
207
|
current_site.the_posts.where(id: post_or_slug_or_id).first
|
|
192
208
|
else # model
|
|
@@ -194,15 +210,16 @@ module CamaleonCms
|
|
|
194
210
|
end
|
|
195
211
|
|
|
196
212
|
@post = @post.try(:decorate)
|
|
197
|
-
if
|
|
198
|
-
if params[:format] == 'html' ||
|
|
213
|
+
if @post.blank? || !(force_visit || @post.can_visit?)
|
|
214
|
+
if params[:format] == 'html' || params[:format].blank?
|
|
199
215
|
page_not_found
|
|
200
216
|
else
|
|
201
|
-
head
|
|
217
|
+
head :not_found
|
|
202
218
|
end
|
|
203
219
|
else
|
|
204
220
|
@object = @post
|
|
205
|
-
|
|
221
|
+
CurrentRequest.frontend_object = @object
|
|
222
|
+
mark_frontend_post_visited(@post)
|
|
206
223
|
@post_type = @post.the_post_type
|
|
207
224
|
@comments = @post.the_comments
|
|
208
225
|
@categories = @post.the_categories
|
|
@@ -213,10 +230,11 @@ module CamaleonCms
|
|
|
213
230
|
rescue StandardError
|
|
214
231
|
nil
|
|
215
232
|
end
|
|
233
|
+
post_template = @post.get_template(@post_type)
|
|
216
234
|
r_file = if lookup_context.template_exists?("page_#{@post.id}")
|
|
217
235
|
"page_#{@post.id}"
|
|
218
|
-
elsif
|
|
219
|
-
|
|
236
|
+
elsif post_template.present? && lookup_context.template_exists?(post_template)
|
|
237
|
+
post_template
|
|
220
238
|
elsif home_page.present? && @post.id.to_s == home_page
|
|
221
239
|
'index'
|
|
222
240
|
elsif lookup_context.template_exists?("post_types/#{@post_type.the_slug}/single")
|
|
@@ -261,17 +279,54 @@ module CamaleonCms
|
|
|
261
279
|
# if url hasn't a locale, then it will use default locale set on application.rb
|
|
262
280
|
def init_frontent
|
|
263
281
|
# preview theme initializing
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
282
|
+
previewing_theme = cama_sign_in? && params[:ccc_theme_preview].present? && can?(:manage, :themes)
|
|
283
|
+
if previewing_theme
|
|
284
|
+
preview_theme = current_site.themes.where(slug: params[:ccc_theme_preview]).first_or_create!.decorate
|
|
285
|
+
@_current_theme = preview_theme
|
|
286
|
+
CurrentRequest.frontend_current_theme = preview_theme
|
|
287
|
+
ensure_preview_site_defaults
|
|
288
|
+
end
|
|
267
289
|
|
|
268
290
|
@_site_options = current_site.options
|
|
269
|
-
|
|
291
|
+
# Only a scalar language param participates in locale resolution — a non-scalar
|
|
292
|
+
# (?locale[]= / ?cama_set_language[]=) would crash to_sym and 500 the request
|
|
293
|
+
set_language = params[:cama_set_language]
|
|
294
|
+
session[:cama_current_language] = set_language.to_sym if set_language.is_a?(String) && set_language.present?
|
|
270
295
|
session[:cama_current_language] = nil if current_site.get_languages.exclude?(session[:cama_current_language])
|
|
271
|
-
|
|
272
|
-
|
|
296
|
+
requested_locale = params[:locale] if params[:locale].is_a?(String)
|
|
297
|
+
I18n.locale = requested_locale || session[:cama_current_language] || current_site.get_languages.first
|
|
298
|
+
# The availability gate renders the site's 404 (directly or via a custom error_404
|
|
299
|
+
# post), so the theme lookup prefixes must already be registered when it fires
|
|
300
|
+
configure_frontend_lookup_prefixes
|
|
301
|
+
theme_init
|
|
302
|
+
return if current_site.get_languages.include?(I18n.locale.to_sym)
|
|
303
|
+
|
|
304
|
+
# The unoffered locale must not style the 404 page or leak into its links
|
|
305
|
+
I18n.locale = current_site.get_languages.first
|
|
306
|
+
page_not_found
|
|
307
|
+
end
|
|
308
|
+
|
|
309
|
+
# initialize hooks before to execute action
|
|
310
|
+
def before_hooks
|
|
311
|
+
hooks_run('front_before_load')
|
|
312
|
+
end
|
|
313
|
+
|
|
314
|
+
# initialize hooks after executed action
|
|
315
|
+
def after_hooks
|
|
316
|
+
hooks_run('front_after_load')
|
|
317
|
+
end
|
|
318
|
+
|
|
319
|
+
# define default options for url helpers
|
|
320
|
+
# control for default locale
|
|
321
|
+
def default_url_options(options = {})
|
|
322
|
+
return options if current_site.get_languages.first.to_s == I18n.locale.to_s
|
|
273
323
|
|
|
274
|
-
|
|
324
|
+
{ locale: I18n.locale }.merge!(options)
|
|
325
|
+
rescue StandardError
|
|
326
|
+
options
|
|
327
|
+
end
|
|
328
|
+
|
|
329
|
+
def configure_frontend_lookup_prefixes
|
|
275
330
|
lookup_context.prefixes.delete('frontend')
|
|
276
331
|
lookup_context.prefixes.delete('application')
|
|
277
332
|
lookup_context.prefixes.delete('camaleon_cms/frontend')
|
|
@@ -282,36 +337,51 @@ module CamaleonCms
|
|
|
282
337
|
t =~ %r{themes/(.*)/views}i || t == 'camaleon_cms/default_theme' || t == "themes/#{current_site.id}/views"
|
|
283
338
|
end
|
|
284
339
|
|
|
285
|
-
|
|
286
|
-
|
|
340
|
+
# Per-site theme override: views placed under app/apps/themes/<site_id>/views
|
|
341
|
+
# take precedence over the active theme's views (it is appended first).
|
|
342
|
+
if Dir.exist?(Rails.root.join('app', 'apps', 'themes', current_site.id.to_s).to_s)
|
|
343
|
+
lookup_context.prefixes.append("themes/#{current_site.id}/views")
|
|
344
|
+
end
|
|
287
345
|
lookup_context.prefixes.append("themes/#{current_theme.slug}/views")
|
|
288
346
|
lookup_context.prefixes.append('camaleon_cms/default_theme')
|
|
289
347
|
|
|
290
348
|
lookup_context.prefixes = lookup_context.prefixes.uniq
|
|
291
349
|
lookup_context.use_camaleon_partial_prefixes = true
|
|
292
|
-
theme_init
|
|
293
350
|
end
|
|
294
351
|
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
352
|
+
def ensure_preview_site_defaults
|
|
353
|
+
preview_required_menu_slugs.each do |slug|
|
|
354
|
+
current_site.nav_menus.where(slug: slug).first_or_create! do |menu|
|
|
355
|
+
menu.name = slug.to_s.humanize
|
|
356
|
+
end
|
|
357
|
+
end
|
|
298
358
|
end
|
|
299
359
|
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
360
|
+
def preview_required_menu_slugs
|
|
361
|
+
slugs = ['main_menu']
|
|
362
|
+
slugs.concat(extract_theme_menu_slugs(current_theme.settings['path']))
|
|
363
|
+
slugs.uniq
|
|
303
364
|
end
|
|
304
365
|
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
366
|
+
def extract_theme_menu_slugs(theme_path)
|
|
367
|
+
return [] if theme_path.blank?
|
|
368
|
+
|
|
369
|
+
views_path = File.join(theme_path, 'views')
|
|
370
|
+
return [] unless Dir.exist?(views_path)
|
|
371
|
+
|
|
372
|
+
Dir.glob(File.join(views_path, '**', '*.erb')).flat_map do |file_path|
|
|
373
|
+
extract_menu_slugs_from_template(File.read(file_path))
|
|
374
|
+
end.uniq
|
|
375
|
+
end
|
|
376
|
+
|
|
377
|
+
def extract_menu_slugs_from_template(content)
|
|
378
|
+
slugs = []
|
|
379
|
+
slugs.concat(content.scan(/nav_menus\.where\(\s*slug:\s*'([^']+)'\s*\)/).flatten)
|
|
380
|
+
slugs.concat(content.scan(/nav_menus\.where\(\s*slug:\s*"([^"]+)"\s*\)/).flatten)
|
|
381
|
+
content.scan(/nav_menus\.where\(\s*slug:\s*\[([^\]]+)\]\s*\)/).flatten.each do |array_content|
|
|
382
|
+
slugs.concat(array_content.scan(/['"]([^'"]+)['"]/).flatten)
|
|
312
383
|
end
|
|
313
|
-
|
|
314
|
-
options
|
|
384
|
+
slugs
|
|
315
385
|
end
|
|
316
386
|
end
|
|
317
387
|
end
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
module CamaleonCms
|
|
2
|
+
module Admin
|
|
3
|
+
module CustomFieldsConcern
|
|
4
|
+
extend ActiveSupport::Concern
|
|
5
|
+
|
|
6
|
+
private
|
|
7
|
+
|
|
8
|
+
# Only permit field values whose slug is registered under object_class. param_key selects
|
|
9
|
+
# which request param carries the payload, so sibling params (the theme form's
|
|
10
|
+
# theme_fields) get the same allowed-slugs permit as the default field_options.
|
|
11
|
+
def cama_permitted_field_options(object_class, param_key: :field_options)
|
|
12
|
+
field_options = params[param_key]
|
|
13
|
+
# A non-hash payload (a scalar `field_options=foo`, or an array) carries no groups to permit,
|
|
14
|
+
# so treat it as empty instead of calling #keys/#permit on it. Guarding here rather than
|
|
15
|
+
# `params.require` avoids a NoMethodError -> 500 an authenticated caller could trigger with a
|
|
16
|
+
# malformed param (the same crash every set_field_values caller shared).
|
|
17
|
+
return {} unless field_options.is_a?(ActionController::Parameters)
|
|
18
|
+
|
|
19
|
+
allowed_keys = cama_custom_field_allowed_slugs(object_class)
|
|
20
|
+
return {} if allowed_keys.blank?
|
|
21
|
+
|
|
22
|
+
permitted = field_options.permit(field_options.keys.select { |k| k.to_s =~ /\A\d+\z/ }.index_with do
|
|
23
|
+
allowed_keys.index_with { [:id, :group_number, { values: {} }] }
|
|
24
|
+
end).to_h
|
|
25
|
+
# Drop groups left empty after filtering. set_field_values deletes every existing value
|
|
26
|
+
# before writing, so handing it a non-blank-but-empty payload (a group whose submitted
|
|
27
|
+
# slugs were all unregistered) would wipe the object's stored values and write nothing.
|
|
28
|
+
permitted.reject { |_group, fields| fields.blank? }
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# The allow-list covers fields registered directly under object_class. For a post
|
|
32
|
+
# ('PostType_Post') this intentionally spans only the post type's own groups -- not per-post
|
|
33
|
+
# ('Post') or category-inherited ('Category_Post') groups the edit form also renders. It
|
|
34
|
+
# matches PostsController#save_post_with_fields, so the main post save and drafts confine field
|
|
35
|
+
# writes identically; values for those sibling scopes are deliberately not written this way.
|
|
36
|
+
def cama_custom_field_allowed_slugs(object_class)
|
|
37
|
+
CamaleonCms::CustomField.where(
|
|
38
|
+
parent_id: CamaleonCms::CustomField.where(object_class: object_class).select(:id),
|
|
39
|
+
object_class: '_fields'
|
|
40
|
+
).pluck(:slug).uniq
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
@@ -4,7 +4,8 @@ module CamaleonCms
|
|
|
4
4
|
# visiting sitemap.xml
|
|
5
5
|
# With hook "on_render_sitemap" you can skip post_types, categories, tags or posts
|
|
6
6
|
# you can change render file and layout
|
|
7
|
-
# you can add custom sitemap elements in the attr "custom",
|
|
7
|
+
# you can add custom sitemap elements in the attr "custom",
|
|
8
|
+
# like: https://github.com/owen2345/camaleon-cms/issues/106#issuecomment-146232211
|
|
8
9
|
# you can customize your content for html or xml format
|
|
9
10
|
def sitemap
|
|
10
11
|
r = { layout: (params[:format] == 'html' ? nil : false), render: 'sitemap', custom: {}, format: params[:format],
|
|
@@ -31,21 +32,33 @@ module CamaleonCms
|
|
|
31
32
|
# save comment from a post
|
|
32
33
|
def save_comment
|
|
33
34
|
flash[:comment_submit] = {}
|
|
34
|
-
|
|
35
|
+
# Security (audit Low): this is a public endpoint. A post id naming no post used to reach
|
|
36
|
+
# `.decorate` on nil (500), and the anonymous branch indexed a missing post_comment param.
|
|
37
|
+
# Fail closed with a graceful error instead of a 500 an attacker can trigger at will.
|
|
38
|
+
@post = current_site.posts.find_by(id: params[:post_id])&.decorate
|
|
35
39
|
user = cama_current_user
|
|
36
40
|
comment_data = {}
|
|
37
|
-
|
|
38
|
-
flash[:comment_submit][:error] =
|
|
39
|
-
|
|
41
|
+
if @post.nil?
|
|
42
|
+
flash[:comment_submit][:error] = t('.post_not_found', default: 'Post not found')
|
|
43
|
+
elsif !@post.can_commented?
|
|
44
|
+
flash[:comment_submit][:error] = t('.comments_not_enabled', default: 'This post can not be commented')
|
|
40
45
|
end
|
|
46
|
+
|
|
47
|
+
# Security (audit Low): params[:post_comment] is attacker-controlled and may arrive as a scalar
|
|
48
|
+
# or array, not the expected hash. `|| {}` only covered nil; indexing a String/Array with a
|
|
49
|
+
# symbol key raises TypeError (500). Coerce anything not hash-shaped to an empty hash so every
|
|
50
|
+
# post_comment[...] read below is safe.
|
|
51
|
+
post_comment = params[:post_comment]
|
|
52
|
+
post_comment = {} unless post_comment.is_a?(ActionController::Parameters) || post_comment.is_a?(Hash)
|
|
53
|
+
|
|
41
54
|
if user.present?
|
|
42
55
|
comment_data[:author] = user.fullname
|
|
43
56
|
comment_data[:author_email] = user.email
|
|
44
57
|
elsif current_site.get_option('permit_anonimos_comment', false)
|
|
45
58
|
user = current_site.get_anonymous_user
|
|
46
59
|
comment_data[:is_anonymous] = true
|
|
47
|
-
comment_data[:author] =
|
|
48
|
-
comment_data[:author_email] =
|
|
60
|
+
comment_data[:author] = post_comment[:name]
|
|
61
|
+
comment_data[:author_email] = post_comment[:email]
|
|
49
62
|
if current_site.is_enable_captcha_for_comments? && !cama_captcha_verified?
|
|
50
63
|
flash[:comment_submit][:error] =
|
|
51
64
|
t('camaleon_cms.admin.users.message.error_captcha',
|
|
@@ -56,24 +69,40 @@ module CamaleonCms
|
|
|
56
69
|
unless flash[:comment_submit][:error]
|
|
57
70
|
if user.present?
|
|
58
71
|
comment_data[:user_id] = user.id
|
|
59
|
-
comment_data[:author_url] =
|
|
72
|
+
comment_data[:author_url] = post_comment[:url] || ''
|
|
60
73
|
comment_data[:author_IP] = request.remote_ip.to_s
|
|
61
74
|
comment_data[:approved] = current_site.front_comment_status
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
75
|
+
# Browsers always send a User-Agent but API clients/bots may not; record it nil-safely
|
|
76
|
+
# and without mutating the request's header string in place.
|
|
77
|
+
comment_data[:agent] = request.user_agent.to_s.encode('UTF-8', 'ISO-8859-1')
|
|
78
|
+
comment_data[:content] = post_comment[:content]
|
|
79
|
+
# Security (audit Low): a crafted parent_id naming no comment on this post made find_by
|
|
80
|
+
# return nil and the chained `.children` raise (500). Resolve the parent first and fail
|
|
81
|
+
# closed with a graceful error when a supplied parent_id matches nothing.
|
|
82
|
+
parent_id = post_comment[:parent_id]
|
|
83
|
+
parent = @post.comments.find_by(id: parent_id) if parent_id.present?
|
|
84
|
+
if parent_id.present? && parent.nil?
|
|
85
|
+
flash[:comment_submit][:error] = t('.parent_comment_not_found', default: 'Parent comment not found')
|
|
67
86
|
else
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
87
|
+
@comment = parent ? parent.children.new(comment_data) : @post.comments.main.new(comment_data)
|
|
88
|
+
if @comment.save
|
|
89
|
+
flash[:comment_submit][:notice] = t('camaleon_cms.admin.comments.message.created')
|
|
90
|
+
else
|
|
91
|
+
base = t('camaleon_cms.common.comment_error', default: 'An error was occurred on save comment')
|
|
92
|
+
flash[:comment_submit][:error] = "#{base}:<br> #{@comment.errors.full_messages.join(', ')}"
|
|
93
|
+
end
|
|
71
94
|
end
|
|
72
95
|
else
|
|
73
96
|
flash[:comment_submit][:error] = t('camaleon_cms.admin.message.unauthorized')
|
|
74
97
|
end
|
|
75
98
|
end
|
|
76
|
-
|
|
99
|
+
|
|
100
|
+
return render(json: flash.discard(:comment_submit).to_hash) if params[:format] == 'json'
|
|
101
|
+
|
|
102
|
+
# Security (audit Low): the Referer header is attacker-controlled; redirecting to it raw is an
|
|
103
|
+
# open redirect (Rails < 7) or an UnsafeRedirectError 500 (Rails >= 7). Vet it through the shared
|
|
104
|
+
# same-host/allowlist redirect helper, falling back to the post URL (or root).
|
|
105
|
+
cama_safe_redirect(request.referer, @post&.the_url(as_path: true) || '/')
|
|
77
106
|
end
|
|
78
107
|
end
|
|
79
108
|
end
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
module CamaleonCms
|
|
2
|
+
module FrontendVisitedStateConcern
|
|
3
|
+
extend ActiveSupport::Concern
|
|
4
|
+
|
|
5
|
+
LEGACY_VISITED_IVAR_BY_ATTR = {
|
|
6
|
+
frontend_visited_home: :@cama_visited_home,
|
|
7
|
+
frontend_visited_post: :@cama_visited_post,
|
|
8
|
+
frontend_visited_ajax: :@cama_visited_ajax,
|
|
9
|
+
frontend_visited_search: :@cama_visited_search,
|
|
10
|
+
frontend_visited_post_type: :@cama_visited_post_type,
|
|
11
|
+
frontend_visited_tag: :@cama_visited_tag,
|
|
12
|
+
frontend_visited_category: :@cama_visited_category,
|
|
13
|
+
frontend_visited_profile: :@cama_visited_profile
|
|
14
|
+
}.freeze
|
|
15
|
+
|
|
16
|
+
private
|
|
17
|
+
|
|
18
|
+
def mark_frontend_home_visited
|
|
19
|
+
set_frontend_visited_state(:frontend_visited_home, true)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def mark_frontend_post_visited(post)
|
|
23
|
+
set_frontend_visited_state(:frontend_visited_post, post)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def mark_frontend_ajax_visited
|
|
27
|
+
set_frontend_visited_state(:frontend_visited_ajax, true)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def mark_frontend_search_visited
|
|
31
|
+
set_frontend_visited_state(:frontend_visited_search, true)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def mark_frontend_post_type_visited(post_type)
|
|
35
|
+
set_frontend_visited_state(:frontend_visited_post_type, post_type)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def mark_frontend_tag_visited(post_tag)
|
|
39
|
+
set_frontend_visited_state(:frontend_visited_tag, post_tag)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def mark_frontend_category_visited(category)
|
|
43
|
+
set_frontend_visited_state(:frontend_visited_category, category)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def mark_frontend_profile_visited(user = nil)
|
|
47
|
+
set_frontend_visited_state(:frontend_visited_profile, true)
|
|
48
|
+
CurrentRequest.frontend_user = user if user.present?
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def set_frontend_visited_state(current_request_attr, value)
|
|
52
|
+
CurrentRequest.public_send("#{current_request_attr}=", value)
|
|
53
|
+
legacy_ivar = LEGACY_VISITED_IVAR_BY_ATTR[current_request_attr]
|
|
54
|
+
return if legacy_ivar.blank?
|
|
55
|
+
|
|
56
|
+
instance_variable_set(legacy_ivar, value)
|
|
57
|
+
warn_frontend_legacy_visited_ivar(legacy_ivar, current_request_attr)
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def warn_frontend_legacy_visited_ivar(legacy_ivar, current_request_attr)
|
|
61
|
+
warned_legacy_ivars = self.class.instance_variable_get(:@_warned_frontend_legacy_visited_ivars) || {}
|
|
62
|
+
return if warned_legacy_ivars[legacy_ivar]
|
|
63
|
+
|
|
64
|
+
ActiveSupport::Deprecation._instance.warn(
|
|
65
|
+
"Controller compatibility ivar #{legacy_ivar} is deprecated and will be removed in a future major release. " \
|
|
66
|
+
"Use CurrentRequest.#{current_request_attr} instead."
|
|
67
|
+
)
|
|
68
|
+
warned_legacy_ivars[legacy_ivar] = true
|
|
69
|
+
self.class.instance_variable_set(:@_warned_frontend_legacy_visited_ivars, warned_legacy_ivars)
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
end
|