agile_rails 0.0.0.1

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 (259) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +5 -0
  3. data/MIT-LICENSE +20 -0
  4. data/README.md +285 -0
  5. data/Rakefile +39 -0
  6. data/agile_rails.gemspec +36 -0
  7. data/app/assets/fonts/ibm-plex-sans-300.woff2 +0 -0
  8. data/app/assets/fonts/ibm-plex-sans-400.woff2 +0 -0
  9. data/app/assets/fonts/ibm-plex-sans-500.woff2 +0 -0
  10. data/app/assets/fonts/ibm-plex-sans-600.woff2 +0 -0
  11. data/app/assets/fonts/ibm-plex-sans-700.woff2 +0 -0
  12. data/app/assets/fonts/ibm-plex-sans-italic.woff2 +0 -0
  13. data/app/assets/images/32px.png +0 -0
  14. data/app/assets/images/throbber.gif +0 -0
  15. data/app/assets/javascripts/agile/agile.js +1489 -0
  16. data/app/assets/javascripts/agile/jquery-migrate.js +702 -0
  17. data/app/assets/javascripts/agile/jquery.bpopup.js +372 -0
  18. data/app/assets/javascripts/agile/jquery.datetimepicker.js +1353 -0
  19. data/app/assets/javascripts/agile/jstree.min.js +6 -0
  20. data/app/assets/javascripts/agile/select-multiple.js +459 -0
  21. data/app/assets/javascripts/agile/some_scripts.js +33 -0
  22. data/app/assets/javascripts/agile.js +22 -0
  23. data/app/assets/javascripts/agile_application.js +22 -0
  24. data/app/assets/javascripts/agile_editor.js +22 -0
  25. data/app/assets/stylesheets/agile/agile.css +1882 -0
  26. data/app/assets/stylesheets/agile/agile_apps.css +149 -0
  27. data/app/assets/stylesheets/agile/jquery.datetimepicker.css +304 -0
  28. data/app/assets/stylesheets/agile/jstree.css +1107 -0
  29. data/app/assets/stylesheets/agile/select-multiple.css +110 -0
  30. data/app/assets/stylesheets/agile/th-bg.png +0 -0
  31. data/app/assets/stylesheets/agile/theme.css +49 -0
  32. data/app/assets/stylesheets/agile.css +21 -0
  33. data/app/assets/stylesheets/agile_application.css +20 -0
  34. data/app/assets/stylesheets/agile_editor.css +19 -0
  35. data/app/controllers/agile_application_controller.rb +735 -0
  36. data/app/controllers/agile_common_controller.rb +345 -0
  37. data/app/controllers/agile_controller.rb +977 -0
  38. data/app/controllers/agile_main_controller.rb +36 -0
  39. data/app/controls/agile_control.rb +120 -0
  40. data/app/controls/agile_report.rb +364 -0
  41. data/app/controls/ar_category_control.rb +39 -0
  42. data/app/controls/ar_help_control.rb +139 -0
  43. data/app/controls/ar_image_control.rb +180 -0
  44. data/app/controls/ar_journal_control.rb +47 -0
  45. data/app/controls/ar_menu_item_control.rb +55 -0
  46. data/app/controls/ar_page_control.rb +64 -0
  47. data/app/controls/ar_poll_result_control.rb +84 -0
  48. data/app/controls/ar_setup_control.rb +62 -0
  49. data/app/controls/belongs_to_control.rb +61 -0
  50. data/app/controls/browse_models_control.rb +98 -0
  51. data/app/controls/settings_form_control.rb +137 -0
  52. data/app/forms/agile_help.yml +112 -0
  53. data/app/forms/agile_menu.yml +140 -0
  54. data/app/forms/agile_report_defaults.yml +39 -0
  55. data/app/forms/all_options.yml +810 -0
  56. data/app/forms/ar_ad.yml +121 -0
  57. data/app/forms/ar_big_table.yml +60 -0
  58. data/app/forms/ar_big_table_value.yml +52 -0
  59. data/app/forms/ar_browse_fields.yml +35 -0
  60. data/app/forms/ar_browse_models.yml +48 -0
  61. data/app/forms/ar_category.yml +73 -0
  62. data/app/forms/ar_category_as_tree.yml +31 -0
  63. data/app/forms/ar_design.yml +75 -0
  64. data/app/forms/ar_filter.yml +52 -0
  65. data/app/forms/ar_folder_permission.yml +56 -0
  66. data/app/forms/ar_folder_rule.yml +48 -0
  67. data/app/forms/ar_gallery.yml +55 -0
  68. data/app/forms/ar_image.yml +126 -0
  69. data/app/forms/ar_image_search.yml +83 -0
  70. data/app/forms/ar_journal.yml +76 -0
  71. data/app/forms/ar_json_ld.yml +56 -0
  72. data/app/forms/ar_key_value.yml +33 -0
  73. data/app/forms/ar_key_value_store.yml +33 -0
  74. data/app/forms/ar_link.yml +60 -0
  75. data/app/forms/ar_menu.yml +67 -0
  76. data/app/forms/ar_menu_item.yml +141 -0
  77. data/app/forms/ar_page.yml +187 -0
  78. data/app/forms/ar_part.yml +91 -0
  79. data/app/forms/ar_permission.yml +52 -0
  80. data/app/forms/ar_permission_rule.yml +40 -0
  81. data/app/forms/ar_piece.yml +106 -0
  82. data/app/forms/ar_policy.yml +64 -0
  83. data/app/forms/ar_policy_rule.yml +42 -0
  84. data/app/forms/ar_policy_rule_nocms.yml +40 -0
  85. data/app/forms/ar_poll.yml +118 -0
  86. data/app/forms/ar_poll_item.yml +78 -0
  87. data/app/forms/ar_poll_result.yml +88 -0
  88. data/app/forms/ar_poll_result_export.yml +35 -0
  89. data/app/forms/ar_removed_url.yml +41 -0
  90. data/app/forms/ar_role.yml +43 -0
  91. data/app/forms/ar_seo.yml +32 -0
  92. data/app/forms/ar_setup.yml +45 -0
  93. data/app/forms/ar_site.yml +149 -0
  94. data/app/forms/ar_steps_template.yml +51 -0
  95. data/app/forms/ar_user.yml +140 -0
  96. data/app/forms/ar_user_role.yml +57 -0
  97. data/app/forms/help/dc_category_as_tree.en +4 -0
  98. data/app/forms/help/dc_category_as_tree.sl +5 -0
  99. data/app/forms/json_ld_schema.yml +168 -0
  100. data/app/helpers/agile_application_helper.rb +1162 -0
  101. data/app/helpers/agile_category_helper.rb +128 -0
  102. data/app/helpers/agile_common_helper.rb +308 -0
  103. data/app/helpers/agile_edit_helper.rb +645 -0
  104. data/app/helpers/agile_helper.rb +509 -0
  105. data/app/helpers/agile_index_helper.rb +677 -0
  106. data/app/helpers/ar_image_helper.rb +128 -0
  107. data/app/models/agile_form_fields/action.rb +61 -0
  108. data/app/models/agile_form_fields/agile_form_field.rb +322 -0
  109. data/app/models/agile_form_fields/belongs_to.rb +112 -0
  110. data/app/models/agile_form_fields/check_box.rb +73 -0
  111. data/app/models/agile_form_fields/comment.rb +62 -0
  112. data/app/models/agile_form_fields/date_picker.rb +104 -0
  113. data/app/models/agile_form_fields/date_select.rb +68 -0
  114. data/app/models/agile_form_fields/datetime_picker.rb +88 -0
  115. data/app/models/agile_form_fields/datetime_select.rb +73 -0
  116. data/app/models/agile_form_fields/file_field.rb +52 -0
  117. data/app/models/agile_form_fields/file_select.rb +69 -0
  118. data/app/models/agile_form_fields/hidden_field.rb +51 -0
  119. data/app/models/agile_form_fields/html_field.rb +69 -0
  120. data/app/models/agile_form_fields/journal_diff.rb +62 -0
  121. data/app/models/agile_form_fields/link_to.rb +69 -0
  122. data/app/models/agile_form_fields/method.rb +66 -0
  123. data/app/models/agile_form_fields/multitext_autocomplete.rb +215 -0
  124. data/app/models/agile_form_fields/number_field.rb +92 -0
  125. data/app/models/agile_form_fields/password_field.rb +63 -0
  126. data/app/models/agile_form_fields/radio_button.rb +95 -0
  127. data/app/models/agile_form_fields/readonly.rb +77 -0
  128. data/app/models/agile_form_fields/select.rb +281 -0
  129. data/app/models/agile_form_fields/submit_tag.rb +58 -0
  130. data/app/models/agile_form_fields/text_area.rb +61 -0
  131. data/app/models/agile_form_fields/text_autocomplete.rb +171 -0
  132. data/app/models/agile_form_fields/text_field.rb +55 -0
  133. data/app/models/agile_form_fields/text_with_select.rb +94 -0
  134. data/app/models/agile_form_fields/tree_select.rb +170 -0
  135. data/app/models/ar_big_table.rb +82 -0
  136. data/app/models/ar_big_table_value.rb +53 -0
  137. data/app/models/ar_category.rb +109 -0
  138. data/app/models/ar_design.rb +116 -0
  139. data/app/models/ar_filter.rb +200 -0
  140. data/app/models/ar_folder_permission.rb +50 -0
  141. data/app/models/ar_folder_rule.rb +47 -0
  142. data/app/models/ar_gallery.rb +53 -0
  143. data/app/models/ar_image.rb +198 -0
  144. data/app/models/ar_internals.rb +60 -0
  145. data/app/models/ar_journal.rb +46 -0
  146. data/app/models/ar_json_ld.rb +131 -0
  147. data/app/models/ar_key_value_store.rb +128 -0
  148. data/app/models/ar_link.rb +48 -0
  149. data/app/models/ar_memory.rb +172 -0
  150. data/app/models/ar_menu.rb +144 -0
  151. data/app/models/ar_menu_item.rb +106 -0
  152. data/app/models/ar_page.rb +74 -0
  153. data/app/models/ar_part.rb +66 -0
  154. data/app/models/ar_permission.rb +180 -0
  155. data/app/models/ar_permission_rule.rb +65 -0
  156. data/app/models/ar_policy.rb +78 -0
  157. data/app/models/ar_policy_rule.rb +65 -0
  158. data/app/models/ar_poll.rb +74 -0
  159. data/app/models/ar_poll_item.rb +47 -0
  160. data/app/models/ar_poll_result.rb +38 -0
  161. data/app/models/ar_removed_url.rb +42 -0
  162. data/app/models/ar_role.rb +84 -0
  163. data/app/models/ar_setup.rb +115 -0
  164. data/app/models/ar_site.rb +68 -0
  165. data/app/models/ar_temp.rb +150 -0
  166. data/app/models/ar_user.rb +72 -0
  167. data/app/models/ar_user_group.rb +38 -0
  168. data/app/models/ar_user_role.rb +54 -0
  169. data/app/models/ar_visit.rb +41 -0
  170. data/app/models/concerns/ar_page_concern.rb +128 -0
  171. data/app/models/concerns/ar_part_concern.rb +48 -0
  172. data/app/models/concerns/ar_piece_concern.rb +48 -0
  173. data/app/models/concerns/ar_policy_rule_concern.rb +87 -0
  174. data/app/models/concerns/ar_seo_concern.rb +66 -0
  175. data/app/models/concerns/ar_site_concern.rb +103 -0
  176. data/app/models/concerns/ar_user_concern.rb +195 -0
  177. data/app/renderers/agile_common_renderer.rb +93 -0
  178. data/app/renderers/agile_renderer.rb +59 -0
  179. data/app/renderers/ar_ad_renderer.rb +219 -0
  180. data/app/renderers/ar_captcha_renderer.rb +113 -0
  181. data/app/renderers/ar_common_renderer.rb +90 -0
  182. data/app/renderers/ar_gallery_renderer.rb +107 -0
  183. data/app/renderers/ar_menu_renderer.rb +195 -0
  184. data/app/renderers/ar_page_renderer.rb +147 -0
  185. data/app/renderers/ar_part_renderer.rb +235 -0
  186. data/app/renderers/ar_piece_renderer.rb +119 -0
  187. data/app/renderers/ar_poll_renderer.rb +272 -0
  188. data/app/views/agile/_edit_stuff.html.erb +57 -0
  189. data/app/views/agile/_form.html.erb +24 -0
  190. data/app/views/agile/_result.html.erb +28 -0
  191. data/app/views/agile/edit.html.erb +13 -0
  192. data/app/views/agile/error.html.erb +2 -0
  193. data/app/views/agile/index.html.erb +14 -0
  194. data/app/views/agile/login.html.erb +19 -0
  195. data/app/views/agile/new.html.erb +12 -0
  196. data/app/views/agile_common/_help.html.erb +18 -0
  197. data/app/views/agile_common/_iframe_edit.html.erb +2 -0
  198. data/app/views/agile_common/paste_clipboard.html.erb +17 -0
  199. data/app/views/layouts/agile.html.erb +17 -0
  200. data/app/views/layouts/content.html.erb +20 -0
  201. data/app/views/models/dump_models.html.erb +47 -0
  202. data/config/initializers/kaminari_patch.rb +56 -0
  203. data/config/locales/agile_de.yml +138 -0
  204. data/config/locales/agile_en.yml +162 -0
  205. data/config/locales/agile_sl.yml +163 -0
  206. data/config/locales/datetimepicker.yml +19 -0
  207. data/config/locales/de.yml +231 -0
  208. data/config/locales/en.yml +13 -0
  209. data/config/locales/kaminari.yml +26 -0
  210. data/config/locales/models_en.yml +1032 -0
  211. data/config/locales/models_sl.yml +1065 -0
  212. data/config/locales/sl.yml +211 -0
  213. data/db/migrate/20240120160001_add_sessions_table.rb +12 -0
  214. data/db/migrate/20240120160002_ar_big_table.rb +17 -0
  215. data/db/migrate/20240120160003_ar_big_table_value.rb +18 -0
  216. data/db/migrate/20240120160004_ar_category.rb +22 -0
  217. data/db/migrate/20240120160005_ar_design.rb +20 -0
  218. data/db/migrate/20240120160006_ar_filter.rb +17 -0
  219. data/db/migrate/20240120160007_ar_gallery.rb +21 -0
  220. data/db/migrate/20240120160008_ar_journal.rb +19 -0
  221. data/db/migrate/20240120160009_ar_key_value_store.rb +11 -0
  222. data/db/migrate/20240120160010_ar_link.rb +19 -0
  223. data/db/migrate/20240120160011_ar_memory.rb +8 -0
  224. data/db/migrate/20240120160012_ar_menu.rb +21 -0
  225. data/db/migrate/20240120160013_ar_menu_item.rb +28 -0
  226. data/db/migrate/20240120160014_ar_page.rb +50 -0
  227. data/db/migrate/20240120160015_ar_part.rb +33 -0
  228. data/db/migrate/20240120160016_ar_permission.rb +16 -0
  229. data/db/migrate/20240120160017_ar_permission_rule.rb +17 -0
  230. data/db/migrate/20240120160018_ar_piece.rb +28 -0
  231. data/db/migrate/20240120160019_ar_policy.rb +21 -0
  232. data/db/migrate/20240120160020_ar_policy_rule.rb +18 -0
  233. data/db/migrate/20240120160021_ar_poll.rb +27 -0
  234. data/db/migrate/20240120160022_ar_poll_item.rb +23 -0
  235. data/db/migrate/20240120160023_ar_poll_result.rb +14 -0
  236. data/db/migrate/20240120160024_ar_removed_url.rb +16 -0
  237. data/db/migrate/20240120160025_ar_role.rb +17 -0
  238. data/db/migrate/20240120160026_ar_site.rb +37 -0
  239. data/db/migrate/20240120160027_ar_temp.rb +11 -0
  240. data/db/migrate/20240120160028_ar_user.rb +42 -0
  241. data/db/migrate/20240120160029_ar_user_group.rb +12 -0
  242. data/db/migrate/20240120160030_ar_user_role.rb +18 -0
  243. data/db/migrate/20240120160031_ar_visit.rb +15 -0
  244. data/db/migrate/20240703016001_ar_setup.rb +16 -0
  245. data/db/migrate/20240703016002_ar_folder_permission.rb +15 -0
  246. data/db/migrate/20240703016003_ar_folder_rule.rb +14 -0
  247. data/db/migrate/20250115000001_ar_image.rb +25 -0
  248. data/lib/agile/configuration.rb +43 -0
  249. data/lib/agile/engine.rb +29 -0
  250. data/lib/agile/version.rb +27 -0
  251. data/lib/agile.rb +282 -0
  252. data/lib/agile_rails.rb +1 -0
  253. data/lib/generators/agile/USAGE +11 -0
  254. data/lib/generators/agile/new_form_generator.rb +369 -0
  255. data/lib/generators/convert_to_ar/convert_to_ar_generator.rb +158 -0
  256. data/lib/tasks/agile_db_clone.rake +132 -0
  257. data/lib/tasks/agile_db_export_to_yaml.rake +37 -0
  258. data/lib/tasks/agile_db_migrate.rake +35 -0
  259. metadata +414 -0
@@ -0,0 +1,735 @@
1
+ #--
2
+ # Copyright (c) 2024+ Damjan Rems
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # "Software"), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+ #+
23
+
24
+ ##########################################################################
25
+ # AgileApplicationController holds methods which are useful for all
26
+ # application controllers.
27
+ ##########################################################################
28
+ class AgileApplicationController < ActionController::Base
29
+ protect_from_forgery with: :null_session, only: Proc.new { _1.request.format.json? }
30
+ before_action :agile_set_locale
31
+
32
+ ########################################################################
33
+ # Writes anything passed as parameter to logger file.
34
+ # Very useful for debuging strange errors.
35
+ #
36
+ # @param [Objects] args any parameter can be passed
37
+ ########################################################################
38
+ def agile_dump(*args)
39
+ args.each do |arg|
40
+ logger.info arg.to_s
41
+ end
42
+ end
43
+
44
+ ####################################################################
45
+ # Return true if CMS is in edit mode
46
+ #
47
+ # @return [Boolean] True if user CMS edit mode is selected
48
+ ####################################################################
49
+ def agile_edit_mode?
50
+ session[:edit_mode].to_i > 1
51
+ end
52
+
53
+ ####################################################################
54
+ # Checks if user has required role.
55
+ #
56
+ # @param [ArRole or String] role can be passed as ArRole object or
57
+ # as role name. If passed as name, ar_policy_roles is searched for appropriate role.
58
+ #
59
+ # @return [Boolean] True if user has required role added to his profile.
60
+ #
61
+ # @example If user has required role
62
+ # if agile_user_has_role?('admin') ...
63
+ # if agile_user_has_role?('Site editors') ...
64
+ ####################################################################
65
+ def agile_user_has_role?(role)
66
+ role = ArRole.get_role(role)
67
+ return false if role.nil? || session[:user_roles].nil?
68
+ # role exists in user_roles
69
+ session[:user_roles].include?(role.id)
70
+ end
71
+
72
+ ####################################################################
73
+ # Determines site from url and returns site record.
74
+ #
75
+ # @return [ArSite] site record. If site is not found and not in production environment,
76
+ # 'development' record is returned. If site record has alias set then alias site record is
77
+ # returned.
78
+ #
79
+ # @example Returns Google analytics code from site settings
80
+ # settings = agile_get_site.params['ga_acc']
81
+ ####################################################################
82
+ def agile_get_site
83
+ return @site if @site
84
+
85
+ uri = URI.parse(request.url)
86
+ cache_key = ['ar_site', uri.host]
87
+ @site = Agile.cache_read(cache_key)
88
+ return @site if @site
89
+
90
+ @site = ArSite.find_by(name: uri.host)
91
+ # Site can be aliased
92
+ if @site&.alias_for.present?
93
+ @site = ArSite.find_by(name: @site.alias_for)
94
+ end
95
+ # Development environment. Check if site with name development exists and use
96
+ # alias_for as pointer to our site.
97
+ if @site.nil? && !Rails.env.production?
98
+ @site = ArSite.find_by(name: 'development')
99
+ @site = ArSite.find_by(name: @site.alias_for) if @site
100
+ end
101
+ @site = nil unless @site&.active # might be disabled
102
+ Agile.cache_write(cache_key, @site)
103
+ end
104
+
105
+ ##########################################################################
106
+ # Will set page title according to data on ar_page or ar_site
107
+ #
108
+ # Sets internal @page_title variable.
109
+ ##########################################################################
110
+ def set_page_title
111
+ @page_title = @page.title.blank? ? @page.subject : @page.title
112
+ agile_add_meta_tag(:name, 'description', @page.meta_description)
113
+ end
114
+
115
+ #######################################################################
116
+ # Will render public/404.html file with some debug code includded.
117
+ #
118
+ # @param [Object] Object where_the_error_is. Additional data can be displayed with error.
119
+ #
120
+ # @example Render error
121
+ # site = agile_get_site()
122
+ # return agile_render_404('Site') unless site
123
+ ########################################################################
124
+ def agile_render_404(where_the_error_is=nil)
125
+ logger.info("Error 404;#{request.env['REQUEST_URI'] rescue ''};#{request.referer};#{where_the_error_is}")
126
+ render(file: Rails.root.join('public/404.html'), status: 404)
127
+ end
128
+
129
+ ########################################################################
130
+ # Will write record to ar_visits collection unless visit comes from robot.
131
+ # It also sets session[is_robot] variable to true if robot.
132
+ ########################################################################
133
+ def agile_visit_log
134
+ if request.env["HTTP_USER_AGENT"] and request.env["HTTP_USER_AGENT"].match(/\(.*https?:\/\/.*\)/)
135
+ logger.info "ROBOT: #{Time.now.strftime('%Y.%m.%d %H:%M:%S')} id=#{@page.id} ip=#{request.remote_ip}."
136
+ session[:is_robot] = true
137
+ else
138
+ ArVisit.create(site_id: @site.id,
139
+ user_id: session[:user_id],
140
+ page_id: @page.id,
141
+ ip: request.remote_ip,
142
+ session_id: request.session_options[:id],
143
+ time: Time.now )
144
+ end
145
+ end
146
+
147
+ ##########################################################################
148
+ # This is default page process action. It will search for site, page and
149
+ # design records, collect parameters from different objects, add CMS edit code if allowed
150
+ # and at the end render design.body or design.rails_view or site.rails_view.
151
+ #
152
+ # @example as defined in routes.rb
153
+ # get '*path' => 'agileapplication_controller#agileprocess_default_request'
154
+ # # or
155
+ # get '*path' => 'my_controller#page'
156
+ # # then in my_controller.rb
157
+ # def page
158
+ # agileprocess_default_request
159
+ # end
160
+ ##########################################################################
161
+ def agile_process_default_request
162
+ session[:edit_mode] ||= 0
163
+ # Initialize parts
164
+ @parts = nil
165
+ @js, @css = '', ''
166
+ # find domain name in sites
167
+ @site = agile_get_site
168
+ # site not defined. render 404 error
169
+ return agile_render_404('Site!') if @site.nil?
170
+
171
+ agile_options_set(@site.settings)
172
+ # HOMEPAGE. When no parameters is set
173
+ params[:path] = @site.homepage_link if params[:id].nil? && params[:path].nil?
174
+ @options[:path] = params[:path].to_s.downcase.split('/')
175
+ params[:path] = @options[:path].first if @options[:path].size > 1
176
+ # some other process request. It should fail if not defined
177
+ return send(@site.request_processor) unless @site.request_processor.blank?
178
+
179
+ # Search for page
180
+ page_class = @site.page_klass
181
+ if params[:id]
182
+ @page = page_class.find_by(ar_site_id: [@site.id, nil], link: params[:id], active: true)
183
+ @page = page_class.find(params[:id]) if @page.nil? # there will be more link searchers than by id
184
+ elsif params[:path]
185
+ # path may point direct to page's link
186
+ @page = page_class.find_by( :ar_site_id => [@site.id, nil], link: params[:path], active: true)
187
+ if @page.nil?
188
+ # no. Find if defined in links
189
+ if (link = ArLink.find_by( :ar_site_id => [@site.id, nil], link: params[:path]))
190
+ if link.page_id
191
+ agile_options_set link.params
192
+ @page = page_class.find(link.page_id)
193
+ else
194
+ redirect_to(link.redirect, allow_other_host: true) and return
195
+ end
196
+ end
197
+ end
198
+ end
199
+ # if @page is not found render 404 error
200
+ return agile_render_404('Page!') unless @page
201
+
202
+ agile_mobile_set unless session[:is_mobile] # do it only once per session
203
+ # find design if defined. Otherwise design MUST be declared in site
204
+ if @page.ar_design_id
205
+ @design = ArDesign.find(@page.ar_design_id)
206
+ return agile_render_404('Design!') unless @design
207
+ end
208
+ agile_options_set(@design.params) if @design
209
+ agile_options_set(@page.params)
210
+ #agile_add_json_ld(@page.get_json_ld)
211
+ # Add edit menu
212
+ if session[:edit_mode] > 0
213
+ session[:site_id] = @site.id
214
+ session[:site_page_class] = @site.page_class
215
+ session[:page_id] = @page.id
216
+ else
217
+ # Log visits from non-editors
218
+ #agile_visit_log()
219
+ end
220
+ set_page_title()
221
+ agile_render_design(@design)
222
+ end
223
+
224
+ protected
225
+
226
+ ###########################################################################
227
+ # Checks if user can perform (read, create, edit, delete) record in specified table.
228
+ #
229
+ # @param [Integer] permission: Required permission level
230
+ # @param [String] table: Collection (table) name for which permission is queried. Defaults to params[table].
231
+ #
232
+ # @return [Boolean] true if user's role permits (is higher or equal then required) operation on a table (table).
233
+ #
234
+ # @Example True when user has view permission on the table
235
+ # if agile_user_can(ArPermission::CAN_VIEW, params[:table]) then ...
236
+ ############################################################################
237
+ def agile_user_can(permission, table = AgileHelper.table_param(params))
238
+ table = table.underscore
239
+ cache_key = ['ar_permission', table, session[:user_id], agile_get_site.id]
240
+ permissions = Agile.cache_read(cache_key) { ArPermission.permissions_for_table(table) }
241
+ session[:user_roles].find { permissions[_1] && permissions[_1] >= permission }
242
+ end
243
+
244
+ ####################################################################
245
+ # Detects if called from mobile agent according to http://detectmobilebrowsers.com/
246
+ # and set session[:is_mobile]
247
+ #
248
+ # Detect also if caller is a robot and set session[:is_robot]
249
+ ####################################################################
250
+ def agile_mobile_set
251
+ 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])
252
+ : false
253
+ session[:is_mobile] = is_mobile ? 1 : 0
254
+
255
+ if request.env["HTTP_USER_AGENT "] && request.env["HTTP_USER_AGENT"].match(/\(.*https?:\/\/.*\)/)
256
+ logger.info "ROBOT: #{Time.now.strftime('%Y.%m.%d %H:%M:%S')} id=#{@page.id} ip=#{request.remote_ip}."
257
+ session[:is_robot] = true
258
+ end
259
+ end
260
+
261
+ ##########################################################################
262
+ # Merge values from parameters fields (from site, page ...) into internal @options hash.
263
+ #
264
+ # @param [String] parameters: passed as YAML string.
265
+ ##########################################################################
266
+ def agile_options_set(parameters)
267
+ @options ||= {}
268
+ return if parameters.to_s.size < 3
269
+ # parameters are set as YAML. This should be default in future.
270
+ parms = YAML.load(parameters) rescue {}
271
+ @options = @options.deep_merge(parms) if parms.present?
272
+ end
273
+
274
+ ##########################################################################
275
+ # Check if record(s) has been modified since last visit. It turned out that caching
276
+ # is not that simple and that there are multiple caching scenarios that can be used.
277
+ # So this code is here just for a example, how records can be checked for changed status.
278
+ #
279
+ # @param [records] List of records which are checked against last visit date
280
+ #
281
+ # @return [Boolean] true when none of documents is changed.
282
+ ##########################################################################
283
+ def agile_not_modified?(*records)
284
+ return false unless request.env.include? 'HTTP_IF_MODIFIED_SINCE'
285
+
286
+ since_date = Time.parse request.env['HTTP_IF_MODIFIED_SINCE']
287
+ last_modified = since_date
288
+ records.each do |record|
289
+ next unless record.respond_to?(:updated_at)
290
+ last_modified = record.updated_at if record.updated_at > last_modified
291
+ end
292
+
293
+ if last_modified >= since_date then
294
+ render :nothing => true, :status => 304
295
+ return true
296
+ end
297
+ false
298
+ end
299
+
300
+ ##########################################################################
301
+ # Will determine design content or view filename which defines design.
302
+ #
303
+ # Returns:
304
+ # design_body: design body as defined in site or design record.
305
+ # design_view: view file name which will be used for rendering design
306
+ ##########################################################################
307
+ def agile_render_design(design_record)
308
+ layout = @site.site_layout.blank? ? 'content' : @site.site_layout
309
+ site_top = '<%= agile_page_top %>'
310
+ site_bottom = '<%= agile_page_bottom %>'
311
+ # the rails way
312
+ if @options[:control] && @options[:action]
313
+ controller = "#{@options[:control]}_control".classify.constantize rescue nil
314
+ extend controller if controller
315
+ return send @options[:action] if respond_to?(@options[:action])
316
+ end
317
+ # design record present
318
+ if design_record
319
+ # defined as rails view
320
+ design = if design_record.rails_view.blank? || design_record.rails_view == 'site'
321
+ @site.rails_view
322
+ else
323
+ design_record.rails_view
324
+ end
325
+ return render design, layout: layout unless design.blank?
326
+ # defined as inline code
327
+ design = design_record.body.blank? ? @site.design : design_record.body
328
+ design = site_top + design + site_bottom
329
+ return render(inline: design, layout: layout) unless design.blank?
330
+ end
331
+ # Design record not defined
332
+ if @site.rails_view.blank?
333
+ design = site_top + @site.design + site_bottom
334
+ render(inline: design, layout: layout)
335
+ else
336
+ render @site.rails_view, layout: layout
337
+ end
338
+ end
339
+
340
+ ########################################################################
341
+ # Decamelize string. Does opposite of camelize method. It probably doesn't work
342
+ # very good with non ascii chars. Since this method is used for converting from model
343
+ # to collection names it is very unwise to use non ascii chars for table (table) names.
344
+ #
345
+ # @param [Object] model_string to be converted
346
+ #
347
+ # @example
348
+ # decamelize_type(ModelName) # 'ModelName' => 'model_name'
349
+ ########################################################################
350
+ def decamelize_type(model_string)
351
+ model_string ? model_string.to_s.underscore : nil
352
+ end
353
+
354
+ ####################################################################
355
+ # Return's error messages for the document formated for display on edit form.
356
+ #
357
+ # @param [Document] document object which will be examined for errors.
358
+ #
359
+ # @return [String] HTML code for displaying error on edit form.
360
+ ####################################################################
361
+ def agile_error_messages_for(document)
362
+ return '' unless document.errors.any?
363
+
364
+ msg = document.errors.inject('') do |r, error|
365
+ label = t("helpers.label.#{decamelize_type(document.class)}.#{error.attribute}")
366
+ label = error.attribute if label.match( /translation missing/i )
367
+ r += "<li>#{label} : #{error.message}</li>"
368
+ end
369
+
370
+ %(
371
+ <div class="ar-form-error">
372
+ <h2>#{t('agile.errors_no')} #{document.errors.size}</h2>
373
+ <ul>#{msg}</ul>
374
+ </div>).html_safe
375
+ end
376
+
377
+ ######################################################################
378
+ # Call rake task from controller.
379
+ #
380
+ # @param [String] task: Arke task name
381
+ # @param [Hash] options: Options that will be send to task as environment variables
382
+ #
383
+ # @example Call rake task from application
384
+ # agile_call_rake('clear:all', some_parm: some_id)
385
+ ######################################################################
386
+ def agile_call_rake(task, options = {})
387
+ options[:rails_env] ||= Rails.env
388
+ args = options.map { |o, v| "#{o.to_s.upcase}='#{v}'" }
389
+ system "rake #{task} #{args.join(' ')} --trace 2>&1 >> #{Rails.root}/log/rake.log &"
390
+ end
391
+
392
+ ######################################################################
393
+ # A helper for rendering ajax return code from controller. When ajax call is
394
+ # made from Agile form return may be quite complicated. All ajax return combinations
395
+ # can be found in agile.js file.
396
+ #
397
+ # @param [Hash] opts: Options
398
+ #
399
+ # @return [JSON Response] Formatted to be used for ajax return.
400
+ #
401
+ # @example
402
+ # html_code = '<span>Some text</span>'
403
+ # agile_render_ajax(div: 'mydiv', prepand: html_code) # Will prepand code to mydiv div
404
+ # agile_render_ajax(class: 'myclass', append: html_code) # Will append code to all objects with myclass class
405
+ # agile_render_ajax(operation: 'window', value: "/pdf_file.pdf") # will open pdf file in new window.
406
+ #
407
+ ######################################################################
408
+ def agile_render_ajax(opts)
409
+ result = {}
410
+ if opts[:div] || opts[:class]
411
+ selector = opts[:div] ? '#' : '.' # for div . for class
412
+ key = case
413
+ when opts[:prepend] then "#{selector}+div"
414
+ when opts[:append] then "#{selector}div+"
415
+ else "#{selector}div"
416
+ end
417
+ key += "_#{opts[:div]}#{opts[:class]}"
418
+ else
419
+ logger.error 'Error: agile_render_ajax. Operation is not set!' if opts[:operation].nil?
420
+ key = "#{opts[:operation]}_"
421
+ end
422
+ result[key] = opts[:value] || opts[:url] || ''
423
+ render json: result
424
+ end
425
+
426
+ ########################################################################
427
+ # Find document by parameters. This is how AgileRails finds document based on url parameters.
428
+ #
429
+ # @param [String] Table name. Could be ar_page;ar_part;... when searching for embedded document.
430
+ # @param [String] Id of the document
431
+ # @param [String] Ids of parent documents when document is embedded. Ids are separated by ; char.
432
+ #
433
+ # @return [document]. Required document or nil if not found.
434
+ #
435
+ # @example As used in agile_controller
436
+ # agile_document_find(params[:table], params[:id])
437
+ ########################################################################
438
+ def agile_document_find(table, id)
439
+ table.classify.constantize.find(id)
440
+ end
441
+
442
+ ########################################################################
443
+ # Reload patches in development. Since patching files are not automatically loaded in
444
+ # development environment this little method automatically reloads all patch files
445
+ # found in Agile.paths(:patches) path array.
446
+ ########################################################################
447
+ def agile_reload_patches
448
+ Agile.paths(:patches).each do |patches|
449
+ Dir["#{patches}/**/*.rb"].each { |file| require_dependency(file) }
450
+ end
451
+ end
452
+
453
+ ########################################################################
454
+ # Will set new default locale for application
455
+ #
456
+ # @param [String] new_locale : New locale value. If omitted it will be provided from params[:locale].
457
+ # if new_locale value is blank, application's default_locale will be used.
458
+ ########################################################################
459
+ def agile_set_locale(new_locale = params[:locale])
460
+ if new_locale && new_locale != session[:locale]
461
+ session[:locale] = new_locale.blank? ? nil : new_locale.to_sym
462
+ end
463
+ I18n.locale = session[:locale] || I18n.default_locale
464
+ end
465
+
466
+ ############################################################################
467
+ # Writes out deprication msg. It also adds site_name to message, so it is easier to
468
+ # find where the message is comming from.
469
+ ############################################################################
470
+ def agile_deprecate(msg)
471
+ ActiveSupport::Deprecation.warn("#{ agile_get_site.name}: #{msg}")
472
+ end
473
+
474
+ ####################################################################
475
+ # Clears all session data related to login.
476
+ ####################################################################
477
+ def clear_login_data
478
+ session[:edit_mode] = 0
479
+ session[:user_id] = nil
480
+ session[:user_name] = nil
481
+ session[:user_roles] = []
482
+ set_default_guest_user_role
483
+ cookies.delete :remember_me
484
+ end
485
+
486
+ ############################################################################
487
+ # Sets at least default guest user to user roles when no user is set.
488
+ ############################################################################
489
+ def set_default_guest_user_role
490
+ guest = ArRole.get_role('guest')
491
+ session[:user_roles] = [guest.id] if guest
492
+ end
493
+
494
+ ####################################################################
495
+ # Fills session with data related to successful login.
496
+ #
497
+ # @param [ArUser] user : User's document
498
+ # @param [Boolean] remember_me : false by default
499
+ ####################################################################
500
+ def set_login_data(user, remember_me = false)
501
+ clear_login_data
502
+ return unless user&.active
503
+
504
+ session[:user_id] = user.id
505
+ session[:user_name] = user.name.squish
506
+ # special for SUPERADMIN
507
+ sa = ArRole.get_role('superadmin')
508
+ if sa && user.has_role?(sa.id)
509
+ session[:user_roles] << sa.id
510
+ session[:edit_mode] = 2
511
+ return
512
+ end
513
+
514
+ # read default policy from site. Policy might be inherited from other site
515
+ site = agile_get_site()
516
+ site = ArSite.find(policy_site.inherit_policy) if site.inherit_policy
517
+ default_policy = site.default_policy
518
+
519
+ # select only roles defined in default site policy and set edit_mode
520
+ user.roles.each do |role_id|
521
+ # check if role is active in this site
522
+ policy_role = default_policy.find { |role| role.ar_role_id == role_id }
523
+ next unless policy_role&.active
524
+ # set edit_mode
525
+ session[:edit_mode] = 1 if policy_role.permission > 1
526
+ session[:user_roles] << role_id
527
+ end
528
+
529
+ # Save remember me cookie if user doesn't have editor rights
530
+ if session[:edit_mode] == 0 && remember_me
531
+ cookies.signed[:remember_me] = { value: user.id, expires: 180.days.from_now }
532
+ end
533
+ end
534
+
535
+ ##########################################################################
536
+ # Will check if user's login data is still valid and reload user roles.
537
+ #
538
+ # @param [Time] repeat_after : Check is repeated after time. This is by default performed every 24 hours.
539
+ ##########################################################################
540
+ def agile_user_rights_check(repeat_after = 1.day)
541
+ return if session[:user_id].nil?
542
+ # last check more than repeat_after ago
543
+ if (session[:user_chk] ||= Time.now) < repeat_after.ago
544
+ user_id = session[:user_id]
545
+ clear_login_data()
546
+ # reload user roles
547
+ user = ArUser.find( user_id ) rescue nil
548
+ set_login_data(user)
549
+ session[:user_chk] = Time.now
550
+ end
551
+ end
552
+
553
+ ##########################################################################
554
+ # Evaluates Class.method in more predictable context then just calling eval
555
+ #
556
+ # @param [String] class_method defined as MyClass.method_name
557
+ # @param [Object] params: optional parameters send to class_method
558
+ ##########################################################################
559
+ def agile_class_method_eval(class_method, params = nil)
560
+ klass, method = class_method.split('.')
561
+ # check if class exists
562
+ klass = klass.classify.constantize rescue nil
563
+ if klass.nil?
564
+ logger.error " Class in #{class_method} not defined!"
565
+ return nil
566
+ end
567
+ # call method
568
+ if klass.respond_to?(method)
569
+ klass.send(method, params)
570
+ else
571
+ logger.error "Method in #{class_method} not defined!"
572
+ nil
573
+ end
574
+ end
575
+
576
+ ##########################################################################
577
+ # Will add new element to json_ld structure
578
+ #
579
+ # Parameters:
580
+ # [element] Hash or Array of hashes:
581
+ ##########################################################################
582
+ def agile_add_json_ld(element)
583
+ @json_ld ||= []
584
+ if element.class == Array
585
+ @json_ld += element
586
+ else
587
+ @json_ld << element
588
+ end
589
+ end
590
+
591
+ ########################################################################
592
+ # Will add a meta tag to internal hash structure. If meta tag already exists it
593
+ # will be overwritten.
594
+ #
595
+ # Parameters:
596
+ # [name] String: meta name
597
+ # [content] String: meta content
598
+ #
599
+ ########################################################################
600
+ def agile_add_meta_tag(type, name, content)
601
+ return if content.blank?
602
+
603
+ @meta_tags ||= {}
604
+ key = "#{type}=\"#{name}\""
605
+ @meta_tags[key] = content
606
+ end
607
+
608
+ ########################################################################
609
+ # Will prepare flash[:update] which is used for updating elements on parent form.
610
+ #
611
+ # Parameters passed as hash:
612
+ # [field] String: Field name
613
+ # [head] String: Field name to be updated in head of form
614
+ # [value] String: New value
615
+ # [readonly] Boolean: Field is readonly
616
+ #
617
+ ########################################################################
618
+ def agile_update_form_element(field: nil, head: nil, value:, readonly: true)
619
+ key = if field
620
+ (readonly ? 'td_' : '') + "record_#{field}"
621
+ elsif head
622
+ "head-#{head}"
623
+ end
624
+ return if key.nil?
625
+
626
+ flash[:update] ||= {}
627
+ flash[:update][key] = value
628
+ end
629
+
630
+ private
631
+
632
+ ########################################################################
633
+ # Extends AgileRails form file. Extended file is processed first and then merged
634
+ # with code in current form file.
635
+ #
636
+ # Form can extend more than one form file. If so, form names must then be delimited with comma.
637
+ #
638
+ # [Parameters:]
639
+ # [extend_option] : Value of @form['extend'] option
640
+ ########################################################################
641
+ def agile_form_extend(extend_option)
642
+ extend_option.chomp.split(',').each do |a_file|
643
+ form_file_name = AgileHelper.form_file_find(a_file.strip)
644
+ @form_js += form_read_js(form_file_name)
645
+ form = YAML.load_file( form_file_name )
646
+ @form = AgileHelper.forms_merge(form, @form)
647
+ # If combined form contains tabs and fields options, move fields into fields tab
648
+ if @form.dig('form', 'tabs') && @form.dig('form', 'fields')
649
+ @form['form']['tabs']['fields'] = @form['form']['fields']
650
+ @form['form']['fields'] = nil
651
+ end
652
+ end
653
+ end
654
+
655
+ ########################################################################
656
+ # Include code from another AgileRails form file. Included code is merged
657
+ # with current form file code. Form can include more than one AgileRails forms. If so, form names must
658
+ # be delimited with comma.
659
+ #
660
+ # [Parameters:]
661
+ # [include_option] : Value of @form['include'] option
662
+ ########################################################################
663
+ def agile_form_include(include_option)
664
+ includes = include_option.class == Array ? include_option : include_option.split(/\,|\;/)
665
+ includes.each do |include_file|
666
+ form_file_name = AgileHelper.form_file_find(include_file)
667
+ @form_js += form_read_js(form_file_name)
668
+ form = YAML.load_file(form_file_name)
669
+ @form = AgileHelper.forms_merge(@form, form)
670
+ end
671
+ end
672
+
673
+ ########################################################################
674
+ # Will read data from form_file_name.js if exists.
675
+ #
676
+ # [Parameters:]
677
+ # [form_file_name] : Physical form filename
678
+ ########################################################################
679
+ def form_read_js(form_file_name)
680
+ js_form_file_name = form_file_name.sub('.yml', '.js')
681
+ File.exist?(js_form_file_name) ? File.read(js_form_file_name) : ''
682
+ end
683
+
684
+ ########################################################################
685
+ # Read AgileRails form into @form object. Subroutine of authorization_check
686
+ ########################################################################
687
+ def agile_form_read
688
+ params[:table] ||= params[:t] || AgileHelper.form_param(params)
689
+ table_name = decamelize_type(AgileHelper.table_param(params).strip)
690
+ @tables = table_name.split(';').map{ [(_1.classify.constantize rescue nil), _1] }
691
+
692
+ # split ids passed when embedded document
693
+ @ids = params[:ids].to_s.strip.downcase.split(';')
694
+
695
+ # form_name defaults to last table specified
696
+ form_name = AgileHelper.form_param(params) || @tables.last[1]
697
+ @form_js = ''
698
+
699
+ # dynamically generated form
700
+ @form = if AgileHelper.form_param(params) == 'method'
701
+ agile_class_method_eval(params[:form_method], params)
702
+ else
703
+ form_file_name = AgileHelper.form_file_find(form_name)
704
+ @form_js = form_read_js(form_file_name)
705
+ YAML.load_file(form_file_name)
706
+ end
707
+
708
+ # form includes or extends another form file
709
+ agile_form_include(@form['include']) if @form['include']
710
+ agile_form_extend(@form['extend']) if @form['extend']
711
+ @form['script'] = @form['script'].to_s + @form_js
712
+ # add readonly key to form if readonly parameter is passed in url
713
+ @form['readonly'] = 1 if params['readonly']
714
+
715
+ # !!!!!! Always use strings for key names since @form_params['table'] != @form_params[:table]
716
+ @form_params = { 'table' => table_name, 'ids' => params[:ids], 'form_name' => form_name,
717
+ 'return_to' => params['return_to'], 'edit_only' => params['edit_only'],
718
+ 'readonly' => params['readonly'], 'window_close' => params['window_close'],
719
+ 'belongs_to' => params[:belongs_to], 'belongs_to_id' => params[:belongs_to_id]
720
+ }
721
+ end
722
+
723
+ ########################################################################
724
+ # Will search for help file and return it's full path name if found.
725
+ ########################################################################
726
+ def self.find_help_file(help_file_name)
727
+ file_name = nil
728
+ Agile.paths(:forms).reverse.each do |path|
729
+ f = "#{path}/help/#{help_file_name}.#{I18n.locale}"
730
+ file_name = f and break if File.exist?(f)
731
+ end
732
+ file_name
733
+ end
734
+
735
+ end