camaleon_cms 2.9.1 → 2.9.2

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 (111) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +12 -5
  3. data/app/apps/plugins/front_cache/admin_controller.rb +1 -0
  4. data/app/apps/plugins/front_cache/front_cache_helper.rb +23 -14
  5. data/app/apps/plugins/visibility_post/visibility_post_helper.rb +1 -1
  6. data/app/apps/themes/default/views/category.html.erb +1 -1
  7. data/app/apps/themes/default/views/post_tag.html.erb +1 -1
  8. data/app/apps/themes/default/views/post_type.html.erb +1 -1
  9. data/app/apps/themes/default/views/search.html.erb +1 -1
  10. data/app/apps/themes/new/views/category.html.erb +1 -1
  11. data/app/apps/themes/new/views/post_tag.html.erb +1 -1
  12. data/app/apps/themes/new/views/post_type.html.erb +1 -1
  13. data/app/apps/themes/new/views/search.html.erb +1 -1
  14. data/app/controllers/camaleon_cms/admin/appearances/nav_menus_controller.rb +22 -5
  15. data/app/controllers/camaleon_cms/admin/appearances/widgets/assign_controller.rb +4 -2
  16. data/app/controllers/camaleon_cms/admin/appearances/widgets/main_controller.rb +3 -3
  17. data/app/controllers/camaleon_cms/admin/appearances/widgets/sidebar_controller.rb +2 -2
  18. data/app/controllers/camaleon_cms/admin/categories_controller.rb +9 -5
  19. data/app/controllers/camaleon_cms/admin/media_controller.rb +18 -5
  20. data/app/controllers/camaleon_cms/admin/post_tags_controller.rb +7 -4
  21. data/app/controllers/camaleon_cms/admin/posts/drafts_controller.rb +1 -1
  22. data/app/controllers/camaleon_cms/admin/posts_controller.rb +6 -3
  23. data/app/controllers/camaleon_cms/admin/sessions_controller.rb +2 -2
  24. data/app/controllers/camaleon_cms/admin/settings/custom_fields_controller.rb +33 -11
  25. data/app/controllers/camaleon_cms/admin/settings/post_types_controller.rb +13 -4
  26. data/app/controllers/camaleon_cms/admin/settings/sites_controller.rb +7 -4
  27. data/app/controllers/camaleon_cms/admin/settings_controller.rb +7 -4
  28. data/app/controllers/camaleon_cms/admin/user_roles_controller.rb +2 -2
  29. data/app/controllers/camaleon_cms/admin/users_controller.rb +16 -12
  30. data/app/controllers/camaleon_cms/admin_controller.rb +8 -0
  31. data/app/controllers/camaleon_cms/apps/plugins_admin_controller.rb +5 -0
  32. data/app/controllers/concerns/camaleon_cms/admin/custom_fields_concern.rb +29 -0
  33. data/app/decorators/camaleon_cms/post_decorator.rb +1 -1
  34. data/app/decorators/camaleon_cms/user_decorator.rb +1 -1
  35. data/app/helpers/camaleon_cms/admin/application_helper.rb +17 -17
  36. data/app/helpers/camaleon_cms/admin/post_type_helper.rb +25 -22
  37. data/app/helpers/camaleon_cms/comment_helper.rb +74 -40
  38. data/app/helpers/camaleon_cms/frontend/content_select_helper.rb +1 -1
  39. data/app/helpers/camaleon_cms/frontend/nav_menu_helper.rb +1 -1
  40. data/app/helpers/camaleon_cms/html_helper.rb +15 -1
  41. data/app/helpers/camaleon_cms/session_helper.rb +13 -1
  42. data/app/helpers/camaleon_cms/site_helper.rb +16 -3
  43. data/app/helpers/camaleon_cms/uploader_helper.rb +102 -51
  44. data/app/models/camaleon_cms/ability.rb +54 -102
  45. data/app/models/camaleon_cms/category.rb +2 -0
  46. data/app/models/camaleon_cms/custom_field.rb +14 -0
  47. data/app/models/camaleon_cms/custom_field_group.rb +38 -1
  48. data/app/models/camaleon_cms/custom_fields_relationship.rb +1 -1
  49. data/app/models/camaleon_cms/nav_menu.rb +2 -0
  50. data/app/models/camaleon_cms/nav_menu_item.rb +2 -0
  51. data/app/models/camaleon_cms/plugin.rb +2 -0
  52. data/app/models/camaleon_cms/post_tag.rb +2 -0
  53. data/app/models/camaleon_cms/post_type.rb +2 -0
  54. data/app/models/camaleon_cms/site.rb +2 -0
  55. data/app/models/camaleon_cms/term_taxonomy.rb +0 -2
  56. data/app/models/camaleon_cms/theme.rb +2 -0
  57. data/app/models/camaleon_cms/user_role.rb +13 -0
  58. data/app/models/camaleon_cms/widget/main.rb +2 -0
  59. data/app/models/camaleon_cms/widget/sidebar.rb +2 -0
  60. data/app/models/camaleon_record.rb +34 -0
  61. data/app/models/concerns/camaleon_cms/custom_fields_read.rb +4 -4
  62. data/app/models/concerns/camaleon_cms/metas.rb +1 -1
  63. data/app/models/current_request.rb +16 -0
  64. data/app/uploaders/camaleon_cms_aws_uploader.rb +8 -1
  65. data/app/validators/camaleon_cms/post_uniq_validator.rb +16 -4
  66. data/app/views/camaleon_cms/admin/appearances/nav_menus/_left_menu_items.html.erb +2 -2
  67. data/app/views/camaleon_cms/admin/appearances/widgets/main/form.html.erb +1 -1
  68. data/app/views/camaleon_cms/admin/categories/index.html.erb +1 -1
  69. data/app/views/camaleon_cms/admin/comments/index.html.erb +2 -2
  70. data/app/views/camaleon_cms/admin/comments/list.html.erb +1 -1
  71. data/app/views/camaleon_cms/admin/post_tags/index.html.erb +1 -1
  72. data/app/views/camaleon_cms/admin/posts/_sidebar.html.erb +1 -1
  73. data/app/views/camaleon_cms/admin/posts/index.html.erb +3 -3
  74. data/app/views/camaleon_cms/admin/search.html.erb +1 -1
  75. data/app/views/camaleon_cms/admin/settings/custom_fields/_render.html.erb +23 -2
  76. data/app/views/camaleon_cms/admin/settings/custom_fields/fields/_select_eval.html.erb +1 -1
  77. data/app/views/camaleon_cms/admin/settings/custom_fields/form.html.erb +1 -1
  78. data/app/views/camaleon_cms/admin/settings/custom_fields/index.html.erb +1 -1
  79. data/app/views/camaleon_cms/admin/settings/post_types/index.html.erb +1 -1
  80. data/app/views/camaleon_cms/admin/settings/sites/index.html.erb +1 -1
  81. data/app/views/camaleon_cms/admin/user_roles/form.html.erb +79 -5
  82. data/app/views/camaleon_cms/admin/user_roles/index.html.erb +1 -1
  83. data/app/views/camaleon_cms/admin/users/index.html.erb +1 -1
  84. data/app/views/layouts/camaleon_cms/admin/_flash_messages.html.erb +2 -2
  85. data/config/initializers/custom_initializers.rb +2 -2
  86. data/config/locales/camaleon_cms/admin/ar.yml +6 -2
  87. data/config/locales/camaleon_cms/admin/de.yml +6 -2
  88. data/config/locales/camaleon_cms/admin/en.yml +6 -2
  89. data/config/locales/camaleon_cms/admin/es.yml +6 -2
  90. data/config/locales/camaleon_cms/admin/fr.yml +6 -2
  91. data/config/locales/camaleon_cms/admin/it.yml +6 -2
  92. data/config/locales/camaleon_cms/admin/nl.yml +7 -2
  93. data/config/locales/camaleon_cms/admin/pt-BR.yml +6 -2
  94. data/config/locales/camaleon_cms/admin/pt.yml +6 -2
  95. data/config/locales/camaleon_cms/admin/ru.yml +6 -2
  96. data/config/locales/camaleon_cms/admin/uk.yml +6 -2
  97. data/config/locales/camaleon_cms/admin/zh-CH.yml +6 -2
  98. data/db/migrate/20150611161134_post_table_into_utf8.rb +14 -14
  99. data/db/migrate/20150926095310_rename_column_posts.rb +3 -3
  100. data/db/migrate/20151212095328_add_confirm_token_to_users.rb +3 -3
  101. data/db/migrate/20160504155652_add_feature_to_posts.rb +1 -1
  102. data/db/migrate/20160504155653_move_first_name_of_users.rb +2 -2
  103. data/db/migrate/20160609121449_add_group_to_custom_field_values.rb +1 -1
  104. data/db/migrate/20161215202255_drop_user_relationship_table.rb +1 -1
  105. data/db/migrate/20180124132318_create_media.rb +1 -1
  106. data/db/migrate/20180704211100_adjust_field_length.rb +1 -1
  107. data/lib/camaleon_cms/version.rb +1 -1
  108. data/lib/ext/string.rb +3 -3
  109. data/lib/plugin_routes.rb +3 -3
  110. data/lib/tasks/custom_fields_roles.rake +56 -0
  111. metadata +64 -5
@@ -1,5 +1,7 @@
1
1
  module CamaleonCms
2
2
  class Plugin < CamaleonCms::TermTaxonomy
3
+ normalize_attrs(:name, :description)
4
+
3
5
  # attrs:
4
6
  # term_group => status active (1, nil)
5
7
  # slug => plugin key
@@ -1,5 +1,7 @@
1
1
  module CamaleonCms
2
2
  class PostTag < CamaleonCms::TermTaxonomy
3
+ normalize_attrs(:name, :description)
4
+
3
5
  default_scope { where(taxonomy: :post_tag) }
4
6
 
5
7
  has_many :posts, foreign_key: :objectid, through: :term_relationships, source: :object
@@ -1,5 +1,7 @@
1
1
  module CamaleonCms
2
2
  class PostType < CamaleonCms::TermTaxonomy
3
+ normalize_attrs(:name, :description)
4
+
3
5
  alias_attribute :site_id, :parent_id
4
6
  default_scope { where(taxonomy: :post_type) }
5
7
 
@@ -1,5 +1,7 @@
1
1
  module CamaleonCms
2
2
  class Site < CamaleonCms::TermTaxonomy
3
+ normalize_attrs(:name, :description)
4
+
3
5
  include CamaleonCms::SiteDefaultSettings
4
6
 
5
7
  # attrs: [name, description, slug]
@@ -18,8 +18,6 @@ module CamaleonCms
18
18
  # attr_accessible :data_options
19
19
  # attr_accessible :data_metas
20
20
 
21
- normalize_attrs(:name, :description)
22
-
23
21
  # callbacks
24
22
  before_validation :before_validating
25
23
  before_destroy :destroy_dependencies
@@ -1,5 +1,7 @@
1
1
  module CamaleonCms
2
2
  class Theme < CamaleonCms::TermTaxonomy
3
+ normalize_attrs(:name, :description)
4
+
3
5
  # attrs:
4
6
  # slug => plugin key
5
7
  belongs_to :site, class_name: 'CamaleonCms::Site', foreign_key: :parent_id, required: false
@@ -1,5 +1,7 @@
1
1
  module CamaleonCms
2
2
  class UserRole < CamaleonCms::TermTaxonomy
3
+ normalize_attrs(:name, :description)
4
+
3
5
  after_destroy :set_users_as_cilent
4
6
 
5
7
  default_scope { where(taxonomy: :user_roles) }
@@ -122,6 +124,17 @@ module CamaleonCms
122
124
  label: I18n.t('camaleon_cms.admin.sidebar.settings').to_s,
123
125
  description: I18n.t('camaleon_cms.admin.users.tool_tip.settings').to_s
124
126
  },
127
+ {
128
+ key: 'custom_fields',
129
+ label: I18n.t('camaleon_cms.admin.sidebar.custom_fields', default: 'Custom Fields').to_s,
130
+ description: I18n.t('camaleon_cms.admin.users.tool_tip.custom_fields',
131
+ default: 'Manage custom field groups and fields, including the select_eval type.').to_s
132
+ },
133
+ {
134
+ key: 'select_eval',
135
+ label: I18n.t('camaleon_cms.admin.custom_field.select_eval', default: 'Select Eval').to_s,
136
+ description: I18n.t('camaleon_cms.admin.users.tool_tip.select_eval', default: 'Allow toggling and using select_eval custom fields in the admin UI.').to_s
137
+ },
125
138
  {
126
139
  key: 'theme_settings',
127
140
  label: I18n.t('camaleon_cms.admin.settings.theme_setting', default: 'Theme Settings').to_s,
@@ -1,6 +1,8 @@
1
1
  module CamaleonCms
2
2
  module Widget
3
3
  class Main < CamaleonCms::TermTaxonomy
4
+ normalize_attrs(:name)
5
+
4
6
  default_scope { where(taxonomy: :widget) }
5
7
  # attr_accessible :excerpt, :renderer
6
8
  # name: "title"
@@ -1,6 +1,8 @@
1
1
  module CamaleonCms
2
2
  module Widget
3
3
  class Sidebar < CamaleonCms::TermTaxonomy
4
+ normalize_attrs(:name, :description)
5
+
4
6
  default_scope { where(taxonomy: :sidebar) }
5
7
 
6
8
  has_many :metas, lambda {
@@ -49,4 +49,38 @@ class CamaleonRecord < ActiveRecord::Base
49
49
  def cama_build_cache_key(key)
50
50
  _key = "cama_cache_#{self.class.name}_#{id}_#{key}"
51
51
  end
52
+
53
+ # Return the current user for this thread/request context.
54
+ # Uses ActiveSupport::CurrentAttributes (CurrentRequest.user)
55
+ def current_user
56
+ return @current_user if defined?(@current_user)
57
+
58
+ @current_user = CurrentRequest.user
59
+ end
60
+
61
+ # Authorization helpers that delegate to central Ability (CanCan)
62
+ def can?(*args)
63
+ # Return false if no user or site context (e.g., background jobs, console)
64
+ return false if current_user.nil? || current_site.nil?
65
+
66
+ ability.can?(*args)
67
+ end
68
+
69
+ def ability
70
+ # Memoize Ability per request to avoid repeated DB queries and object instantiation.
71
+ # In tests that modify role meta mid-request, call reset_ability to invalidate cache.
72
+ @ability ||= CamaleonCms::Ability.new(current_user, current_site)
73
+ end
74
+
75
+ # Reset cached ability instance (useful in tests when role meta changes)
76
+ def reset_ability
77
+ @ability = nil
78
+ end
79
+
80
+ # current_site memoized from the CurrentRequest.site
81
+ def current_site
82
+ return @current_site if defined?(@current_site) && @current_site.present?
83
+
84
+ @current_site = CurrentRequest.site
85
+ end
52
86
  end
@@ -135,7 +135,7 @@ module CamaleonCms
135
135
  def get_field_values_hash(include_options = false)
136
136
  fields = {}
137
137
  custom_field_values.to_a.uniq.each do |field_value|
138
- custom_field = field_value.custom_fields
138
+ custom_field = field_value.custom_field
139
139
  values = custom_field.values.where(objectid: id).pluck(:value)
140
140
  unless include_options
141
141
  fields[field_value.custom_field_slug] =
@@ -155,8 +155,8 @@ module CamaleonCms
155
155
  # deprecated f attribute
156
156
  def get_fields_object(_f = true)
157
157
  fields = {}
158
- custom_field_values.eager_load(:custom_fields).to_a.uniq.each do |field_value|
159
- custom_field = field_value.custom_fields
158
+ custom_field_values.eager_load(:custom_field).to_a.uniq.each do |field_value|
159
+ custom_field = field_value.custom_field
160
160
  # if custom_field.options[:show_frontend].to_s.to_bool
161
161
  values = custom_field.values.where(objectid: id).pluck(:value)
162
162
  fields[field_value.custom_field_slug] =
@@ -303,7 +303,7 @@ module CamaleonCms
303
303
 
304
304
  def fix_meta_value(value)
305
305
  return value.to_json if value.is_a?(ActionController::Parameters)
306
- return JSON.fast_generate(value) if value.is_a?(Array) || value.is_a?(Hash)
306
+ return JSON.generate(value) if value.is_a?(Array) || value.is_a?(Hash)
307
307
 
308
308
  value
309
309
  end
@@ -134,7 +134,7 @@ module CamaleonCms
134
134
  changed_value = if value.is_a?(ActionController::Parameters)
135
135
  value.to_json
136
136
  elsif value.is_a?(Array) || value.is_a?(Hash)
137
- JSON.fast_generate(value)
137
+ JSON.generate(value)
138
138
  else
139
139
  value
140
140
  end
@@ -0,0 +1,16 @@
1
+ # CurrentRequest holds per-request state (user, site) accessible to models
2
+ # via ActiveSupport::CurrentAttributes (thread-safe, resets after each request).
3
+ #
4
+ # Usage in controllers:
5
+ # CurrentRequest.user = cama_current_user
6
+ # CurrentRequest.site = current_site
7
+ #
8
+ # Usage in models:
9
+ # current_user # delegates to CurrentRequest.user via CamaleonRecord
10
+ # current_site # delegates to CurrentRequest.site via CamaleonRecord
11
+ #
12
+ # Note: Rails automatically resets CurrentAttributes between requests, ensuring no leakage.
13
+ # In specs, call CurrentRequest.reset in before/after hooks to avoid cross-test pollution.
14
+ class CurrentRequest < ActiveSupport::CurrentAttributes
15
+ attribute :user, :site
16
+ end
@@ -37,6 +37,8 @@ class CamaleonCmsAwsUploader < CamaleonCmsUploader
37
37
  end
38
38
 
39
39
  def fetch_file(file_name)
40
+ return { error: 'Invalid file path' } unless valid_folder_path?(file_name)
41
+
40
42
  return file_name if file_exists?(file_name)
41
43
 
42
44
  return file_name if bucket.object(file_name).download_file(file_name) && file_exists?(file_name)
@@ -84,8 +86,9 @@ class CamaleonCmsAwsUploader < CamaleonCmsUploader
84
86
  # - same_name: false => avoid to overwrite an existent file with same key and search for an available key
85
87
  # - is_thumb: true => if this file is a thumbnail of an uploaded file
86
88
  def add_file(uploaded_io_or_file_path, key, args = {})
89
+ return { error: 'Invalid file path' } unless valid_folder_path?(key)
90
+
87
91
  args = { same_name: false, is_thumb: false }.merge(args)
88
- res = nil
89
92
  key = "#{@aws_settings['inner_folder']}/#{key}" if @aws_settings['inner_folder'].present? && !args[:is_thumb]
90
93
  key = key.cama_fix_media_key
91
94
  key = search_new_key(key) unless args[:same_name]
@@ -117,6 +120,8 @@ class CamaleonCmsAwsUploader < CamaleonCmsUploader
117
120
 
118
121
  # delete a folder in AWS with :key
119
122
  def delete_folder(key)
123
+ return { error: 'Invalid folder path' } unless valid_folder_path?(key)
124
+
120
125
  key = "#{@aws_settings['inner_folder']}/#{key}" if @aws_settings['inner_folder'].present?
121
126
  key = key.cama_fix_media_key
122
127
  bucket.objects(prefix: key.slice(1..-1) << '/').delete
@@ -125,6 +130,8 @@ class CamaleonCmsAwsUploader < CamaleonCmsUploader
125
130
 
126
131
  # delete a file in AWS with :key
127
132
  def delete_file(key)
133
+ return { error: 'Invalid file path' } unless valid_folder_path?(key)
134
+
128
135
  key = "#{@aws_settings['inner_folder']}/#{key}" if @aws_settings['inner_folder'].present?
129
136
  key = key.cama_fix_media_key
130
137
  begin
@@ -7,11 +7,23 @@ module CamaleonCms
7
7
  ptype = record.post_type
8
8
  return unless ptype.present? # only for posts that belongs to a post type model
9
9
 
10
+ post_table = CamaleonCms::Post.table_name
11
+
12
+ conditions = []
13
+ params = []
14
+
15
+ slug_array.each do |s|
16
+ conditions << "#{post_table}.slug LIKE ?"
17
+ params << "%-->#{s}<!--%"
18
+ end
19
+
20
+ conditions << "#{post_table}.slug = ?"
21
+ params << record.slug
22
+
23
+ where_clause = "(#{conditions.join(' OR ')})"
24
+
10
25
  posts = ptype.site.posts
11
- .where(
12
- "(#{slug_array.map { |s| "#{CamaleonCms::Post.table_name}.slug LIKE '%-->#{s}<!--%'" }
13
- .join(' OR ')} ) OR #{CamaleonCms::Post.table_name}.slug = ?", record.slug
14
- )
26
+ .where(where_clause, *params)
15
27
  .where.not(id: record.id)
16
28
  .where.not(status: %i[draft draft_child trash])
17
29
  unless posts.empty?
@@ -46,12 +46,12 @@
46
46
  </div>
47
47
  <% if pt.manage_categories? %>
48
48
  <div class="tab-pane class_type" id="tab-<%= pt.slug %>-categories" data-type="category" data-post_type="<%= pt.slug %>">
49
- <%= raw post_type_html_inputs(pt, "categories", "categories", "checkbox", [], "categorychecklist") %>
49
+ <%= post_type_html_inputs(pt, "categories", "categories", "checkbox", [], "categorychecklist") %>
50
50
  </div>
51
51
  <% end %>
52
52
  <% if pt.manage_tags? %>
53
53
  <div class="tab-pane class_type" id="tab-<%= pt.slug %>-tags" data-type="post_tag" data-post_type="<%= pt.slug %>">
54
- <%= raw post_type_html_inputs(pt, "post_tags", "post_tags", "checkbox", [], "categorychecklist") %>
54
+ <%= post_type_html_inputs(pt, "post_tags", "post_tags", "checkbox", [], "categorychecklist") %>
55
55
  </div>
56
56
  <% end %>
57
57
  </div>
@@ -1,3 +1,4 @@
1
+ <div class="alert alert-warning"><%= t('camaleon_cms.admin.widgets.warning') %></div>
1
2
  <%= form_for @widget, as: "widget_main", url: { action: (@widget.new_record? ? "create" : "update"), controller: "camaleon_cms/admin/appearances/widgets/main", id: @widget }, html: { role: 'form', class: "validate cama_ajax_request", id: "widget_form" } do |f| %>
2
3
  <%= render partial: 'layouts/camaleon_cms/admin/form_error', locals: {data: @widget} %>
3
4
  <div class="form-group">
@@ -24,4 +25,3 @@
24
25
  jQuery(function(){ init_form_validations($("#widget_form")); });
25
26
  </script>
26
27
  <% end %>
27
-
@@ -58,7 +58,7 @@
58
58
  </tbody>
59
59
  </table>
60
60
  <%= content_tag("div", raw(t('camaleon_cms.admin.message.data_found_list')), class: "alert alert-warning") if @categories.empty? %>
61
- <%= raw cama_do_pagination(@categories) %>
61
+ <%= cama_do_pagination(@categories) %>
62
62
  </div>
63
63
  </div>
64
64
  <!-- END BASIC TABLE SAMPLE -->
@@ -15,7 +15,7 @@
15
15
  <div class="panel-body">
16
16
  <div class="messages messages-img">
17
17
  <%= raw "<div class='alert alert-warning'>#{t('camaleon_cms.admin.comments.message.there_no_comments')}</div>" if @comments.size == 0 %>
18
- <%= raw cama_comments_render_html(@comments) %>
18
+ <%= cama_comments_render_html(@comments) %>
19
19
  </div>
20
20
  </div>
21
- </div>
21
+ </div>
@@ -31,6 +31,6 @@
31
31
  </tbody>
32
32
  </table>
33
33
  <%= content_tag("div", raw(t('camaleon_cms.admin.message.data_found_list')), class: "alert alert-warning") if @posts.empty? %>
34
- <%= raw cama_do_pagination(@posts) %>
34
+ <%= cama_do_pagination(@posts) %>
35
35
  </div>
36
36
  </div>
@@ -46,7 +46,7 @@
46
46
  </tbody>
47
47
  </table>
48
48
  <%= content_tag("div", raw(t('camaleon_cms.admin.message.data_found_list')), class: "alert alert-warning") if @post_tags.empty? %>
49
- <%= raw cama_do_pagination(@post_tags) %>
49
+ <%= cama_do_pagination(@post_tags) %>
50
50
  </div>
51
51
  </div>
52
52
  <!-- END BASIC TABLE SAMPLE -->
@@ -101,7 +101,7 @@
101
101
  </div>
102
102
  <div class="panel-body ">
103
103
  <div class="form-group list-categories">
104
- <%= raw post_type_html_inputs(@post_type, "categories", "categories" , @post_type.get_option('has_single_category', false) ? 'radio' : "checkbox" ,params[:categories] || (@post.new_record? ? [] : @post.categories.pluck("#{CamaleonCms::TermTaxonomy.table_name}.id")), "categorychecklist", true )%>
104
+ <%= post_type_html_inputs(@post_type, "categories", "categories" , @post_type.get_option('has_single_category', false) ? 'radio' : "checkbox" ,params[:categories] || (@post.new_record? ? [] : @post.categories.pluck("#{CamaleonCms::TermTaxonomy.table_name}.id")), "categorychecklist", true )%>
105
105
  </div>
106
106
  </div>
107
107
  </div>
@@ -60,10 +60,10 @@
60
60
  <td><%= link_to raw(f.the_status), {action: :index, s: f.status}, class: "cama_ajax_request" %> </td>
61
61
  <td><%= f.author.fullname %></td>
62
62
  <% if @post_type.manage_categories? %>
63
- <td><%= raw post_type_list_taxonomy(f.categories, "success") %></td>
63
+ <td><%= post_type_list_taxonomy(f.categories, "success") %></td>
64
64
  <% end %>
65
65
  <% if @post_type.manage_tags? %>
66
- <td><%= raw post_type_list_taxonomy(f.post_tags, "default") %></td>
66
+ <td><%= post_type_list_taxonomy(f.post_tags, "default") %></td>
67
67
  <% end %>
68
68
  <% extra_column = {post: f, post_type: @post_type, content: "", from_body: true}; hooks_run("list_post_extra_columns", extra_column) %>
69
69
  <%= raw extra_column[:content] %>
@@ -107,6 +107,6 @@
107
107
  </tbody>
108
108
  </table>
109
109
  <%= content_tag("div", raw(t('camaleon_cms.admin.message.data_found_list')), class: "alert alert-warning") if @posts.empty? %>
110
- <%= raw cama_do_pagination(@posts) %>
110
+ <%= cama_do_pagination(@posts) %>
111
111
  </div>
112
112
  </div>
@@ -62,7 +62,7 @@
62
62
  </tbody>
63
63
  </table>
64
64
  <%= content_tag("div", raw(t('camaleon_cms.admin.message.data_found_list')), class: "alert alert-warning") if @items.empty? %>
65
- <%= raw cama_do_pagination(@items, panel_class: "cama_ajax_request") %>
65
+ <%= cama_do_pagination(@items, panel_class: "cama_ajax_request") %>
66
66
  </div>
67
67
  </div>
68
68
  </div>
@@ -23,7 +23,7 @@
23
23
  <%= field.name %>
24
24
  <%= raw "<em class='text-danger'>*</em>" if field.options[:required].to_s.to_bool %>
25
25
  <% if current_site.get_option('custom_fields_show_shortcodes') && ["post", "posttype", "category", "postTag", "site", "user", "navmenu", "theme"].include?(obj_class) %>
26
- <small class="shortcode_field"><br><%= raw cama_shortcode_print("[data field='#{field.slug}' #{"object='#{obj_class}' #{"id='#{record.id}'" if obj_class != "Theme" }" unless record.new_record?}]") %></small>
26
+ <small class="shortcode_field"><br><%= cama_shortcode_print("[data field='#{field.slug}' #{"object='#{obj_class}' #{"id='#{record.id}'" if obj_class != "Theme" }" unless record.new_record?}]") %></small>
27
27
  <% end %>
28
28
  </label>
29
29
  <% if field.description.present? %>
@@ -40,7 +40,28 @@
40
40
  </div>
41
41
  <% end %>
42
42
  </div>
43
- <script> jQuery(function(){ build_custom_field_group(<%= raw(params[:field_options].present? ? (r = []; params[:field_options].each{|k, v| val = {}; v.each{|kk, vv| val["#{kk}"] = (vv['values'].values rescue vv['values']); }; r << val }; r.to_json) : record.get_fields_grouped(fields.pluck(:slug).uniq).to_json) %>, '<%= group.id %>', <%= raw group_field_data.to_json %>, <%= group.is_repeat %>, '<%= field_name %>'); }); </script>
43
+ <%
44
+ field_options_json = if params[:field_options].present?
45
+ params[:field_options].to_unsafe_h.each_with_object([]) do |(_k, v), r|
46
+ r << v.each_with_object({}) do |(kk, vv), val|
47
+ val[kk.to_s] = (vv['values'].values rescue vv['values'])
48
+ end
49
+ end.to_json
50
+ else
51
+ record.get_fields_grouped(fields.pluck(:slug).uniq).to_json
52
+ end
53
+ %>
54
+ <script>
55
+ jQuery(function () {
56
+ build_custom_field_group(
57
+ <%= json_escape(field_options_json).html_safe %>,
58
+ '<%= group.id %>',
59
+ <%= json_escape(group_field_data.to_json).html_safe %>,
60
+ <%= group.is_repeat %>,
61
+ '<%= field_name %>'
62
+ );
63
+ });
64
+ </script>
44
65
  </div>
45
66
  </div>
46
67
  <% if group.is_repeat %>
@@ -1,3 +1,3 @@
1
1
  <div class="group-input-fields-content">
2
- <%= select_tag "#{field_name}[#{field.slug}][values][]", instance_eval(field.options[:command].to_s.strip), class: "form-control input-value #{'required' if field.options[:required].to_s.to_bool}" %>
2
+ <%= select_tag "#{field_name}[#{field.slug}][values][]", instance_eval(field.options[:command].to_s.strip), class: "form-control input-value #{'required' if field.options[:required].to_s.to_bool}" %>
3
3
  </div>
@@ -152,7 +152,7 @@
152
152
  <div class="panel-body">
153
153
  <div id="content-items-default" class="form-group input-group-sm">
154
154
  <% cama_custom_field_elements.each do |i,item| %>
155
- <% next if item[:key] == "select_eval" %>
155
+ <% next if item[:key] == 'select_eval' %>
156
156
  <a id="item-<%= item[:key] %>" class="btn btn-default" href="<%= get_items_cama_admin_settings_custom_fields_path(item[:key]) %>" style="margin-bottom: 4px"><%= item[:label] %></a>
157
157
  <% end %>
158
158
  </div>
@@ -44,7 +44,7 @@
44
44
  </tbody>
45
45
  </table>
46
46
  <%= content_tag("div", raw(t('camaleon_cms.admin.message.data_found_list')), class: "alert alert-warning") if @field_groups.empty? %>
47
- <%= raw cama_do_pagination(@field_groups) %>
47
+ <%= cama_do_pagination(@field_groups) %>
48
48
  </div>
49
49
  </div>
50
50
  <!-- END BASIC TABLE SAMPLE -->
@@ -42,7 +42,7 @@
42
42
  </tbody>
43
43
  </table>
44
44
  <%= content_tag("div", raw(t('camaleon_cms.admin.message.data_found_list')), class: "alert alert-warning") if @post_types.empty? %>
45
- <%= raw cama_do_pagination(@post_types) %>
45
+ <%= cama_do_pagination(@post_types) %>
46
46
  </div>
47
47
  </div>
48
48
  <!-- END BASIC TABLE SAMPLE -->
@@ -50,7 +50,7 @@
50
50
  </tbody>
51
51
  </table>
52
52
  <%= content_tag("div", raw(t('camaleon_cms.admin.message.data_found_list')), class: "alert alert-warning") if @sites.empty? %>
53
- <%= raw cama_do_pagination(@sites) %>
53
+ <%= cama_do_pagination(@sites) %>
54
54
  </div>
55
55
  </div>
56
56
  <!-- END BASIC TABLE SAMPLE -->
@@ -61,12 +61,12 @@
61
61
  </div>
62
62
 
63
63
  <div class="">
64
- <h5><%= t('camaleon_cms.admin.users.others_permissions')%></h5>
64
+ <h5><%= t('camaleon_cms.admin.users.other_permissions')%></h5>
65
65
  <div class="row">
66
66
  <% values = rol_values_manager || {} %>
67
67
  <% cama_get_roles_values[:manager].each do |value| %>
68
68
  <div class="col-md-4">
69
- <label><input type="checkbox" name="rol_values[manager][<%= value[:key] %>]" value="1" <%= "checked" if values[value[:key].to_sym].present? %> <%= "disabled" unless @user_role.editable? %> >&nbsp; <%= raw value[:label] %></label>
69
+ <label><input type="checkbox" name="rol_values[manager][<%= value[:key] %>]" value="1" <%= "checked" if values[value[:key].to_sym].present? %> <%= "disabled" unless @user_role.editable? %> <%= 'data-danger-select-eval=1' if value[:key].to_s == 'select_eval' %> >&nbsp; <%= raw value[:label] %></label>
70
70
  &nbsp;<%= raw cama_html_tooltip(value[:description], 'right') if value[:description].present? %>
71
71
  </div>
72
72
  <% end %>
@@ -119,20 +119,94 @@
119
119
  <!-- END PAGE CONTENT WRAPPER -->
120
120
  </div>
121
121
 
122
+ <div class="modal fade" id="select-eval-danger-modal" tabindex="-1" role="dialog" aria-labelledby="select-eval-danger-modal-title" aria-hidden="true">
123
+ <div class="modal-dialog" role="document">
124
+ <div class="modal-content">
125
+ <div class="modal-header">
126
+ <button type="button" class="close" data-dismiss="modal" aria-label="<%= t('camaleon_cms.admin.button.cancel') %>">
127
+ <span aria-hidden="true">&times;</span>
128
+ </button>
129
+ <h4 class="modal-title" id="select-eval-danger-modal-title"><%= t('camaleon_cms.admin.users.select_eval_modal.title') %></h4>
130
+ </div>
131
+ <div class="modal-body">
132
+ <p><%= t('camaleon_cms.admin.users.select_eval_modal.description') %></p>
133
+ </div>
134
+ <div class="modal-footer">
135
+ <button type="button" class="btn btn-default" data-role="select-eval-cancel" data-dismiss="modal"><%= t('camaleon_cms.admin.button.cancel') %></button>
136
+ <button type="button" class="btn btn-danger" data-role="select-eval-confirm"><%= t('camaleon_cms.admin.button.accept') %></button>
137
+ </div>
138
+ </div>
139
+ </div>
140
+ </div>
141
+
122
142
  <script>
123
143
  jQuery(function($){
144
+ var pendingDangerSelectEval = null
145
+ var pendingDangerSelectEvalConfirmed = false
146
+ var $allCheckboxes = $("#contents-checkbox input[type='checkbox']")
147
+ var $selectEvalCheckbox = $("#contents-checkbox input[data-danger-select-eval='1']")
148
+ var $selectEvalModal = $("#select-eval-danger-modal")
149
+
150
+ function openSelectEvalDangerModal(checkbox){
151
+ pendingDangerSelectEval = checkbox
152
+ pendingDangerSelectEvalConfirmed = false
153
+ checkbox.prop("checked", false)
154
+ $selectEvalModal.modal("show")
155
+ }
156
+
157
+ function shouldWarnForSelectEvalEnable(wasChecked){
158
+ return $selectEvalCheckbox.length && !$selectEvalCheckbox.prop("disabled") && !wasChecked
159
+ }
160
+
124
161
  $("#contents-checkbox input:checked").each(function(){$(this).attr("data-checked", 1)})
162
+
163
+ $("#contents-checkbox").on("change", "input[data-danger-select-eval='1']", function(){
164
+ if($(this).prop("checked")){
165
+ openSelectEvalDangerModal($(this))
166
+ }
167
+ })
168
+
169
+ $selectEvalModal.find("[data-role='select-eval-confirm']").on("click", function(){
170
+ if(pendingDangerSelectEval){
171
+ pendingDangerSelectEval.prop("checked", true)
172
+ pendingDangerSelectEvalConfirmed = true
173
+ }
174
+ $selectEvalModal.modal("hide")
175
+ })
176
+
177
+ $(document).on("keydown", function(event){
178
+ if(event.which === 27 && $selectEvalModal.hasClass("in")){
179
+ $selectEvalModal.modal("hide")
180
+ }
181
+ })
182
+
183
+ $selectEvalModal.on("hidden.bs.modal", function(){
184
+ if(pendingDangerSelectEval && !pendingDangerSelectEvalConfirmed){
185
+ pendingDangerSelectEval.prop("checked", false)
186
+ }
187
+ pendingDangerSelectEval = null
188
+ pendingDangerSelectEvalConfirmed = false
189
+ })
190
+
125
191
  $("#checked-actions a[data-type]").click(function(){
126
192
  switch ($(this).attr("data-type")){
127
193
  case 'all':
128
- $("#contents-checkbox input[type='checkbox']").prop('checked', true);
194
+ var wasSelectEvalChecked = $selectEvalCheckbox.prop('checked');
195
+ $allCheckboxes.prop('checked', true);
196
+ if(shouldWarnForSelectEvalEnable(wasSelectEvalChecked)){
197
+ openSelectEvalDangerModal($selectEvalCheckbox)
198
+ }
129
199
  break;
130
200
  case 'none':
131
- $("#contents-checkbox input[type='checkbox']").prop('checked', false);
201
+ $allCheckboxes.prop('checked', false);
132
202
  break;
133
203
  case 'restore':
134
- $("#contents-checkbox input[type='checkbox']").prop('checked', false);
204
+ var wasSelectEvalCheckedBeforeRestore = $selectEvalCheckbox.prop('checked');
205
+ $allCheckboxes.prop('checked', false);
135
206
  $("#contents-checkbox input[data-checked]").prop('checked', true);
207
+ if(shouldWarnForSelectEvalEnable(wasSelectEvalCheckedBeforeRestore) && $selectEvalCheckbox.is("[data-checked]")){
208
+ openSelectEvalDangerModal($selectEvalCheckbox)
209
+ }
136
210
  break;
137
211
  }
138
212
  return false;
@@ -45,7 +45,7 @@
45
45
  </tbody>
46
46
  </table>
47
47
  <%= content_tag("div", raw(t('camaleon_cms.admin.message.data_found_list')), class: "alert alert-warning") if @user_roles.empty? %>
48
- <%= raw cama_do_pagination(@user_roles) %>
48
+ <%= cama_do_pagination(@user_roles) %>
49
49
 
50
50
  </div>
51
51
 
@@ -53,7 +53,7 @@
53
53
  </tbody>
54
54
  </table>
55
55
  <%= content_tag("div", raw(t('camaleon_cms.admin.message.data_found_list')), class: "alert alert-warning") if @users.empty? %>
56
- <%= raw cama_do_pagination(@users) %>
56
+ <%= cama_do_pagination(@users) %>
57
57
  </div>
58
58
  </div>
59
59
  <!-- END BASIC TABLE SAMPLE -->
@@ -6,11 +6,11 @@
6
6
  </div>
7
7
  </div>
8
8
  <% end %>
9
- <% if params[:info] %>
9
+ <% if flash[:info].present? %>
10
10
  <div class="flash_messages">
11
11
  <div class="alert alert-info">
12
12
  <button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">&times;</span></button>
13
- <%= raw(params[:info]) %>
13
+ <%= flash[:info] %>
14
14
  </div>
15
15
  </div>
16
16
  <% end %>
@@ -4,10 +4,10 @@ Rails.application.config.to_prepare do |_config|
4
4
  next unless ap['path'].present?
5
5
 
6
6
  f = File.join(ap['path'], 'config', 'initializer.rb')
7
- eval(File.read(f)) if File.exist?(f)
7
+ load f if File.exist?(f)
8
8
 
9
9
  f = File.join(ap['path'], 'config', 'custom_models.rb')
10
- eval(File.read(f)) if File.exist?(f)
10
+ load f if File.exist?(f)
11
11
  end
12
12
 
13
13
  # This block can be overridden in the app initializer to wrap the sleep and delete_file in an async job,