camaleon_cms 2.7.5 → 2.8.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of camaleon_cms might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/README.md +20 -20
- data/app/apps/plugins/attack/config/config.json +2 -2
- data/app/apps/plugins/front_cache/admin_controller.rb +4 -6
- data/app/apps/plugins/front_cache/config/config.json +1 -1
- data/app/apps/plugins/front_cache/config/locales/translation.yml +1 -1
- data/app/apps/plugins/front_cache/front_cache_helper.rb +3 -3
- data/app/apps/plugins/visibility_post/config/config.json +2 -2
- data/app/apps/themes/camaleon_first/assets/js/main.js +1 -1
- data/app/apps/themes/camaleon_first/views/index.html.erb +1 -1
- data/app/apps/themes/default/assets/js/main.js +1 -1
- data/app/apps/themes/new/assets/js/main.js +1 -1
- data/app/apps/themes/new/views/index.html.erb +4 -4
- data/app/apps/themes/new/views/layouts/_footer.html.erb +2 -2
- data/app/assets/javascripts/camaleon_cms/admin/admin-basic-manifest.js +2 -2
- data/app/assets/javascripts/camaleon_cms/admin/admin-manifest.js +1 -1
- data/app/assets/javascripts/camaleon_cms/admin/tinymce/langs/de.js +2 -2
- data/app/assets/javascripts/camaleon_cms/admin/tinymce/langs/en.js +2 -2
- data/app/assets/javascripts/camaleon_cms/admin/tinymce/langs/fr.js +2 -2
- data/app/assets/javascripts/camaleon_cms/admin/tinymce/langs/it.js +2 -2
- data/app/assets/javascripts/camaleon_cms/admin/tinymce/langs/nl.js +1 -1
- data/app/assets/javascripts/camaleon_cms/admin/tinymce/langs/pt-BR.js +2 -2
- data/app/assets/javascripts/camaleon_cms/admin/tinymce/langs/ru.js +2 -2
- data/app/assets/javascripts/camaleon_cms/admin/tinymce/langs/uk.js +2 -2
- data/app/assets/javascripts/camaleon_cms/admin/tinymce/langs/zh-CN.js +1 -1
- data/app/assets/javascripts/camaleon_cms/admin/uploader/_media_manager.js +2 -2
- data/app/controllers/camaleon_cms/admin/appearances/nav_menus_controller.rb +15 -10
- data/app/controllers/camaleon_cms/admin/installers_controller.rb +1 -1
- data/app/controllers/camaleon_cms/admin/settings_controller.rb +1 -1
- data/app/controllers/camaleon_cms/camaleon_controller.rb +8 -2
- data/app/decorators/camaleon_cms/application_decorator.rb +8 -0
- data/app/decorators/camaleon_cms/category_decorator.rb +1 -1
- data/app/decorators/camaleon_cms/post_decorator.rb +5 -5
- data/app/decorators/camaleon_cms/post_type_decorator.rb +3 -3
- data/app/decorators/camaleon_cms/term_taxonomy_decorator.rb +1 -1
- data/app/helpers/camaleon_cms/admin/category_helper.rb +1 -1
- data/app/helpers/camaleon_cms/frontend/nav_menu_helper.rb +12 -11
- data/app/helpers/camaleon_cms/html_helper.rb +6 -6
- data/app/helpers/camaleon_cms/plugins_helper.rb +1 -1
- data/app/helpers/camaleon_cms/session_helper.rb +1 -1
- data/app/helpers/camaleon_cms/short_code_helper.rb +1 -1
- data/app/helpers/camaleon_cms/site_helper.rb +1 -1
- data/app/helpers/camaleon_cms/theme_helper.rb +1 -1
- data/app/helpers/camaleon_cms/uploader_helper.rb +10 -5
- data/app/models/camaleon_cms/ability.rb +1 -1
- data/app/models/camaleon_cms/custom_field_group.rb +2 -2
- data/app/models/camaleon_cms/nav_menu.rb +1 -1
- data/app/models/camaleon_cms/post.rb +1 -1
- data/app/models/camaleon_cms/post_default.rb +1 -1
- data/app/models/camaleon_cms/post_type.rb +8 -8
- data/app/models/camaleon_cms/site.rb +1 -1
- data/app/models/camaleon_cms/term_taxonomy.rb +13 -0
- data/app/models/concerns/camaleon_cms/custom_fields_read.rb +11 -22
- data/app/models/concerns/camaleon_cms/site_default_settings.rb +1 -1
- data/app/uploaders/camaleon_cms_uploader.rb +5 -0
- data/app/validators/camaleon_cms/post_uniq_validator.rb +11 -12
- data/app/validators/camaleon_cms/uniq_validator.rb +9 -3
- data/app/views/camaleon_cms/admin/media/index.html.erb +1 -1
- data/app/views/camaleon_cms/admin/settings/_email_settings.html.erb +2 -2
- data/app/views/camaleon_cms/default_theme/index.html.erb +4 -4
- data/app/views/camaleon_cms/default_theme/sitemap.xml.builder +3 -3
- data/app/views/layouts/camaleon_cms/admin/_footer.html.erb +1 -1
- data/config/initializers/custom_initializers.rb +14 -0
- data/lib/camaleon_cms/engine.rb +1 -1
- data/lib/camaleon_cms/version.rb +1 -1
- data/lib/ext/hash.rb +1 -1
- data/lib/ext/string.rb +2 -2
- data/lib/generators/camaleon_cms/theme_template/assets/js/main.js +1 -1
- metadata +21 -7
@@ -41,8 +41,8 @@ module CamaleonCms
|
|
41
41
|
if th.present?
|
42
42
|
th
|
43
43
|
else
|
44
|
-
|
45
|
-
|
44
|
+
default || object.post_type.get_option('default_thumb',
|
45
|
+
nil) || h.asset_url('camaleon_cms/image-not-found.png')
|
46
46
|
end
|
47
47
|
end
|
48
48
|
alias the_image_url the_thumb_url
|
@@ -61,12 +61,12 @@ module CamaleonCms
|
|
61
61
|
end
|
62
62
|
|
63
63
|
# return front url for this post
|
64
|
-
# sample:
|
64
|
+
# sample: https://localhost.com/my-page.html
|
65
65
|
# args:
|
66
66
|
# locale: language (default current language)
|
67
67
|
# as_path: return the path instead of full url, sample: /my-page.html
|
68
68
|
# Also, you can pass extra attributes as params for the url, sample: page.the_url(my_param: 'value', other: "asd")
|
69
|
-
# =>
|
69
|
+
# => https://localhost.com/my-page.html?my_param=value&other=asd
|
70
70
|
# Return String URL
|
71
71
|
def the_url(*args)
|
72
72
|
args = args.extract_options!
|
@@ -127,7 +127,7 @@ module CamaleonCms
|
|
127
127
|
end
|
128
128
|
|
129
129
|
# return a hash of frontend urls for this post
|
130
|
-
# sample: {es: '
|
130
|
+
# sample: {es: 'https://mydomain.com/es/articulo-3.html', en: 'https://mydomain.com/en/post-3.html'}
|
131
131
|
def the_urls(*args)
|
132
132
|
args = args.extract_options!
|
133
133
|
res = {}
|
@@ -55,14 +55,14 @@ module CamaleonCms
|
|
55
55
|
|
56
56
|
# return main categories (first level) for the post_type (active_record) filtered by permissions
|
57
57
|
# in return object, you can add custom where's or pagination like here:
|
58
|
-
#
|
58
|
+
# https://edgeguides.rubyonrails.org/active_record_querying.html
|
59
59
|
def the_categories
|
60
60
|
object.categories
|
61
61
|
end
|
62
62
|
|
63
63
|
# return full categories (all levels) for the post_type (active_record) filtered by permissions
|
64
64
|
# in return object, you can add custom where's or pagination like here:
|
65
|
-
#
|
65
|
+
# https://edgeguides.rubyonrails.org/active_record_querying.html
|
66
66
|
def the_full_categories
|
67
67
|
object.full_categories
|
68
68
|
end
|
@@ -76,7 +76,7 @@ module CamaleonCms
|
|
76
76
|
|
77
77
|
# return all post_tags for the post_type (active_record) filtered by permissions + hidden posts + roles + etc...
|
78
78
|
# in return object, you can add custom where's or pagination like here:
|
79
|
-
#
|
79
|
+
# https://edgeguides.rubyonrails.org/active_record_querying.html
|
80
80
|
def the_post_tags
|
81
81
|
object.post_tags
|
82
82
|
end
|
@@ -48,7 +48,7 @@ module CamaleonCms
|
|
48
48
|
# ---------------------- filters
|
49
49
|
# return all posts for this model (active_record) filtered by permissions + hidden posts + roles + etc...
|
50
50
|
# in return object, you can add custom where's or pagination like here:
|
51
|
-
#
|
51
|
+
# https://edgeguides.rubyonrails.org/active_record_querying.html
|
52
52
|
def the_posts
|
53
53
|
h.verify_front_visibility(object.posts)
|
54
54
|
end
|
@@ -17,7 +17,7 @@ module CamaleonCms
|
|
17
17
|
options << [('—' * level) + category.the_title, category.id]
|
18
18
|
children = attrs[:max_level] < level ? [] : category.children
|
19
19
|
children = [] if attrs[:until_cats].include?(category.id)
|
20
|
-
options += cama_category_get_options_html(children, level + 1, attrs)
|
20
|
+
options += cama_category_get_options_html(children, level + 1, attrs) unless children.empty?
|
21
21
|
end
|
22
22
|
options
|
23
23
|
end
|
@@ -23,7 +23,7 @@ module CamaleonCms
|
|
23
23
|
item_class_parent: 'dropdown', # class for all menu items that contain sub items
|
24
24
|
sub_container: 'ul', # type of container for sub items
|
25
25
|
sub_class: 'dropdown-menu', # class for sub container
|
26
|
-
callback_item: ->(args) {},
|
26
|
+
callback_item: ->(args) {}, # rubocop:disable Lint/ShadowingOuterLocalVariable
|
27
27
|
# callback executed for each item (args = { menu_item, link, level, settings, has_children, link_attrs = "", index}).
|
28
28
|
# menu_item: (Object) Menu object
|
29
29
|
# link: (Hash) link data: {link: '', name: ''}
|
@@ -48,10 +48,11 @@ module CamaleonCms
|
|
48
48
|
container_append: '' # content append for menu container
|
49
49
|
}
|
50
50
|
|
51
|
-
args = args_def.merge(args)
|
51
|
+
args = args_def.merge!(args)
|
52
52
|
nav_menu = current_site.nav_menus.find_by_slug(args[:menu_slug])
|
53
|
-
nav_menu
|
54
|
-
html = "<#{args[:container]} class='#{args[:container_class]}'
|
53
|
+
nav_menu ||= current_site.nav_menus.first
|
54
|
+
html = "<#{args[:container]} class='#{args[:container_class]}' "\
|
55
|
+
"id='#{args[:container_id]}'>#{args[:container_prepend]}{__}#{args[:container_append]}</#{args[:container]}>"
|
55
56
|
if nav_menu.present?
|
56
57
|
html.sub('{__}', cama_menu_draw_items(args, nav_menu.children.reorder(:term_order)))
|
57
58
|
else
|
@@ -69,10 +70,10 @@ module CamaleonCms
|
|
69
70
|
data_nav_item = cama_parse_menu_item(nav_menu_item)
|
70
71
|
next if data_nav_item == false
|
71
72
|
|
72
|
-
_is_current = data_nav_item[:current] || site_current_path == data_nav_item[:link] ||
|
73
|
-
|
74
|
-
|
75
|
-
|
73
|
+
_is_current = data_nav_item[:current] || site_current_path == data_nav_item[:link] ||
|
74
|
+
site_current_path == data_nav_item[:link].sub('.html', '')
|
75
|
+
has_children = nav_menu_item.have_children? && (args[:levels] == -1 ||
|
76
|
+
(args[:levels] != -1 && level <= args[:levels]))
|
76
77
|
r = {
|
77
78
|
menu_item: nav_menu_item.decorate,
|
78
79
|
link: data_nav_item,
|
@@ -116,7 +117,7 @@ module CamaleonCms
|
|
116
117
|
index += 1
|
117
118
|
end
|
118
119
|
|
119
|
-
if level
|
120
|
+
if level == 0
|
120
121
|
html
|
121
122
|
else
|
122
123
|
html = "<#{args[:sub_container]} class='#{args[:sub_class]} #{if parent_current
|
@@ -142,7 +143,7 @@ module CamaleonCms
|
|
142
143
|
'.html', ''
|
143
144
|
)
|
144
145
|
has_children = nav_menu_item.have_children?
|
145
|
-
has_children = false if max_levels
|
146
|
+
has_children = false if max_levels > 0 && max_levels == internal_level
|
146
147
|
data_nav_item[:label] = data_nav_item[:name]
|
147
148
|
data_nav_item[:url] = data_nav_item[:link]
|
148
149
|
r = {
|
@@ -169,7 +170,7 @@ module CamaleonCms
|
|
169
170
|
res << r
|
170
171
|
end
|
171
172
|
|
172
|
-
if internal_level
|
173
|
+
if internal_level == 0
|
173
174
|
res
|
174
175
|
else
|
175
176
|
[res, is_current_parent, levels.max]
|
@@ -72,14 +72,14 @@ module CamaleonCms
|
|
72
72
|
def cama_draw_custom_assets
|
73
73
|
cama_html_helpers_init unless @_assets_libraries.present?
|
74
74
|
libs = []
|
75
|
-
@_assets_libraries.
|
75
|
+
@_assets_libraries.each_value do |assets|
|
76
76
|
libs += assets[:css] if assets[:css].present?
|
77
77
|
end
|
78
78
|
stylesheets = libs.uniq
|
79
79
|
css = stylesheet_link_tag(*stylesheets, media: 'all')
|
80
80
|
|
81
81
|
libs = []
|
82
|
-
@_assets_libraries.
|
82
|
+
@_assets_libraries.each_value do |assets|
|
83
83
|
libs += assets[:js] if assets[:js].present?
|
84
84
|
end
|
85
85
|
javascripts = libs.uniq
|
@@ -98,7 +98,7 @@ module CamaleonCms
|
|
98
98
|
terms.all.each do |term|
|
99
99
|
options << [('—' * level) + term.name, term.id] unless @term.id == term.id
|
100
100
|
children = term.children
|
101
|
-
options += cama_get_options_html_from_items(children, level + 1)
|
101
|
+
options += cama_get_options_html_from_items(children, level + 1) unless children.empty?
|
102
102
|
end
|
103
103
|
options
|
104
104
|
end
|
@@ -121,18 +121,18 @@ module CamaleonCms
|
|
121
121
|
libs[:datepicker] = { js: [] }
|
122
122
|
libs[:datetimepicker] = { js: [], css: [] }
|
123
123
|
libs[:tinymce] =
|
124
|
-
{ js: [
|
124
|
+
{ js: %w[camaleon_cms/admin/tinymce/tinymce.min camaleon_cms/admin/tinymce/plugins/filemanager/plugin.min],
|
125
125
|
css: ['camaleon_cms/admin/tinymce/skins/lightgray/content.min'] }
|
126
126
|
libs[:form_ajax] = { js: ['camaleon_cms/admin/form/jquery.form'] }
|
127
127
|
libs[:cropper] = {} # loaded by default
|
128
128
|
libs[:post] =
|
129
|
-
{ js: [
|
129
|
+
{ js: %w[camaleon_cms/admin/jquery.tagsinput.min camaleon_cms/admin/post],
|
130
130
|
css: ['camaleon_cms/admin/jquery.tagsinput'] }
|
131
131
|
libs[:multiselect] = { js: ['camaleon_cms/admin/bootstrap-select.js'] }
|
132
132
|
libs[:validate] = { js: ['camaleon_cms/admin/jquery.validate'] }
|
133
133
|
libs[:nav_menu] =
|
134
134
|
{ css: ['camaleon_cms/admin/nestable/jquery.nestable'],
|
135
|
-
js: [
|
135
|
+
js: %w[camaleon_cms/admin/jquery.nestable camaleon_cms/admin/nav_menu] }
|
136
136
|
libs[:admin_intro] =
|
137
137
|
{ js: ['camaleon_cms/admin/introjs/intro.min'], css: ['camaleon_cms/admin/introjs/introjs.min'] }
|
138
138
|
@_cama_assets_libraries = libs
|
@@ -127,7 +127,7 @@ module CamaleonCms
|
|
127
127
|
# asset: (String) asset name
|
128
128
|
# plugin_key: (optional) plugin name, default (current plugin caller to this function)
|
129
129
|
# sample:
|
130
|
-
# plugin_asset_url("css/main.css") => return:
|
130
|
+
# plugin_asset_url("css/main.css") => return: https://myhost.com/assets/plugins/my_plugin/assets/css/main-54505620f.css
|
131
131
|
def plugin_asset_url(asset, plugin_key = nil)
|
132
132
|
key = plugin_key || self_plugin_key(1)
|
133
133
|
p = PluginRoutes.plugin_info(key)['gem_mode'] ? "plugins/#{key}/#{asset}" : "plugins/#{key}/assets/#{asset}"
|
@@ -6,7 +6,7 @@ module CamaleonCms
|
|
6
6
|
# redirect_url (default nil): after initialized the session, this will be redirected to
|
7
7
|
# "redirect_url" if defined
|
8
8
|
# it doesn't redirect if redirect_url === false
|
9
|
-
# return to previous page if defined the cookie['return_to'] or login url received extra param: return_to=
|
9
|
+
# return to previous page if defined the cookie['return_to'] or login url received extra param: return_to=https://mysite.com
|
10
10
|
def login_user(user, remember_me = false, redirect_url = nil)
|
11
11
|
c = { value: [user.auth_token, request.user_agent, request.ip], expires: 24.hours.from_now }
|
12
12
|
c[:domain] = :all if PluginRoutes.system_info['users_share_sites'].present? && CamaleonCms::Site.count > 1
|
@@ -32,7 +32,7 @@ module CamaleonCms
|
|
32
32
|
nil
|
33
33
|
end
|
34
34
|
unless r[:site].present?
|
35
|
-
Rails.logger.error 'Camaleon CMS - Please define your current site: $current_site = CamaleonCms::Site.first.decorate or map your domains:
|
35
|
+
Rails.logger.error 'Camaleon CMS - Please define your current site: $current_site = CamaleonCms::Site.first.decorate or map your domains: https://camaleon.website/documentation/category/139779-examples/how.html'.cama_log_style(:red)
|
36
36
|
end
|
37
37
|
@current_site = r[:site]
|
38
38
|
end
|
@@ -26,7 +26,7 @@ module CamaleonCms
|
|
26
26
|
# asset: (String) asset name
|
27
27
|
# theme_name: (optional) theme name, default (current theme caller to this function)
|
28
28
|
# sample:
|
29
|
-
# theme_asset_url("css/main.css") => return:
|
29
|
+
# theme_asset_url("css/main.css") => return: https://myhost.com/assets/themes/my_theme/assets/css/main-54505620f.css
|
30
30
|
def theme_asset_url(asset, theme_name = nil)
|
31
31
|
p = theme_asset_path(asset, theme_name)
|
32
32
|
begin
|
@@ -16,7 +16,7 @@ module CamaleonCms
|
|
16
16
|
# sample "test.png", versions: '200x200,450x450' will generate: thumb/test-png_200x200.png, test-png_450x450.png
|
17
17
|
# thumb_size: String (redefine the dimensions of the thumbnail, sample: '100x100' ==> only for images)
|
18
18
|
# temporal_time: if great than 0 seconds, then this file will expire (removed) in that time (default: 0)
|
19
|
-
# To manage jobs, please check
|
19
|
+
# To manage jobs, please check https://edgeguides.rubyonrails.org/active_job_basics.html
|
20
20
|
# Note: if you are using temporal_time, you will need to copy the file to another directory later
|
21
21
|
# sample: upload_file(params[:my_file], {formats: "images", folder: "temporal"})
|
22
22
|
# sample: upload_file(params[:my_file], {formats: "jpg,png,gif,mp3,mp4", temporal_time: 10.minutes, maximum: 10.megabytes})
|
@@ -45,7 +45,7 @@ module CamaleonCms
|
|
45
45
|
generate_thumb: true,
|
46
46
|
temporal_time: 0,
|
47
47
|
filename: begin
|
48
|
-
|
48
|
+
cached_name || uploaded_io.original_filename
|
49
49
|
rescue StandardError
|
50
50
|
uploaded_io.path.split('/').last
|
51
51
|
end.cama_fix_filename,
|
@@ -72,7 +72,6 @@ module CamaleonCms
|
|
72
72
|
# save file
|
73
73
|
key = File.join(settings[:folder], settings[:filename]).to_s.cama_fix_slash
|
74
74
|
res = cama_uploader.add_file(settings[:uploaded_io], key, { same_name: settings[:same_name] })
|
75
|
-
{} if (settings[:temporal_time]).positive?
|
76
75
|
|
77
76
|
# generate image versions
|
78
77
|
if res['file_type'] == 'image'
|
@@ -92,6 +91,12 @@ module CamaleonCms
|
|
92
91
|
FileUtils.rm_f(uploaded_io.path) if settings[:remove_source] && File.exist?(uploaded_io.path)
|
93
92
|
|
94
93
|
hooks_run('after_upload', settings)
|
94
|
+
|
95
|
+
# temporal file upload (always put as local for temporal files)
|
96
|
+
if settings[:temporal_time] > 0
|
97
|
+
CamaleonCmsUploader.delete_block.call(settings, cama_uploader, key)
|
98
|
+
end
|
99
|
+
|
95
100
|
res
|
96
101
|
end
|
97
102
|
|
@@ -237,7 +242,7 @@ module CamaleonCms
|
|
237
242
|
# upload tmp file
|
238
243
|
# support for url and local path
|
239
244
|
# sample:
|
240
|
-
# cama_tmp_upload('
|
245
|
+
# cama_tmp_upload('https://camaleon.website/media/132/logo2.png') ==> /var/rails/my_project/public/tmp/1/logo2.png
|
241
246
|
# cama_tmp_upload('/var/www/media/132/logo 2.png') ==> /var/rails/my_project/public/tmp/1/logo-2.png
|
242
247
|
# accept args:
|
243
248
|
# name: to indicate the name to use, sample: cama_tmp_upload('/var/www/media/132/logo 2.png', {name: 'owen.png', formats: 'images'})
|
@@ -324,7 +329,7 @@ module CamaleonCms
|
|
324
329
|
cloud_front: current_site.get_option('filesystem_s3_cloudfront'),
|
325
330
|
aws_file_upload_settings: lambda { |settings|
|
326
331
|
settings
|
327
|
-
}, # permit to add your custom attributes for file_upload
|
332
|
+
}, # permit to add your custom attributes for file_upload https://docs.aws.amazon.com/sdkforruby/api/Aws/S3/Object.html#upload_file-instance_method
|
328
333
|
aws_file_read_settings: lambda { |data, _s3_file|
|
329
334
|
data
|
330
335
|
} # permit to read custom attributes from aws file and add to file parsed object
|
@@ -105,7 +105,7 @@ module CamaleonCms
|
|
105
105
|
end
|
106
106
|
|
107
107
|
# support for custom abilities for each posttype
|
108
|
-
# sample:
|
108
|
+
# sample: https://camaleon.website/documentation/category/40756-uncategorized/custom-models.html
|
109
109
|
@roles_post_type.each do |k, v|
|
110
110
|
next if %w[edit edit_other edit_publish publish manage_categories].include?(k.to_s)
|
111
111
|
|
@@ -5,8 +5,8 @@ module CamaleonCms
|
|
5
5
|
alias_attribute :site_id, :parent_id
|
6
6
|
|
7
7
|
default_scope do
|
8
|
-
where
|
9
|
-
|
8
|
+
where("object_class != '_fields'")
|
9
|
+
.reorder("#{CamaleonCms::CustomField.table_name}.field_order ASC")
|
10
10
|
end
|
11
11
|
|
12
12
|
has_many :metas, -> { where(object_class: 'CustomFieldGroup') }, foreign_key: :objectid, dependent: :destroy
|
@@ -10,7 +10,7 @@ module CamaleonCms
|
|
10
10
|
# add menu item for current menu
|
11
11
|
# value: (Hash) is a hash object that contains label, type, link
|
12
12
|
# options for type: post | category | post_type | post_tag | external
|
13
|
-
# sample: {label: "my label", type: "external", link: "
|
13
|
+
# sample: {label: "my label", type: "external", link: "https://camaleon.website", target: '_blank'}
|
14
14
|
# sample: {label: "my label", type: "post", link: 10}
|
15
15
|
# sample: {label: "my label", type: "category", link: 12}
|
16
16
|
# return item created
|
@@ -42,7 +42,7 @@ module CamaleonCms
|
|
42
42
|
validates_with CamaleonCms::PostUniqValidator
|
43
43
|
attr_accessor :show_title_with_parent
|
44
44
|
|
45
|
-
before_create :fix_post_order, if: ->(p) { !p.post_order.present? || p.post_order
|
45
|
+
before_create :fix_post_order, if: ->(p) { !p.post_order.present? || p.post_order == 0 }
|
46
46
|
|
47
47
|
# return all parents for current page hierarchy ordered bottom to top
|
48
48
|
def parents
|
@@ -42,7 +42,7 @@ module CamaleonCms
|
|
42
42
|
res = where("#{CamaleonCms::Post.table_name}.slug = ? OR #{CamaleonCms::Post.table_name}.slug LIKE ? ", slug,
|
43
43
|
"%-->#{slug}<!--%")
|
44
44
|
# end
|
45
|
-
res.
|
45
|
+
res.take
|
46
46
|
end
|
47
47
|
|
48
48
|
# return the parent of a post (support for sub contents or tree of posts)
|
@@ -101,7 +101,7 @@ module CamaleonCms
|
|
101
101
|
# add a post for current model
|
102
102
|
# title: title for post, => required
|
103
103
|
# content: html text content, => required
|
104
|
-
# thumb: image url, => default (empty). check
|
104
|
+
# thumb: image url, => default (empty). check https://camaleon.website/api-methods.html#section_fileuploads
|
105
105
|
# categories: [1,3,4,5], => default (empty)
|
106
106
|
# tags: String comma separated, => default (empty)
|
107
107
|
# slug: string key for post, => default (empty)
|
@@ -111,7 +111,7 @@ module CamaleonCms
|
|
111
111
|
# settings: Hash of post settings, sample => settings:
|
112
112
|
# {has_content: false, has_summary: true, default_layout: 'my_layout', default_template: 'my_template' } (optional, see more in post.set_setting(...))
|
113
113
|
# data_metas: {template: "", layout: ""}
|
114
|
-
# sample: my_posttype.add_post(title: "My Title", post_order: 5, content: 'lorem_ipsum', settings: {default_template: "home/counters", has_content: false, has_seo: false, skip_fields: ["sub_tite", 'banner']}, fields: {pattern: true, bg: '
|
114
|
+
# sample: my_posttype.add_post(title: "My Title", post_order: 5, content: 'lorem_ipsum', settings: {default_template: "home/counters", has_content: false, has_seo: false, skip_fields: ["sub_tite", 'banner']}, fields: {pattern: true, bg: 'https://www.reallusion.com/de/images/3dx5/whatsnew/3dx5_features_banner_bg_02.jpg'})
|
115
115
|
# More samples here: https://gist.github.com/owen2345/eba9691585ed78ad6f7b52e9591357bf
|
116
116
|
# return created post if it was created, else return errors
|
117
117
|
def add_post(args)
|
@@ -139,12 +139,12 @@ module CamaleonCms
|
|
139
139
|
# return all available route formats of this post type for content posts
|
140
140
|
def contents_route_formats
|
141
141
|
{
|
142
|
-
'post_of_post_type' => '<code>/group/:post_type_id-:title/:slug</code><br> (Sample:
|
143
|
-
'post_of_category' => '<code>/category/:category_id-:title/:slug</code><br> (Sample:
|
144
|
-
'post_of_category_post_type' => '<code>/:post_type_title/category/:category_id-:title/:slug</code><br> (Sample:
|
145
|
-
'post_of_posttype' => '<code>/:post_type_title/:slug</code><br> (Sample:
|
146
|
-
'post' => '<code>/:slug</code><br> (Sample:
|
147
|
-
'hierarchy_post' => '<code>/:parent1_slug/:parent2_slug/.../:slug</code><br> (Sample:
|
142
|
+
'post_of_post_type' => '<code>/group/:post_type_id-:title/:slug</code><br> (Sample: https://localhost.com/group/17-services/myservice.html)',
|
143
|
+
'post_of_category' => '<code>/category/:category_id-:title/:slug</code><br> (Sample: https://localhost.com/category/17-services/myservice.html)',
|
144
|
+
'post_of_category_post_type' => '<code>/:post_type_title/category/:category_id-:title/:slug</code><br> (Sample: https://localhost.com/services/category/17-services/myservice.html)',
|
145
|
+
'post_of_posttype' => '<code>/:post_type_title/:slug</code><br> (Sample: https://localhost.com/services/myservice.html)',
|
146
|
+
'post' => '<code>/:slug</code><br> (Sample: https://localhost.com/myservice.html)',
|
147
|
+
'hierarchy_post' => '<code>/:parent1_slug/:parent2_slug/.../:slug</code><br> (Sample: https://localhost.com/item-1/item-1-1/item-111.html)'
|
148
148
|
}
|
149
149
|
end
|
150
150
|
|
@@ -91,7 +91,7 @@ module CamaleonCms
|
|
91
91
|
# return theme model with slug theme_slug for this site
|
92
92
|
# theme_slug: (optional) if it is null, this will return current theme for this site
|
93
93
|
def get_theme(theme_slug = nil)
|
94
|
-
themes.where(slug:
|
94
|
+
themes.where(slug: theme_slug || get_theme_slug, status: nil).first_or_create!
|
95
95
|
end
|
96
96
|
|
97
97
|
# return plugin model with slug plugin_slug
|
@@ -16,6 +16,19 @@ module CamaleonCms
|
|
16
16
|
# attr_accessible :data_options
|
17
17
|
# attr_accessible :data_metas
|
18
18
|
|
19
|
+
# TODO: Remove the 1st branch when support will be dropped of Rails < 7.1
|
20
|
+
if ::Rails::VERSION::STRING < '7.1.0'
|
21
|
+
before_validation(on: %i[create update]) do
|
22
|
+
%i[name description].each do |attr|
|
23
|
+
next unless new_record? || attribute_changed?(attr)
|
24
|
+
|
25
|
+
self[attr] = ActionController::Base.helpers.sanitize(__send__(attr))
|
26
|
+
end
|
27
|
+
end
|
28
|
+
else
|
29
|
+
normalizes :name, :description, with: ->(field) { ActionController::Base.helpers.sanitize(field) }
|
30
|
+
end
|
31
|
+
|
19
32
|
# callbacks
|
20
33
|
before_validation :before_validating
|
21
34
|
before_destroy :destroy_dependencies
|
@@ -3,18 +3,6 @@ module CamaleonCms
|
|
3
3
|
extend ActiveSupport::Concern
|
4
4
|
included do
|
5
5
|
before_destroy :_destroy_custom_field_groups
|
6
|
-
# DEPRECATED, INSTEAD USE: custom_fields
|
7
|
-
has_many :fields, lambda { |object|
|
8
|
-
where(object_class: object.class.to_s.gsub('Decorator', '').gsub('CamaleonCms::', ''))
|
9
|
-
}, class_name: 'CamaleonCms::CustomField', foreign_key: :objectid
|
10
|
-
# DEPRECATED, INSTEAD USE: custom_field_values
|
11
|
-
has_many :field_values, lambda { |object|
|
12
|
-
where(object_class: object.class.to_s.gsub('Decorator', '').gsub('CamaleonCms::', ''))
|
13
|
-
}, class_name: 'CamaleonCms::CustomFieldsRelationship', foreign_key: :objectid, dependent: :delete_all
|
14
|
-
# DEPRECATED, INSTEAD USE: custom_field_groups
|
15
|
-
has_many :field_groups, lambda { |object|
|
16
|
-
where(object_class: object.class.to_s.parseCamaClass)
|
17
|
-
}, class_name: 'CamaleonCms::CustomFieldGroup', foreign_key: :objectid
|
18
6
|
end
|
19
7
|
|
20
8
|
# get custom field groups for current object
|
@@ -38,7 +26,7 @@ module CamaleonCms
|
|
38
26
|
{ kind: args,
|
39
27
|
include_parent: false }
|
40
28
|
else
|
41
|
-
{ kind: 'Post', include_parent: false }.merge(args)
|
29
|
+
{ kind: 'Post', include_parent: false }.merge!(args)
|
42
30
|
end
|
43
31
|
class_name = self.class.to_s.parseCamaClass
|
44
32
|
case class_name
|
@@ -73,7 +61,7 @@ module CamaleonCms
|
|
73
61
|
CamaleonCms::CustomFieldGroup.where(object_class: "PostType_#{args[:kind]}", objectid: id)
|
74
62
|
end
|
75
63
|
else # 'Plugin' or other classes
|
76
|
-
|
64
|
+
custom_field_groups
|
77
65
|
end
|
78
66
|
end
|
79
67
|
|
@@ -131,7 +119,7 @@ module CamaleonCms
|
|
131
119
|
# puts res[0]['my_slug1'].first ==> "val 1"
|
132
120
|
def get_fields_grouped(field_keys)
|
133
121
|
res = []
|
134
|
-
custom_field_values.where(custom_field_slug: field_keys).order(group_number: :asc).group_by(&:group_number).
|
122
|
+
custom_field_values.where(custom_field_slug: field_keys).order(group_number: :asc).group_by(&:group_number).each_value do |group_fields|
|
135
123
|
group = {}
|
136
124
|
field_keys.each do |field_key|
|
137
125
|
_tmp = []
|
@@ -196,8 +184,8 @@ module CamaleonCms
|
|
196
184
|
# kind: argument only for PostType model: (Post | Category | PostTag), default => Post. If kind = "" this will add group for all post_types
|
197
185
|
def add_custom_field_group(values, kind = 'Post')
|
198
186
|
values = values.with_indifferent_access
|
199
|
-
group = get_field_groups(kind).
|
200
|
-
unless group
|
187
|
+
group = get_field_groups(kind).find_by(slug: values[:slug])
|
188
|
+
unless group
|
201
189
|
site = _cama_get_field_site
|
202
190
|
values[:parent_id] = site.id if site.present?
|
203
191
|
group = if is_a?(CamaleonCms::Post) # harcoded for post to support custom field groups
|
@@ -206,6 +194,7 @@ module CamaleonCms
|
|
206
194
|
get_field_groups(kind).create!(values)
|
207
195
|
end
|
208
196
|
end
|
197
|
+
|
209
198
|
group
|
210
199
|
end
|
211
200
|
alias add_field_group add_custom_field_group
|
@@ -215,8 +204,8 @@ module CamaleonCms
|
|
215
204
|
# more details in add_manual_field(item, options) from custom field groups
|
216
205
|
# kind: argument only for PostType model: (Post | Category | PostTag), default => Post
|
217
206
|
def add_custom_field_to_default_group(item, options, kind = 'Post')
|
218
|
-
g = get_field_groups(kind).
|
219
|
-
g
|
207
|
+
g = get_field_groups(kind).find_by(slug: '_default')
|
208
|
+
g ||= add_custom_field_group({ name: 'Default Field Group', slug: '_default' }, kind)
|
220
209
|
g.add_manual_field(item, options)
|
221
210
|
end
|
222
211
|
alias add_field add_custom_field_to_default_group
|
@@ -243,7 +232,7 @@ module CamaleonCms
|
|
243
232
|
|
244
233
|
ActiveRecord::Base.transaction do
|
245
234
|
custom_field_values.delete_all
|
246
|
-
datas.
|
235
|
+
datas.each_value do |fields_data|
|
247
236
|
fields_data.each do |field_key, values|
|
248
237
|
next unless values[:values].present?
|
249
238
|
|
@@ -260,7 +249,7 @@ module CamaleonCms
|
|
260
249
|
# update new value for field with slug _key
|
261
250
|
# Sample: my_posy.update_field_value('sub_title', 'Test Sub Title')
|
262
251
|
def update_field_value(_key, value = nil, group_number = 0)
|
263
|
-
custom_field_values.
|
252
|
+
custom_field_values.find_by(custom_field_slug: _key, group_number: group_number)&.update_column('value', value)
|
264
253
|
rescue StandardError
|
265
254
|
nil
|
266
255
|
end
|
@@ -287,7 +276,7 @@ module CamaleonCms
|
|
287
276
|
# sample: my_post.set_field_value('subtitle', 'Sub Title', {group_number: 1})
|
288
277
|
# sample: my_post.set_field_value('subtitle', 'Sub Title', {group_number: 1, group_number: 1}) # add field values for fields in group 1
|
289
278
|
def set_field_value(key, value, args = {})
|
290
|
-
args = { order: 0, group_number: 0, field_id: nil, clear: true }.merge(args)
|
279
|
+
args = { order: 0, group_number: 0, field_id: nil, clear: true }.merge!(args)
|
291
280
|
unless args[:field_id].present?
|
292
281
|
args[:field_id] = begin
|
293
282
|
get_field_object(key).id
|
@@ -25,7 +25,7 @@ module CamaleonCms
|
|
25
25
|
else
|
26
26
|
title = 'Welcome'
|
27
27
|
slug = 'welcome'
|
28
|
-
content = "<p style='text-align: center;'><img width='155' height='155' src='
|
28
|
+
content = "<p style='text-align: center;'><img width='155' height='155' src='https://camaleon.website/media/132/logo2.png' alt='logo' /></p><p><strong>Camaleon CMS</strong> is a free and open-source tool and a fexible content management system (CMS) based on <a href='https://rubyonrails.org'>Ruby on Rails</a>.</p> <p>With Camaleon you can do the following:</p> <ul> <li>Create instantly a lot of sites in the same installation</li> <li>Manage your content information in several languages</li> <li>Extend current functionality by plugins (MVC structure and no more echo or prints anywhere)</li> <li>Create or install different themes for each site</li> <li>Create your own structure without coding anything (adapt Camaleon as you want and not you for Camaleon)</li> <li>Create your store and start to sell your products using our plugins</li> <li>Avoid web attacks</li> <li>Compare the speed and enjoy the speed of your new Camaleon site</li> <li>Customize or create your themes for mobile support</li> <li>Support more visitors at the same time</li> <li>Manage your information with a panel like wordpress </li> <li>All urls are oriented for SEO</li> <li>Multiples roles of users</li> </ul>"
|
29
29
|
end
|
30
30
|
user = users.admin_scope.first
|
31
31
|
unless user.present?
|
@@ -14,18 +14,17 @@ module CamaleonCms
|
|
14
14
|
)
|
15
15
|
.where.not(id: record.id)
|
16
16
|
.where.not(status: %i[draft draft_child trash])
|
17
|
-
|
18
|
-
record.errors[:base] <<
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
end
|
17
|
+
unless posts.empty?
|
18
|
+
record.errors[:base] <<
|
19
|
+
if slug_array.size > 1
|
20
|
+
"#{I18n.t('camaleon_cms.admin.post.message.requires_different_slug')}: #{posts.pluck(:slug).map do |slug|
|
21
|
+
record.slug.to_s.translations.map do |lng, r_slug|
|
22
|
+
"#{r_slug} (#{lng})" if slug.translations_array.include?(r_slug)
|
23
|
+
end.join(',')
|
24
|
+
end.join(',').split(',').uniq.clean_empty.join(', ')} "
|
25
|
+
else
|
26
|
+
"#{I18n.t('camaleon_cms.admin.post.message.requires_different_slug')}: #{record.slug} "
|
27
|
+
end
|
29
28
|
end
|
30
29
|
|
31
30
|
# avoid recursive page parent
|
@@ -3,9 +3,15 @@ module CamaleonCms
|
|
3
3
|
def validate(record)
|
4
4
|
return if record.skip_slug_validation?
|
5
5
|
|
6
|
-
|
7
|
-
|
8
|
-
|
6
|
+
taxonomy_table = CamaleonCms::TermTaxonomy.table_name
|
7
|
+
slug_exists = CamaleonCms::TermTaxonomy.where(slug: record.slug)
|
8
|
+
.where.not(id: record.id)
|
9
|
+
.where("#{taxonomy_table}.taxonomy" => record.taxonomy)
|
10
|
+
.where("#{taxonomy_table}.parent_id" => record.parent_id).exists?
|
11
|
+
|
12
|
+
return unless slug_exists
|
13
|
+
|
14
|
+
record.errors[:base] << I18n.t('camaleon_cms.admin.post.message.requires_different_slug').to_s
|
9
15
|
end
|
10
16
|
end
|
11
17
|
end
|
@@ -48,7 +48,7 @@
|
|
48
48
|
<fieldset>
|
49
49
|
<legend><%= t("camaleon_cms.admin.media.external", default: 'From URL') %></legend>
|
50
50
|
<div class="form-group">
|
51
|
-
<input type="text" name="remote_file" class="form-control" placeholder="
|
51
|
+
<input type="text" name="remote_file" class="form-control" placeholder="https://..." class="required">
|
52
52
|
</div>
|
53
53
|
<div class="form-group">
|
54
54
|
<button type="submit" class="btn btn-primary"><%= t("camaleon_cms.admin.button.submit") %></button>
|