scrivito_sdk 0.66.0 → 0.70.0.rc1

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.
Files changed (73) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/scrivito/blobs_controller.rb +5 -0
  3. data/app/controllers/scrivito/objs_controller.rb +2 -1
  4. data/app/controllers/scrivito/ui_controller.rb +33 -3
  5. data/app/helpers/scrivito_helper.rb +14 -20
  6. data/app/views/scrivito/objs/update.json.jbuilder +1 -1
  7. data/app/views/scrivito/ui/index.html.erb +1 -1
  8. data/app/views/scrivito/webservice/_workspace.json.jbuilder +2 -1
  9. data/config/ca-bundle.crt +1 -1
  10. data/config/precedence_routes.rb +3 -2
  11. data/lib/assets/javascripts/scrivito.js +46 -0
  12. data/lib/assets/javascripts/scrivito_ui.js +931 -501
  13. data/lib/assets/stylesheets/scrivito.css +1 -0
  14. data/lib/assets/stylesheets/scrivito_ui.css +1 -1
  15. data/lib/generators/scrivito/install/templates/app/views/page/index.html.erb +3 -3
  16. data/lib/generators/scrivito/page/page_generator.rb +3 -0
  17. data/lib/generators/scrivito/page/templates/model.erb +3 -0
  18. data/lib/generators/scrivito/widget/templates/model.erb +3 -0
  19. data/lib/generators/scrivito/widget/widget_generator.rb +3 -0
  20. data/lib/scrivito/attribute_content.rb +93 -60
  21. data/lib/scrivito/attribute_definition.rb +3 -3
  22. data/lib/scrivito/attribute_serializer.rb +2 -2
  23. data/lib/scrivito/backend/obj_data_cache.rb +22 -9
  24. data/lib/scrivito/basic_obj.rb +238 -130
  25. data/lib/scrivito/basic_widget.rb +32 -20
  26. data/lib/scrivito/binary.rb +74 -45
  27. data/lib/scrivito/binary_routing.rb +52 -0
  28. data/lib/scrivito/cache_middleware.rb +0 -5
  29. data/lib/scrivito/client_attribute_serializer.rb +134 -0
  30. data/lib/scrivito/cms_backend.rb +51 -33
  31. data/lib/scrivito/cms_data_cache.rb +1 -0
  32. data/lib/scrivito/cms_dispatch_controller.rb +1 -1
  33. data/lib/scrivito/cms_env.rb +1 -11
  34. data/lib/scrivito/cms_field_tag.rb +10 -7
  35. data/lib/scrivito/cms_rest_api/rate_limit.rb +5 -5
  36. data/lib/scrivito/cms_rest_api/request_timer.rb +27 -0
  37. data/lib/scrivito/cms_rest_api/widget_extractor.rb +8 -6
  38. data/lib/scrivito/cms_rest_api.rb +107 -54
  39. data/lib/scrivito/cms_routing.rb +13 -25
  40. data/lib/scrivito/configuration.rb +5 -2
  41. data/lib/scrivito/controller_actions.rb +68 -7
  42. data/lib/scrivito/controller_runtime.rb +8 -0
  43. data/lib/scrivito/date_attribute.rb +8 -0
  44. data/lib/scrivito/errors.rb +6 -3
  45. data/lib/scrivito/generator_helper.rb +13 -0
  46. data/lib/scrivito/image_tag.rb +24 -30
  47. data/lib/scrivito/layout_tags.rb +12 -6
  48. data/lib/scrivito/link.rb +46 -30
  49. data/lib/scrivito/log_subscriber.rb +15 -0
  50. data/lib/scrivito/membership.rb +3 -3
  51. data/lib/scrivito/membership_collection.rb +10 -10
  52. data/lib/scrivito/meta_data_collection.rb +22 -0
  53. data/lib/scrivito/model_library.rb +7 -1
  54. data/lib/scrivito/obj_collection.rb +18 -16
  55. data/lib/scrivito/obj_params_parser.rb +1 -1
  56. data/lib/scrivito/obj_search_enumerator.rb +35 -35
  57. data/lib/scrivito/page_config.rb +55 -0
  58. data/lib/scrivito/request_homepage.rb +23 -0
  59. data/lib/scrivito/routing_helper.rb +8 -8
  60. data/lib/scrivito/sdk_engine.rb +2 -3
  61. data/lib/scrivito/ui_config.rb +85 -0
  62. data/lib/scrivito/user.rb +30 -23
  63. data/lib/scrivito/user_definition.rb +48 -47
  64. data/lib/scrivito/widget_tag.rb +11 -0
  65. data/lib/scrivito/workspace.rb +93 -35
  66. data/lib/scrivito/workspace_selection_middleware.rb +8 -1
  67. data/lib/scrivito_sdk.rb +24 -24
  68. metadata +24 -33
  69. data/lib/assets/javascripts/scrivito_sdk.js +0 -57
  70. data/lib/assets/stylesheets/scrivito_sdk.css +0 -1
  71. data/lib/scrivito/client_config.rb +0 -113
  72. data/lib/scrivito/editing_context_helper.rb +0 -19
  73. data/lib/scrivito/named_link.rb +0 -39
@@ -1,6 +1,10 @@
1
1
  module Scrivito
2
2
 
3
- # The CMS widget class
3
+ # The CMS widget class. Widget classes let you create widget types for the individual kinds
4
+ # of content editors want to place on pages or into widgets. All widget classes are based on
5
+ # subclasses of {Scrivito::BasicWidget Widget}. As with CMS objects, the content of a widget
6
+ # is stored in its attributes.
7
+ # @see http://scrivito.com/page-with-widgets Creating a page type with widgets
4
8
  # @api public
5
9
  class BasicWidget
6
10
  extend AttributeContent::ClassMethods
@@ -67,13 +71,13 @@ class BasicWidget
67
71
  # @api public
68
72
  # @param [Hash] attributes
69
73
  #
70
- # @example Create a widget using a subclass
71
- # # you can create widgets by explicitly providing the attribute `_obj_class`
74
+ # @example Create a widget using a subclass:
75
+ # # you can create widgets by explicitly providing the '_obj_class' attribute
72
76
  # new_widget = Widget.new(_obj_class: "MyWidget")
73
77
  # # but it is better to simply use the constructor of a subclass
74
78
  # new_widget = MyWidget.new
75
79
  #
76
- # @example Create a widget and store it inside an Obj
80
+ # @example Create a widget and store it inside an Obj:
77
81
  # # create the widget
78
82
  # new_widget = Widget.new(_obj_class: "MyWidget")
79
83
  # # store it inside an obj
@@ -85,12 +89,15 @@ class BasicWidget
85
89
  end
86
90
 
87
91
  #
88
- # Creates a new {Scrivito::BasicWidget Widget}.
92
+ # Creates a new {Scrivito::BasicWidget Widget}. The defaults set via
93
+ # {Scrivito::AttributeContent::ClassMethods#default_for Widget.default_for}
94
+ # are taken into account.
89
95
  #
90
96
  # @api public
91
97
  #
92
- # It also considers the defaults set via
93
- # {Scrivito::AttributeContent::ClassMethods#default_for Widget.default_for}.
98
+ # @note Note that creating a widget does not implicitly persist it. The widget is only persisted
99
+ # if its creation is part of the creation of the object containing it, or as the object or
100
+ # widget containing it is updated.
94
101
  #
95
102
  # @param [Hash] attributes for the new widget
96
103
  # @param [Hash] context in which the object creating should happen
@@ -112,9 +119,14 @@ class BasicWidget
112
119
  obj.revision
113
120
  end
114
121
 
115
- # Update the attributes of this Widget
122
+ # Updates the attributes of this {Scrivito::BasicWidget Widget}.
123
+ # See {Scrivito::BasicObj.create Obj.create} for a detailed overview of how to set attributes.
124
+ # @example Set the title of a specific widget contained in the 'main_content' attribute of an Obj:
125
+ # obj.main_content[4].update(title: "New Title")
116
126
  #
117
- # See {Scrivito::BasicObj.create Obj.create} for a detailed overview of how to set attributes
127
+ # @example Add a widget to the 'main_content' widgetlist attribute:
128
+ # widgets = obj.main_content << MyWidget.new(title: "Fresh")
129
+ # obj.update(main_content: widgets)
118
130
  # @api public
119
131
  # @param [Hash] attributes
120
132
  def update(attributes)
@@ -122,7 +134,7 @@ class BasicWidget
122
134
  reload
123
135
  end
124
136
 
125
- # Destroys the {Scrivito::BasicWidget Widget} in the current {Workspace}
137
+ # Destroys the {Scrivito::BasicWidget Widget} in the current {Workspace}.
126
138
  # @api public
127
139
  def destroy
128
140
  new_widget_list = container[container_attribute_name] - [self]
@@ -134,11 +146,11 @@ class BasicWidget
134
146
  #
135
147
  # @api public
136
148
  #
137
- # The copy will have all attributes of the original widget including its widgets.
138
- # Its attributes can be accessed only after it has been stored in a widget field of an
139
- # {Scrivito::BasicObj Obj}, since initially the copy is not stored in any widget field.
149
+ # The copy will have all the attributes of the original widget including its widgets.
150
+ # Its attributes can be accessed only after it has been stored in a +widgetlist+ field of an
151
+ # {Scrivito::BasicObj Obj}, since initially the copy is not stored in such a field.
140
152
  #
141
- # @example Duplicate the first widget in field +my_widget+
153
+ # @example Duplicate the first widget contained in the +my_widget+ field.
142
154
  # obj.update(my_widgets: obj.my_widgets.push(obj.my_widgets.first.copy))
143
155
  #
144
156
  def copy
@@ -197,9 +209,9 @@ class BasicWidget
197
209
  #
198
210
  # @api public
199
211
  #
200
- # @note This method does not support +Widget+s, which are +new+.
212
+ # @note This method does not support +new+ +Widget+s.
201
213
  # Please use {Scrivito::BasicWidget#destroy Widget#destroy} to destroy them.
202
- # @note This method does not support +Widget+s, which are +deleted+.
214
+ # @note This method does not support +deleted+ +Widget+s.
203
215
  # Please use {Scrivito::BasicObj#revert Obj#revert} to restore them.
204
216
  #
205
217
  # @raise [ScrivitoError] If the current workspace is +published+.
@@ -265,19 +277,19 @@ class BasicWidget
265
277
  end
266
278
  end
267
279
 
268
- # returns the entity ({Scrivito::BasicObj} or {Scrivito::BasicWidget}) that references this widget
280
+ # Returns the entity ({Scrivito::BasicObj} or {Scrivito::BasicWidget}) that references this widget.
269
281
  # @api public
270
282
  def container
271
283
  @container || container_and_attribute_name.first
272
284
  end
273
285
 
274
- # returns the name of the widget attribute that references this widget
286
+ # Returns the name of the +widgetlist+ attribute that references this widget.
275
287
  # @api public
276
288
  def container_attribute_name
277
289
  @container_attribute_name || container_and_attribute_name.second
278
290
  end
279
291
 
280
- # returns the name of the widget field that references this widget
292
+ # Returns the name of the 'widgetlist' field that references this widget.
281
293
  # @api public
282
294
  # @deprecated
283
295
  def container_field_name
@@ -328,7 +340,7 @@ class BasicWidget
328
340
  end
329
341
 
330
342
  # @api public
331
- # This method determines the description to be shown in the widget tooltips. By default,
343
+ # This method determines the description to be shown as widget tooltips. By default,
332
344
  # it uses the value of the +Widget.description_for_editor+ class method.
333
345
  #
334
346
  # This method can be overridden to customize the description displayed to the editor.
@@ -1,8 +1,8 @@
1
1
  module Scrivito
2
2
 
3
3
  # @api public
4
- # The Binary class represents the data stored in a binary attribute of an Obj
5
- # or Widget
4
+ # The Binary class represents the data stored in a binary attribute of an {Scrivito::BasicObj Obj}
5
+ # or a {Scrivito::BasicWidget Widget}.
6
6
  class Binary
7
7
  attr_reader :id, :transformation_definition
8
8
 
@@ -29,6 +29,12 @@ class Binary
29
29
  # @api public
30
30
  # The URL for accessing the binary data and downloading it using an HTTP GET request.
31
31
  #
32
+ # @note The URL is calculated on demand, i.e. if the URL has not been cached yet,
33
+ # this method calls the Scrivito API to retrieve the URL.
34
+ # If you want to link to a Binary, consider using {Scrivito::RoutingHelper#scrivito_url}
35
+ # instead. This is generally much faster,
36
+ # as it performs the Scrivito API call asynchronously.
37
+ #
32
38
  # @note URLs for private content have an expiration time in order to protect them.
33
39
  # Therefore, the URL should be accessed immediately after it has been returned
34
40
  # (i.e. within a couple of minutes). Accessing it after expiration causes an error.
@@ -49,39 +55,40 @@ class Binary
49
55
  end
50
56
 
51
57
  # @api public
52
- # the filename of this binary data, for example "my_image.jpg"
53
- # @return [String] the filename of binary
58
+ # The filename of this binary data, for example "my_image.jpg".
59
+ # @return [String] the filename of the binary
54
60
  def filename
55
61
  File.basename(URI(url).path)
56
62
  end
57
63
 
58
64
  # @api public
59
- # the content type of this binary data, for example "image/jpeg"
65
+ # The content type of this binary data, for example "image/jpeg".
60
66
  # @return [String] content type
61
67
  def content_type
62
68
  headers[:content_type]
63
69
  end
64
70
 
65
71
  # @api public
66
- # the length of this binary data, in bytes.
72
+ # The length of this binary data, in bytes.
67
73
  # @return [Integer] number of bytes
68
74
  def content_length
69
75
  headers[:content_length].to_i
70
76
  end
71
77
 
72
78
  #
73
- # Returns a transformed {Scrivito::Binary}.
79
+ # Use this method to transform images, i.e. to scale down large images or to generate thumbnails of images.
80
+ # Only applicable if this {Scrivito::Binary} is an image.
74
81
  #
75
- # @api beta
82
+ # @api public
76
83
  #
77
- # Calling this method will not change the binary, but instead return a copy of it,
84
+ # This method does not change the binary. Instead, it returns a copy of it,
78
85
  # transformed using the +definition+.
79
86
  #
80
- # If the original binary has already been transformed, then the returned binary will be a
81
- # combination of the transformations. Thus the transformations can be chained (see examples).
87
+ # If the original binary has already been transformed, the returned binary will be a
88
+ # combination of the transformations. Thus, the transformations can be chained (see examples).
82
89
  #
83
- # The transformed data is calculated "lazily", so calling {Scrivito::Binary#transform} will not
84
- # trigger any calculation. The calculation will be triggered only if data is accessed, for example
90
+ # The transformed data is calculated "lazily", so calling {Scrivito::Binary#transform} does not
91
+ # trigger any calculation. The calculation is triggered only when data is accessed, for example
85
92
  # via {Scrivito::Binary#url}.
86
93
  #
87
94
  # @param [Hash] definition transformation definition
@@ -89,87 +96,90 @@ class Binary
89
96
  # @option definition [Fixnum,String] :width The width in pixels of the output image. Must be a
90
97
  # positive integer.
91
98
  #
92
- # If only this dimension is specified, the other dimension will be calculated automatically to
99
+ # If only this dimension has been specified, the other dimension is calculated automatically to
93
100
  # preserve the aspect ratio of the input image.
94
101
  #
95
- # If the +fit+ parameter is set to +:clip+, then the actual output one of width and height may
96
- # be equal to or less than the dimensions you specify to prevent distortion.
102
+ # If the +fit+ parameter is set to +:clip+, then either the actual output width or the output
103
+ # height may be less than the amount you specified to prevent distortion.
97
104
  #
98
105
  # If neither +width+ nor +height+ is given, the width and height of the input image
99
- # will be used.
106
+ # is used.
100
107
  #
101
- # The maximum output image size width + height = 4096 pixels. The given width and height may be
102
- # adjusted to accomodate this limit. The output image will never be larger than the source
103
- # image, i.e. the given width and height may be adjusted to keep the output image from exceeding
104
- # the dimensions of the input image.
108
+ # The maximum size of the output image is defined as width + height = 4096 pixels. The given
109
+ # width and height may be adjusted to accommodate this limit. The output image will never be
110
+ # larger than the source image, i.e. the given width and height may be adjusted to prevent the
111
+ # dimensions of the output image from exceeding those of the input image.
105
112
  #
106
- # When the given width and height are adjusted, the aspect ratio is preserved.
113
+ # If the given width and height are adjusted, the aspect ratio is preserved.
107
114
  #
108
115
  # @option definition [Fixnum,String] :height The height in pixels of the output image. Must be a
109
116
  # positive integer.
110
117
  #
111
- # If only this dimension is specified, the other dimension will be calculated automatically to
118
+ # If only this dimension has been specified, the other dimension is calculated automatically to
112
119
  # preserve the aspect ratio of the input image.
113
120
  #
114
- # If the +fit+ parameter is set to +:clip+, then the actual output one of width and height may
115
- # be equal to or less than the dimensions you specify to prevent distortion.
121
+ # If the +fit+ parameter is set to +:clip+, then either the actual output width or the output
122
+ # height may be less than the amount you specified to prevent distortion.
116
123
  #
117
124
  # If neither +width+ nor +height+ is given, the width and height of the input image
118
- # will be used.
125
+ # is used.
119
126
  #
120
- # The maximum output image size width + height = 4096 pixels. The given width and height may be
121
- # adjusted to accomodate this limit. The output image will never be larger than the source
122
- # image, i.e. the given width and height may be adjusted to keep the output image from exceeding
123
- # the dimensions of the input image.
127
+ # The maximum size of the output image is defined as width + height = 4096 pixels. The given
128
+ # width and height may be adjusted to accommodate this limit. The output image will never be
129
+ # larger than the source image, i.e. the given width and height may be adjusted to prevent the
130
+ # dimensions of the output image from exceeding those of the input image.
124
131
  #
125
- # When the given width and height are adjusted, the aspect ratio is preserved.
132
+ # If the given width and height are adjusted, the aspect ratio is preserved.
126
133
  #
127
134
  # @option definition [Symbol,String] :fit Controls how the tranformed image is fitted to the
128
135
  # given width and heigth. Valid values are +:clip+ and +:crop+. The default value is +:clip+.
129
136
  #
130
- # If set to +:clip+ it resizes the image to fit within the width and height boundaries without
131
- # cropping or distorting the image. The resulting image is assured to match one of the
137
+ # If set to +:clip+, the image is resized so as to fit within the width and height boundaries
138
+ # without cropping or distorting the image. The resulting image is assured to match one of the
132
139
  # constraining dimensions, while the other dimension is altered to maintain the same aspect
133
140
  # ratio of the input image.
134
141
  #
135
- # If set to +:crop+ it resizes the image to fill the given width and height and preserves the
136
- # aspect ration by cropping any excess image data. The resulting image will match both the given
137
- # width and height without distorting the image. The crop is done centered, i.e. the center of
142
+ # If set to +:crop+, the image is resized so as to fill the given width and height, preserving
143
+ # the aspect ratio by cropping any excess image data. The resulting image will match both the given
144
+ # width and height without distorting the image. Cropping is done centered, i.e. the center of
138
145
  # the image is preserved.
139
146
  #
140
147
  # @option definition [Fixnum,String] :quality Controls the output quality of lossy file formats.
141
- # Applies when the format is +"jpg"+. Valid values are in the range from +0+ to +100+.
148
+ # Applies if the format is +"jpg"+. Valid values are in the range from +0+ to +100+.
142
149
  # The default value is +75+.
143
150
  #
144
151
  # @return [Scrivito::Binary] transformed binary
145
152
  #
146
- # @example Crop image to fit into 50 x 50 pixel square
153
+ # @example Crop image to fit into 50 x 50 pixel square.
147
154
  # @obj.blob.transform(width: 50, height: 50, fit: :crop)
148
155
  #
149
- # @example Convert image to a low quality JPEG
156
+ # @example Convert image to a low quality JPEG.
150
157
  # @obj.blob.transform(quality: 25)
151
158
  #
152
- # @example Combine the both transformations
159
+ # @example Combine two transformations.
153
160
  # @obj.blob.transform(width: 50, height: 50, fit: :crop).transform(quality: 25)
154
161
  #
162
+ # @see Scrivito::Configuration
163
+ # @see ScrivitoHelper#scrivito_image_tag
164
+ #
155
165
  def transform(definition)
156
166
  self.class.new(id, public?, (transformation_definition || {}).merge(definition), original)
157
167
  end
158
168
 
159
169
  #
160
- # Returns whether a binary is transformed.
161
- # @api beta
170
+ # Returns whether a binary has been transformed.
171
+ # @api public
162
172
  #
163
173
  def transformed?
164
174
  !!transformation_definition
165
175
  end
166
176
 
167
177
  #
168
- # Returns the transformation original of a binary.
178
+ # Returns the original version of a transformed binary.
169
179
  #
170
- # @api beta
180
+ # @api public
171
181
  #
172
- # If a binary is a result of a transformation, then its original binary is returned.
182
+ # If a binary is the result of a transformation, the original version of the binary is returned.
173
183
  # Otherwise +self+.
174
184
  #
175
185
  # @return [Scrivito::Binary] original binary
@@ -184,6 +194,13 @@ class Binary
184
194
  @original || self
185
195
  end
186
196
 
197
+ def meta_data
198
+ @meta_data ||= begin
199
+ deserialized_meta_data = deserialize_meta_data(CmsBackend.instance.find_binary_meta_data(id))
200
+ MetaDataCollection.new(deserialized_meta_data)
201
+ end
202
+ end
203
+
187
204
  private
188
205
 
189
206
  def public_content?
@@ -211,6 +228,18 @@ class Binary
211
228
  def access_type
212
229
  public? ? 'public_access' : 'private_access'
213
230
  end
231
+
232
+ def deserialize_meta_data(raw_meta_data)
233
+ deserialized_meta_data = {}
234
+ raw_meta_data.each_pair do |key, (type, value)|
235
+ deserialized_meta_data[key] = case type
236
+ when 'date' then DateAttribute.parse(value)
237
+ when 'number' then value.to_i
238
+ else value
239
+ end
240
+ end
241
+ deserialized_meta_data
242
+ end
214
243
  end
215
244
 
216
245
  end
@@ -0,0 +1,52 @@
1
+ module Scrivito
2
+
3
+ class BinaryRouting < Struct.new(:request, :scrivito_engine)
4
+ def binary_url(binary)
5
+ binary_url_from_cache(binary) || binary_redirect_url(binary)
6
+ end
7
+
8
+ def binary_obj_url(obj, binary, image_options = {})
9
+ binary = if image_options.has_key?(:transform)
10
+ apply_custom_transformation(binary, image_options[:transform])
11
+ else
12
+ apply_default_transformation(binary, obj)
13
+ end
14
+ binary_url(binary)
15
+ end
16
+
17
+ def resolved_binary_obj_url(obj, binary)
18
+ apply_default_transformation(binary, obj).url
19
+ end
20
+
21
+ private
22
+
23
+ def binary_url_from_cache(binary)
24
+ if url_from_cache = binary.url_from_cache
25
+ BinaryRewrite.call(request, url_from_cache)
26
+ end
27
+ end
28
+
29
+ def binary_redirect_url(binary)
30
+ encrypted_params = BinaryParamVerifier.generate(binary)
31
+ scrivito_engine.binary_path(encrypted_params: encrypted_params)
32
+ end
33
+
34
+ def apply_custom_transformation(binary, transformation_definition)
35
+ if transformation_definition
36
+ binary.transform(transformation_definition)
37
+ else
38
+ binary
39
+ end
40
+ end
41
+
42
+ def apply_default_transformation(binary, obj)
43
+ if (transformation_definition = Scrivito::Configuration.default_image_transformation) &&
44
+ obj.apply_image_transformation?
45
+ binary.transform(transformation_definition)
46
+ else
47
+ binary
48
+ end
49
+ end
50
+ end
51
+
52
+ end
@@ -7,7 +7,6 @@ class CacheMiddleware
7
7
 
8
8
  def call(env)
9
9
  clear_caches
10
- clear_runtime
11
10
 
12
11
  @app.call(env)
13
12
  end
@@ -15,10 +14,6 @@ class CacheMiddleware
15
14
 
16
15
  private
17
16
 
18
- def clear_runtime
19
- Scrivito::LogSubscriber.reset_runtime
20
- end
21
-
22
17
  def clear_caches
23
18
  Workspace.cache.clear
24
19
  CmsBackend.instance.clear_cache
@@ -0,0 +1,134 @@
1
+ module Scrivito
2
+
3
+ module ClientAttributeSerializer
4
+ def self.serialize_obj(obj)
5
+ serialized_output = {}
6
+
7
+ # system attributes
8
+ serialized_output.merge!(serialize_system_attrs(obj))
9
+
10
+ # custom attributes
11
+ serialized_output.merge!(serialize_custom_attrs(obj))
12
+
13
+ # _widget_pool
14
+ serialized_output.merge!(serialize_widget_pool(obj.widgets))
15
+
16
+ serialized_output
17
+ end
18
+
19
+ def self.serialize_system_attrs(obj)
20
+ {
21
+ '_id' => obj.id,
22
+ '_obj_class' => obj.obj_class_name,
23
+ '_path' => obj.path,
24
+ '_permalink' => obj.permalink,
25
+ }
26
+ end
27
+
28
+ def self.serialize_custom_attrs(obj_or_widget)
29
+ Hash[
30
+ obj_or_widget.attribute_definitions.map do |definition|
31
+ name = definition.name
32
+ type = definition.type
33
+ value = obj_or_widget[name]
34
+
35
+ [name, serialize_custom_attr_value(type, value)]
36
+ end
37
+ ]
38
+ end
39
+
40
+ def self.serialize_widget_pool(widgets)
41
+ {
42
+ '_widget_pool' => Hash[
43
+ widgets.map do |widget|
44
+ [widget.id, serialize_widget(widget)]
45
+ end
46
+ ]
47
+ }
48
+ end
49
+
50
+ def self.serialize_custom_attr_value(type, value)
51
+ return unless value
52
+
53
+ case type
54
+ when 'binary' then serialize_binary_value(value)
55
+ when 'date' then serialize_date_value(value)
56
+ when 'enum' then serialize_enum_value(value)
57
+ when 'html' then serialize_html_value(value)
58
+ when 'link' then serialize_link_value(value)
59
+ when 'linklist' then serialize_linklist_value(value)
60
+ when 'multienum' then serialize_multienum_value(value)
61
+ when 'reference' then serialize_reference_value(value)
62
+ when 'referencelist' then serialize_referencelist_value(value)
63
+ when 'string' then serialize_string_value(value)
64
+ when 'stringlist' then serialize_stringlist_value(value)
65
+ when 'widgetlist' then serialize_widgetlist_value(value)
66
+ end
67
+ end
68
+
69
+ def self.serialize_binary_value(value)
70
+ {'url' => value.url, 'filename' => value.filename}
71
+ end
72
+
73
+ def self.serialize_date_value(value)
74
+ value.utc.iso8601
75
+ end
76
+
77
+ def self.serialize_enum_value(value)
78
+ value
79
+ end
80
+
81
+ def self.serialize_html_value(value)
82
+ value
83
+ end
84
+
85
+ def self.serialize_link_value(value)
86
+ value.to_cms_api_linklist_params.stringify_keys
87
+ end
88
+
89
+ def self.serialize_linklist_value(value)
90
+ value.map do |link|
91
+ serialize_link_value(link)
92
+ end
93
+ end
94
+
95
+ def self.serialize_multienum_value(value)
96
+ value.map do |enum|
97
+ serialize_enum_value(enum)
98
+ end
99
+ end
100
+
101
+ def self.serialize_reference_value(value)
102
+ value.id
103
+ end
104
+
105
+ def self.serialize_referencelist_value(value)
106
+ value.map do |reference|
107
+ serialize_reference_value(reference)
108
+ end
109
+ end
110
+
111
+ def self.serialize_string_value(value)
112
+ value
113
+ end
114
+
115
+ def self.serialize_stringlist_value(value)
116
+ value.map do |string|
117
+ serialize_string_value(string)
118
+ end
119
+ end
120
+
121
+ def self.serialize_widgetlist_value(value)
122
+ value.map do |widget|
123
+ widget.id
124
+ end
125
+ end
126
+
127
+ def self.serialize_widget(widget)
128
+ {
129
+ '_obj_class' => widget.obj_class_name
130
+ }.merge(serialize_custom_attrs(widget))
131
+ end
132
+ end
133
+
134
+ end