module CamaleonCms
class CustomFieldGroup < CamaleonCms::CustomField
self.primary_key = :id
# attrs required: name, slug, description
alias_attribute :site_id, :parent_id
default_scope do
where("object_class != '_fields'")
.reorder("#{CamaleonCms::CustomField.table_name}.field_order ASC")
end
has_many :metas, -> { where(object_class: 'CustomFieldGroup') }, foreign_key: :objectid, dependent: :destroy
has_many :fields, -> { where(object_class: '_fields') }, class_name: 'CamaleonCms::CustomField',
foreign_key: :parent_id, dependent: :destroy
belongs_to :site, foreign_key: :parent_id, required: false
validates_uniqueness_of :slug, scope: %i[object_class objectid parent_id]
before_validation :before_validating
# add fields to group
# item:
# - sample: {"name"=>"Label", "slug"=>"my_slug", "description"=>"my description (optional)"}
# - options (textbox sample): {"field_key":"text_box","multiple":"1","required":"1",
# "translate":"1"}
# * field_key (string) | translate (boolean) | default_value (unique value) |
# default_values (array - multiple values for this field) | multiple_options (array)
# * multiple_options (used for select, radio and checkboxes ): [{"title"=>"Option Title",
# "value"=>"2", "default"=>"1"}, {"title"=>"abcde", "value"=>"3"}]
# ****** check all options for each case in Admin::CustomFieldsHelper ****
# SAMPLE: my_model.add_field({"name"=>"Sub Title", "slug"=>"subtitle"}, {"field_key"=>"text_box",
# "translate"=>true, default_value: "Get in Touch"})
def add_manual_field(item, options)
c = get_field(item[:slug] || item['slug'])
return c if c.present?
field_item = fields.new(item)
if field_item.save
field_item.set_options(options)
auto_save_default_values(field_item, options)
end
field_item
end
alias add_field add_manual_field
# return a field with slug = slug from current group
def get_field(slug)
fields.find_by(slug: slug)
end
# only used by form on admin panel (protected)
# return array of failed_fields and full_fields [[failed fields], [all fields]]
def add_fields(items, item_options)
fields.where.not(id: items.to_h.map { |_k, obj| obj['id'] }.uniq).destroy_all
cache_fields = []
order_index = 0
errors_saved = []
if items.present?
items.each do |i, item|
item[:field_order] = order_index
options = item_options[i] || {}
if item[:id].present? && (field_item = fields.find_by(id: item[:id])).present?
saved = field_item.update(item)
cache_fields << field_item
else
field_item = fields.new(item)
cache_fields << field_item
saved = field_item.save
auto_save_default_values(field_item, options) if saved
errors_saved << field_item unless saved
end
if saved
field_item.set_meta('_default', options)
order_index += 1
end
end
end
[errors_saved, cache_fields]
end
# generate the caption for this group
def get_caption
caption = ''
begin
case object_class
when 'PostType_Post'
caption = "Fields for Contents in #{site.post_types.find(objectid).decorate.the_title}"
when 'PostType_Category'
caption = "Fields for Categories in #{site.post_types.find(objectid).decorate.the_title}"
when 'PostType_PostTag'
caption = "Fields for Post tags in #{site.post_types.find(objectid).decorate.the_title}"
when 'Widget::Main'
caption = "Fields for Widget (#{CamaleonCms::Widget::Main.find(objectid).name.translate})"
when 'Theme'
caption = "Field settings for Theme (#{begin
site.themes.find(objectid).name
rescue StandardError
objectid
end})"
when 'NavMenu'
caption = "Field settings for Menus (#{CamaleonCms::NavMenu.find(objectid).name})"
when 'Site'
caption = 'Field settings the site'
when 'PostType'
caption = 'Fields for all Post_Types'
when 'Post'
p = CamaleonCms::Post.find(objectid).decorate
caption = "Fields for content (#{p.the_title})"
else # 'Plugin' or other class
caption = "Fields for #{object_class}"
end
rescue StandardError => e
Rails.logger.debug "Camaleon CMS - Menu Item Error: #{e.message} ==> Attrs: #{attributes}"
end
caption
end
private
def before_validating
self.slug = "_group-#{name.to_s.parameterize}" unless slug.present?
end
# auto save the default field values
def auto_save_default_values(field, options)
class_name = object_class.split('_').first
return unless %w[Post Category Plugin
Theme].include?(class_name) && objectid && (options[:default_value].present? || options[:default_values].present?)
owner = if class_name == 'Theme'
"CamaleonCms::#{class_name}".constantize.find(objectid) # owner model
else
begin
"CamaleonCms::#{class_name}".constantize.find(objectid)
rescue StandardError
"CamaleonCms::#{class_name}".constantize.find_by(slug: objectid)
end
end
(options[:default_values] || [options[:default_value]] || []).each do |value|
if owner.present?
owner.custom_field_values.create!(custom_field_id: field.id, custom_field_slug: field.slug,
value: fix_meta_value(value))
end
end
end
end
end