drg_cms 0.6.0.8 → 0.6.1.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (85) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +25 -10
  3. data/app/assets/javascripts/drg_cms/drg_cms.js +208 -81
  4. data/app/assets/stylesheets/drg_cms/drg_cms.css +298 -93
  5. data/app/assets/stylesheets/drg_cms/select-multiple.css +1 -1
  6. data/app/controllers/cmsedit_controller.rb +174 -167
  7. data/app/controllers/dc_application_controller.rb +230 -196
  8. data/app/controllers/dc_common_controller.rb +88 -50
  9. data/app/controls/dc_help_control.rb +138 -0
  10. data/app/controls/dc_report.rb +12 -16
  11. data/app/forms/all_options.yml +14 -5
  12. data/app/forms/cms_menu.yml +7 -1
  13. data/app/forms/dc_big_table.yml +0 -2
  14. data/app/forms/dc_big_table_value.yml +0 -2
  15. data/app/forms/dc_category.yml +2 -1
  16. data/app/forms/dc_design.yml +2 -2
  17. data/app/forms/dc_folder_permission.yml +0 -2
  18. data/app/forms/dc_help_1.yml +110 -0
  19. data/app/forms/dc_journal.yml +3 -1
  20. data/app/forms/dc_json_ld.yml +0 -3
  21. data/app/forms/dc_link.yml +1 -1
  22. data/app/forms/dc_menu.yml +8 -12
  23. data/app/forms/dc_menu_item.yml +2 -3
  24. data/app/forms/dc_page.yml +7 -2
  25. data/app/forms/dc_part.yml +1 -0
  26. data/app/forms/dc_piece.yml +1 -0
  27. data/app/forms/dc_policy.yml +2 -5
  28. data/app/forms/dc_poll.yml +13 -16
  29. data/app/forms/dc_seo.yml +1 -2
  30. data/app/forms/dc_simple_menu.yml +3 -2
  31. data/app/forms/dc_site.yml +5 -8
  32. data/app/forms/dc_user.yml +27 -11
  33. data/app/forms/dc_user_role.yml +3 -0
  34. data/app/helpers/cms_common_helper.rb +68 -4
  35. data/app/helpers/cms_edit_helper.rb +73 -55
  36. data/app/helpers/cms_helper.rb +70 -32
  37. data/app/helpers/cms_index_helper.rb +155 -102
  38. data/app/helpers/dc_application_helper.rb +132 -109
  39. data/app/models/concerns/dc_page_concern.rb +14 -4
  40. data/app/models/concerns/dc_piece_concern.rb +1 -1
  41. data/app/models/concerns/dc_policy_rule_concern.rb +20 -8
  42. data/app/models/concerns/dc_site_concern.rb +56 -44
  43. data/app/models/concerns/dc_user_concern.rb +58 -19
  44. data/app/models/dc_big_table.rb +2 -2
  45. data/app/models/dc_design.rb +29 -19
  46. data/app/models/dc_filter.rb +28 -22
  47. data/app/models/dc_key_value_store.rb +1 -0
  48. data/app/models/dc_permission.rb +19 -9
  49. data/app/models/dc_policy.rb +25 -14
  50. data/app/models/dc_policy_role.rb +22 -11
  51. data/app/models/dc_temp.rb +8 -1
  52. data/app/models/dc_user_role.rb +2 -2
  53. data/app/models/drgcms_form_fields/comment.rb +11 -2
  54. data/app/models/drgcms_form_fields/date_picker.rb +2 -0
  55. data/app/models/drgcms_form_fields/drgcms_field.rb +2 -1
  56. data/app/models/drgcms_form_fields/embedded.rb +9 -10
  57. data/app/models/drgcms_form_fields/file_field.rb +1 -1
  58. data/app/models/drgcms_form_fields/file_select.rb +2 -2
  59. data/app/models/drgcms_form_fields/hash_field.rb +11 -7
  60. data/app/models/drgcms_form_fields/link_to.rb +2 -2
  61. data/app/models/drgcms_form_fields/method.rb +5 -4
  62. data/app/models/drgcms_form_fields/multitext_autocomplete.rb +1 -1
  63. data/app/models/drgcms_form_fields/number_field.rb +4 -3
  64. data/app/models/drgcms_form_fields/readonly.rb +13 -17
  65. data/app/models/drgcms_form_fields/select.rb +24 -25
  66. data/app/models/drgcms_form_fields/text_autocomplete.rb +22 -14
  67. data/app/renderers/dc_page_renderer.rb +7 -6
  68. data/app/renderers/dc_poll_renderer.rb +16 -20
  69. data/app/views/cmsedit/_edit_stuff.html.erb +5 -2
  70. data/app/views/cmsedit/_form.html.erb +3 -2
  71. data/app/views/cmsedit/_result.html.erb +21 -18
  72. data/app/views/cmsedit/edit.html.erb +4 -1
  73. data/app/views/cmsedit/index.html.erb +3 -2
  74. data/app/views/cmsedit/new.html.erb +5 -2
  75. data/app/views/dc_common/_help.html.erb +17 -0
  76. data/app/views/layouts/models.html.erb +2 -1
  77. data/config/locales/drgcms_en.yml +17 -2
  78. data/config/locales/drgcms_sl.yml +20 -2
  79. data/config/locales/models_en.yml +7 -5
  80. data/config/locales/models_sl.yml +12 -9
  81. data/drg_cms.gemspec +16 -16
  82. data/lib/drg_cms/version.rb +1 -1
  83. data/lib/drg_cms.rb +94 -2
  84. metadata +32 -30
  85. data/app/models/__dc_dummy.rb +0 -102
@@ -1,4 +1,3 @@
1
- #coding: utf-8
2
1
  #--
3
2
  # Copyright (c) 2012+ Damjan Rems
4
3
  #
@@ -27,10 +26,10 @@
27
26
  # application controllers.
28
27
  ##########################################################################
29
28
  class DcApplicationController < ActionController::Base
30
- protect_from_forgery
31
-
32
- before_action :dc_reload_patches if Rails.env.development?
33
-
29
+ protect_from_forgery with: :null_session, only: Proc.new { |c| c.request.format.json? }
30
+ before_action :dc_reload_patches if Rails.env.development?
31
+ before_action :dc_set_locale
32
+
34
33
  ########################################################################
35
34
  # Writes anything passed as parameter to logger file.
36
35
  # Very useful for debuging strange errors.
@@ -55,9 +54,9 @@ end
55
54
  ####################################################################
56
55
  # Checks if user has required role.
57
56
  #
58
- # @param [DcPolicyRole] role can be passed as DcPolicyRole object or
59
- # @param [String] role as role name. If passed as name, dc_policy_roles is searched for appropriate role.
60
- #
57
+ # @param [DcPolicyRole or String] role can be passed as DcPolicyRole object or
58
+ # as role name. If passed as name, dc_policy_roles is searched for appropriate role.
59
+ #
61
60
  # @return [Boolean] True if user has required role added to his profile.
62
61
  #
63
62
  # @example If user has required role
@@ -66,8 +65,8 @@ end
66
65
  ####################################################################
67
66
  def dc_user_has_role(role)
68
67
  role = DcPolicyRole.get_role(role)
69
- return false if role.nil? or session[:user_roles].nil?
70
- # role is found in user_roles
68
+ return false if role.nil? || session[:user_roles].nil?
69
+ # role exists in user_roles
71
70
  session[:user_roles].include?(role._id)
72
71
  end
73
72
 
@@ -81,22 +80,28 @@ end
81
80
  # @example Returns Google analytics code from site settings
82
81
  # settings = dc_get_site.params['ga_acc']
83
82
  ####################################################################
84
- def dc_get_site()
85
- return @site if @site
83
+ def dc_get_site
84
+ return @site if @site
85
+
86
86
  uri = URI.parse(request.url)
87
+ cache_key = ['dc_site', uri.host]
88
+
89
+ @site = dc_cache_read(cache_key)
90
+ return @site if @site
91
+
87
92
  @site = DcSite.find_by(name: uri.host)
88
- # Site can be aliased
89
- if @site and !@site.alias_for.blank?
93
+ # Site can be aliased
94
+ if @site && !@site.alias_for.blank?
90
95
  @site = DcSite.find_by(name: @site.alias_for)
91
96
  end
92
- # Development environment. Check if site with name test exists and use
93
- # alias_for as pointer to real site.
94
- if @site.nil? and ENV["RAILS_ENV"] != 'production'
97
+ # Development environment. Check if site with name test exists and use
98
+ # alias_for as pointer to real site.
99
+ if @site.nil? && ENV["RAILS_ENV"] != 'production'
95
100
  @site = DcSite.find_by(name: 'test')
96
101
  @site = DcSite.find_by(name: @site.alias_for) if @site
97
- end
98
- @site = nil if @site and !@site.active # site is disabled
99
- @site
102
+ end
103
+ @site = nil if @site && !@site.active # site is disabled
104
+ dc_cache_write(cache_key, @site)
100
105
  end
101
106
 
102
107
  ##########################################################################
@@ -104,7 +109,7 @@ end
104
109
  #
105
110
  # Sets internal @page_title variable.
106
111
  ##########################################################################
107
- def set_page_title()
112
+ def set_page_title
108
113
  @page_title = @page.title.blank? ? @page.subject : @page.title
109
114
  dc_add_meta_tag(:name, 'description', @page.meta_description)
110
115
  end
@@ -115,18 +120,17 @@ end
115
120
  # @param [String] Form file name. File name can be passed as gem_name.filename. This can
116
121
  # be useful when you are extending form but want to retain same name as original form
117
122
  # For example. You are extending dc_user form from drg_cms gem and want to
118
- # retain same dc_user name. This can be done by setting drg_cms.dc_user to extend option.
123
+ # retain same dc_user name. This can be done by setting drg_cms.dc_user as extend option.
119
124
  #
120
125
  # @return [String] Form file name including path or nil if not found.
121
126
  ########################################################################
122
127
  def dc_find_form_file(form_file)
123
- form_path=nil
124
- if form_file.match(/\.|\//)
125
- form_path,form_file=form_file.split(/\.|\//)
126
- end
128
+ form_path = nil
129
+ form_path, form_file = form_file.split(/\.|\//) if form_file.match(/\.|\//)
130
+
127
131
  DrgCms.paths(:forms).reverse.each do |path|
128
132
  f = "#{path}/#{form_file}.yml"
129
- return f if File.exist?(f) and (form_path.nil? or path.to_s.match(/\/#{form_path}\//i))
133
+ return f if File.exist?(f) && (form_path.nil? || path.to_s.match(/\/#{form_path}(-|\/)/i))
130
134
  end
131
135
  raise "Exception: Form file '#{form_file}' not found!"
132
136
  end
@@ -149,7 +153,7 @@ end
149
153
  # Will write document to dc_visits collection unless visit comes from robot.
150
154
  # It also sets session[is_robot] variable to true if robot.
151
155
  ########################################################################
152
- def dc_log_visit()
156
+ def dc_log_visit
153
157
  if request.env["HTTP_USER_AGENT"] and request.env["HTTP_USER_AGENT"].match(/\(.*https?:\/\/.*\)/)
154
158
  logger.info "ROBOT: #{Time.now.strftime('%Y.%m.%d %H:%M:%S')} id=#{@page.id} ip=#{request.remote_ip}."
155
159
  session[:is_robot] = true
@@ -165,73 +169,79 @@ end
165
169
 
166
170
  protected
167
171
 
168
- #############################################################################
169
- # Add permissions. Subroutine of dc_user_can
170
- ############################################################################
171
- def __add_permissions_for(table_name=nil) # :nodoc:
172
- perm = table_name.nil? ? DcPermission.find_by(is_default: true) : DcPermission.find_by(table_name: table_name, active: true)
173
- (perm.dc_policy_rules.each {|p1| @permissions[p1.dc_policy_role_id] = p1.permission }) if perm
174
- end
175
-
176
- ############################################################################
172
+ ###########################################################################
177
173
  # Checks if user can perform (read, create, edit, delete) document in specified
178
174
  # table (collection).
179
175
  #
180
- # @param [Integer] Required permission level
181
- # @param [String] Collection (table) name for which permission is queried. Defaults to params[table].
176
+ # @param [Integer] permission: Required permission level
177
+ # @param [String] table: Collection (table) name for which permission is queried. Defaults to params[table].
182
178
  #
183
179
  # @return [Boolean] true if user's role permits (is higher or equal then required) operation on a table (collection).
184
180
  #
185
181
  # @Example True when user has view permission on the table
186
182
  # if dc_user_can(DcPermission::CAN_VIEW, params[:table]) then ...
187
183
  ############################################################################
188
- def __dc_user_can(permission, table=params[:table])
189
- if @permissions.nil?
190
- @permissions = {}
191
- add_permissions_for # default permission
192
- table_name = ''
193
- # permission can be set for table or object embedded in table. Read all possible values
194
- table.strip.downcase.split(';').each do |t|
195
- table_name << (table_name.size > 0 ? ';' : '') + t # table;embedded;another;...
196
- add_permissions_for table_name
197
- end
184
+ def dc_user_can(permission, table = params[:table])
185
+ table = table.underscore
186
+ cache_key = ['dc_permission', table, session[:user_id], dc_get_site.id]
187
+ permissions = dc_cache_read(cache_key)
188
+ if permissions.nil?
189
+ permissions = DcPermission.permissions_for_table(table)
190
+ dc_cache_write(cache_key, permissions)
198
191
  end
199
- # Return true if any of the permissions user has is higher or equal to requested permission
200
- session[:user_roles].each {|r| return true if @permissions[r] and @permissions[r] >= permission }
192
+ session[:user_roles].each { |r| return true if permissions[r] && permissions[r] >= permission }
201
193
  false
202
- end
194
+ end
203
195
 
204
- ###########################################################################
205
- # Checks if user can perform (read, create, edit, delete) document in specified
206
- # table (collection).
207
- #
208
- # @param [Integer] Required permission level
209
- # @param [String] Collection (table) name for which permission is queried. Defaults to params[table].
210
- #
211
- # @return [Boolean] true if user's role permits (is higher or equal then required) operation on a table (collection).
212
- #
213
- # @Example True when user has view permission on the table
214
- # if dc_user_can(DcPermission::CAN_VIEW, params[:table]) then ...
215
- ############################################################################
216
- def dc_user_can(permission, table=params[:table])
217
- @permissions ||= DcPermission.permissions_for_table(table)
218
- # Return true if any of the permissions user has is higher or equal to requested permission
219
- session[:user_roles].each {|r| return true if @permissions[r] and @permissions[r] >= permission }
220
- false
196
+ ####################################################################
197
+ # Read from cache
198
+ #
199
+ # @keys [Array] Array of keys
200
+ #
201
+ # @return [Object] Data returned from cache
202
+ ####################################################################
203
+ def dc_cache_read(keys)
204
+ if redis_cache_store?
205
+ keys = keys.dup
206
+ first = keys.shift
207
+ data = redis.hget(first, keys.join(''))
208
+ data ? Marshal.load(data) : nil
209
+ else
210
+ Rails.cache.read(keys.join(''))
211
+ end
221
212
  end
222
213
 
223
214
  ####################################################################
224
- # Detects if called from mobile agent according to http://detectmobilebrowsers.com/
215
+ # Write data to cache
216
+ #
217
+ # @param [Array] keys: Array of keys
218
+ # @param [Object] data: Data written to cache
219
+ #
220
+ # @return [Object] data so dc_cache_write can be used as last statement in method.
221
+ ####################################################################
222
+ def dc_cache_write(keys, data)
223
+ if redis_cache_store?
224
+ keys = keys.dup
225
+ first = keys.shift
226
+ redis.hset(first, keys.join(''), Marshal.dump(data))
227
+ else
228
+ Rails.cache.write(keys.join(''), data)
229
+ end
230
+ data
231
+ end
232
+
233
+ ####################################################################
234
+ # Detects if called from mobile agent according to http://detectmobilebrowsers.com/
225
235
  # and set session[:is_mobile]
226
- #
236
+ #
227
237
  # Detect also if caller is a robot and set session[:is_robot]
228
238
  ####################################################################
229
239
  def dc_set_is_mobile
230
240
  is_mobile = request.user_agent ? /(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows (ce|phone)|xda|xiino/i.match(request.user_agent) || /1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.match(request.user_agent[0..3])
231
241
  : false
232
242
  session[:is_mobile] = is_mobile ? 1 : 0
233
- #
234
- if request.env["HTTP_USER_AGENT"] and request.env["HTTP_USER_AGENT"].match(/\(.*https?:\/\/.*\)/)
243
+
244
+ if request.env["HTTP_USER_AGENT "] && request.env["HTTP_USER_AGENT"].match(/\(.*https?:\/\/.*\)/)
235
245
  logger.info "ROBOT: #{Time.now.strftime('%Y.%m.%d %H:%M:%S')} id=#{@page.id} ip=#{request.remote_ip}."
236
246
  session[:is_robot] = true
237
247
  end
@@ -240,23 +250,13 @@ end
240
250
  ##########################################################################
241
251
  # Merge values from parameters fields (from site, page ...) into internal @options hash.
242
252
  #
243
- # @param [String] YAML string.
253
+ # @param [String] parameters: passed as YAML string.
244
254
  ##########################################################################
245
255
  def dc_set_options(parameters)
246
256
  @options ||= {}
247
257
  return if parameters.to_s.size < 3
248
- # parameters are set az YAML. This should be default in future.
249
- parms = YAML.load(parameters) rescue nil
250
- if parms.nil? # error when loadnig yaml, try the old way parsing manually
251
- parms = {}
252
- parameters.split("\n").each do |line|
253
- line.chomp.split(',').each do |parm|
254
- key, value = parm.split(':')
255
- value = value.to_s.strip.gsub(/\'|\"/,'')
256
- parms[key.strip] = (value == '/' ? nil : value)
257
- end
258
- end
259
- end
258
+ # parameters are set as YAML. This should be default in future.
259
+ parms = YAML.load(parameters) rescue {}
260
260
  @options.merge!(parms)
261
261
  end
262
262
 
@@ -270,7 +270,6 @@ end
270
270
  # @return [Boolean] true when none of documents is changed.
271
271
  ##########################################################################
272
272
  def dc_not_modified?(*documents)
273
- # request.env.each {|k,v| p k,'*',v}
274
273
  return false unless request.env.include? 'HTTP_IF_MODIFIED_SINCE'
275
274
 
276
275
  since_date = Time.parse request.env['HTTP_IF_MODIFIED_SINCE']
@@ -279,7 +278,7 @@ def dc_not_modified?(*documents)
279
278
  next unless doc.respond_to?(:updated_at)
280
279
  last_modified = doc.updated_at if doc.updated_at > last_modified
281
280
  end
282
- # p last_modified, since_date
281
+
283
282
  if last_modified >= since_date then
284
283
  render :nothing => true, :status => 304
285
284
  return true
@@ -298,16 +297,16 @@ def get_design_and_render(design_doc)
298
297
  layout = @site.site_layout.blank? ? 'content' : @site.site_layout
299
298
  site_top = '<%= dc_page_top %>'
300
299
  site_bottom = '<%= dc_page_bottom %>'
301
- # lets try the rails way
302
- if @options[:control] and @options[:action]
300
+ # lets try the rails way
301
+ if @options[:control] && @options[:action]
303
302
  controller = "#{@options[:control]}_control".classify.constantize rescue nil
304
303
  extend controller if controller
305
304
  return send @options[:action] if respond_to?(@options[:action])
306
305
  end
307
- # design doc present
306
+ # design doc present
308
307
  if design_doc
309
308
  # defined as rails view
310
- design = if design_doc.rails_view.blank? or design_doc.rails_view == 'site'
309
+ design = if design_doc.rails_view.blank? || design_doc.rails_view == 'site'
311
310
  @site.rails_view
312
311
  else
313
312
  design_doc.rails_view
@@ -318,8 +317,8 @@ def get_design_and_render(design_doc)
318
317
  design = site_top + design + site_bottom
319
318
  return render(inline: design, layout: layout) unless design.blank?
320
319
  end
321
- # Design doc not defined
322
- if @site.rails_view.blank?
320
+ # Design doc not defined
321
+ if @site.rails_view.blank?
323
322
  design = site_top + @site.design + site_bottom
324
323
  render(inline: design, layout: layout)
325
324
  else
@@ -341,34 +340,35 @@ end
341
340
  # dc_process_default_request
342
341
  # end
343
342
  ##########################################################################
344
- def dc_process_default_request()
343
+ def dc_process_default_request
345
344
  session[:edit_mode] ||= 0
346
- # Initialize parts
345
+ # Initialize parts
347
346
  @parts = nil
348
347
  @js, @css = '', ''
349
- # find domain name in sites
348
+ # find domain name in sites
350
349
  @site = dc_get_site
351
- # site not defined. render 404 error
350
+ # site not defined. render 404 error
352
351
  return dc_render_404('Site!') if @site.nil?
352
+
353
353
  dc_set_options(@site.settings)
354
- # HOMEPAGE. When no parameters is set
354
+ # HOMEPAGE. When no parameters is set
355
355
  params[:path] = @site.homepage_link if params[:id].nil? and params[:path].nil?
356
356
  @options[:path] = params[:path].to_s.downcase.split('/')
357
357
  params[:path] = @options[:path].first if @options[:path].size > 1
358
- # some other process request. It should fail if not defined
358
+ # some other process request. It should fail if not defined
359
359
  return send(@site.request_processor) unless @site.request_processor.blank?
360
360
 
361
- # Search for page
361
+ # Search for page
362
362
  pageclass = @site.page_klass
363
363
  if params[:id]
364
364
  #Page.where(id: params[:id]).or(subject_link: params[:id]).first
365
365
  @page = pageclass.find_by(:dc_site_id.in => [@site._id, nil], subject_link: params[:id], active: true)
366
366
  @page = pageclass.find(params[:id]) if @page.nil? # I think that there will be more subject_link searchers than id
367
367
  elsif params[:path]
368
- # path may point direct to page's subject_link
368
+ # path may point direct to page's subject_link
369
369
  @page = pageclass.find_by(:dc_site_id.in => [@site._id, nil], subject_link: params[:path], active: true)
370
370
  if @page.nil?
371
- # no. Find if defined in links
371
+ # no. Find if defined in links
372
372
  link = DcLink.find_by(:dc_site_id.in => [@site._id, nil], name: params[:path])
373
373
  if link
374
374
  #pageclass.find_by(alt_link: params[:path])
@@ -377,10 +377,11 @@ def dc_process_default_request()
377
377
  end
378
378
  end
379
379
  end
380
- # if @page is not found render 404 error
380
+ # if @page is not found render 404 error
381
381
  return dc_render_404('Page!') unless @page
382
+
382
383
  dc_set_is_mobile unless session[:is_mobile] # do it only once per session
383
- # find design if defined. Otherwise design MUST be declared in site
384
+ # find design if defined. Otherwise design MUST be declared in site
384
385
  if @page.dc_design_id
385
386
  @design = DcDesign.find(@page.dc_design_id)
386
387
  return dc_render_404('Design!') unless @design
@@ -388,20 +389,20 @@ def dc_process_default_request()
388
389
  dc_set_options @design.params if @design
389
390
  dc_set_options @page.params
390
391
  dc_add_json_ld(@page.get_json_ld)
391
- # Add edit menu
392
+ # Add edit menu
392
393
  if session[:edit_mode] > 0
393
394
  session[:site_id] = @site.id
394
395
  session[:site_page_class] = @site.page_class
395
396
  session[:page_id] = @page.id
396
- else
397
- # Log only visits from non-editors
397
+ else
398
+ # Log only visits from non-editors
398
399
  dc_log_visit()
399
400
  end
400
401
  set_page_title()
401
402
  get_design_and_render @design
402
403
  end
403
404
 
404
- ##########################################################################
405
+ ###########################################################################
405
406
  # Single site document kind of request handler.
406
407
  #
407
408
  # This request handler assumes that all data for the site is saved in the site document.
@@ -417,18 +418,17 @@ def dc_single_sitedoc_request
417
418
  if @site.nil?
418
419
  session[:edit_mode] ||= 0
419
420
  @site = dc_get_site
420
- # @site is not defined. render 404 error
421
+ # @site is not defined. render 404 error
421
422
  return dc_render_404('Site!') unless @site
423
+
422
424
  dc_set_options(@site.settings)
423
425
  end
424
- # HOMEPAGE. When no parameters is set
426
+ # HOMEPAGE. When no parameters is set
425
427
  params[:path] = @site.homepage_link if params[:path].nil?
426
428
  @parts = @site.dc_parts
427
429
  @part = @parts.find_by(link: params[:path])
428
430
  return dc_render_404('Part!') unless @part
429
- # Document was not modified since last visit
430
- # return if dc_not_modified?(@site, @part)
431
- #
431
+
432
432
  @page_title = "#{@site.page_title} #{@part.name}"
433
433
  @js, @css = '', ''
434
434
  get_design_and_render nil
@@ -439,46 +439,36 @@ end
439
439
  # very good with non ascii chars. Since this method is used for converting from model
440
440
  # to collection names it is very unwise to use non ascii chars for table (collection) names.
441
441
  #
442
- # @param [String] String to be converted
443
- #
442
+ # @param [Object] model_string to be converted
443
+ #
444
444
  # @example
445
445
  # decamelize_type(ModelName) # 'ModelName' => 'model_name'
446
446
  ########################################################################
447
- def decamelize_type(string)
448
- return nil unless string
449
- r = ''
450
- string.to_s.each_char do |c|
451
- r << case
452
- when r.size == 0 then c.downcase
453
- when c.downcase != c then '_' + c.downcase
454
- else c
455
- end
456
- end
457
- r
447
+ def decamelize_type(model_string)
448
+ model_string ? model_string.underscore : nil
458
449
  end
459
450
 
460
451
  ####################################################################
461
452
  # Return's error messages for the document formated for display on edit form.
462
453
  #
463
- # @param [Document] Document object which will be examined for errors.
464
- #
454
+ # @param [Document] document object which will be examined for errors.
455
+ #
465
456
  # @return [String] HTML code for displaying error on edit form.
466
457
  ####################################################################
467
458
  def dc_error_messages_for(document)
468
459
  return '' unless document.errors.any?
460
+
469
461
  msg = ''
470
- document.errors.each do |attribute, errors_array|
471
- label = t("helpers.label.#{decamelize_type(document.class)}.#{attribute}")
472
- msg << "<li>#{label} : #{errors_array}</li>"
462
+ document.errors.each do |error|
463
+ label = t("helpers.label.#{decamelize_type(document.class)}.#{error.attribute}", error.attribute)
464
+ msg << "<li>#{label} : #{error.message}</li>"
473
465
  end
474
466
 
475
- html = <<eot
467
+ %(
476
468
  <div class="dc-form-error">
477
469
  <h2>#{t('drgcms.errors_no')} #{document.errors.size}</h2>
478
470
  <ul>#{msg}</ul>
479
- </div>
480
- eot
481
- html.html_safe
471
+ </div>).html_safe
482
472
  end
483
473
 
484
474
  ####################################################################
@@ -487,8 +477,8 @@ end
487
477
  # model errors or when saving to multiple collections and where each save must be
488
478
  # checked if succesfull.
489
479
  #
490
- # @param [Document] Document object which will be checked
491
- # @param [Boolean] If true method should end in runtime error. Default = false.
480
+ # @param [Document] document: Document object to be checked
481
+ # @param [Boolean] crash: If true method should end in runtime error. Default = false.
492
482
  #
493
483
  # @return [String] Error messages or empty string if everything is OK.
494
484
  #
@@ -500,16 +490,16 @@ end
500
490
  # end
501
491
  #
502
492
  ####################################################################
503
- def dc_check_model(document, crash=false)
504
- DcApplicationController.dc_check_model(document, crash=false)
493
+ def dc_check_model(document, crash = false)
494
+ DrgCms.model_check(document, crash)
505
495
  end
506
496
 
507
497
  ######################################################################
508
498
  # Call rake task from controller.
509
499
  #
510
- # @param [String] Rake task name
511
- # @param [Hash] Options that will be send to task as environment variables
512
- #
500
+ # @param [String] task: Rake task name
501
+ # @param [Hash] options: Options that will be send to task as environment variables
502
+ #
513
503
  # @example Call rake task from application
514
504
  # dc_call_rake('clear:all', some_parm: some_id)
515
505
  ######################################################################
@@ -524,8 +514,8 @@ end
524
514
  # made from DRG CMS form return may be quite complicated. All ajax return combinations
525
515
  # can be found in drg_cms.js file.
526
516
  #
527
- # @param [Hash] Options
528
- #
517
+ # @param [Hash] opts: Options
518
+ #
529
519
  # @return [JSON Response] Formatted to be used for ajax return.
530
520
  #
531
521
  # @example
@@ -537,7 +527,7 @@ end
537
527
  ######################################################################
538
528
  def dc_render_ajax(opts)
539
529
  result = {}
540
- if opts[:div] or opts[:class]
530
+ if opts[:div] || opts[:class]
541
531
  selector = opts[:div] ? '#' : '.' # for div . for class
542
532
  key = case
543
533
  when opts[:prepend] then "#{selector}+div"
@@ -559,7 +549,7 @@ end
559
549
  # @param [String] Table (collection) name. Could be dc_page;dc_part;... when searching for embedded document.
560
550
  # @param [String] Id of the document
561
551
  # @param [String] Ids of parent documents when document is embedded. Ids are separated by ; char.
562
- #
552
+ #
563
553
  # @return [document]. Required document or nil if not found.
564
554
  #
565
555
  # @example As used in Cmsedit_controller
@@ -589,6 +579,20 @@ def dc_reload_patches
589
579
  end
590
580
  end
591
581
 
582
+ ########################################################################
583
+ # Will set new default locale for application
584
+ #
585
+ # @param [String] new_locale : New locale value. If omitted it will be provided from params[:locale].
586
+ # if new_locale value is 00, application's default_locale will be used.
587
+ ########################################################################
588
+ def dc_set_locale(new_locale = nil)
589
+ new_locale ||= params[:locale]
590
+ if new_locale && new_locale != session[:locale]
591
+ session[:locale] = new_locale == '00' ? nil : new_locale.to_sym
592
+ end
593
+ I18n.locale = session[:locale] ? session[:locale] : I18n.default_locale
594
+ end
595
+
592
596
  ############################################################################
593
597
  # Writes out deprication msg. It also adds site_name to message, so it is easier to
594
598
  # find where the message is comming from.
@@ -604,7 +608,7 @@ def clear_login_data
604
608
  session[:edit_mode] = 0
605
609
  session[:user_id] = nil
606
610
  session[:user_name] = nil
607
- session[:user_roles] = nil
611
+ set_default_guest_user_role
608
612
  cookies.delete :remember_me
609
613
  end
610
614
 
@@ -622,32 +626,48 @@ end
622
626
  # @param [DcUser] user : User's document
623
627
  # @param [Boolean] remember_me : false by default
624
628
  ####################################################################
625
- def fill_login_data(user, remember_me=false)
626
- session[:user_id] = user.id if user
627
- session[:user_name] = user.name if user
628
- session[:edit_mode] = 0
629
- session[:user_roles] = []
630
- # Every user has guest role
631
- # guest = DcPolicyRole.find_by(system_name: 'guest')
632
- # session[:user_roles] << guest.id if guest
629
+ def fill_login_data(user, remember_me = false)
630
+ session[:user_id] = user.id if user
631
+ session[:user_name] = user.name.squish if user
632
+ session[:edit_mode] = 0
633
633
  set_default_guest_user_role
634
- return unless user and user.active
634
+ return unless user&.active
635
+
635
636
  # special for SUPERADMIN
636
637
  sa = DcPolicyRole.find_by(system_name: 'superadmin')
637
- if sa and (role = user.dc_user_roles.find_by(dc_policy_role_id: sa.id))
638
+ if sa && (role = user.dc_user_roles.find_by(dc_policy_role_id: sa.id))
638
639
  session[:user_roles] << role.dc_policy_role_id
639
- session[:edit_mode] = 2
640
+ session[:edit_mode] = 2
640
641
  return
641
642
  end
642
- # read default policy from site. Policy might be inherited
643
+ # read default policy from site. Policy might be inherited from other site
643
644
  policy_site = dc_get_site()
644
645
  policy_site = DcSite.find(policy_site.inherit_policy) if policy_site.inherit_policy
645
646
  default_policy = policy_site.dc_policies.find_by(is_default: true)
646
- # load user roles
647
+
648
+ # load user roles from groups
649
+ roles = {}
650
+ user.member.each do |group_id|
651
+ group = DcUser.find(group_id)
652
+ next unless group.active
653
+
654
+ group.dc_user_roles.each do |role|
655
+ next unless role.active?
656
+ roles[role.dc_policy_role_id] = role
657
+ end
658
+ end unless user.member.blank?
659
+
660
+ # load user roles from user
647
661
  user.dc_user_roles.each do |role|
648
- next unless role.active
649
- next if role.valid_from and role.valid_from > Time.now.end_of_day.to_date
650
- next if role.valid_to and role.valid_to < Time.now.to_date
662
+ # not active in user roles will remove role defined in groups
663
+ unless role.active?
664
+ roles.delete(role.dc_policy_role_id) if roles[role.dc_policy_role_id]
665
+ next
666
+ end
667
+ roles[role.dc_policy_role_id] = role
668
+ end
669
+ # select only roles defined in default site policy and set edit_mode
670
+ roles.each do |key, role|
651
671
  # check if role is active in this site
652
672
  policy_role = default_policy.dc_policy_rules.find_by(dc_policy_role_id: role.dc_policy_role_id)
653
673
  next unless policy_role
@@ -656,20 +676,19 @@ def fill_login_data(user, remember_me=false)
656
676
  session[:user_roles] << role.dc_policy_role_id
657
677
  end
658
678
  # Save remember me cookie if not CMS user and remember me is selected
659
- if session[:edit_mode] == 0 and remember_me
660
- cookies.signed[:remember_me] = { :value => user.id, :expires => 180.days.from_now}
679
+ if session[:edit_mode] == 0 && remember_me
680
+ cookies.signed[:remember_me] = { value: user.id, expires: 180.days.from_now }
661
681
  end
662
682
  end
663
683
 
664
684
  ##########################################################################
665
- # Will check if user's login data is stil valid and reload user roles.
685
+ # Will check if user's login data is still valid and reload user roles.
666
686
  #
667
687
  # @param [Time] repeat_after : Check is repeated after time. This is by default performed every 24 hours.
668
688
  ##########################################################################
669
- def dc_check_user_still_valid(repeat_after=1.day)
670
- # not needed
671
- return if session[:user_id].nil?
672
- # last check more than a day ago
689
+ def dc_check_user_still_valid(repeat_after = 1.day)
690
+ return if session[:user_id].nil?
691
+ # last check more than repeat_after ago
673
692
  if (session[:user_chk] ||= Time.now) < repeat_after.ago
674
693
  user_id = session[:user_id]
675
694
  clear_login_data
@@ -684,9 +703,9 @@ end
684
703
  # Evaluates Class.method in more predictable context then just calling eval
685
704
  #
686
705
  # @param [String] class_method defined as MyClass.method_name
687
- # @param [Object] optional parameters send to class_method
706
+ # @param [Object] params: optional parameters send to class_method
688
707
  ##########################################################################
689
- def dc_eval_class_method(class_method, params=nil)
708
+ def dc_eval_class_method(class_method, params = nil)
690
709
  klass, method = class_method.split('.')
691
710
  # check if class exists
692
711
  klass = klass.classify.constantize rescue nil
@@ -729,25 +748,33 @@ end
729
748
  ########################################################################
730
749
  def dc_add_meta_tag(type, name, content)
731
750
  return if content.blank?
751
+
732
752
  @meta_tags ||= {}
733
753
  key = "#{type}=\"#{name}\""
734
754
  @meta_tags[key] = content
735
755
  end
736
756
 
737
757
  ########################################################################
738
- # Will prepare flash[:update] data, which will be used for updating fields
739
- # on forms parent form fields.
740
- #
741
- # Parameters:
742
- # [field_name] String: Field name
758
+ # Will prepare flash[:update] data, which is used for updating elements
759
+ # on parent form.
760
+ #
761
+ # Parameters passed as hash:
762
+ # [field] String: Field name
763
+ # [head] String: Filed name in head of form
743
764
  # [value] String: New value
744
765
  # [readonly] Boolean: Field is readonly
745
- #
766
+ #
746
767
  ########################################################################
747
- def dc_update_form_field(field_name, value, readonly=false)
748
- key_name = (readonly ? 'td_' : '') + "record_#{field_name}"
768
+ def dc_update_form_element(field: nil, head: nil, value:, readonly: true)
769
+ key = if field
770
+ (readonly ? 'td_' : '') + "record_#{field}"
771
+ elsif head
772
+ "head-#{head}"
773
+ end
774
+ return if key.nil?
775
+
749
776
  flash[:update] ||= {}
750
- flash[:update][key_name] = value
777
+ flash[:update][key] = value
751
778
  end
752
779
 
753
780
  ####################################################################
@@ -769,20 +796,8 @@ end
769
796
  # end
770
797
  #
771
798
  ####################################################################
772
- def self.dc_check_model(document, crash=false)
773
- return nil unless document.errors.any?
774
- msg = ""
775
- document.errors.each do |attribute, errors_array|
776
- msg << "#{attribute}: #{errors_array}\n"
777
- end
778
- #
779
- if crash and msg.size > 0
780
- msg = "Validation errors in #{document.class}:\n" + msg
781
- pp msg
782
- Rails.logger.error(msg)
783
- raise "Validation error. See log for more information."
784
- end
785
- msg
799
+ def self.dc_check_model(document, crash = false)
800
+ DrgCms.model_check(document, crash)
786
801
  end
787
802
 
788
803
  ########################################################################
@@ -798,5 +813,24 @@ def dc_dump_exception(exception)
798
813
  Rails.logger.error msg
799
814
  end
800
815
 
816
+ private
817
+
818
+ ########################################################################
819
+ # Determines if redis cache store is active
820
+ #
821
+ # @return [Boolean] : True if redis cache store is active
822
+ ########################################################################
823
+ def redis_cache_store?
824
+ (Rails.application.config.cache_store.first == :redis_cache_store) rescue false
825
+ end
826
+
827
+ ########################################################################
828
+ # Returns redis object
829
+ #
830
+ # @return [Object] : Redis object
831
+ ########################################################################
832
+ def redis
833
+ Rails.cache.redis
834
+ end
801
835
 
802
836
  end