lib/scrivito/basic_widget.rb in scrivito_sdk-0.50.1 vs lib/scrivito/basic_widget.rb in scrivito_sdk-0.60.0.rc1
- old
+ new
@@ -1,26 +1,60 @@
module Scrivito
# The CMS widget class
# @api public
class BasicWidget
+ # @!parse extend Scrivito::AttributeContent::ClassMethods
+
include AttributeContent
def self.type_computer
@_type_computer ||= TypeComputer.new(Scrivito::BasicWidget, ::Widget)
end
def self.reset_type_computer!
@_type_computer = nil
end
- def self.hide_from_widget_class_selection?
- false
+ #
+ # @api public
+ # This method can be overridden in subclasses to control to which pages or
+ # widgets the given widget class can be added. This method can be used
+ # to ensure that only a special type of widget can be added to a specific
+ # container. An example for this is a +TabGroupWidget+ that should
+ # contain widgets of the +TabWidget+ type only, and, vice versa, a +TabWidget+
+ # should only be contained in a +TabGroupWidget+. A value of +nil+ means that
+ # no additional restrictions are applied.
+ #
+ # This method only further restricts the list of valid classes defined
+ # by means of {AttributeContent#valid_widget_classes_for}.
+ #
+ # @return [Array<String, Symbol, Class>, nil]
+ #
+ # @example
+ # class TabGroupWidget < Widget
+ # def valid_widget_classes_for(field_name)
+ # [TabWidget]
+ # end
+ # end
+ #
+ # class TabWidget < Widget
+ # def self.valid_container_classes
+ # [TabGroupWidget]
+ # end
+ # end
+ #
+ def self.valid_container_classes
end
- attr_accessor :container, :container_field_name
+ def self.valid_inside_container?(container_class)
+ valid_container_classes.nil? ||
+ valid_container_classes.map(&:to_s).include?(container_class.name)
+ end
+ attr_accessor :container, :container_attribute_name
+
attr_writer :obj, :id
attr_reader :attributes_to_be_saved
delegate :widget_from_pool, to: :obj
@@ -44,13 +78,22 @@
# new_widget = Widget.new(_obj_class: "MyWidget")
# # store it inside an obj
# my_obj(my_widget_field: [new_widget])
#
def initialize(attributes = {})
- @attributes_to_be_saved = self.class.with_default_obj_class(attributes)
+ @attributes_to_be_saved = self.class.prepare_attributes_for_instantiation(attributes)
+ @attribute_cache = {}
end
+ def self.new(attributes = {})
+ if obj_class = extract_obj_class_from_attributes(attributes)
+ obj_class.new(attributes)
+ else
+ super
+ end
+ end
+
def revision
obj.revision
end
# Update the attributes of this Widget
@@ -64,12 +107,12 @@
end
# Destroys the {Scrivito::BasicWidget Widget} in the current {Workspace}
# @api public
def destroy
- new_widget_list = container[container_field_name] - [self]
- container.update(container_field_name => new_widget_list)
+ new_widget_list = container[container_attribute_name] - [self]
+ container.update(container_attribute_name => new_widget_list)
end
#
# Create a copy of a {Scrivito::BasicWidget Widget}.
#
@@ -81,29 +124,34 @@
#
# @example Duplicate the first widget in field +my_widget+
# obj.update(my_widgets: obj.my_widgets.push(obj.my_widgets.first.copy))
#
def copy
- attrs = {}
- each_custom_attribute do |attr_name, attr_value, attr_type|
- attrs[attr_name] = attr_type == 'widget' ? attr_value.map(&:copy) : attr_value
+ attributes = {}
+ attribute_definitions.each do |attribute_definition|
+ attribute_name = attribute_definition.name
+ attribute_value = read_attribute(attribute_name)
+ attribute_value = attribute_value.map(&:copy) if attribute_definition.widgetlist?
+ attributes[attribute_name] = attribute_value
end
- self.class.new(attrs)
+ self.class.new(attributes)
end
def copy_for_restore(referenced_ids)
- attrs = {}
- each_custom_attribute do |attr_name, attr_value, attr_type|
- attrs[attr_name] = if attr_type == 'widget'
- attr_value.reject { |widget| referenced_ids.include?(widget.id) }
+ attributes = {}
+ attribute_definitions.each do |attribute_definition|
+ attribute_name = attribute_definition.name
+ attribute_value = read_attribute(attribute_name)
+ if attribute_definition.widgetlist?
+ attribute_value = attribute_value
+ .reject { |widget| referenced_ids.include?(widget.id) }
.map { |widget| widget.copy_for_restore(referenced_ids) }
- else
- attr_value
end
+ attributes[attribute_name] = attribute_value
end
- attrs['_id'] = id
- self.class.new(attrs)
+ attributes['_id'] = id
+ self.class.new(attributes)
end
def clone
raise "The method `clone' was removed. Please use `copy' instead"
end
@@ -152,11 +200,11 @@
when Modification::EDITED
previous_obj_content =
CmsRestApi.get("revisions/#{workspace.base_revision_id}/objs/#{obj.id}")
previous_widget_content = previous_obj_content["_widget_pool"]["#{id}"]
previous_widget_content.delete_if do |attribute_name, _|
- type_of_attribute(attribute_name) == "widget"
+ type_of_attribute(attribute_name) == 'widgetlist'
end
CmsRestApi.put("workspaces/#{workspace.id}/objs/#{obj.id}",
{ obj: {_widget_pool: {id => previous_widget_content}} })
else
raise ScrivitoError, "cannot revert changes, since widget is #{modification}."
@@ -203,21 +251,31 @@
end
# returns the entity ({Scrivito::BasicObj} or {Scrivito::BasicWidget}) that references this widget
# @api public
def container
- @container || cache_container_and_field_name_for_widget.first
+ @container || container_and_attribute_name.first
end
+ # returns the name of the widget attribute that references this widget
+ # @api public
+ def container_attribute_name
+ @container_attribute_name || container_and_attribute_name.second
+ end
+
# returns the name of the widget field that references this widget
# @api public
+ # @deprecated
def container_field_name
- @container_field_name || cache_container_and_field_name_for_widget.second
+ Scrivito::Deprecation.warn('Scrivito::BasicWidget#container_field_name is deprecated'\
+ ' and will be removed in a future version.'\
+ ' Please use Scrivito::BasicWidget#container_attribute_name instead.')
+ container_attribute_name
end
- def container_field_index
- container[container_field_name].index(self)
+ def container_attribute_index
+ container[container_attribute_name].index(self)
end
def has_attribute?(key)
key.to_s == '_obj_class' || super
end
@@ -259,43 +317,51 @@
# @api public
def description_for_editor
obj_class_name
end
+ def data_from_cms
+ if persisted?
+ super
+ else
+ raise_not_persisted_error
+ end
+ end
+
private
def workspace
if revision.workspace
revision.workspace
else
raise ScrivitoError, "No workspace set for the obj of this widget"
end
end
- def data_from_cms
- if persisted?
- super
- else
- raise_not_persisted_error
- end
- end
-
def raise_not_persisted_error
raise ScrivitoError.new('Can not access a new widget before it has been saved')
end
def cms_data_for_revision(revision)
obj.widget_data_for_revision(id, revision)
end
- def cache_container_and_field_name_for_widget
- @cache_container_and_field_name_for_widget ||= obj.container_and_field_name_for_widget(id)
+ def container_and_attribute_name
+ @container_and_attribute_name ||= obj.find_container_and_attribute_name_for_widget(id)
end
- def each_custom_attribute
- data_from_cms.all_custom_attributes.each do |attr_name|
- yield attr_name, read_attribute(attr_name), type_of_attribute(attr_name)
- end
+ def has_system_attribute?(attribute_name)
+ attribute_name == '_obj_class'
+ end
+
+ alias_method :has_public_system_attribute?, :has_system_attribute?
+
+ def type_of_system_attribute(attribute_name)
+ 'string' if attribute_name == 'obj_class'
+ end
+
+ def value_of_system_attribute(attribute_name)
+ data_from_cms.value_of(attribute_name)
end
end
end