camaleon_cms 2.7.5 → 2.8.1
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 -27
- 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/assets/stylesheets/camaleon_cms/admin/admin-manifest.css +2 -1
- data/app/assets/stylesheets/camaleon_cms/admin/{colorpicker.css.scss → colorpicker.css} +5 -5
- 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/media_controller.rb +12 -9
- 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 +7 -7
- 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 +60 -17
- data/app/models/camaleon_cms/ability.rb +1 -1
- data/app/models/camaleon_cms/custom_field_group.rb +3 -6
- 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_aws_uploader.rb +3 -3
- data/app/uploaders/camaleon_cms_local_uploader.rb +10 -4
- data/app/uploaders/camaleon_cms_uploader.rb +13 -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/admin/settings/custom_fields/_get_items.html.erb +1 -2
- data/app/views/camaleon_cms/admin/settings/custom_fields/_render.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/config/initializers/sass.rb +12 -16
- data/lib/camaleon_cms/engine.rb +2 -2
- 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 +53 -39
@@ -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?
|
@@ -36,11 +36,11 @@ class CamaleonCmsAwsUploader < CamaleonCmsUploader
|
|
36
36
|
end
|
37
37
|
|
38
38
|
def fetch_file(file_name)
|
39
|
-
|
39
|
+
return file_name if file_exists?(file_name)
|
40
40
|
|
41
|
-
|
41
|
+
return file_name if bucket.object(file_name).download_file(file_name) && file_exists?(file_name)
|
42
42
|
|
43
|
-
|
43
|
+
{ error: 'File not found' }
|
44
44
|
end
|
45
45
|
|
46
46
|
# parse an AWS file into custom file_object
|
@@ -1,8 +1,8 @@
|
|
1
1
|
class CamaleonCmsLocalUploader < CamaleonCmsUploader
|
2
2
|
def after_initialize
|
3
|
-
@root_folder = @
|
3
|
+
@root_folder = @current_site.upload_directory
|
4
4
|
|
5
|
-
FileUtils.mkdir_p(@root_folder)
|
5
|
+
FileUtils.mkdir_p(@root_folder) unless Dir.exist?(@root_folder)
|
6
6
|
end
|
7
7
|
|
8
8
|
def setup_private_folder
|
@@ -25,9 +25,11 @@ class CamaleonCmsLocalUploader < CamaleonCmsUploader
|
|
25
25
|
end
|
26
26
|
|
27
27
|
def fetch_file(file_name)
|
28
|
-
|
28
|
+
return { error: 'Invalid file path' } if file_name.include?('..')
|
29
|
+
|
30
|
+
return file_name if file_exists?(file_name)
|
29
31
|
|
30
|
-
|
32
|
+
{ error: 'File not found' }
|
31
33
|
end
|
32
34
|
|
33
35
|
def file_parse(key)
|
@@ -107,6 +109,8 @@ class CamaleonCmsLocalUploader < CamaleonCmsUploader
|
|
107
109
|
|
108
110
|
# remove an existent folder
|
109
111
|
def delete_folder(key)
|
112
|
+
return { error: 'Invalid folder path' } if key.include?('..')
|
113
|
+
|
110
114
|
folder = File.join(@root_folder, key)
|
111
115
|
FileUtils.rm_rf(folder) if Dir.exist? folder
|
112
116
|
get_media_collection.find_by_key(key).take.destroy
|
@@ -114,6 +118,8 @@ class CamaleonCmsLocalUploader < CamaleonCmsUploader
|
|
114
118
|
|
115
119
|
# remove an existent file
|
116
120
|
def delete_file(key)
|
121
|
+
return { error: 'Invalid file path' } if key.include?('..')
|
122
|
+
|
117
123
|
file = File.join(@root_folder, key)
|
118
124
|
FileUtils.rm(file) if File.exist? file
|
119
125
|
@instance.hooks_run('after_delete', key)
|
@@ -125,6 +125,14 @@ class CamaleonCmsUploader
|
|
125
125
|
valid_formats.include?(File.extname(key).sub('.', '').split('?').first.try(:downcase))
|
126
126
|
end
|
127
127
|
|
128
|
+
def self.valid_folder_path?(path)
|
129
|
+
return true if path == '/'
|
130
|
+
|
131
|
+
return false if path.include?('..') || File.absolute_path?(path) || path.include?('://')
|
132
|
+
|
133
|
+
true
|
134
|
+
end
|
135
|
+
|
128
136
|
# verify if this file name already exist
|
129
137
|
# if the file is already exist, return a new name for this file
|
130
138
|
# sample: search_new_key("my_file/file.txt")
|
@@ -158,6 +166,11 @@ class CamaleonCmsUploader
|
|
158
166
|
File.exist?(file_name)
|
159
167
|
end
|
160
168
|
|
169
|
+
def self.delete_block(&block)
|
170
|
+
@delete_block = block if block
|
171
|
+
@delete_block
|
172
|
+
end
|
173
|
+
|
161
174
|
private
|
162
175
|
|
163
176
|
def cache_key
|
@@ -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>
|
@@ -10,7 +10,7 @@
|
|
10
10
|
<hr>
|
11
11
|
<div class="alert alert-info">Gmail Need Permissions:
|
12
12
|
<div class="pull-left">
|
13
|
-
<a href="
|
13
|
+
<a href="https://know.mailsbestfriend.com/smtp_error_password_command_failed_5345714-1194946499.shtml" target="_blank">Check
|
14
14
|
here.</a>
|
15
15
|
</div>
|
16
16
|
<div class="pull-right">
|
@@ -55,4 +55,4 @@
|
|
55
55
|
return false;
|
56
56
|
});
|
57
57
|
});
|
58
|
-
</script>
|
58
|
+
</script>
|
@@ -23,7 +23,6 @@
|
|
23
23
|
<div class="panel-body">
|
24
24
|
<%= hidden_field(:fields, :id, index: @index, value: @item_id) %>
|
25
25
|
<%= hidden_field(:field_options, :field_key, index: @index, value: @key) %>
|
26
|
-
<%= hidden_field(:field_options, :label_eval, index: @index, value: @item_options_value[:label_eval].to_s.cama_true? ? 'true' : '') %>
|
27
26
|
<%= hidden_field(:field_options, :panel_hidden, index: @index, value: @item_options_value[:panel_hidden], class: 'input-panel-hidden') %>
|
28
27
|
<div class="form-group input-group-sm">
|
29
28
|
<label for=""><%= t('camaleon_cms.admin.table.name') %></label><br>
|
@@ -182,4 +181,4 @@
|
|
182
181
|
jQuery(function () {
|
183
182
|
$('#<%= @panel_id %>').find('.translatable').Translatable();
|
184
183
|
})
|
185
|
-
</script>
|
184
|
+
</script>
|
@@ -20,14 +20,14 @@
|
|
20
20
|
<input name="<%= field_name %>[<%= field.slug %>][id]" type="hidden" value="<%= field.id %>"/>
|
21
21
|
<input name="<%= field_name %>[<%= field.slug %>][group_number]" class="cama_custom_group_number" type="hidden" value="0"/>
|
22
22
|
<label>
|
23
|
-
<%= field.
|
23
|
+
<%= field.name %>
|
24
24
|
<%= raw "<em class='text-danger'>*</em>" if field.options[:required].to_s.to_bool %>
|
25
25
|
<% if current_site.get_option('custom_fields_show_shortcodes') && ["post", "posttype", "category", "postTag", "site", "user", "navmenu", "theme"].include?(obj_class) %>
|
26
26
|
<small class="shortcode_field"><br><%= raw cama_shortcode_print("[data field='#{field.slug}' #{"object='#{obj_class}' #{"id='#{record.id}'" if obj_class != "Theme" }" unless record.new_record?}]") %></small>
|
27
27
|
<% end %>
|
28
28
|
</label>
|
29
29
|
<% if field.description.present? %>
|
30
|
-
<p><small><%= field.
|
30
|
+
<p><small><%= field.description %></small></p>
|
31
31
|
<% end %>
|
32
32
|
<div class="editor-custom-fields content-field-<%= field.id %>" data-add_field_title="<%= t('camaleon_cms.admin.button.add_new_field', default: 'Add new field')%>">
|
33
33
|
<%= begin
|
@@ -12,19 +12,19 @@
|
|
12
12
|
<!-- Wrapper for slides -->
|
13
13
|
<div class="carousel-inner">
|
14
14
|
<div class="item active">
|
15
|
-
<img src="
|
15
|
+
<img src="https://placehold.it/800x400" alt="...">
|
16
16
|
<div class="carousel-caption">
|
17
17
|
<h2>Heading</h2>
|
18
18
|
</div>
|
19
19
|
</div>
|
20
20
|
<div class="item">
|
21
|
-
<img src="
|
21
|
+
<img src="https://placehold.it/800x400" alt="...">
|
22
22
|
<div class="carousel-caption">
|
23
23
|
<h2>Heading</h2>
|
24
24
|
</div>
|
25
25
|
</div>
|
26
26
|
<div class="item">
|
27
|
-
<img src="
|
27
|
+
<img src="https://placehold.it/800x400" alt="...">
|
28
28
|
<div class="carousel-caption">
|
29
29
|
<h2>Heading</h2>
|
30
30
|
</div>
|
@@ -67,4 +67,4 @@
|
|
67
67
|
</div>
|
68
68
|
|
69
69
|
</div>
|
70
|
-
</section>
|
70
|
+
</section>
|
@@ -1,7 +1,7 @@
|
|
1
1
|
xml.instruct! :xml, version: '1.0'
|
2
|
-
xml.urlset 'xmlns' => '
|
2
|
+
xml.urlset 'xmlns' => 'https://www.sitemaps.org/schemas/sitemap/0.9' do
|
3
3
|
current_site.get_languages.each_with_index do |lang, index|
|
4
|
-
lang = (index
|
4
|
+
lang = (index == 0 ? nil : lang)
|
5
5
|
xml.url do
|
6
6
|
xml.loc current_site.the_url(locale: lang)
|
7
7
|
xml.lastmod current_site.updated_at.to_date
|
@@ -54,7 +54,7 @@ xml.urlset 'xmlns' => 'http://www.sitemaps.org/schemas/sitemap/0.9' do
|
|
54
54
|
end
|
55
55
|
end
|
56
56
|
|
57
|
-
@r[:custom].
|
57
|
+
@r[:custom].each_value do |item|
|
58
58
|
xml.url do
|
59
59
|
xml.loc item[:url]
|
60
60
|
xml.lastmod item[:lastmod] || Date.today.to_s
|
@@ -1,6 +1,6 @@
|
|
1
1
|
<footer class="main-footer" id="main-footer">
|
2
2
|
<div class="row">
|
3
|
-
<div class="col-md-6"><strong>Copyright © 2015 - <%= Time.now.year %> <a href="
|
3
|
+
<div class="col-md-6"><strong>Copyright © 2015 - <%= Time.now.year %> <a href="https://camaleon.website">Camaleon CMS.</a> </strong></div>
|
4
4
|
<div class="col-md-6 hidden-xs">
|
5
5
|
<div class="pull-left">
|
6
6
|
<a id="link_see_intro" href="#" onclick="init_intro(); return false;"><i class="fa fa-tv"></i> <%= I18n.t('camaleon_cms.see_intro') %>.</a>
|
@@ -9,4 +9,18 @@ Rails.application.config.to_prepare do |_config|
|
|
9
9
|
f = File.join(ap['path'], 'config', 'custom_models.rb')
|
10
10
|
eval(File.read(f)) if File.exist?(f)
|
11
11
|
end
|
12
|
+
|
13
|
+
# This block can be overridden in the app initializer to wrap the sleep and delete_file in an async job,
|
14
|
+
# something like this:
|
15
|
+
#
|
16
|
+
# CamaleonDeleteFileJob.set(wait: temporal_time).perform_later(file_key)
|
17
|
+
# # put this in app/jobs/camaleon_delete_file_job.rb:
|
18
|
+
# include CamaleonCms::UploaderHelper
|
19
|
+
# cama_uploader.delete_file(file_key)
|
20
|
+
CamaleonCmsUploader.delete_block do |settings, cama_uploader, file_key|
|
21
|
+
next unless Rails.env.test?
|
22
|
+
|
23
|
+
sleep(settings[:temporal_time])
|
24
|
+
cama_uploader.delete_file(file_key)
|
25
|
+
end
|
12
26
|
end
|
data/config/initializers/sass.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'sassc'
|
2
|
+
|
1
3
|
module Sprockets
|
2
4
|
# Processor engine class for the SASS/SCSS compiler. Depends on the `sass` gem.
|
3
5
|
#
|
@@ -11,23 +13,23 @@ module Sprockets
|
|
11
13
|
# return them path (this prefix automatically the path with current theme location)
|
12
14
|
# Sample: .container{ background: #ffffff url(asset_theme_path('img/patterns/pattern1.jpg')); }
|
13
15
|
def asset_theme_path(path, options = {})
|
14
|
-
asset_path(
|
16
|
+
asset_path(::SassC::Script::Value::String.new("#{get_theme_prefix}/#{path.value}".gsub('//', '/')), options)
|
15
17
|
end
|
16
18
|
|
17
19
|
# return them path (this prefix automatically the path with current theme location)
|
18
20
|
# Sample: .container{ background: #ffffff asset-theme-url('img/patterns/pattern1.jpg'); }
|
19
21
|
def asset_theme_url(path, options = {})
|
20
|
-
asset_url(
|
22
|
+
asset_url(::SassC::Script::Value::String.new("#{get_theme_prefix}/#{path.value}".gsub('//', '/')), options)
|
21
23
|
end
|
22
24
|
|
23
25
|
# return them path (this prefix automatically the path with current theme location)
|
24
26
|
def asset_plugin_path(path, options = {})
|
25
|
-
asset_path(
|
27
|
+
asset_path(::SassC::Script::Value::String.new("#{get_plugin_prefix}/#{path.value}"), options)
|
26
28
|
end
|
27
29
|
|
28
30
|
# return them path (this prefix automatically the path with current theme location)
|
29
31
|
def asset_plugin_url(path, options = {})
|
30
|
-
asset_url(
|
32
|
+
asset_url(::SassC::Script::Value::String.new("#{get_plugin_prefix}/#{path.value}"), options)
|
31
33
|
end
|
32
34
|
|
33
35
|
private
|
@@ -35,23 +37,17 @@ module Sprockets
|
|
35
37
|
# get plugin asset prefix
|
36
38
|
def get_plugin_prefix
|
37
39
|
file = options[:filename]
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
'assets/'
|
42
|
-
end}"
|
43
|
-
end
|
44
|
-
res
|
40
|
+
return '' unless file.include?('/plugins/')
|
41
|
+
|
42
|
+
"plugins/#{file.split('/plugins/').last.split('/').first}/#{file.include?('apps/plugins/') ? 'assets/' : ''}"
|
45
43
|
end
|
46
44
|
|
47
45
|
# get theme asset prefix
|
48
46
|
def get_theme_prefix
|
49
47
|
file = options[:filename]
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
end
|
54
|
-
res
|
48
|
+
return '' unless file.include?('/themes/')
|
49
|
+
|
50
|
+
"themes/#{file.split('/themes/').last.split('/').first}/#{'assets/' if file.include?('apps/themes/')}"
|
55
51
|
end
|
56
52
|
end
|
57
53
|
end
|
data/lib/camaleon_cms/engine.rb
CHANGED
@@ -10,7 +10,7 @@ require 'aws-sdk-s3'
|
|
10
10
|
require 'font-awesome-rails'
|
11
11
|
require 'tinymce-rails'
|
12
12
|
require 'jquery-rails'
|
13
|
-
require '
|
13
|
+
require 'dartsass-sprockets'
|
14
14
|
require 'cama_contact_form'
|
15
15
|
require 'cama_meta_tag'
|
16
16
|
|
@@ -59,7 +59,7 @@ module CamaleonCms
|
|
59
59
|
app.config.assets.paths << File.join($camaleon_engine_dir, 'app', 'assets', 'fonts')
|
60
60
|
app.config.encoding = 'utf-8'
|
61
61
|
|
62
|
-
# add prefix url, like:
|
62
|
+
# add prefix url, like: https://localhost.com/blog/
|
63
63
|
# config.action_controller.relative_url_root = PluginRoutes.system_info["relative_url_root"] if PluginRoutes.system_info["relative_url_root"].present?
|
64
64
|
|
65
65
|
# multiple route files
|
data/lib/camaleon_cms/version.rb
CHANGED
data/lib/ext/hash.rb
CHANGED
data/lib/ext/string.rb
CHANGED
@@ -66,11 +66,11 @@ class String
|
|
66
66
|
end
|
67
67
|
|
68
68
|
# parse string into domain
|
69
|
-
#
|
69
|
+
# https://owen.camaleon.website into owen.camaleon.website
|
70
70
|
def parse_domain
|
71
71
|
url = self
|
72
72
|
uri = URI.parse(url)
|
73
|
-
uri = URI.parse("
|
73
|
+
uri = URI.parse("https://#{url}") if uri.scheme.nil?
|
74
74
|
host = (uri.host || self).downcase
|
75
75
|
h = host.start_with?('www.') ? host[4..] : host
|
76
76
|
"#{h}#{":#{uri.port}" unless [80, 443].include?(uri.port)}"
|