camaleon_cms 2.9.2 → 2.9.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +17 -4
- data/Rakefile +3 -16
- data/app/apps/plugins/attack/admin_controller.rb +9 -6
- data/app/apps/plugins/attack/attack_helper.rb +35 -25
- data/app/apps/plugins/authoring_post/authoring_post_helper.rb +23 -16
- data/app/apps/plugins/front_cache/admin_controller.rb +14 -10
- data/app/apps/plugins/front_cache/config/initializer.rb +1 -1
- data/app/apps/plugins/front_cache/config/locales/translation.yml +0 -7
- data/app/apps/plugins/front_cache/front_cache_helper.rb +109 -37
- data/app/apps/plugins/front_cache/views/admin/settings.html.erb +0 -5
- data/app/apps/plugins/visibility_post/config/config.json +1 -0
- data/app/apps/plugins/visibility_post/config/routes_front.txt +1 -0
- data/app/apps/plugins/visibility_post/front_controller.rb +23 -0
- data/app/apps/plugins/visibility_post/visibility_post_helper.rb +141 -70
- data/app/apps/themes/camaleon_first/main_helper.rb +18 -12
- data/app/apps/themes/default/assets/css/style.css.scss +24 -0
- data/app/apps/themes/default/assets/genericons/genericons.css +3 -8
- data/app/apps/themes/default/default_helper.rb +2 -1
- data/app/apps/themes/default/views/layouts/index.html.erb +3 -1
- data/app/apps/themes/new/assets/css/styles.css.scss +24 -0
- data/app/apps/themes/new/custom_helper.rb +5 -9
- data/app/apps/themes/new/views/layouts/_header.html.erb +3 -1
- data/app/assets/javascripts/camaleon_cms/admin/_data.js +16 -0
- data/app/assets/javascripts/camaleon_cms/admin/_post.js +5 -2
- data/app/assets/javascripts/camaleon_cms/admin/nav_menu.js +14 -3
- data/app/assets/javascripts/camaleon_cms/admin/uploader/_media_manager.js +5 -0
- data/app/controllers/camaleon_cms/admin/appearances/nav_menus_controller.rb +8 -6
- data/app/controllers/camaleon_cms/admin/appearances/themes_controller.rb +8 -5
- data/app/controllers/camaleon_cms/admin/appearances/widgets/assign_controller.rb +7 -2
- data/app/controllers/camaleon_cms/admin/appearances/widgets/main_controller.rb +2 -1
- data/app/controllers/camaleon_cms/admin/categories_controller.rb +19 -4
- data/app/controllers/camaleon_cms/admin/comments_controller.rb +0 -1
- data/app/controllers/camaleon_cms/admin/installers_controller.rb +32 -1
- data/app/controllers/camaleon_cms/admin/media_controller.rb +66 -14
- data/app/controllers/camaleon_cms/admin/plugins_controller.rb +1 -3
- data/app/controllers/camaleon_cms/admin/post_tags_controller.rb +10 -4
- data/app/controllers/camaleon_cms/admin/posts/drafts_controller.rb +40 -11
- data/app/controllers/camaleon_cms/admin/posts_controller.rb +55 -22
- data/app/controllers/camaleon_cms/admin/sessions_controller.rb +237 -44
- data/app/controllers/camaleon_cms/admin/settings/custom_fields_controller.rb +80 -13
- data/app/controllers/camaleon_cms/admin/settings/post_types_controller.rb +5 -2
- data/app/controllers/camaleon_cms/admin/settings/sites_controller.rb +26 -3
- data/app/controllers/camaleon_cms/admin/settings_controller.rb +5 -3
- data/app/controllers/camaleon_cms/admin/user_roles_controller.rb +7 -5
- data/app/controllers/camaleon_cms/admin/users_controller.rb +78 -11
- data/app/controllers/camaleon_cms/admin_controller.rb +136 -26
- data/app/controllers/camaleon_cms/camaleon_controller.rb +37 -92
- data/app/controllers/camaleon_cms/frontend_controller.rb +146 -74
- data/app/controllers/concerns/camaleon_cms/admin/custom_fields_concern.rb +20 -5
- data/app/controllers/concerns/camaleon_cms/frontend_concern.rb +46 -17
- data/app/controllers/concerns/camaleon_cms/frontend_visited_state_concern.rb +72 -0
- data/app/controllers/concerns/camaleon_cms/hook_lifecycle_concern.rb +104 -0
- data/app/controllers/concerns/camaleon_cms/request_context_concern.rb +113 -0
- data/app/controllers/concerns/camaleon_cms/runtime_admin_menu_concern.rb +237 -0
- data/app/controllers/concerns/camaleon_cms/runtime_captcha_image_concern.rb +13 -0
- data/app/controllers/concerns/camaleon_cms/runtime_html_content_concern.rb +143 -0
- data/app/controllers/concerns/camaleon_cms/runtime_shortcode_theme_concern.rb +246 -0
- data/app/controllers/concerns/camaleon_cms/runtime_state_concern.rb +13 -0
- data/app/controllers/concerns/camaleon_cms/runtime_uploader_concern.rb +54 -0
- data/app/controllers/concerns/camaleon_cms/session_captcha_runtime_concern.rb +19 -0
- data/app/controllers/concerns/camaleon_cms/session_runtime_concern.rb +40 -0
- data/app/decorators/camaleon_cms/application_decorator.rb +11 -8
- data/app/decorators/camaleon_cms/category_decorator.rb +3 -2
- data/app/decorators/camaleon_cms/post_comment_decorator.rb +13 -5
- data/app/decorators/camaleon_cms/post_decorator.rb +68 -50
- data/app/decorators/camaleon_cms/post_type_decorator.rb +1 -1
- data/app/decorators/camaleon_cms/site_decorator.rb +33 -25
- data/app/decorators/camaleon_cms/term_taxonomy_decorator.rb +21 -10
- data/app/decorators/camaleon_cms/theme_decorator.rb +3 -3
- data/app/decorators/camaleon_cms/user_decorator.rb +26 -5
- data/app/helpers/camaleon_cms/admin/application_helper.rb +5 -8
- data/app/helpers/camaleon_cms/admin/breadcrumb_helper.rb +1 -1
- data/app/helpers/camaleon_cms/admin/custom_fields_helper.rb +24 -23
- data/app/helpers/camaleon_cms/admin/menus_helper.rb +249 -139
- data/app/helpers/camaleon_cms/admin/post_type_helper.rb +34 -17
- data/app/helpers/camaleon_cms/camaleon_helper.rb +31 -39
- data/app/helpers/camaleon_cms/captcha_helper.rb +73 -53
- data/app/helpers/camaleon_cms/comment_helper.rb +19 -7
- data/app/helpers/camaleon_cms/content_helper.rb +13 -6
- data/app/helpers/camaleon_cms/email_helper.rb +7 -3
- data/app/helpers/camaleon_cms/frontend/application_helper.rb +6 -1
- data/app/helpers/camaleon_cms/frontend/content_select_helper.rb +34 -20
- data/app/helpers/camaleon_cms/frontend/nav_menu_helper.rb +143 -66
- data/app/helpers/camaleon_cms/frontend/seo_helper.rb +39 -28
- data/app/helpers/camaleon_cms/frontend/site_helper.rb +32 -12
- data/app/helpers/camaleon_cms/hooks_helper.rb +14 -4
- data/app/helpers/camaleon_cms/html_helper.rb +58 -37
- data/app/helpers/camaleon_cms/plugins_helper.rb +23 -24
- data/app/helpers/camaleon_cms/session_helper.rb +188 -44
- data/app/helpers/camaleon_cms/short_code_helper.rb +181 -85
- data/app/helpers/camaleon_cms/site_helper.rb +34 -13
- data/app/helpers/camaleon_cms/theme_helper.rb +35 -19
- data/app/helpers/camaleon_cms/uploader_helper.rb +19 -473
- data/app/helpers/camaleon_cms/user_roles_helper.rb +5 -4
- data/app/mailers/camaleon_cms/html_mailer.rb +4 -4
- data/app/models/camaleon_cms/ability.rb +15 -7
- data/app/models/camaleon_cms/category.rb +6 -6
- data/app/models/camaleon_cms/custom_field.rb +15 -6
- data/app/models/camaleon_cms/custom_field_group.rb +39 -22
- data/app/models/camaleon_cms/custom_fields_relationship.rb +140 -2
- data/app/models/camaleon_cms/media.rb +8 -2
- data/app/models/camaleon_cms/meta.rb +2 -2
- data/app/models/camaleon_cms/nav_menu.rb +5 -3
- data/app/models/camaleon_cms/nav_menu_item.rb +16 -8
- data/app/models/camaleon_cms/plugin.rb +3 -4
- data/app/models/camaleon_cms/post.rb +137 -27
- data/app/models/camaleon_cms/post_comment.rb +10 -6
- data/app/models/camaleon_cms/post_default.rb +42 -12
- data/app/models/camaleon_cms/post_relationship.rb +6 -4
- data/app/models/camaleon_cms/post_tag.rb +4 -5
- data/app/models/camaleon_cms/post_type.rb +21 -13
- data/app/models/camaleon_cms/site.rb +39 -29
- data/app/models/camaleon_cms/term_relationship.rb +10 -7
- data/app/models/camaleon_cms/term_taxonomy.rb +58 -4
- data/app/models/camaleon_cms/theme.rb +2 -4
- data/app/models/camaleon_cms/user.rb +17 -5
- data/app/models/camaleon_cms/user_role.rb +81 -6
- data/app/models/camaleon_cms/widget/assigned.rb +11 -6
- data/app/models/camaleon_cms/widget/main.rb +12 -8
- data/app/models/camaleon_cms/widget/sidebar.rb +3 -8
- data/app/models/camaleon_record.rb +89 -5
- data/app/models/concerns/camaleon_cms/categories_tags_for_posts.rb +36 -42
- data/app/models/concerns/camaleon_cms/common_relationships.rb +18 -5
- data/app/models/concerns/camaleon_cms/content_shortcode_gate.rb +73 -0
- data/app/models/concerns/camaleon_cms/custom_fields_read.rb +111 -54
- data/app/models/concerns/camaleon_cms/metas.rb +31 -6
- data/app/models/concerns/camaleon_cms/normalize_attrs.rb +2 -8
- data/app/models/concerns/camaleon_cms/site_default_settings.rb +120 -16
- data/app/models/concerns/camaleon_cms/user_methods.rb +44 -19
- data/app/models/current_request.rb +8 -1
- data/app/uploaders/camaleon_cms_aws_uploader.rb +31 -10
- data/app/uploaders/camaleon_cms_local_uploader.rb +76 -19
- data/app/uploaders/camaleon_cms_uploader.rb +23 -10
- data/app/validators/camaleon_cms/post_uniq_validator.rb +5 -4
- data/app/validators/camaleon_cms/uniq_validator.rb +1 -1
- data/app/validators/camaleon_cms/user_url_validator.rb +215 -36
- data/app/views/camaleon_cms/admin/categories/index.html.erb +2 -2
- data/app/views/camaleon_cms/admin/installers/form.html.erb +5 -0
- data/app/views/camaleon_cms/admin/installers/welcome.html.erb +30 -6
- data/app/views/camaleon_cms/admin/plugins/_plugins_list.html.erb +2 -2
- data/app/views/camaleon_cms/admin/post_tags/index.html.erb +2 -2
- data/app/views/camaleon_cms/admin/posts/_sidebar.html.erb +1 -1
- data/app/views/camaleon_cms/admin/posts/form.html.erb +3 -2
- data/app/views/camaleon_cms/admin/posts/index.html.erb +5 -5
- data/app/views/camaleon_cms/admin/sessions/back_to_parent.html.erb +39 -0
- data/app/views/camaleon_cms/admin/sessions/logout_confirm.html.erb +27 -0
- data/app/views/camaleon_cms/admin/settings/_email_settings.html.erb +4 -1
- data/app/views/camaleon_cms/admin/settings/custom_fields/_get_items.html.erb +1 -1
- data/app/views/camaleon_cms/admin/settings/custom_fields/_render.html.erb +19 -4
- data/app/views/camaleon_cms/admin/settings/custom_fields/_render_category_simple.html.erb +1 -1
- data/app/views/camaleon_cms/admin/settings/custom_fields/form.html.erb +4 -3
- data/app/views/camaleon_cms/admin/settings/shortcodes.html.erb +4 -4
- data/app/views/camaleon_cms/admin/settings/site.html.erb +1 -1
- data/app/views/camaleon_cms/admin/settings/sites/form.html.erb +1 -1
- data/app/views/camaleon_cms/admin/user_roles/form.html.erb +24 -3
- data/app/views/camaleon_cms/admin/users/form.html.erb +8 -4
- data/app/views/camaleon_cms/admin/users/index.html.erb +1 -1
- data/app/views/camaleon_cms/default_theme/partials/_render_custom_field.html.erb +8 -2
- data/app/views/camaleon_cms/default_theme/sitemap.html.erb +1 -1
- data/app/views/camaleon_cms/default_theme/sitemap.xml.builder +1 -1
- data/app/views/layouts/camaleon_cms/admin/_header.html.erb +1 -1
- data/config/initializers/action_view.rb +42 -5
- data/config/initializers/active_record_extension.rb +13 -27
- data/config/initializers/assets.rb +52 -23
- data/config/initializers/custom_initializers.rb +1 -1
- data/config/locales/camaleon_cms/admin/ar.yml +1 -0
- data/config/locales/camaleon_cms/admin/de.yml +1 -0
- data/config/locales/camaleon_cms/admin/en.yml +36 -0
- data/config/locales/camaleon_cms/admin/es.yml +1 -0
- data/config/locales/camaleon_cms/admin/fr.yml +1 -0
- data/config/locales/camaleon_cms/admin/it.yml +1 -0
- data/config/locales/camaleon_cms/admin/nl.yml +1 -0
- data/config/locales/camaleon_cms/admin/pt-BR.yml +1 -0
- data/config/locales/camaleon_cms/admin/pt.yml +1 -0
- data/config/locales/camaleon_cms/admin/ru.yml +1 -0
- data/config/locales/camaleon_cms/admin/uk.yml +1 -0
- data/config/locales/camaleon_cms/admin/zh-CH.yml +1 -0
- data/config/routes/admin.rb +33 -15
- data/config/routes/frontend.rb +21 -15
- data/lib/camaleon_cms/assets_precompile.rb +86 -0
- data/lib/camaleon_cms/captcha_image_generation.rb +65 -0
- data/lib/camaleon_cms/content_security.rb +158 -0
- data/lib/camaleon_cms/engine.rb +45 -21
- data/lib/camaleon_cms/media_security_headers.rb +27 -0
- data/lib/camaleon_cms/setup_token.rb +69 -0
- data/lib/camaleon_cms/shortcode_registry.rb +102 -0
- data/lib/camaleon_cms/svg_content_checker.rb +123 -0
- data/lib/camaleon_cms/task_reporter.rb +14 -0
- data/lib/camaleon_cms/unsafe_markup.rb +207 -0
- data/lib/camaleon_cms/uploader_content_security.rb +248 -0
- data/lib/camaleon_cms/uploader_image_processing.rb +166 -0
- data/lib/camaleon_cms/uploader_path_security.rb +146 -0
- data/lib/camaleon_cms/uploader_pipeline.rb +350 -0
- data/lib/camaleon_cms/uploader_support.rb +86 -0
- data/lib/camaleon_cms/version.rb +1 -1
- data/lib/camaleon_cms.rb +23 -0
- data/lib/ext/hash.rb +28 -2
- data/lib/ext/string.rb +10 -5
- data/lib/ext/translator.rb +10 -2
- data/lib/generators/camaleon_cms/gem_plugin_template/app/controllers/plugins/my_plugin/admin_controller.rb +5 -1
- data/lib/generators/camaleon_cms/install_generator.rb +7 -4
- data/lib/generators/camaleon_cms/install_template/plugin_routes.rb +5 -12
- data/lib/generators/camaleon_cms/theme_generator.rb +5 -10
- data/lib/generators/camaleon_cms/theme_template/views/layouts/index.html.erb +3 -1
- data/lib/plugin_routes.rb +412 -368
- data/lib/tasks/camaleon_cms/camaleon_tasks.rake +2 -1
- data/lib/tasks/cross_site_field_groups.rake +74 -0
- data/lib/tasks/custom_fields_roles.rake +15 -13
- data/lib/tasks/orphaned_comments.rake +42 -0
- data/lib/tasks/private_upload_acls.rake +31 -0
- data/lib/tasks/site_custom_field_groups.rake +36 -0
- data/lib/tasks/unsafe_stored_content.rake +42 -0
- data/lib/tasks/unsafe_stored_uploads.rake +70 -0
- data/lib/tasks/user_field_groups.rake +27 -0
- metadata +125 -4
data/lib/plugin_routes.rb
CHANGED
|
@@ -1,119 +1,33 @@
|
|
|
1
1
|
# frozen_string_literal: false
|
|
2
2
|
|
|
3
3
|
require 'json'
|
|
4
|
-
|
|
5
|
-
@@_vars = []
|
|
6
|
-
@@_after_reload = []
|
|
7
|
-
@@anonymous_hooks = {}
|
|
8
|
-
# load plugin routes if it is enabled
|
|
9
|
-
def self.load(env = 'admin')
|
|
10
|
-
plugins = all_enabled_plugins
|
|
11
|
-
res = ''
|
|
12
|
-
case env
|
|
13
|
-
when 'front'
|
|
14
|
-
res << "namespace :plugins do \n"
|
|
15
|
-
plugins.each do |plugin|
|
|
16
|
-
res << "namespace '#{plugin['key']}' do \n"
|
|
17
|
-
begin
|
|
18
|
-
res << "#{File.open(File.join(plugin['path'], 'config', "routes_#{env}.txt")).read}\n"
|
|
19
|
-
rescue StandardError
|
|
20
|
-
''
|
|
21
|
-
end
|
|
22
|
-
res << "end\n"
|
|
23
|
-
end
|
|
24
|
-
res << "end\n"
|
|
25
|
-
|
|
26
|
-
when 'admin' # admin
|
|
27
|
-
res << "scope 'admin', as: 'admin' do \n"
|
|
28
|
-
res << "namespace :plugins do \n"
|
|
29
|
-
plugins.each do |plugin|
|
|
30
|
-
res << "namespace '#{plugin['key']}' do \n"
|
|
31
|
-
begin
|
|
32
|
-
res << "#{File.open(File.join(plugin['path'], 'config', "routes_#{env}.txt")).read}\n"
|
|
33
|
-
rescue StandardError
|
|
34
|
-
''
|
|
35
|
-
end
|
|
36
|
-
res << "end\n"
|
|
37
|
-
end
|
|
38
|
-
res << "end\n"
|
|
39
|
-
res << "end\n"
|
|
40
|
-
else # main
|
|
41
|
-
plugins.each do |plugin|
|
|
42
|
-
res << "#{File.open(File.join(plugin['path'], 'config', "routes_#{env}.txt")).read}\n"
|
|
43
|
-
rescue StandardError
|
|
44
|
-
''
|
|
45
|
-
end
|
|
46
|
-
end
|
|
47
|
-
res + load_themes(env)
|
|
48
|
-
end
|
|
49
|
-
|
|
50
|
-
def self.load_themes(env = 'admin')
|
|
51
|
-
plugins = all_enabled_themes
|
|
52
|
-
res = ''
|
|
53
|
-
case env
|
|
54
|
-
when 'front'
|
|
55
|
-
res << "namespace :themes do \n"
|
|
56
|
-
plugins.each do |plugin|
|
|
57
|
-
res << "namespace '#{plugin['key']}' do \n"
|
|
58
|
-
begin
|
|
59
|
-
res << "#{File.open(File.join(plugin['path'], 'config', "routes_#{env}.txt")).read}\n"
|
|
60
|
-
rescue StandardError
|
|
61
|
-
''
|
|
62
|
-
end
|
|
63
|
-
res << "end\n"
|
|
64
|
-
end
|
|
65
|
-
res << "end\n"
|
|
66
|
-
|
|
67
|
-
when 'admin' # admin
|
|
68
|
-
res << "scope 'admin', as: 'admin' do \n"
|
|
69
|
-
res << "namespace :themes do \n"
|
|
70
|
-
plugins.each do |plugin|
|
|
71
|
-
res << "namespace '#{plugin['key']}' do \n"
|
|
72
|
-
begin
|
|
73
|
-
res << "#{File.open(File.join(plugin['path'], 'config', "routes_#{env}.txt")).read}\n"
|
|
74
|
-
rescue StandardError
|
|
75
|
-
''
|
|
76
|
-
end
|
|
77
|
-
res << "end\n"
|
|
78
|
-
end
|
|
79
|
-
res << "end\n"
|
|
80
|
-
res << "end\n"
|
|
81
|
-
else # main
|
|
82
|
-
plugins.each do |plugin|
|
|
83
|
-
res << "#{File.open(File.join(plugin['path'], 'config', "routes_#{env}.txt")).read}\n"
|
|
84
|
-
rescue StandardError
|
|
85
|
-
''
|
|
86
|
-
end
|
|
87
|
-
end
|
|
88
|
-
res
|
|
89
|
-
end
|
|
4
|
+
require 'monitor'
|
|
90
5
|
|
|
6
|
+
class PluginRoutes
|
|
91
7
|
class << self
|
|
92
8
|
# return plugin information
|
|
93
9
|
def plugin_info(plugin_key)
|
|
94
|
-
all_plugins.
|
|
95
|
-
nil
|
|
10
|
+
all_plugins.find { |p| p['key'] == plugin_key || p['path'].split('/').last == plugin_key }
|
|
96
11
|
end
|
|
97
12
|
|
|
98
13
|
# return theme information
|
|
99
14
|
# if theme_name is nil, the use current site theme
|
|
100
15
|
def theme_info(theme_name)
|
|
101
|
-
all_themes.
|
|
102
|
-
nil
|
|
16
|
+
all_themes.find { |p| p['key'] == theme_name }
|
|
103
17
|
end
|
|
104
18
|
|
|
105
19
|
# return system static settings (config.json values)
|
|
106
20
|
def static_system_info
|
|
107
21
|
r = cache_variable('statis_system_info')
|
|
108
|
-
return r
|
|
22
|
+
return r if r
|
|
109
23
|
|
|
110
24
|
settings = {}
|
|
111
25
|
|
|
112
26
|
gem_settings = File.join($camaleon_engine_dir, 'config', 'system.json')
|
|
113
|
-
app_settings = Rails.root.join('config
|
|
27
|
+
app_settings = Rails.root.join('config/system.json')
|
|
114
28
|
|
|
115
|
-
settings
|
|
116
|
-
settings
|
|
29
|
+
settings.merge!(JSON.parse(File.read(gem_settings))) if File.exist?(gem_settings)
|
|
30
|
+
settings.merge!(JSON.parse(File.read(app_settings))) if File.exist?(app_settings)
|
|
117
31
|
|
|
118
32
|
# custom settings
|
|
119
33
|
settings['key'] = 'system'
|
|
@@ -126,15 +40,13 @@ class PluginRoutes
|
|
|
126
40
|
|
|
127
41
|
# convert action parameter into hash
|
|
128
42
|
def fixActionParameter(h)
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
h
|
|
137
|
-
end)
|
|
43
|
+
return h unless h.is_a?(ActionController::Parameters)
|
|
44
|
+
|
|
45
|
+
begin
|
|
46
|
+
h.permit!.to_h
|
|
47
|
+
rescue StandardError
|
|
48
|
+
h.to_hash
|
|
49
|
+
end
|
|
138
50
|
end
|
|
139
51
|
|
|
140
52
|
# add a new anonymous hook
|
|
@@ -144,15 +56,14 @@ class PluginRoutes
|
|
|
144
56
|
# @param callback [Lambda], anonymous function to be called when the hook was called
|
|
145
57
|
# @return nil
|
|
146
58
|
def add_anonymous_hook(hook_key, callback, hook_id = '')
|
|
147
|
-
|
|
148
|
-
@@anonymous_hooks[hook_key] << { id: hook_id, callback: callback }
|
|
59
|
+
(anonymous_hooks[hook_key] ||= []) << { id: hook_id, callback: callback }
|
|
149
60
|
end
|
|
150
61
|
|
|
151
62
|
# return all registered anonymous hooks for hook_key
|
|
152
63
|
# @param hook_key [String] name of the hook
|
|
153
64
|
# @return [Array] array of hooks for hook_key
|
|
154
65
|
def get_anonymous_hooks(hook_key)
|
|
155
|
-
(
|
|
66
|
+
(anonymous_hooks[hook_key.to_s] || []).map { |item| item[:callback] }
|
|
156
67
|
end
|
|
157
68
|
|
|
158
69
|
# return all registered anonymous hooks for hook_key
|
|
@@ -160,323 +71,456 @@ class PluginRoutes
|
|
|
160
71
|
# @param hook_id [String] identifier of the anonymous hooks
|
|
161
72
|
# @return [Array] array of hooks for hook_key
|
|
162
73
|
def remove_anonymous_hook(hook_key, hook_id)
|
|
163
|
-
(
|
|
74
|
+
(anonymous_hooks[hook_key.to_s] || []).delete_if { |item| item[:id] == hook_id }
|
|
164
75
|
end
|
|
165
76
|
|
|
166
77
|
# return the class name for user model
|
|
167
78
|
def get_user_class_name
|
|
168
79
|
static_system_info['user_model'].presence || 'CamaleonCms::User'
|
|
169
80
|
end
|
|
170
|
-
end
|
|
171
81
|
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
82
|
+
# load plugin routes if it is enabled
|
|
83
|
+
def load(env = 'admin')
|
|
84
|
+
plugins = all_enabled_plugins
|
|
85
|
+
res = ''
|
|
86
|
+
case env
|
|
87
|
+
when 'front'
|
|
88
|
+
res << "namespace :plugins do \n"
|
|
89
|
+
plugins.each do |plugin|
|
|
90
|
+
res << "namespace '#{plugin['key']}' do \n"
|
|
91
|
+
begin
|
|
92
|
+
res << "#{File.open(File.join(plugin['path'], 'config', "routes_#{env}.txt")).read}\n"
|
|
93
|
+
rescue StandardError
|
|
94
|
+
''
|
|
95
|
+
end
|
|
96
|
+
res << "end\n"
|
|
97
|
+
end
|
|
98
|
+
res << "end\n"
|
|
179
99
|
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
100
|
+
when 'admin' # admin
|
|
101
|
+
res << "scope 'admin', as: 'admin' do \n"
|
|
102
|
+
res << "namespace :plugins do \n"
|
|
103
|
+
plugins.each do |plugin|
|
|
104
|
+
res << "namespace '#{plugin['key']}' do \n"
|
|
105
|
+
begin
|
|
106
|
+
res << "#{File.open(File.join(plugin['path'], 'config', "routes_#{env}.txt")).read}\n"
|
|
107
|
+
rescue StandardError
|
|
108
|
+
''
|
|
109
|
+
end
|
|
110
|
+
res << "end\n"
|
|
111
|
+
end
|
|
112
|
+
res << "end\n"
|
|
113
|
+
res << "end\n"
|
|
114
|
+
else # main
|
|
115
|
+
plugins.each do |plugin|
|
|
116
|
+
res << "#{File.open(File.join(plugin['path'], 'config', "routes_#{env}.txt")).read}\n"
|
|
117
|
+
rescue StandardError
|
|
118
|
+
''
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
res + load_themes(env)
|
|
122
|
+
end
|
|
184
123
|
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
124
|
+
def load_themes(env = 'admin')
|
|
125
|
+
plugins = all_enabled_themes
|
|
126
|
+
res = ''
|
|
127
|
+
case env
|
|
128
|
+
when 'front'
|
|
129
|
+
res << "namespace :themes do \n"
|
|
130
|
+
plugins.each do |plugin|
|
|
131
|
+
res << "namespace '#{plugin['key']}' do \n"
|
|
132
|
+
begin
|
|
133
|
+
res << "#{File.open(File.join(plugin['path'], 'config', "routes_#{env}.txt")).read}\n"
|
|
134
|
+
rescue StandardError
|
|
135
|
+
''
|
|
136
|
+
end
|
|
137
|
+
res << "end\n"
|
|
138
|
+
end
|
|
139
|
+
res << "end\n"
|
|
189
140
|
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
141
|
+
when 'admin' # admin
|
|
142
|
+
res << "scope 'admin', as: 'admin' do \n"
|
|
143
|
+
res << "namespace :themes do \n"
|
|
144
|
+
plugins.each do |plugin|
|
|
145
|
+
res << "namespace '#{plugin['key']}' do \n"
|
|
146
|
+
begin
|
|
147
|
+
res << "#{File.open(File.join(plugin['path'], 'config', "routes_#{env}.txt")).read}\n"
|
|
148
|
+
rescue StandardError
|
|
149
|
+
''
|
|
150
|
+
end
|
|
151
|
+
res << "end\n"
|
|
152
|
+
end
|
|
153
|
+
res << "end\n"
|
|
154
|
+
res << "end\n"
|
|
155
|
+
else # main
|
|
156
|
+
plugins.each do |plugin|
|
|
157
|
+
res << "#{File.open(File.join(plugin['path'], 'config', "routes_#{env}.txt")).read}\n"
|
|
158
|
+
rescue StandardError
|
|
159
|
+
''
|
|
160
|
+
end
|
|
161
|
+
end
|
|
162
|
+
res
|
|
194
163
|
end
|
|
195
|
-
res = res.sort_by { |e| e['position'] || 10 }
|
|
196
|
-
cache_variable("enable_plugins_site_#{site.id}", res)
|
|
197
|
-
end
|
|
198
164
|
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
165
|
+
# reload routes (thread-safe)
|
|
166
|
+
def reload
|
|
167
|
+
reload_monitor.synchronize do
|
|
168
|
+
@all_sites = nil
|
|
169
|
+
cache.clear
|
|
170
|
+
Rails.application.reload_routes!
|
|
171
|
+
after_reload_callbacks.uniq.each(&:call)
|
|
172
|
+
end
|
|
173
|
+
end
|
|
205
174
|
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
175
|
+
# Draw the route table at boot so the first request is never served against a half-built set
|
|
176
|
+
# of routes. Production already eager-loads routes; this closes the development window where
|
|
177
|
+
# the first request after a restart races the (multi-site) draw. Guarded by db_installed? and
|
|
178
|
+
# rescued so boot never aborts when the DB is unavailable (migrations, asset precompile, or a
|
|
179
|
+
# fresh install before db:create).
|
|
180
|
+
def draw_routes_eagerly
|
|
181
|
+
return if Rails.application.config.eager_load # production draws routes at boot already
|
|
182
|
+
# Skip while a db: Rake task runs (db:migrate, db:schema:load, app:db:test:prepare, ...): it
|
|
183
|
+
# boots against a schema that is mid-change, so drawing here would query that schema -- and it
|
|
184
|
+
# never serves a request that could race the draw. Other non-server processes (console,
|
|
185
|
+
# workers) still draw: Rails exposes no reliable, version-stable "is this the web server?"
|
|
186
|
+
# signal, and the draw is otherwise bounded and safe (a single guarded, rescued, idempotent
|
|
187
|
+
# draw over long-stable columns), so scoping it further is not worth a fragile gate.
|
|
188
|
+
return if running_db_rake_task?
|
|
189
|
+
return unless db_installed?
|
|
190
|
+
|
|
191
|
+
Rails.application.reload_routes!
|
|
192
|
+
rescue ActiveRecord::ActiveRecordError => e
|
|
193
|
+
# Only swallow database-unavailability (migrations, asset precompile, a fresh install before
|
|
194
|
+
# db:create) so boot never aborts on it. A route-file syntax error, a raised constraint lambda
|
|
195
|
+
# or any other bug in the draw is NOT a boot-safety concern and must surface, not be logged and
|
|
196
|
+
# hidden here where nothing would ever redraw and reveal it.
|
|
197
|
+
Rails.logger&.warn("Camaleon CMS: skipped eager route draw at boot (#{e.class}: #{e.message})")
|
|
198
|
+
nil
|
|
199
|
+
end
|
|
209
200
|
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
end
|
|
201
|
+
# Add a callable (Proc/Lambda) to run after routes reload; strings are not supported.
|
|
202
|
+
def add_after_reload_routes(command)
|
|
203
|
+
raise(ArgumentError, 'Expected a callable (Proc/Lambda), not a String') if command.is_a?(String)
|
|
214
204
|
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
r = cache_variable('all_enabled_themes')
|
|
218
|
-
return r unless r.nil?
|
|
205
|
+
after_reload_callbacks << command
|
|
206
|
+
end
|
|
219
207
|
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
208
|
+
# return all enabled plugins []
|
|
209
|
+
def enabled_plugins(site)
|
|
210
|
+
r = cache_variable("enable_plugins_site_#{site.id}")
|
|
211
|
+
return r if r
|
|
212
|
+
|
|
213
|
+
enabled_ps = site.plugins.active.pluck(:slug)
|
|
214
|
+
res = all_plugins.each_with_object([]) do |plugin, ary|
|
|
215
|
+
ary << plugin if enabled_ps.include?(plugin['key'])
|
|
216
|
+
end
|
|
217
|
+
res = res.sort_by { |e| e['position'] || 10 }
|
|
218
|
+
cache_variable("enable_plugins_site_#{site.id}", res)
|
|
224
219
|
end
|
|
225
|
-
cache_variable('all_enabled_themes', res)
|
|
226
|
-
end
|
|
227
220
|
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
221
|
+
# return all enabled apps for site (themes + system + plugins) []
|
|
222
|
+
# theme_slug: current theme slug
|
|
223
|
+
def enabled_apps(site, theme_slug = nil)
|
|
224
|
+
theme_slug ||= site.get_theme_slug
|
|
225
|
+
r = cache_variable("enabled_apps_#{site.id}_#{theme_slug}")
|
|
226
|
+
return r if r
|
|
232
227
|
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
228
|
+
res = [system_info] + enabled_plugins(site) + [theme_info(theme_slug)]
|
|
229
|
+
cache_variable("enabled_apps_#{site.id}_#{theme_slug}", res)
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
# return all enabled apps as []: system, themes, plugins
|
|
233
|
+
def all_enabled_apps
|
|
234
|
+
[system_info] + all_enabled_themes + all_enabled_plugins
|
|
238
235
|
end
|
|
239
|
-
cache_variable('all_enabled_plugins', res)
|
|
240
|
-
end
|
|
241
236
|
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
237
|
+
# return all enabled themes (a theme is enabled if at least one site is assigned)
|
|
238
|
+
def all_enabled_themes
|
|
239
|
+
r = cache_variable('all_enabled_themes')
|
|
240
|
+
# Do not treat an empty result as a cache hit (an empty [] is truthy): if a draw runs before
|
|
241
|
+
# the DB is ready, get_sites returns [] and this would otherwise cache [] permanently, matching
|
|
242
|
+
# the self-healing all_plugins/all_themes below rather than the sticky-empty behavior.
|
|
243
|
+
return r if r.present?
|
|
244
|
+
|
|
245
|
+
res = get_sites.each_with_object([]) do |site, ary|
|
|
246
|
+
i = theme_info(site.get_theme_slug)
|
|
247
|
+
ary << i if i.present?
|
|
248
|
+
end
|
|
249
|
+
cache_variable('all_enabled_themes', res)
|
|
250
|
+
end
|
|
246
251
|
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
252
|
+
# return all enabled plugins (a theme is enabled if at least one site has installed)
|
|
253
|
+
def all_enabled_plugins
|
|
254
|
+
r = cache_variable('all_enabled_plugins')
|
|
255
|
+
return r if r.present? # an empty [] must not stick as a cache hit -- see all_enabled_themes
|
|
256
|
+
|
|
257
|
+
# Empty get_sites (the DB is not ready during early boot, or there simply are no sites) means
|
|
258
|
+
# no DB work: gate the batched query on it here, as one explicit early return, so the query
|
|
259
|
+
# never runs against a table that may not exist yet and aborts route loading. get_sites rescues
|
|
260
|
+
# to [] on any DB error, so this single guard keeps the whole draw path safe -- and any batched
|
|
261
|
+
# query added below inherits it, rather than each repeating a per-call emptiness check.
|
|
262
|
+
return [] if get_sites.empty?
|
|
263
|
+
|
|
264
|
+
# One query for every enabled plugin slug across all sites, rather than a
|
|
265
|
+
# `site.plugins.active.pluck` per site (the N+1 that dominated multi-site route drawing). A
|
|
266
|
+
# subquery over the site ids avoids marshaling every id into an IN(...) bind list, which can
|
|
267
|
+
# exceed SQLite's SQLITE_MAX_VARIABLE_NUMBER on very large multi-site installs; Postgres and
|
|
268
|
+
# MySQL handle either form.
|
|
269
|
+
enabled_ps = CamaleonCms::Plugin.active.where(parent_id: CamaleonCms::Site.select(:id)).distinct.pluck(:slug)
|
|
270
|
+
res = all_plugins.each_with_object([]) do |plugin, ary|
|
|
271
|
+
ary << plugin if enabled_ps.include?(plugin['key'])
|
|
272
|
+
end
|
|
273
|
+
cache_variable('all_enabled_plugins', res)
|
|
250
274
|
end
|
|
251
|
-
cache_variable('site_plugin_helpers', res)
|
|
252
|
-
end
|
|
253
275
|
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
276
|
+
# all helpers of enabled plugins for site
|
|
277
|
+
def site_plugin_helpers(site)
|
|
278
|
+
r = cache_variable('site_plugin_helpers')
|
|
279
|
+
return r if r
|
|
258
280
|
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
res += settings['helpers'] if settings['helpers'].present?
|
|
281
|
+
res = enabled_apps(site).filter_map { |settings| settings['helpers'].presence }.flatten
|
|
282
|
+
cache_variable('site_plugin_helpers', res)
|
|
262
283
|
end
|
|
263
|
-
cache_variable('plugins_helper', res.uniq)
|
|
264
|
-
end
|
|
265
284
|
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
''
|
|
285
|
+
# all helpers of enabled plugins
|
|
286
|
+
def all_helpers
|
|
287
|
+
r = cache_variable('plugins_helper')
|
|
288
|
+
return r if r
|
|
289
|
+
|
|
290
|
+
res = all_apps.filter_map { |settings| settings['helpers'].presence }.flatten
|
|
291
|
+
cache_variable('plugins_helper', res.uniq)
|
|
272
292
|
end
|
|
273
|
-
PluginRoutes.reload
|
|
274
|
-
end
|
|
275
293
|
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
294
|
+
# destroy plugin
|
|
295
|
+
def destroy_plugin(plugin_key)
|
|
296
|
+
begin
|
|
297
|
+
FileUtils.rm_r(Rails.root.join('app', 'apps', 'plugins', plugin_key))
|
|
298
|
+
rescue StandardError
|
|
299
|
+
nil
|
|
300
|
+
end
|
|
301
|
+
PluginRoutes.reload
|
|
302
|
+
end
|
|
303
|
+
|
|
304
|
+
def cache_variable(var_name, value = nil)
|
|
305
|
+
reload_monitor.synchronize do
|
|
306
|
+
if value.nil?
|
|
307
|
+
cache[var_name]
|
|
308
|
+
else
|
|
309
|
+
cache[var_name] = value
|
|
310
|
+
end
|
|
311
|
+
end
|
|
312
|
+
end
|
|
313
|
+
|
|
314
|
+
# return all sites registered for Plugin routes
|
|
315
|
+
def get_sites
|
|
316
|
+
# Eager-load metas and post_types so the per-site reads route drawing performs come from the
|
|
317
|
+
# loaded associations instead of one query per site: metas back the option/language/theme
|
|
318
|
+
# lookups (get_meta checks metas.loaded?), and post_types back the frontend post-type route
|
|
319
|
+
# loop. On large multi-site installs those N+1s are the bulk of cold-boot route-draw time --
|
|
320
|
+
# the window where the first request races a half-built table.
|
|
321
|
+
#
|
|
322
|
+
# The whole metas set is loaded on purpose, not a scoped subset: get_meta's loaded branch reads
|
|
323
|
+
# a key absent from the loaded records as unset, so preloading only _default/languages_site
|
|
324
|
+
# would make every other site meta read silently return its default. Site-level metas are few
|
|
325
|
+
# rows per site, so this bounded over-fetch is the safe trade against that correctness hazard.
|
|
326
|
+
@all_sites ||= CamaleonCms::Site.includes(:metas, :post_types).order(id: :asc).to_a
|
|
281
327
|
rescue StandardError
|
|
282
|
-
|
|
328
|
+
[]
|
|
283
329
|
end
|
|
284
|
-
return cache if value.nil?
|
|
285
330
|
|
|
286
|
-
#
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
331
|
+
# check if db migrate already done
|
|
332
|
+
def db_installed?
|
|
333
|
+
@db_installed ||= ActiveRecord::Base.connection.table_exists?(CamaleonCms::Site.table_name)
|
|
334
|
+
end
|
|
290
335
|
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
336
|
+
# return all locales for all sites joined by |
|
|
337
|
+
def all_locales
|
|
338
|
+
r = cache_variable('site_all_locales')
|
|
339
|
+
# A blank '' must not stick as a hit: an empty all_locales makes the frontend
|
|
340
|
+
# `locale: /#{all_locales}/` constraint an empty regex `//` that matches anything.
|
|
341
|
+
return r if r.present?
|
|
297
342
|
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
end
|
|
343
|
+
res = get_sites.flat_map(&:get_languages)
|
|
344
|
+
cache_variable('site_all_locales', res.uniq.join('|'))
|
|
345
|
+
end
|
|
302
346
|
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
347
|
+
# return all translations for all languages, sample: ['Sample', 'Ejemplo', '....']
|
|
348
|
+
def all_translations(key, *args)
|
|
349
|
+
args = args.extract_options!
|
|
350
|
+
all_locales.split('|').map { |_l| I18n.t(key, **args.merge({ locale: _l })) }.uniq
|
|
351
|
+
end
|
|
307
352
|
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
353
|
+
# return app's directory path
|
|
354
|
+
def apps_dir
|
|
355
|
+
@apps_dir ||= Rails.root.join('app/apps').to_s
|
|
311
356
|
end
|
|
312
|
-
cache_variable('site_all_locales', res.uniq.join('|'))
|
|
313
|
-
end
|
|
314
357
|
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
358
|
+
# return all plugins located in cms and in this project
|
|
359
|
+
def all_plugins
|
|
360
|
+
camaleon_gem = get_gem('camaleon_cms')
|
|
361
|
+
return [] unless camaleon_gem
|
|
362
|
+
|
|
363
|
+
r = cache_variable('all_plugins')
|
|
364
|
+
return r if r.present?
|
|
365
|
+
|
|
366
|
+
res = get_gem_plugins
|
|
367
|
+
entries = %w[. ..]
|
|
368
|
+
res.each { |plugin| entries << plugin['key'] }
|
|
369
|
+
(Dir["#{apps_dir}/plugins/*"] + Dir["#{camaleon_gem.gem_dir}/app/apps/plugins/*"]).each do |path|
|
|
370
|
+
entry = path.split('/').last
|
|
371
|
+
config = File.join(path, 'config', 'config.json')
|
|
372
|
+
next if entries.include?(entry) || !File.directory?(path) || !File.exist?(config)
|
|
373
|
+
|
|
374
|
+
p = JSON.parse(File.read(config))
|
|
375
|
+
p = begin
|
|
376
|
+
p.with_indifferent_access
|
|
377
|
+
rescue StandardError
|
|
378
|
+
p
|
|
379
|
+
end
|
|
380
|
+
p['key'] = entry
|
|
381
|
+
p['path'] = path
|
|
382
|
+
p['kind'] = 'plugin'
|
|
383
|
+
res << p
|
|
384
|
+
entries << entry
|
|
385
|
+
end
|
|
386
|
+
cache_variable('all_plugins', res)
|
|
387
|
+
end
|
|
320
388
|
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
389
|
+
# return an array of all themes installed for all sites
|
|
390
|
+
def all_themes
|
|
391
|
+
camaleon_gem = get_gem('camaleon_cms')
|
|
392
|
+
return [] unless camaleon_gem
|
|
393
|
+
|
|
394
|
+
r = cache_variable('all_themes')
|
|
395
|
+
return r if r.present?
|
|
396
|
+
|
|
397
|
+
res = get_gem_themes
|
|
398
|
+
entries = %w[. ..]
|
|
399
|
+
res.each { |theme| entries << theme['key'] }
|
|
400
|
+
Dir["#{apps_dir}/themes/*"].each do |path|
|
|
401
|
+
entry = path.split('/').last
|
|
402
|
+
config = File.join(path, 'config', 'config.json')
|
|
403
|
+
next if entries.include?(entry) || !File.directory?(path) || !File.exist?(config)
|
|
404
|
+
|
|
405
|
+
p = JSON.parse(File.read(config))
|
|
406
|
+
p = begin
|
|
407
|
+
p.with_indifferent_access
|
|
408
|
+
rescue StandardError
|
|
409
|
+
p
|
|
410
|
+
end
|
|
411
|
+
p['key'] = entry
|
|
412
|
+
p['path'] = path
|
|
413
|
+
p['kind'] = 'theme'
|
|
414
|
+
p['title'] = p['name']
|
|
415
|
+
res << p
|
|
416
|
+
entries << entry
|
|
417
|
+
end
|
|
418
|
+
cache_variable('all_themes', res)
|
|
419
|
+
end
|
|
325
420
|
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
421
|
+
# return all apps loaded
|
|
422
|
+
def all_apps
|
|
423
|
+
all_plugins + all_themes
|
|
329
424
|
end
|
|
330
|
-
res[false] = ''
|
|
331
|
-
cache_variable('all_locales_for_routes', res)
|
|
332
|
-
end
|
|
333
425
|
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
426
|
+
# return all plugins registered as gems
|
|
427
|
+
def get_gem_plugins
|
|
428
|
+
Gem::Specification.each_with_object([]) do |gem, ary|
|
|
429
|
+
path = gem.gem_dir
|
|
430
|
+
config = File.join(path, 'config', 'camaleon_plugin.json')
|
|
431
|
+
next unless File.exist?(config)
|
|
338
432
|
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
config = File.join(path, 'config', 'config.json')
|
|
353
|
-
next if entries.include?(entry) || !File.directory?(path) || !File.exist?(config)
|
|
354
|
-
|
|
355
|
-
p = JSON.parse(File.read(config))
|
|
356
|
-
p = begin
|
|
357
|
-
p.with_indifferent_access
|
|
358
|
-
rescue StandardError
|
|
359
|
-
p
|
|
433
|
+
p = JSON.parse(File.read(config))
|
|
434
|
+
p = begin
|
|
435
|
+
p.with_indifferent_access
|
|
436
|
+
rescue StandardError
|
|
437
|
+
p
|
|
438
|
+
end
|
|
439
|
+
p['key'] = gem.name if p['key'].nil? # TODO: REVIEW ERROR FOR conflict plugin keys
|
|
440
|
+
p['version'] = gem.version.to_s
|
|
441
|
+
p['path'] = path
|
|
442
|
+
p['kind'] = 'plugin'
|
|
443
|
+
p['descr'] = gem.description if p['descr'].blank?
|
|
444
|
+
p['gem_mode'] = true
|
|
445
|
+
ary << p
|
|
360
446
|
end
|
|
361
|
-
p['key'] = entry
|
|
362
|
-
p['path'] = path
|
|
363
|
-
p['kind'] = 'plugin'
|
|
364
|
-
res << p
|
|
365
|
-
entries << entry
|
|
366
447
|
end
|
|
367
|
-
cache_variable('all_plugins', res)
|
|
368
|
-
end
|
|
369
448
|
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
p.with_indifferent_access
|
|
389
|
-
rescue StandardError
|
|
390
|
-
p
|
|
449
|
+
# return all themes registered as gems
|
|
450
|
+
def get_gem_themes
|
|
451
|
+
Gem::Specification.each_with_object([]) do |gem, ary|
|
|
452
|
+
path = gem.gem_dir
|
|
453
|
+
config = File.join(path, 'config', 'camaleon_theme.json')
|
|
454
|
+
next unless File.exist?(config)
|
|
455
|
+
|
|
456
|
+
p = JSON.parse(File.read(config))
|
|
457
|
+
p = begin
|
|
458
|
+
p.with_indifferent_access
|
|
459
|
+
rescue StandardError
|
|
460
|
+
p
|
|
461
|
+
end
|
|
462
|
+
p['key'] = gem.name if p['key'].nil? # TODO: REVIEW ERROR FOR conflict plugin keys
|
|
463
|
+
p['path'] = path
|
|
464
|
+
p['kind'] = 'theme'
|
|
465
|
+
p['gem_mode'] = true
|
|
466
|
+
ary << p
|
|
391
467
|
end
|
|
392
|
-
|
|
393
|
-
p['path'] = path
|
|
394
|
-
p['kind'] = 'theme'
|
|
395
|
-
p['title'] = p['name']
|
|
396
|
-
res << p
|
|
397
|
-
entries << entry
|
|
398
|
-
end
|
|
399
|
-
cache_variable('all_themes', res)
|
|
400
|
-
end
|
|
468
|
+
end
|
|
401
469
|
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
470
|
+
# check if a gem is available or not
|
|
471
|
+
# Arguemnts:
|
|
472
|
+
# name: name of the gem
|
|
473
|
+
# return (Boolean) true/false
|
|
474
|
+
def get_gem(name)
|
|
475
|
+
Gem::Specification.find_by_name(name)
|
|
476
|
+
rescue Gem::LoadError
|
|
477
|
+
false
|
|
478
|
+
rescue StandardError
|
|
479
|
+
Gem.available?(name)
|
|
480
|
+
end
|
|
406
481
|
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
path = gem.gem_dir
|
|
412
|
-
config = File.join(path, 'config', 'camaleon_plugin.json')
|
|
413
|
-
next unless File.exist?(config)
|
|
414
|
-
|
|
415
|
-
p = JSON.parse(File.read(config))
|
|
416
|
-
p = begin
|
|
417
|
-
p.with_indifferent_access
|
|
482
|
+
# return the default url options for Camaleon CMS
|
|
483
|
+
def default_url_options
|
|
484
|
+
options = { host: begin
|
|
485
|
+
CamaleonCms::Site.main_site.slug
|
|
418
486
|
rescue StandardError
|
|
419
|
-
|
|
420
|
-
end
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
p['kind'] = 'plugin'
|
|
425
|
-
p['descr'] = gem.description unless p['descr'].present?
|
|
426
|
-
p['gem_mode'] = true
|
|
427
|
-
entries << p
|
|
428
|
-
end
|
|
429
|
-
entries
|
|
430
|
-
end
|
|
487
|
+
''
|
|
488
|
+
end }
|
|
489
|
+
options[:protocol] = 'https' if Rails.application.config.force_ssl
|
|
490
|
+
options
|
|
491
|
+
end
|
|
431
492
|
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
entries = []
|
|
435
|
-
Gem::Specification.each do |gem|
|
|
436
|
-
path = gem.gem_dir
|
|
437
|
-
config = File.join(path, 'config', 'camaleon_theme.json')
|
|
438
|
-
next unless File.exist?(config)
|
|
439
|
-
|
|
440
|
-
p = JSON.parse(File.read(config))
|
|
441
|
-
p = begin
|
|
442
|
-
p.with_indifferent_access
|
|
443
|
-
rescue StandardError
|
|
444
|
-
p
|
|
445
|
-
end
|
|
446
|
-
p['key'] = gem.name if p['key'].nil? # TODO: REVIEW ERROR FOR conflict plugin keys
|
|
447
|
-
p['path'] = path
|
|
448
|
-
p['kind'] = 'theme'
|
|
449
|
-
p['gem_mode'] = true
|
|
450
|
-
entries << p
|
|
493
|
+
def migration_class
|
|
494
|
+
ActiveRecord::Migration[4.2]
|
|
451
495
|
end
|
|
452
|
-
entries
|
|
453
|
-
end
|
|
454
496
|
|
|
455
|
-
|
|
456
|
-
# Arguemnts:
|
|
457
|
-
# name: name of the gem
|
|
458
|
-
# return (Boolean) true/false
|
|
459
|
-
def self.get_gem(name)
|
|
460
|
-
Gem::Specification.find_by_name(name)
|
|
461
|
-
rescue Gem::LoadError
|
|
462
|
-
false
|
|
463
|
-
rescue StandardError
|
|
464
|
-
Gem.available?(name)
|
|
465
|
-
end
|
|
497
|
+
private
|
|
466
498
|
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
end }
|
|
474
|
-
options.merge!({ protocol: 'https' }) if Rails.application.config.force_ssl
|
|
475
|
-
options
|
|
476
|
-
end
|
|
499
|
+
# True when this process is running a task in the `db:` Rake namespace (db:migrate,
|
|
500
|
+
# db:schema:load, ... or their engine-prefixed forms like app:db:test:prepare), whether launched
|
|
501
|
+
# through `rails` or `rake`. Rake.application is absent outside a Rake run (the web server,
|
|
502
|
+
# `rails console`, `rails runner`), so this is false there.
|
|
503
|
+
def running_db_rake_task?
|
|
504
|
+
return false unless defined?(Rake) && Rake.respond_to?(:application)
|
|
477
505
|
|
|
478
|
-
|
|
479
|
-
|
|
506
|
+
Rake.application.top_level_tasks.any? { |task| task.to_s.split(':').include?('db') }
|
|
507
|
+
end
|
|
508
|
+
|
|
509
|
+
def anonymous_hooks
|
|
510
|
+
@anonymous_hooks ||= {}
|
|
511
|
+
end
|
|
512
|
+
|
|
513
|
+
def after_reload_callbacks
|
|
514
|
+
@after_reload_callbacks ||= []
|
|
515
|
+
end
|
|
516
|
+
|
|
517
|
+
def reload_monitor
|
|
518
|
+
@reload_monitor ||= Monitor.new
|
|
519
|
+
end
|
|
520
|
+
|
|
521
|
+
def cache
|
|
522
|
+
@cache ||= {}
|
|
523
|
+
end
|
|
480
524
|
end
|
|
481
525
|
end
|
|
482
526
|
CamaManager = PluginRoutes
|