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.
Files changed (241) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +29 -9
  3. data/Rakefile +3 -16
  4. data/app/apps/plugins/attack/admin_controller.rb +9 -6
  5. data/app/apps/plugins/attack/attack_helper.rb +35 -25
  6. data/app/apps/plugins/authoring_post/authoring_post_helper.rb +23 -16
  7. data/app/apps/plugins/front_cache/admin_controller.rb +16 -10
  8. data/app/apps/plugins/front_cache/config/initializer.rb +1 -1
  9. data/app/apps/plugins/front_cache/front_cache_helper.rb +57 -24
  10. data/app/apps/plugins/visibility_post/config/config.json +1 -0
  11. data/app/apps/plugins/visibility_post/config/routes_front.txt +1 -0
  12. data/app/apps/plugins/visibility_post/front_controller.rb +23 -0
  13. data/app/apps/plugins/visibility_post/visibility_post_helper.rb +141 -70
  14. data/app/apps/themes/camaleon_first/main_helper.rb +18 -12
  15. data/app/apps/themes/default/assets/css/style.css.scss +24 -0
  16. data/app/apps/themes/default/assets/genericons/genericons.css +3 -8
  17. data/app/apps/themes/default/default_helper.rb +2 -1
  18. data/app/apps/themes/default/views/category.html.erb +1 -1
  19. data/app/apps/themes/default/views/layouts/index.html.erb +3 -1
  20. data/app/apps/themes/default/views/post_tag.html.erb +1 -1
  21. data/app/apps/themes/default/views/post_type.html.erb +1 -1
  22. data/app/apps/themes/default/views/search.html.erb +1 -1
  23. data/app/apps/themes/new/assets/css/styles.css.scss +24 -0
  24. data/app/apps/themes/new/custom_helper.rb +5 -9
  25. data/app/apps/themes/new/views/category.html.erb +1 -1
  26. data/app/apps/themes/new/views/layouts/_header.html.erb +3 -1
  27. data/app/apps/themes/new/views/post_tag.html.erb +1 -1
  28. data/app/apps/themes/new/views/post_type.html.erb +1 -1
  29. data/app/apps/themes/new/views/search.html.erb +1 -1
  30. data/app/assets/javascripts/camaleon_cms/admin/_data.js +16 -0
  31. data/app/assets/javascripts/camaleon_cms/admin/_post.js +5 -2
  32. data/app/assets/javascripts/camaleon_cms/admin/nav_menu.js +14 -3
  33. data/app/assets/javascripts/camaleon_cms/admin/uploader/_media_manager.js +5 -0
  34. data/app/controllers/camaleon_cms/admin/appearances/nav_menus_controller.rb +29 -10
  35. data/app/controllers/camaleon_cms/admin/appearances/themes_controller.rb +8 -5
  36. data/app/controllers/camaleon_cms/admin/appearances/widgets/assign_controller.rb +9 -2
  37. data/app/controllers/camaleon_cms/admin/appearances/widgets/main_controller.rb +4 -3
  38. data/app/controllers/camaleon_cms/admin/appearances/widgets/sidebar_controller.rb +2 -2
  39. data/app/controllers/camaleon_cms/admin/categories_controller.rb +27 -8
  40. data/app/controllers/camaleon_cms/admin/comments_controller.rb +0 -1
  41. data/app/controllers/camaleon_cms/admin/installers_controller.rb +32 -1
  42. data/app/controllers/camaleon_cms/admin/media_controller.rb +84 -19
  43. data/app/controllers/camaleon_cms/admin/plugins_controller.rb +1 -3
  44. data/app/controllers/camaleon_cms/admin/post_tags_controller.rb +15 -6
  45. data/app/controllers/camaleon_cms/admin/posts/drafts_controller.rb +40 -11
  46. data/app/controllers/camaleon_cms/admin/posts_controller.rb +58 -22
  47. data/app/controllers/camaleon_cms/admin/sessions_controller.rb +238 -45
  48. data/app/controllers/camaleon_cms/admin/settings/custom_fields_controller.rb +103 -18
  49. data/app/controllers/camaleon_cms/admin/settings/post_types_controller.rb +17 -5
  50. data/app/controllers/camaleon_cms/admin/settings/sites_controller.rb +33 -7
  51. data/app/controllers/camaleon_cms/admin/settings_controller.rb +11 -6
  52. data/app/controllers/camaleon_cms/admin/user_roles_controller.rb +9 -7
  53. data/app/controllers/camaleon_cms/admin/users_controller.rb +89 -18
  54. data/app/controllers/camaleon_cms/admin_controller.rb +144 -26
  55. data/app/controllers/camaleon_cms/apps/plugins_admin_controller.rb +5 -0
  56. data/app/controllers/camaleon_cms/camaleon_controller.rb +37 -92
  57. data/app/controllers/camaleon_cms/frontend_controller.rb +140 -70
  58. data/app/controllers/concerns/camaleon_cms/admin/custom_fields_concern.rb +44 -0
  59. data/app/controllers/concerns/camaleon_cms/frontend_concern.rb +46 -17
  60. data/app/controllers/concerns/camaleon_cms/frontend_visited_state_concern.rb +72 -0
  61. data/app/controllers/concerns/camaleon_cms/hook_lifecycle_concern.rb +104 -0
  62. data/app/controllers/concerns/camaleon_cms/request_context_concern.rb +113 -0
  63. data/app/controllers/concerns/camaleon_cms/runtime_admin_menu_concern.rb +237 -0
  64. data/app/controllers/concerns/camaleon_cms/runtime_captcha_image_concern.rb +13 -0
  65. data/app/controllers/concerns/camaleon_cms/runtime_html_content_concern.rb +143 -0
  66. data/app/controllers/concerns/camaleon_cms/runtime_shortcode_theme_concern.rb +246 -0
  67. data/app/controllers/concerns/camaleon_cms/runtime_state_concern.rb +13 -0
  68. data/app/controllers/concerns/camaleon_cms/runtime_uploader_concern.rb +54 -0
  69. data/app/controllers/concerns/camaleon_cms/session_captcha_runtime_concern.rb +19 -0
  70. data/app/controllers/concerns/camaleon_cms/session_runtime_concern.rb +40 -0
  71. data/app/decorators/camaleon_cms/application_decorator.rb +11 -8
  72. data/app/decorators/camaleon_cms/category_decorator.rb +3 -2
  73. data/app/decorators/camaleon_cms/post_comment_decorator.rb +13 -5
  74. data/app/decorators/camaleon_cms/post_decorator.rb +67 -51
  75. data/app/decorators/camaleon_cms/post_type_decorator.rb +1 -1
  76. data/app/decorators/camaleon_cms/site_decorator.rb +29 -23
  77. data/app/decorators/camaleon_cms/term_taxonomy_decorator.rb +21 -10
  78. data/app/decorators/camaleon_cms/theme_decorator.rb +3 -3
  79. data/app/decorators/camaleon_cms/user_decorator.rb +26 -5
  80. data/app/helpers/camaleon_cms/admin/application_helper.rb +21 -24
  81. data/app/helpers/camaleon_cms/admin/breadcrumb_helper.rb +1 -1
  82. data/app/helpers/camaleon_cms/admin/custom_fields_helper.rb +24 -23
  83. data/app/helpers/camaleon_cms/admin/menus_helper.rb +249 -139
  84. data/app/helpers/camaleon_cms/admin/post_type_helper.rb +51 -31
  85. data/app/helpers/camaleon_cms/camaleon_helper.rb +31 -39
  86. data/app/helpers/camaleon_cms/captcha_helper.rb +73 -53
  87. data/app/helpers/camaleon_cms/comment_helper.rb +87 -41
  88. data/app/helpers/camaleon_cms/content_helper.rb +13 -6
  89. data/app/helpers/camaleon_cms/email_helper.rb +7 -3
  90. data/app/helpers/camaleon_cms/frontend/content_select_helper.rb +34 -20
  91. data/app/helpers/camaleon_cms/frontend/nav_menu_helper.rb +144 -67
  92. data/app/helpers/camaleon_cms/frontend/seo_helper.rb +39 -28
  93. data/app/helpers/camaleon_cms/frontend/site_helper.rb +32 -12
  94. data/app/helpers/camaleon_cms/hooks_helper.rb +14 -4
  95. data/app/helpers/camaleon_cms/html_helper.rb +73 -38
  96. data/app/helpers/camaleon_cms/plugins_helper.rb +23 -24
  97. data/app/helpers/camaleon_cms/session_helper.rb +195 -39
  98. data/app/helpers/camaleon_cms/short_code_helper.rb +181 -85
  99. data/app/helpers/camaleon_cms/site_helper.rb +43 -9
  100. data/app/helpers/camaleon_cms/theme_helper.rb +35 -19
  101. data/app/helpers/camaleon_cms/uploader_helper.rb +19 -422
  102. data/app/helpers/camaleon_cms/user_roles_helper.rb +5 -4
  103. data/app/mailers/camaleon_cms/html_mailer.rb +4 -4
  104. data/app/models/camaleon_cms/ability.rb +65 -105
  105. data/app/models/camaleon_cms/category.rb +7 -5
  106. data/app/models/camaleon_cms/custom_field.rb +29 -6
  107. data/app/models/camaleon_cms/custom_field_group.rb +75 -21
  108. data/app/models/camaleon_cms/custom_fields_relationship.rb +133 -2
  109. data/app/models/camaleon_cms/media.rb +8 -2
  110. data/app/models/camaleon_cms/meta.rb +2 -2
  111. data/app/models/camaleon_cms/nav_menu.rb +6 -2
  112. data/app/models/camaleon_cms/nav_menu_item.rb +18 -8
  113. data/app/models/camaleon_cms/plugin.rb +4 -3
  114. data/app/models/camaleon_cms/post.rb +113 -27
  115. data/app/models/camaleon_cms/post_comment.rb +10 -6
  116. data/app/models/camaleon_cms/post_default.rb +42 -12
  117. data/app/models/camaleon_cms/post_relationship.rb +6 -4
  118. data/app/models/camaleon_cms/post_tag.rb +4 -3
  119. data/app/models/camaleon_cms/post_type.rb +22 -12
  120. data/app/models/camaleon_cms/site.rb +40 -28
  121. data/app/models/camaleon_cms/term_relationship.rb +10 -7
  122. data/app/models/camaleon_cms/term_taxonomy.rb +51 -5
  123. data/app/models/camaleon_cms/theme.rb +3 -3
  124. data/app/models/camaleon_cms/user.rb +17 -5
  125. data/app/models/camaleon_cms/user_role.rb +77 -4
  126. data/app/models/camaleon_cms/widget/assigned.rb +11 -6
  127. data/app/models/camaleon_cms/widget/main.rb +13 -7
  128. data/app/models/camaleon_cms/widget/sidebar.rb +3 -6
  129. data/app/models/camaleon_record.rb +123 -5
  130. data/app/models/concerns/camaleon_cms/categories_tags_for_posts.rb +20 -38
  131. data/app/models/concerns/camaleon_cms/common_relationships.rb +18 -5
  132. data/app/models/concerns/camaleon_cms/custom_fields_read.rb +115 -58
  133. data/app/models/concerns/camaleon_cms/metas.rb +32 -7
  134. data/app/models/concerns/camaleon_cms/normalize_attrs.rb +2 -8
  135. data/app/models/concerns/camaleon_cms/site_default_settings.rb +120 -16
  136. data/app/models/concerns/camaleon_cms/user_methods.rb +44 -19
  137. data/app/models/current_request.rb +23 -0
  138. data/app/uploaders/camaleon_cms_aws_uploader.rb +39 -11
  139. data/app/uploaders/camaleon_cms_local_uploader.rb +76 -19
  140. data/app/uploaders/camaleon_cms_uploader.rb +23 -10
  141. data/app/validators/camaleon_cms/post_uniq_validator.rb +21 -8
  142. data/app/validators/camaleon_cms/uniq_validator.rb +1 -1
  143. data/app/validators/camaleon_cms/user_url_validator.rb +215 -36
  144. data/app/views/camaleon_cms/admin/appearances/nav_menus/_left_menu_items.html.erb +2 -2
  145. data/app/views/camaleon_cms/admin/appearances/widgets/main/form.html.erb +1 -1
  146. data/app/views/camaleon_cms/admin/categories/index.html.erb +3 -3
  147. data/app/views/camaleon_cms/admin/comments/index.html.erb +2 -2
  148. data/app/views/camaleon_cms/admin/comments/list.html.erb +1 -1
  149. data/app/views/camaleon_cms/admin/installers/form.html.erb +5 -0
  150. data/app/views/camaleon_cms/admin/installers/welcome.html.erb +30 -6
  151. data/app/views/camaleon_cms/admin/plugins/_plugins_list.html.erb +2 -2
  152. data/app/views/camaleon_cms/admin/post_tags/index.html.erb +3 -3
  153. data/app/views/camaleon_cms/admin/posts/_sidebar.html.erb +2 -2
  154. data/app/views/camaleon_cms/admin/posts/form.html.erb +3 -2
  155. data/app/views/camaleon_cms/admin/posts/index.html.erb +6 -6
  156. data/app/views/camaleon_cms/admin/search.html.erb +1 -1
  157. data/app/views/camaleon_cms/admin/sessions/back_to_parent.html.erb +39 -0
  158. data/app/views/camaleon_cms/admin/sessions/logout_confirm.html.erb +27 -0
  159. data/app/views/camaleon_cms/admin/settings/_email_settings.html.erb +4 -1
  160. data/app/views/camaleon_cms/admin/settings/custom_fields/_get_items.html.erb +1 -1
  161. data/app/views/camaleon_cms/admin/settings/custom_fields/_render.html.erb +42 -6
  162. data/app/views/camaleon_cms/admin/settings/custom_fields/_render_category_simple.html.erb +1 -1
  163. data/app/views/camaleon_cms/admin/settings/custom_fields/fields/_select_eval.html.erb +1 -1
  164. data/app/views/camaleon_cms/admin/settings/custom_fields/form.html.erb +5 -4
  165. data/app/views/camaleon_cms/admin/settings/custom_fields/index.html.erb +1 -1
  166. data/app/views/camaleon_cms/admin/settings/post_types/index.html.erb +1 -1
  167. data/app/views/camaleon_cms/admin/settings/shortcodes.html.erb +4 -4
  168. data/app/views/camaleon_cms/admin/settings/site.html.erb +1 -1
  169. data/app/views/camaleon_cms/admin/settings/sites/form.html.erb +1 -1
  170. data/app/views/camaleon_cms/admin/settings/sites/index.html.erb +1 -1
  171. data/app/views/camaleon_cms/admin/user_roles/form.html.erb +102 -7
  172. data/app/views/camaleon_cms/admin/user_roles/index.html.erb +1 -1
  173. data/app/views/camaleon_cms/admin/users/form.html.erb +8 -4
  174. data/app/views/camaleon_cms/admin/users/index.html.erb +2 -2
  175. data/app/views/camaleon_cms/default_theme/partials/_render_custom_field.html.erb +8 -2
  176. data/app/views/camaleon_cms/default_theme/sitemap.html.erb +1 -1
  177. data/app/views/camaleon_cms/default_theme/sitemap.xml.builder +1 -1
  178. data/app/views/layouts/camaleon_cms/admin/_flash_messages.html.erb +2 -2
  179. data/app/views/layouts/camaleon_cms/admin/_header.html.erb +1 -1
  180. data/config/initializers/action_view.rb +42 -5
  181. data/config/initializers/active_record_extension.rb +13 -27
  182. data/config/initializers/assets.rb +52 -23
  183. data/config/initializers/custom_initializers.rb +3 -3
  184. data/config/locales/camaleon_cms/admin/ar.yml +7 -2
  185. data/config/locales/camaleon_cms/admin/de.yml +7 -2
  186. data/config/locales/camaleon_cms/admin/en.yml +39 -2
  187. data/config/locales/camaleon_cms/admin/es.yml +7 -2
  188. data/config/locales/camaleon_cms/admin/fr.yml +7 -2
  189. data/config/locales/camaleon_cms/admin/it.yml +7 -2
  190. data/config/locales/camaleon_cms/admin/nl.yml +8 -2
  191. data/config/locales/camaleon_cms/admin/pt-BR.yml +7 -2
  192. data/config/locales/camaleon_cms/admin/pt.yml +7 -2
  193. data/config/locales/camaleon_cms/admin/ru.yml +7 -2
  194. data/config/locales/camaleon_cms/admin/uk.yml +7 -2
  195. data/config/locales/camaleon_cms/admin/zh-CH.yml +7 -2
  196. data/config/routes/admin.rb +33 -15
  197. data/config/routes/frontend.rb +21 -15
  198. data/db/migrate/20150611161134_post_table_into_utf8.rb +14 -14
  199. data/db/migrate/20150926095310_rename_column_posts.rb +3 -3
  200. data/db/migrate/20151212095328_add_confirm_token_to_users.rb +3 -3
  201. data/db/migrate/20160504155652_add_feature_to_posts.rb +1 -1
  202. data/db/migrate/20160504155653_move_first_name_of_users.rb +2 -2
  203. data/db/migrate/20160609121449_add_group_to_custom_field_values.rb +1 -1
  204. data/db/migrate/20161215202255_drop_user_relationship_table.rb +1 -1
  205. data/db/migrate/20180124132318_create_media.rb +1 -1
  206. data/db/migrate/20180704211100_adjust_field_length.rb +1 -1
  207. data/lib/camaleon_cms/assets_precompile.rb +86 -0
  208. data/lib/camaleon_cms/captcha_image_generation.rb +65 -0
  209. data/lib/camaleon_cms/content_security.rb +158 -0
  210. data/lib/camaleon_cms/engine.rb +47 -9
  211. data/lib/camaleon_cms/media_security_headers.rb +27 -0
  212. data/lib/camaleon_cms/setup_token.rb +69 -0
  213. data/lib/camaleon_cms/svg_content_checker.rb +123 -0
  214. data/lib/camaleon_cms/task_reporter.rb +14 -0
  215. data/lib/camaleon_cms/unsafe_markup.rb +207 -0
  216. data/lib/camaleon_cms/uploader_content_security.rb +248 -0
  217. data/lib/camaleon_cms/uploader_image_processing.rb +166 -0
  218. data/lib/camaleon_cms/uploader_path_security.rb +146 -0
  219. data/lib/camaleon_cms/uploader_pipeline.rb +350 -0
  220. data/lib/camaleon_cms/uploader_support.rb +86 -0
  221. data/lib/camaleon_cms/version.rb +1 -1
  222. data/lib/camaleon_cms.rb +11 -0
  223. data/lib/ext/hash.rb +28 -2
  224. data/lib/ext/string.rb +13 -8
  225. data/lib/ext/translator.rb +10 -2
  226. data/lib/generators/camaleon_cms/gem_plugin_template/app/controllers/plugins/my_plugin/admin_controller.rb +5 -1
  227. data/lib/generators/camaleon_cms/install_generator.rb +7 -4
  228. data/lib/generators/camaleon_cms/install_template/plugin_routes.rb +5 -12
  229. data/lib/generators/camaleon_cms/theme_generator.rb +5 -10
  230. data/lib/generators/camaleon_cms/theme_template/views/layouts/index.html.erb +3 -1
  231. data/lib/plugin_routes.rb +412 -368
  232. data/lib/tasks/camaleon_cms/camaleon_tasks.rake +2 -1
  233. data/lib/tasks/cross_site_field_groups.rake +74 -0
  234. data/lib/tasks/custom_fields_roles.rake +58 -0
  235. data/lib/tasks/orphaned_comments.rake +42 -0
  236. data/lib/tasks/private_upload_acls.rake +31 -0
  237. data/lib/tasks/site_custom_field_groups.rake +36 -0
  238. data/lib/tasks/unsafe_stored_content.rake +42 -0
  239. data/lib/tasks/unsafe_stored_uploads.rake +70 -0
  240. data/lib/tasks/user_field_groups.rake +27 -0
  241. metadata +185 -7
@@ -9,48 +9,48 @@ module CamaleonCms
9
9
  # return current url visited as path
10
10
  # http://localhost:9001/category/cat-post-2 => /category/cat-post-2
11
11
  def site_current_path
12
- @_site_current_path ||= site_current_url.sub(cama_root_url(locale: nil), '/')
12
+ CurrentRequest.frontend_site_current_path ||= site_current_url.sub(cama_root_url(locale: nil), '/')
13
13
  end
14
14
 
15
15
  # **************** section is a? ****************#
16
16
  # check if current section visited is home page
17
17
  def is_home?
18
- @cama_visited_home.present?
18
+ camaleon_frontend_visited_state(:frontend_visited_home).present?
19
19
  end
20
20
 
21
21
  # check if current section visited is for post
22
22
  def is_page?
23
- @cama_visited_post.present?
23
+ camaleon_frontend_visited_state(:frontend_visited_post).present?
24
24
  end
25
25
 
26
26
  # check if current section visited is for ajax
27
27
  def is_ajax?
28
- @cama_visited_ajax.present?
28
+ camaleon_frontend_visited_state(:frontend_visited_ajax).present?
29
29
  end
30
30
 
31
31
  # check if current section visited is for search
32
32
  def is_search?
33
- @cama_visited_search.present?
33
+ camaleon_frontend_visited_state(:frontend_visited_search).present?
34
34
  end
35
35
 
36
36
  # check if current section visited is for post type
37
37
  def is_post_type?
38
- @cama_visited_post_type.present?
38
+ camaleon_frontend_visited_state(:frontend_visited_post_type).present?
39
39
  end
40
40
 
41
41
  # check if current section visited is for post tag
42
42
  def is_post_tag?
43
- @cama_visited_tag.present?
43
+ camaleon_frontend_visited_state(:frontend_visited_tag).present?
44
44
  end
45
45
 
46
46
  # check if current section visited is for category
47
47
  def is_category?
48
- @cama_visited_category.present?
48
+ camaleon_frontend_visited_state(:frontend_visited_category).present?
49
49
  end
50
50
 
51
51
  # check if visited page is user profile (frontend)
52
52
  def is_profile?
53
- @cama_visited_profile == true
53
+ camaleon_frontend_visited_state(:frontend_visited_profile) == true
54
54
  end
55
55
 
56
56
  # **************** end section is a? ****************#
@@ -60,9 +60,29 @@ module CamaleonCms
60
60
  # seo_attrs: Custom attributes for seo in Hash format
61
61
  # show_seo: (Boolean) control to append or not the seo attributes
62
62
  def the_head(seo_attrs = {}, _show_seo = true)
63
- js = "<script>var ROOT_URL = '#{cama_root_url}'; var LANGUAGE = '#{I18n.locale}'; </script>".html_safe
64
- js += cama_draw_pre_asset_contents
65
- "#{csrf_meta_tag || ''}\n#{display_meta_tags(cama_the_seo(seo_attrs))}\n#{js}\n#{cama_draw_custom_assets}"
63
+ js = javascript_tag("var ROOT_URL = #{cama_root_url.to_json}; var LANGUAGE = #{I18n.locale.to_s.to_json};")
64
+ safe_join(
65
+ [
66
+ csrf_meta_tag.presence,
67
+ display_meta_tags(cama_the_seo(seo_attrs)).presence,
68
+ js,
69
+ cama_draw_pre_asset_contents.presence,
70
+ cama_draw_custom_assets.presence
71
+ ].compact,
72
+ "\n"
73
+ )
74
+ end
75
+
76
+ private
77
+
78
+ def camaleon_frontend_visited_state(current_request_attr)
79
+ value = CurrentRequest.public_send(current_request_attr)
80
+ return value unless value.nil?
81
+
82
+ # Fall back to a legacy @cama_visited_* ivar a plugin front controller may have set directly;
83
+ # core writes both stores, so stock flows never reach here. Regression M20.
84
+ legacy_ivar = CamaleonCms::FrontendVisitedStateConcern::LEGACY_VISITED_IVAR_BY_ATTR[current_request_attr]
85
+ instance_variable_get(legacy_ivar) if legacy_ivar && instance_variable_defined?(legacy_ivar)
66
86
  end
67
87
  end
68
88
  end
@@ -16,7 +16,8 @@ module CamaleonCms
16
16
  # hook_key: hook key
17
17
  # params: params for hook
18
18
  def hooks_run(hook_key, params = nil)
19
- PluginRoutes.enabled_apps(current_site).each do |plugin|
19
+ theme_slug = current_theme&.slug.presence || current_site.get_theme_slug
20
+ PluginRoutes.enabled_apps(current_site, theme_slug).each do |plugin|
20
21
  _do_hook(plugin, hook_key, params)
21
22
  end
22
23
 
@@ -28,16 +29,16 @@ module CamaleonCms
28
29
 
29
30
  # skip hook function with name: hook_function_name
30
31
  def hook_skip(hook_function_name)
31
- @_hooks_skip << hook_function_name
32
+ hook_skip_list << hook_function_name
32
33
  end
33
34
 
34
35
  private
35
36
 
36
37
  def _do_hook(plugin, hook_key, params = nil)
37
- return if !plugin.present? || !plugin['hooks'].present? || !plugin['hooks'][hook_key].present?
38
+ return if plugin.blank? || plugin['hooks'].blank? || plugin['hooks'][hook_key].blank?
38
39
 
39
40
  plugin['hooks'][hook_key].each do |hook|
40
- next if @_hooks_skip.present? && @_hooks_skip.include?(hook)
41
+ next if hook_skip_list.include?(hook)
41
42
 
42
43
  begin
43
44
  if params.nil?
@@ -60,5 +61,14 @@ module CamaleonCms
60
61
  end
61
62
  end
62
63
  end
64
+
65
+ def hook_skip_list
66
+ state = camaleon_hooks_state
67
+ state[:hooks_skip] ||= []
68
+ end
69
+
70
+ def camaleon_hooks_state
71
+ CurrentRequest.hooks_helper_state ||= {}
72
+ end
63
73
  end
64
74
  end
@@ -1,9 +1,10 @@
1
1
  module CamaleonCms
2
2
  module HtmlHelper
3
3
  def cama_html_helpers_init
4
- @_pre_assets_content = [] # Assets contents before the libraries import
5
- @_assets_libraries = {}
6
- @_assets_content = []
4
+ state = camaleon_html_helper_state
5
+ state[:pre_assets_content] = [] # Assets contents before the libraries import
6
+ state[:assets_libraries] = {}
7
+ state[:assets_content] = []
7
8
  end
8
9
 
9
10
  # register a new asset library to be included on demand calling by: cama_load_libraries(...)
@@ -12,36 +13,47 @@ module CamaleonCms
12
13
  def cama_assets_library_register(key, assets = {})
13
14
  key = key.to_sym
14
15
  cama_assets_libraries
15
- @_cama_assets_libraries[key] = { css: [], js: [] } unless @_cama_assets_libraries[key].present?
16
- @_cama_assets_libraries[key][:css] += assets[:css] if assets[:css].present?
17
- @_cama_assets_libraries[key][:js] += assets[:js] if assets[:js].present?
16
+ state = camaleon_html_helper_state
17
+ state[:cama_assets_libraries][key] = { css: [], js: [] } if state[:cama_assets_libraries][key].blank?
18
+ state[:cama_assets_libraries][key][:css] += assets[:css] if assets[:css].present?
19
+ state[:cama_assets_libraries][key][:js] += assets[:js] if assets[:js].present?
18
20
  end
19
21
 
20
22
  # enable to load admin or registered libraries (colorpicker, datepicker, tinymce, form_ajax, cropper)
21
23
  # sample: add_asset_library("datepicker", "colorpicker")
22
24
  # This will add this assets library in the admin head or in a custom place by calling: cama_draw_custom_assets()
23
25
  def cama_load_libraries(*keys)
26
+ state = camaleon_html_helper_state
24
27
  keys.each do |key|
25
28
  library = cama_assets_libraries[key.to_sym]
26
- @_assets_libraries[key.to_sym] = library if library.present?
29
+ state[:assets_libraries][key.to_sym] = library if library.present?
27
30
  end
28
31
  end
29
32
 
30
33
  alias add_asset_library cama_load_libraries
31
34
 
32
- # add custom asset libraries (js, css or both) for the current request, also you can add extra css or js files for existent libraries
33
- # sample: (add new library)
34
- # append_asset_libraries({"my_library_key"=> { js: [plugin_asset("js/my_js"), "plugins/myplugin/assets/js/my_js2"], css: [plugin_asset("css/my_css"), "plugins/myplugin/assets/css/my_css2"] }})
35
+ # add custom asset libraries (js, css or both) for the current request, also you can add extra css or js files for
36
+ # existent libraries
37
+ # sample: (add a new library)
38
+ # append_asset_libraries(
39
+ # {
40
+ # "my_library_key"=> {
41
+ # js: [plugin_asset("js/my_js"), "plugins/myplugin/assets/js/my_js2"],
42
+ # css: [plugin_asset("css/my_css"), "plugins/myplugin/assets/css/my_css2"]
43
+ # }
44
+ # }
45
+ # )
35
46
  # sample: (update existent library)
36
47
  # append_asset_libraries({"colorpicker"=>{js: [plugin_asset("js/my_custom_js")] } })
37
48
  # return nil
38
49
  def append_asset_libraries(libraries)
50
+ state = camaleon_html_helper_state
39
51
  libraries.each do |key, library|
40
- @_assets_libraries[key.to_sym] = if @_assets_libraries.include?(key)
41
- @_assets_libraries[key.to_sym].merge(library)
42
- else
43
- library
44
- end
52
+ state[:assets_libraries][key.to_sym] = if state[:assets_libraries].include?(key)
53
+ state[:assets_libraries][key.to_sym].merge(library)
54
+ else
55
+ library
56
+ end
45
57
  end
46
58
  end
47
59
  alias cama_load_custom_assets append_asset_libraries
@@ -51,7 +63,7 @@ module CamaleonCms
51
63
  # content may be: <style>a{color: red;}</style>
52
64
  # this will be printed with <%raw cama_draw_custom_assets %>
53
65
  def append_asset_content(content)
54
- @_assets_content << content
66
+ camaleon_html_helper_state[:assets_content] << content
55
67
  end
56
68
 
57
69
  # add pre asset content into custom assets
@@ -59,27 +71,30 @@ module CamaleonCms
59
71
  # content may be: <style>a{color: red;}</style>
60
72
  # this will be printed before assets_library with <%raw cama_draw_pre_asset_contents %>
61
73
  def append_pre_asset_content(content)
62
- @_pre_assets_content << content
74
+ camaleon_html_helper_state[:pre_assets_content] << content
63
75
  end
64
76
 
65
77
  # return all scripts to be executed before import the js libraries(cama_draw_custom_assets)
66
78
  def cama_draw_pre_asset_contents
67
- (@_pre_assets_content || []).join('').html_safe
79
+ # rubocop:disable Rails/OutputSafety -- Callers append trusted script/style fragments that must render as markup.
80
+ camaleon_html_helper_state[:pre_assets_content].join('').html_safe
81
+ # rubocop:enable Rails/OutputSafety
68
82
  end
69
83
 
70
84
  # return all js libraries added [aa.js, bb,js, ..]
71
85
  # def get_assets_js
72
86
  def cama_draw_custom_assets
73
- cama_html_helpers_init unless @_assets_libraries.present?
87
+ state = camaleon_html_helper_state
88
+ cama_html_helpers_init if state[:assets_libraries].blank?
74
89
  libs = []
75
- @_assets_libraries.each_value do |assets|
90
+ state[:assets_libraries].each_value do |assets|
76
91
  libs += assets[:css] if assets[:css].present?
77
92
  end
78
93
  stylesheets = libs.uniq
79
94
  css = stylesheet_link_tag(*stylesheets, media: 'all')
80
95
 
81
96
  libs = []
82
- @_assets_libraries.each_value do |assets|
97
+ state[:assets_libraries].each_value do |assets|
83
98
  libs += assets[:js] if assets[:js].present?
84
99
  end
85
100
  javascripts = libs.uniq
@@ -87,33 +102,31 @@ module CamaleonCms
87
102
 
88
103
  args = { stylesheets: stylesheets, javascripts: javascripts, js_html: js, css_html: css }
89
104
  hooks_run('draw_custom_assets', args)
90
- "#{args[:css_html]}\n#{args[:js_html]}\n#{@_assets_content.join('').html_safe}"
91
- end
105
+ # rubocop:disable Rails/OutputSafety -- Asset helper output and appended fragments are trusted framework/plugin markup.
106
+ trusted_fragments = [args[:css_html], args[:js_html], *state[:assets_content]].filter_map do |fragment|
107
+ next if fragment.blank?
92
108
 
93
- # return category tree for category dropdown
94
- # each level is prefixed with -
95
- # level: internal recursive control
96
- def cama_get_options_html_from_items(terms, level = 0)
97
- options = []
98
- terms.all.each do |term|
99
- options << [('—' * level) + term.name, term.id] unless @term.id == term.id
100
- children = term.children
101
- options += cama_get_options_html_from_items(children, level + 1) unless children.empty?
109
+ fragment.is_a?(ActiveSupport::SafeBuffer) ? fragment : fragment.to_s.html_safe
102
110
  end
103
- options
111
+ # rubocop:enable Rails/OutputSafety
112
+
113
+ safe_join(trusted_fragments, "\n")
104
114
  end
105
115
 
106
- # create a html tooltip to include anywhere
116
+ # create an HTML tooltip to include anywhere
107
117
  # text: text of the tooltip
108
118
  # location: location of the tooltip (left | right | top |bottom)
109
119
  def cama_html_tooltip(text = 'Tooltip', location = 'left')
110
- "<a href='javascript:;' title='#{text}' data-toggle='tooltip' data-placement='#{location}'><i class='fa fa-info-circle'></i></a>"
120
+ tag.a(href: 'javascript:;', title: text, data: { toggle: 'tooltip', placement: location }) do
121
+ tag.i(class: 'fa fa-info-circle')
122
+ end
111
123
  end
112
124
 
113
125
  private
114
126
 
115
127
  def cama_assets_libraries
116
- return @_cama_assets_libraries if @_cama_assets_libraries.present?
128
+ state = camaleon_html_helper_state
129
+ return state[:cama_assets_libraries] if state[:cama_assets_libraries].present?
117
130
 
118
131
  libs = {}
119
132
  libs[:colorpicker] =
@@ -135,12 +148,34 @@ module CamaleonCms
135
148
  js: %w[camaleon_cms/admin/jquery.nestable camaleon_cms/admin/nav_menu] }
136
149
  libs[:admin_intro] =
137
150
  { js: ['camaleon_cms/admin/introjs/intro.min'], css: ['camaleon_cms/admin/introjs/introjs.min'] }
138
- @_cama_assets_libraries = libs
151
+ state[:cama_assets_libraries] = libs
152
+ end
153
+
154
+ def camaleon_html_helper_state
155
+ state = CurrentRequest.html_helper_state ||= {}
156
+ state[:pre_assets_content] ||= []
157
+ state[:assets_libraries] ||= {}
158
+ state[:assets_content] ||= []
159
+ state
139
160
  end
140
161
 
141
162
  # execute translation for value if this value is like: t(admin.my_text) ==> My Text
142
163
  def cama_print_i18n_value(value)
143
- value.start_with?('t(') ? eval(value.sub('t(', 'I18n.t(')) : value
164
+ return value unless value.is_a?(String)
165
+ return value unless value.start_with?('t(') && value.end_with?(')')
166
+
167
+ # Use an exclusive end index to strip the trailing ')' without nil-coercion.
168
+ key = value[2...-1].strip
169
+ # If the expression uses matching single/double quotes, unwrap the key before translation;
170
+ # the quoted form still only accepts simple i18n key characters: a-z, A-Z, 0-9, _, ., and -.
171
+ quoted_key_match = key.match(/\A(['"])([a-zA-Z0-9_.-]+)\1\z/)
172
+ key = quoted_key_match[2] if quoted_key_match
173
+
174
+ # Only translate simple i18n keys so arbitrary Ruby is never evaluated.
175
+ # Allowed chars: a-z, A-Z, 0-9, _, ., and -.
176
+ return value unless key.match?(/\A[a-zA-Z0-9_.-]+\z/)
177
+
178
+ I18n.t(key)
144
179
  end
145
180
  end
146
181
  end
@@ -2,21 +2,19 @@ module CamaleonCms
2
2
  module PluginsHelper
3
3
  include CamaleonCms::SiteHelper
4
4
  # load all plugins + theme installed for current site
5
- # METHOD IGNORED (is a partial solution to avoid load helpers and cache it for all sites)
6
- # this method try to load helpers for each request without caching
5
+ # METHOD IGNORED (is a partial solution to avoid loading helpers and cache it for all sites)
6
+ # this method tries to load helpers for each request without caching
7
7
  def plugins_initialize(klass = nil)
8
8
  mod = Module.new
9
9
  PluginRoutes.enabled_apps(current_site).each do |plugin|
10
- next if !plugin.present? || !plugin['helpers'].present?
10
+ next if plugin.blank? || plugin['helpers'].blank?
11
11
 
12
- plugin['helpers'].each do |h|
13
- mod.send :include, h.constantize
14
- end
12
+ plugin['helpers'].each { |h| mod.send :include, h.constantize }
15
13
  end
16
14
  (klass || self).send :extend, mod
17
15
  end
18
16
 
19
- # upgrade installed plugin in current site for a new version
17
+ # upgrade the installed plugin in the current site for a new version
20
18
  # plugin_key: key of the plugin
21
19
  # trigger hook "on_upgrade"
22
20
  # return model of the plugin
@@ -29,7 +27,7 @@ module CamaleonCms
29
27
  plugin_model
30
28
  end
31
29
 
32
- # install a plugin for current site
30
+ # install a plugin for the current site
33
31
  # plugin_key: key of the plugin
34
32
  # return model of the plugin
35
33
  def plugin_install(plugin_key)
@@ -50,7 +48,7 @@ module CamaleonCms
50
48
  end
51
49
  end
52
50
 
53
- # uninstall a plugin from current site
51
+ # uninstall a plugin from the current site
54
52
  # plugin_key: key of the plugin
55
53
  # return model of the plugin
56
54
  def plugin_uninstall(plugin_key)
@@ -66,7 +64,7 @@ module CamaleonCms
66
64
  plugin_model
67
65
  end
68
66
 
69
- # remove a plugin from current site
67
+ # remove a plugin from the current site
70
68
  # plugin_key: key of the plugin
71
69
  # return model of the plugin removed
72
70
  # DEPRECATED: PLUGINS AND THEMES CANNOT BE DESTROYED
@@ -105,8 +103,10 @@ module CamaleonCms
105
103
  # return plugin full asset path
106
104
  # plugin_key: plugin name
107
105
  # asset: (String) asset name
108
- # sample: <script src="<%= plugin_asset_path("admin.js") %>"></script> => /assets/plugins/my_plugin/admin-54505620f.js
109
- # sample: <script src="<%= plugin_asset_path("admin.js", 'my_plugin') %>"></script> => /assets/plugins/my_plugin/admin-54505620f.js
106
+ # sample: <script src="<%= plugin_asset_path("admin.js") %>"></script> =>
107
+ # /assets/plugins/my_plugin/admin-54505620f.js
108
+ # sample: <script src="<%= plugin_asset_path("admin.js", 'my_plugin') %>"></script> =>
109
+ # /assets/plugins/my_plugin/admin-54505620f.js
110
110
  def plugin_asset_path(asset, plugin_key = nil)
111
111
  if plugin_key.present? && plugin_key.include?('/')
112
112
  return plugin_asset_url(plugin_key,
@@ -123,11 +123,12 @@ module CamaleonCms
123
123
  alias plugin_asset plugin_asset_path
124
124
  alias plugin_gem_asset plugin_asset_path
125
125
 
126
- # return the full url for asset of current plugin:
126
+ # return the full url for asset of the current plugin:
127
127
  # asset: (String) asset name
128
128
  # plugin_key: (optional) plugin name, default (current plugin caller to this function)
129
129
  # sample:
130
- # plugin_asset_url("css/main.css") => return: https://myhost.com/assets/plugins/my_plugin/assets/css/main-54505620f.css
130
+ # plugin_asset_url("css/main.css") =>
131
+ # return: https://myhost.com/assets/plugins/my_plugin/assets/css/main-54505620f.css
131
132
  def plugin_asset_url(asset, plugin_key = nil)
132
133
  key = plugin_key || self_plugin_key(1)
133
134
  p = PluginRoutes.plugin_info(key)['gem_mode'] ? "plugins/#{key}/#{asset}" : "plugins/#{key}/assets/#{asset}"
@@ -138,22 +139,22 @@ module CamaleonCms
138
139
  end
139
140
  end
140
141
 
141
- # auto load all helpers of this plugin
142
+ # Autoload all helpers of this plugin
142
143
  def plugin_load_helpers(plugin)
143
- return if !plugin.present? || !plugin['helpers'].present?
144
+ return if plugin.blank? || plugin['helpers'].blank?
144
145
 
145
146
  plugin['helpers'].each do |h|
146
147
  next if self.class.include?(h.constantize)
147
148
 
148
- class_eval do
149
- include h.constantize
150
- end
149
+ class_eval { include h.constantize }
151
150
  rescue StandardError => e
152
- Rails.logger.debug "Camaleon CMS - App loading error for #{h}: #{e.message}. Please check the plugins and themes presence"
151
+ Rails.logger.debug do
152
+ "Camaleon CMS - App loading error for #{h}: #{e.message}. Please check the plugins and themes presence"
153
+ end
153
154
  end
154
155
  end
155
156
 
156
- # return plugin key for current plugin file (helper|controller|view)
157
+ # return the plugin key for the current plugin file (helper|controller|view)
157
158
  # index: internal control (ignored)
158
159
  def self_plugin_key(index = 0)
159
160
  f = caller[index]
@@ -175,9 +176,7 @@ module CamaleonCms
175
176
  # return the plugin model for current site calculated according to the file caller location
176
177
  def current_plugin(plugin_key = nil)
177
178
  _key = plugin_key || self_plugin_key(1)
178
- cama_cache_fetch("current_plugin_#{_key}") do
179
- current_site.get_plugin(_key)
180
- end
179
+ cama_cache_fetch("current_plugin_#{_key}") { current_site.get_plugin(_key) }
181
180
  end
182
181
  end
183
182
  end