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.
- checksums.yaml +4 -4
- data/app/controllers/scrivito/blobs_controller.rb +5 -0
- data/app/controllers/scrivito/objs_controller.rb +2 -1
- data/app/controllers/scrivito/ui_controller.rb +33 -3
- data/app/helpers/scrivito_helper.rb +14 -20
- data/app/views/scrivito/objs/update.json.jbuilder +1 -1
- data/app/views/scrivito/ui/index.html.erb +1 -1
- data/app/views/scrivito/webservice/_workspace.json.jbuilder +2 -1
- data/config/ca-bundle.crt +1 -1
- data/config/precedence_routes.rb +3 -2
- data/lib/assets/javascripts/scrivito.js +46 -0
- data/lib/assets/javascripts/scrivito_ui.js +931 -501
- data/lib/assets/stylesheets/scrivito.css +1 -0
- data/lib/assets/stylesheets/scrivito_ui.css +1 -1
- data/lib/generators/scrivito/install/templates/app/views/page/index.html.erb +3 -3
- data/lib/generators/scrivito/page/page_generator.rb +3 -0
- data/lib/generators/scrivito/page/templates/model.erb +3 -0
- data/lib/generators/scrivito/widget/templates/model.erb +3 -0
- data/lib/generators/scrivito/widget/widget_generator.rb +3 -0
- data/lib/scrivito/attribute_content.rb +93 -60
- data/lib/scrivito/attribute_definition.rb +3 -3
- data/lib/scrivito/attribute_serializer.rb +2 -2
- data/lib/scrivito/backend/obj_data_cache.rb +22 -9
- data/lib/scrivito/basic_obj.rb +238 -130
- data/lib/scrivito/basic_widget.rb +32 -20
- data/lib/scrivito/binary.rb +74 -45
- data/lib/scrivito/binary_routing.rb +52 -0
- data/lib/scrivito/cache_middleware.rb +0 -5
- data/lib/scrivito/client_attribute_serializer.rb +134 -0
- data/lib/scrivito/cms_backend.rb +51 -33
- data/lib/scrivito/cms_data_cache.rb +1 -0
- data/lib/scrivito/cms_dispatch_controller.rb +1 -1
- data/lib/scrivito/cms_env.rb +1 -11
- data/lib/scrivito/cms_field_tag.rb +10 -7
- data/lib/scrivito/cms_rest_api/rate_limit.rb +5 -5
- data/lib/scrivito/cms_rest_api/request_timer.rb +27 -0
- data/lib/scrivito/cms_rest_api/widget_extractor.rb +8 -6
- data/lib/scrivito/cms_rest_api.rb +107 -54
- data/lib/scrivito/cms_routing.rb +13 -25
- data/lib/scrivito/configuration.rb +5 -2
- data/lib/scrivito/controller_actions.rb +68 -7
- data/lib/scrivito/controller_runtime.rb +8 -0
- data/lib/scrivito/date_attribute.rb +8 -0
- data/lib/scrivito/errors.rb +6 -3
- data/lib/scrivito/generator_helper.rb +13 -0
- data/lib/scrivito/image_tag.rb +24 -30
- data/lib/scrivito/layout_tags.rb +12 -6
- data/lib/scrivito/link.rb +46 -30
- data/lib/scrivito/log_subscriber.rb +15 -0
- data/lib/scrivito/membership.rb +3 -3
- data/lib/scrivito/membership_collection.rb +10 -10
- data/lib/scrivito/meta_data_collection.rb +22 -0
- data/lib/scrivito/model_library.rb +7 -1
- data/lib/scrivito/obj_collection.rb +18 -16
- data/lib/scrivito/obj_params_parser.rb +1 -1
- data/lib/scrivito/obj_search_enumerator.rb +35 -35
- data/lib/scrivito/page_config.rb +55 -0
- data/lib/scrivito/request_homepage.rb +23 -0
- data/lib/scrivito/routing_helper.rb +8 -8
- data/lib/scrivito/sdk_engine.rb +2 -3
- data/lib/scrivito/ui_config.rb +85 -0
- data/lib/scrivito/user.rb +30 -23
- data/lib/scrivito/user_definition.rb +48 -47
- data/lib/scrivito/widget_tag.rb +11 -0
- data/lib/scrivito/workspace.rb +93 -35
- data/lib/scrivito/workspace_selection_middleware.rb +8 -1
- data/lib/scrivito_sdk.rb +24 -24
- metadata +24 -33
- data/lib/assets/javascripts/scrivito_sdk.js +0 -57
- data/lib/assets/stylesheets/scrivito_sdk.css +0 -1
- data/lib/scrivito/client_config.rb +0 -113
- data/lib/scrivito/editing_context_helper.rb +0 -19
- data/lib/scrivito/named_link.rb +0 -39
data/lib/scrivito/basic_obj.rb
CHANGED
@@ -4,11 +4,19 @@ require 'active_model/naming'
|
|
4
4
|
|
5
5
|
module Scrivito
|
6
6
|
#
|
7
|
-
# The abstract base class for
|
7
|
+
# The abstract base class for CMS objects.
|
8
8
|
#
|
9
|
-
#
|
9
|
+
# A CMS object is a collection of properties and their values, as defined
|
10
|
+
# by its object class. These properties can be accessed in views, either
|
11
|
+
# directly as the object itself is rendered, or indirectly when other objects
|
12
|
+
# are rendered. The description of an image, for example, can be retrieved
|
13
|
+
# from within any view that requires it, e.g. a page on which the image is
|
14
|
+
# displayed.
|
15
|
+
#
|
16
|
+
# @note Please do not use {Scrivito::BasicObj} directly
|
10
17
|
# as it is intended as an abstract class.
|
11
18
|
# Always use {Obj} or a subclass of {Obj}.
|
19
|
+
# @see http://scrivito.com/objects-widgets-classes CMS objects, widgets, and classes
|
12
20
|
# @api public
|
13
21
|
#
|
14
22
|
class BasicObj
|
@@ -59,27 +67,27 @@ module Scrivito
|
|
59
67
|
#
|
60
68
|
# @api public
|
61
69
|
#
|
62
|
-
# This allows you to set the different attributes
|
63
|
-
#
|
64
|
-
#
|
70
|
+
# This allows you to set the different attributes of an Obj by providing a hash containing the
|
71
|
+
# attribute names as keys and the corresponding values you want to set. The defaults set via
|
72
|
+
# {Scrivito::AttributeContent::ClassMethods#default_for Obj.default_for} are taken into account.
|
65
73
|
#
|
66
|
-
# @param [Hash] attributes
|
67
|
-
# @param [Hash] context in which the object
|
74
|
+
# @param [Hash] attributes of the new obj
|
75
|
+
# @param [Hash] context in which the object is created
|
68
76
|
# @option context [Scrivito::User] :scrivito_user current visitor
|
69
77
|
# @return [Obj] the newly created {Scrivito::BasicObj Obj}
|
70
78
|
#
|
71
79
|
# @see Scrivito::AttributeContent::ClassMethods#default_for
|
72
80
|
#
|
73
|
-
# @example
|
81
|
+
# @example Provide reference lists as an Array of {Scrivito::BasicObj Obj}.
|
74
82
|
# Obj.create(:reference_list => [other_obj])
|
75
83
|
#
|
76
|
-
# @example Passing an {Scrivito::BasicObj Obj} allows you to set a reference
|
84
|
+
# @example Passing an {Scrivito::BasicObj Obj} allows you to set a reference.
|
77
85
|
# Obj.create(:reference => other_obj)
|
78
86
|
#
|
79
|
-
# @example
|
87
|
+
# @example You can upload files by passing a Ruby File object.
|
80
88
|
# Obj.create(:blob => File.new("image.png"))
|
81
89
|
#
|
82
|
-
# @example
|
90
|
+
# @example A link list can be set as an Array of {Link Links}.
|
83
91
|
# Obj.create(:link_list => [
|
84
92
|
# # external link
|
85
93
|
# Link.new(:url => "http://www.example.com", :title => "Example"),
|
@@ -89,34 +97,35 @@ module Scrivito
|
|
89
97
|
#
|
90
98
|
# @example Passing a {Link Link} allows you to set a link.
|
91
99
|
# Obj.create(
|
92
|
-
# external_link: Link.new(url: 'http://www.example.com', title: 'Example')
|
100
|
+
# external_link: Link.new(url: 'http://www.example.com', title: 'Example'),
|
93
101
|
# internal_link: Link.new(obj: other_obj, title: 'Other Obj')
|
94
102
|
# )
|
95
103
|
#
|
96
|
-
# @example
|
104
|
+
# @example Date attributes accept Time, Date and their subclasses (DateTime, for example).
|
97
105
|
# Obj.create(:date => Time.new)
|
98
106
|
# Obj.create(:date => Date.now)
|
99
107
|
#
|
100
|
-
# @example String, html and enum can be set by passing a {String} value
|
108
|
+
# @example String, html and enum attributes can be set by passing a {String} value.
|
101
109
|
# Obj.create(:title => "My Title")
|
102
110
|
#
|
103
|
-
# @example
|
111
|
+
# @example Multienum attributes can be set using an Array of {String Strings}.
|
104
112
|
# Obj.create(:tags => ["ruby", "rails"])
|
105
113
|
#
|
106
|
-
# @example Simply pass an Array of {Scrivito::BasicWidget Widgets} to
|
114
|
+
# @example Simply pass an Array of {Scrivito::BasicWidget Widgets} to populate a widget field. See {Scrivito::BasicWidget#copy Widget#copy} on how to copy a widget.
|
107
115
|
# # Add new widgets
|
108
116
|
# Obj.create(:widgets => [Widget.new(_obj_class: 'TitleWidget', title: 'My Title')])
|
109
117
|
#
|
110
|
-
# # Add a widget
|
118
|
+
# # Add a copy of a widget
|
111
119
|
# Obj.create(:widgets => [another_obj.widgets.first.copy])
|
112
120
|
#
|
113
|
-
# #
|
121
|
+
# # Change a widget field
|
114
122
|
# obj.update(:widgets => [obj.widgets.first])
|
115
123
|
#
|
116
124
|
# # Clear a widget field
|
117
125
|
# obj.update(:widgets => [])
|
118
126
|
#
|
119
127
|
def self.create(attributes = {}, context = {})
|
128
|
+
attributes = with_default_id_attribute(attributes)
|
120
129
|
if obj_class = extract_obj_class_from_attributes(attributes)
|
121
130
|
obj_class.create(attributes, context)
|
122
131
|
else
|
@@ -131,8 +140,8 @@ module Scrivito
|
|
131
140
|
end
|
132
141
|
|
133
142
|
# Create a new {Scrivito::BasicObj Obj} instance with the given values and attributes.
|
134
|
-
# Normally this method should not be used.
|
135
|
-
# Instead
|
143
|
+
# Normally, this method should not be used.
|
144
|
+
# Instead, CMS objects should be retrieved from the CMS database.
|
136
145
|
def initialize(attributes = {})
|
137
146
|
update_data(ObjDataFromHash.new(attributes))
|
138
147
|
end
|
@@ -153,8 +162,10 @@ module Scrivito
|
|
153
162
|
|
154
163
|
### FINDERS ####################
|
155
164
|
|
156
|
-
# Find
|
157
|
-
# If the parameter is an Array
|
165
|
+
# Find an {Scrivito::BasicObj Obj} by its id.
|
166
|
+
# If the parameter is an Array of ids, the list of corresponding objects is returned.
|
167
|
+
# @example Find several CMS objects at once:
|
168
|
+
# Obj.find(['id1', 'id2'])
|
158
169
|
# @param [String, Integer, Array<String, Integer>]id_or_list
|
159
170
|
# @return [Obj, Array<Obj>]
|
160
171
|
# @api public
|
@@ -166,8 +177,8 @@ module Scrivito
|
|
166
177
|
Workspace.current.objs.find_by_id(id)
|
167
178
|
end
|
168
179
|
|
169
|
-
# Find
|
170
|
-
# If the parameter is an Array containing ids, return a list of corresponding
|
180
|
+
# Find an {Scrivito::BasicObj Obj} by its id.
|
181
|
+
# If the parameter is an Array containing ids, return a list of corresponding objects.
|
171
182
|
# The results include deleted objects as well.
|
172
183
|
# @param [String, Integer, Array<String, Integer>]id_or_list
|
173
184
|
# @return [Obj, Array<Obj>]
|
@@ -176,17 +187,26 @@ module Scrivito
|
|
176
187
|
Workspace.current.objs.find_including_deleted(id_or_list)
|
177
188
|
end
|
178
189
|
|
179
|
-
# Returns
|
190
|
+
# Returns an {ObjSearchEnumerator} with the given initial subquery consisting of the four arguments.
|
180
191
|
#
|
181
192
|
# Note that +field+ and +value+ can also be arrays for searching several fields or searching for several values.
|
182
193
|
#
|
183
|
-
# @note If invoked on a subclass of Obj, the result will be restricted to instances of
|
194
|
+
# @note If invoked on a subclass of Obj, the result will be restricted to instances of this subclass.
|
184
195
|
#
|
185
196
|
# {ObjSearchEnumerator}s can be chained using one of the chainable methods
|
186
197
|
# (e.g. {ObjSearchEnumerator#and} and {ObjSearchEnumerator#and_not}).
|
187
198
|
#
|
188
|
-
# @example Look for
|
199
|
+
# @example Look for objects containing "Lorem", boosting headline matches:
|
200
|
+
# Obj.where(:*, :contains, 'Lorem', headline: 2).to_a
|
201
|
+
#
|
202
|
+
# @example Look for the first 10 objects whose object class is "Pressrelease" and whose title contains "quarterly":
|
189
203
|
# Obj.where(:_obj_class, :equals, 'Pressrelease').and(:title, :contains, 'quarterly').take(10)
|
204
|
+
#
|
205
|
+
# @example Look for all objects whose class is "Item". The path should start with a defined location. Furthermore, select only items of a particular category:
|
206
|
+
# Obj.where(:_obj_class, :equals, 'Item').and(:_path, :starts_with, '/en/items/').select do |item|
|
207
|
+
# item.categories.include?(category)
|
208
|
+
# end
|
209
|
+
#
|
190
210
|
# @param [Symbol, String, Array<Symbol, String>] field See {ObjSearchEnumerator#and} for details
|
191
211
|
# @param [Symbol, String] operator See {ObjSearchEnumerator#and} for details
|
192
212
|
# @param [String, Array<String>] value See {ObjSearchEnumerator#and} for details
|
@@ -204,8 +224,8 @@ module Scrivito
|
|
204
224
|
end
|
205
225
|
end
|
206
226
|
|
207
|
-
# Returns
|
208
|
-
# If invoked on a subclass of Obj, the result
|
227
|
+
# Returns an {ObjSearchEnumerator} of all {Scrivito::BasicObj Obj}s.
|
228
|
+
# If invoked on a subclass of Obj, the result is restricted to instances of this subclass.
|
209
229
|
# @return [ObjSearchEnumerator]
|
210
230
|
# @raise [ScrivitoError] if called directly on +BasicObj+. Use +Obj.all+ instead.
|
211
231
|
# @api public
|
@@ -218,8 +238,8 @@ module Scrivito
|
|
218
238
|
end
|
219
239
|
end
|
220
240
|
|
221
|
-
# Returns
|
222
|
-
# @param [String] obj_class name of the
|
241
|
+
# Returns an {ObjSearchEnumerator} of all CMS objects with the given +obj_class+.
|
242
|
+
# @param [String] obj_class name of the object class.
|
223
243
|
# @return [ObjSearchEnumerator]
|
224
244
|
# @api public
|
225
245
|
def self.find_all_by_obj_class(obj_class)
|
@@ -236,8 +256,8 @@ module Scrivito
|
|
236
256
|
end
|
237
257
|
|
238
258
|
# Find an {Scrivito::BasicObj Obj} with the given name.
|
239
|
-
# If several
|
240
|
-
# If no Obj with
|
259
|
+
# If several objects with the given name exist, an arbitrary one is chosen and returned.
|
260
|
+
# If no Obj with this name exists, +nil+ is returned.
|
241
261
|
# @param [String] name Name of the {Scrivito::BasicObj Obj}.
|
242
262
|
# @return [Obj]
|
243
263
|
# @api public
|
@@ -245,7 +265,7 @@ module Scrivito
|
|
245
265
|
where(:_name, :equals, name).batch_size(1).first
|
246
266
|
end
|
247
267
|
|
248
|
-
# Returns
|
268
|
+
# Returns an {ObjSearchEnumerator} of all CMS objects with the given name.
|
249
269
|
# @param [String] name Name of the {Scrivito::BasicObj Obj}.
|
250
270
|
# @return [ObjSearchEnumerator]
|
251
271
|
# @api public
|
@@ -253,8 +273,8 @@ module Scrivito
|
|
253
273
|
where(:_name, :equals, name)
|
254
274
|
end
|
255
275
|
|
256
|
-
# Returns the {Scrivito::BasicObj Obj} with the given permalink, or +nil+ if no
|
257
|
-
# exists.
|
276
|
+
# Returns the {Scrivito::BasicObj Obj} with the given permalink, or +nil+ if no
|
277
|
+
# matching Obj exists.
|
258
278
|
# @param [String] permalink The permalink of the {Scrivito::BasicObj Obj}.
|
259
279
|
# @return [Obj]
|
260
280
|
# @api public
|
@@ -262,7 +282,7 @@ module Scrivito
|
|
262
282
|
Workspace.current.objs.find_by_permalink(permalink)
|
263
283
|
end
|
264
284
|
|
265
|
-
# Returns the {Scrivito::BasicObj Obj} with the given permalink, or
|
285
|
+
# Returns the {Scrivito::BasicObj Obj} with the given permalink, or raises ResourceNotFound if
|
266
286
|
# no matching Obj exists.
|
267
287
|
# @param [String] permalink The permalink of the {Scrivito::BasicObj Obj}.
|
268
288
|
# @return [Obj]
|
@@ -272,19 +292,19 @@ module Scrivito
|
|
272
292
|
raise ResourceNotFound, "Could not find Obj with permalink '#{permalink}'"
|
273
293
|
end
|
274
294
|
|
275
|
-
# Hook method
|
276
|
-
# Override it to allow only
|
295
|
+
# Hook method that lets you control which page classes are made available for pages with the given path.
|
296
|
+
# Override it to allow only specific classes or none at all.
|
277
297
|
# Must return either +NilClass+, or +Array+.
|
278
298
|
#
|
279
299
|
# Be aware that the given argument is a parent path.
|
280
|
-
# E.g
|
300
|
+
# E.g., when creating a page whose path is +/products/shoes+, the argument must be +/products+.
|
281
301
|
# The given parent path can also be +NilClass+.
|
282
302
|
#
|
283
|
-
# If +NilClass+ is returned,
|
284
|
-
# By default +NilClass+ is returned.
|
303
|
+
# If +NilClass+ is returned, all page classes are made available.
|
304
|
+
# By default, +NilClass+ is returned.
|
285
305
|
#
|
286
|
-
# If +Array+ is returned,
|
287
|
-
#
|
306
|
+
# If an +Array+ is returned, it is expected to contain the available classes.
|
307
|
+
# The order of the classes is preserved.
|
288
308
|
#
|
289
309
|
# @param [String, NilClass] parent_path Path of the parent obj
|
290
310
|
# @return [NilClass, Array<Class>]
|
@@ -297,9 +317,9 @@ module Scrivito
|
|
297
317
|
Scrivito.models.pages.to_a
|
298
318
|
end
|
299
319
|
|
300
|
-
# Update the {Scrivito::BasicObj Obj}
|
320
|
+
# Update the {Scrivito::BasicObj Obj} using the attributes provided.
|
301
321
|
#
|
302
|
-
# For an overview of
|
322
|
+
# For an overview of the values you can set via this method, see the
|
303
323
|
# documentation of {Scrivito::BasicObj.create Obj.create}.
|
304
324
|
#
|
305
325
|
# Additionally, +update+ accepts a +_widget_pool+ hash in +attributes+ to modify widgets.
|
@@ -308,6 +328,20 @@ module Scrivito
|
|
308
328
|
#
|
309
329
|
# @api public
|
310
330
|
# @param [Hash] attributes
|
331
|
+
# @example Update the URL of a link:
|
332
|
+
# link = obj.my_link
|
333
|
+
# link.url = "http://www.example.com"
|
334
|
+
# obj.update(my_link: link)
|
335
|
+
#
|
336
|
+
# @example Update binary attributes:
|
337
|
+
# obj.update(blob: img_obj.binary)
|
338
|
+
# obj.update(thumbnail: File.new("/path/to/small.jpg"))
|
339
|
+
#
|
340
|
+
# @example Remove the first and the last widget from a widget field:
|
341
|
+
# obj.update(
|
342
|
+
# my_widget_field: obj[:my_widget_field][1..-2]
|
343
|
+
# )
|
344
|
+
#
|
311
345
|
# @example Move the +widget_to_move+ widget from the +left+ widget field of the +two_column_widget1+ widget to +left+ of +two_column_widget2+:
|
312
346
|
# obj.update(
|
313
347
|
# _widget_pool: {
|
@@ -317,7 +351,7 @@ module Scrivito
|
|
317
351
|
# headline: "Some widgets were moved!"
|
318
352
|
# )
|
319
353
|
#
|
320
|
-
# @example Move the +widget_to_move+ widget from the +right+ widget field of the +two_column_widget1+ widget to the top-level widget field
|
354
|
+
# @example Move the +widget_to_move+ widget from the +right+ widget field of the +two_column_widget1+ widget to the top-level +main_content+ widget field:
|
321
355
|
# obj.update(
|
322
356
|
# main_content: @obj.main_content + [widget_to_move],
|
323
357
|
# _widget_pool: {
|
@@ -334,7 +368,7 @@ module Scrivito
|
|
334
368
|
self
|
335
369
|
end
|
336
370
|
|
337
|
-
# Creates a copy of the
|
371
|
+
# Creates a copy of the {Scrivito::BasicObj Obj}.
|
338
372
|
# @api public
|
339
373
|
# @param [Hash] options
|
340
374
|
# @option options [String,Symbol] :_path (nil) the path of the copy.
|
@@ -342,16 +376,19 @@ module Scrivito
|
|
342
376
|
# @option options [String,Symbol] :_permalink (nil) the permalink of the copy.
|
343
377
|
# @raise [ArgumentError] if +options+ includes invalid keys.
|
344
378
|
# @return [Obj] the created copy
|
345
|
-
# @example Copy a blog post
|
379
|
+
# @example Copy a blog post:
|
346
380
|
# blog_post = Obj.find_by_path('/blog/first_post')
|
347
381
|
# blog_post.copy(_path: '/blog/second_post')
|
348
382
|
def copy(options={})
|
349
383
|
options = options.stringify_keys.assert_valid_keys('_path', '_id', '_permalink')
|
350
|
-
|
384
|
+
attributes_for_copy = self.class.with_default_id_attribute(copyable_attributes)
|
385
|
+
attributes_for_copy = copy_binaries(attributes_for_copy)
|
386
|
+
|
387
|
+
json = workspace.api_request(:post, '/objs', obj: attributes_for_copy.merge(options))
|
351
388
|
self.class.find(json['_id'])
|
352
389
|
end
|
353
390
|
|
354
|
-
# Destroys the {Scrivito::BasicObj Obj} in the current {Workspace}
|
391
|
+
# Destroys the {Scrivito::BasicObj Obj} in the current {Workspace}.
|
355
392
|
# @api public
|
356
393
|
def destroy
|
357
394
|
if children.any?
|
@@ -364,8 +401,8 @@ module Scrivito
|
|
364
401
|
id
|
365
402
|
end
|
366
403
|
|
367
|
-
#
|
368
|
-
#
|
404
|
+
# Returns the {Scrivito::BasicObj Obj} that is the parent of this Obj.
|
405
|
+
# Returns +nil+ for the root Obj.
|
369
406
|
# @api public
|
370
407
|
def parent
|
371
408
|
if child_path?
|
@@ -373,7 +410,7 @@ module Scrivito
|
|
373
410
|
end
|
374
411
|
end
|
375
412
|
|
376
|
-
# Returns an Array of all the ancestor objects, starting at the root and ending at this object
|
413
|
+
# Returns an Array of all the ancestor objects, starting at the root and ending at the parent of this object.
|
377
414
|
# @return [Array<Obj>]
|
378
415
|
# @api public
|
379
416
|
def ancestors
|
@@ -386,7 +423,7 @@ module Scrivito
|
|
386
423
|
Workspace.current.objs.find_by_paths(ancestor_paths)
|
387
424
|
end
|
388
425
|
|
389
|
-
#
|
426
|
+
# Returns a list of all child {Scrivito::BasicObj Obj}s.
|
390
427
|
# @return [Array<Obj>]
|
391
428
|
# @api public
|
392
429
|
def children
|
@@ -397,13 +434,13 @@ module Scrivito
|
|
397
434
|
|
398
435
|
### ATTRIBUTES #################
|
399
436
|
|
400
|
-
#
|
437
|
+
# Returns the path of the {Scrivito::BasicObj Obj} as a String.
|
401
438
|
# @api public
|
402
439
|
def path
|
403
440
|
read_attribute('_path')
|
404
441
|
end
|
405
442
|
|
406
|
-
#
|
443
|
+
# Returns the name of the {Scrivito::BasicObj Obj}. The name is the last component of a path.
|
407
444
|
# @api public
|
408
445
|
def name
|
409
446
|
if child_path?
|
@@ -413,7 +450,7 @@ module Scrivito
|
|
413
450
|
end
|
414
451
|
end
|
415
452
|
|
416
|
-
# Returns the root {Scrivito::BasicObj Obj},
|
453
|
+
# Returns the root {Scrivito::BasicObj Obj}, the object whose path is "/".
|
417
454
|
# @return [Obj]
|
418
455
|
# @api public
|
419
456
|
def self.root
|
@@ -423,27 +460,19 @@ module Scrivito
|
|
423
460
|
'Try "bundle exec rake scrivito:migrate scrivito:migrate:publish".'
|
424
461
|
end
|
425
462
|
|
426
|
-
# Returns the homepage obj. This can be overridden in your application's +Obj+.
|
427
|
-
# Use {#homepage?} to check if an obj is the homepage.
|
428
|
-
# @return [Obj]
|
429
|
-
# @api public
|
430
|
-
def self.homepage
|
431
|
-
root
|
432
|
-
end
|
433
|
-
|
434
463
|
def self.generate_widget_pool_id
|
435
464
|
SecureRandom.hex(4)
|
436
465
|
end
|
437
466
|
|
438
|
-
#
|
467
|
+
# Returns the permalink of the {Scrivito::BasicObj Obj}.
|
439
468
|
# @api public
|
440
469
|
def permalink
|
441
470
|
read_attribute('_permalink')
|
442
471
|
end
|
443
472
|
|
444
|
-
# This method determines the controller
|
445
|
-
# By default a controller matching the
|
446
|
-
# If the controller does not exist, the CmsController
|
473
|
+
# This method determines the controller to be invoked when the +Obj+ is requested.
|
474
|
+
# By default, a controller matching the obj_class of the Obj is used.
|
475
|
+
# If the controller does not exist, the CmsController is used as a fallback.
|
447
476
|
# Override this method to force a different controller to be used.
|
448
477
|
# @return [String]
|
449
478
|
# @api public
|
@@ -451,7 +480,7 @@ module Scrivito
|
|
451
480
|
obj_class_name
|
452
481
|
end
|
453
482
|
|
454
|
-
# This method determines the action
|
483
|
+
# This method determines the action to be invoked when the +Obj+ is requested.
|
455
484
|
# The default action is 'index'.
|
456
485
|
# Override this method to force a different action to be used.
|
457
486
|
# @return [String]
|
@@ -460,15 +489,9 @@ module Scrivito
|
|
460
489
|
"index"
|
461
490
|
end
|
462
491
|
|
463
|
-
# Returns true if the current obj is the {.homepage} obj.
|
464
|
-
# @api public
|
465
|
-
def homepage?
|
466
|
-
self == self.class.homepage
|
467
|
-
end
|
468
|
-
|
469
492
|
# This method is used to calculate a part of a URL of this Obj.
|
470
493
|
#
|
471
|
-
# The routing schema: <code><em><obj.
|
494
|
+
# The routing schema: <code><em><obj.slug></em>-<em><obj.id></em></code>
|
472
495
|
#
|
473
496
|
# The default is {http://apidock.com/rails/ActiveSupport/Inflector/parameterize parameterize}
|
474
497
|
# on +obj.title+.
|
@@ -481,8 +504,8 @@ module Scrivito
|
|
481
504
|
end
|
482
505
|
|
483
506
|
#
|
484
|
-
# This method determines the description
|
485
|
-
#
|
507
|
+
# This method determines the description shown in the UI.
|
508
|
+
# It defaults to {Scrivito::BasicObj#display_title}. It can be overridden by a custom value.
|
486
509
|
#
|
487
510
|
# @api public
|
488
511
|
#
|
@@ -505,7 +528,7 @@ module Scrivito
|
|
505
528
|
|
506
529
|
# The alt description of an +Obj+ used for {ScrivitoHelper#scrivito_image_tag}.
|
507
530
|
#
|
508
|
-
# By default this method returns the +title+ of
|
531
|
+
# By default, this method returns the +title+ of the +Obj+.
|
509
532
|
#
|
510
533
|
# You can customize this part by overriding {#alt_description}.
|
511
534
|
#
|
@@ -521,11 +544,11 @@ module Scrivito
|
|
521
544
|
end
|
522
545
|
|
523
546
|
# @api public
|
524
|
-
# This method indicates
|
547
|
+
# This method indicates whether the Obj represents binary data. Binaries are
|
525
548
|
# handled differently in that they are not rendered using the normal layout
|
526
549
|
# but sent as a file. Examples of binary resources are Images or PDFs.
|
527
550
|
#
|
528
|
-
# Every Obj that has
|
551
|
+
# Every Obj that has a +blob+ attribute of the +binary+ type is
|
529
552
|
# considered a binary
|
530
553
|
#
|
531
554
|
# @return true if this Obj represents a binary resource.
|
@@ -535,15 +558,15 @@ module Scrivito
|
|
535
558
|
end
|
536
559
|
|
537
560
|
#
|
538
|
-
# When delivering binary
|
539
|
-
# applied by default.
|
561
|
+
# When delivering binary objects, this method decides whether the image transformations should
|
562
|
+
# be applied by default.
|
540
563
|
#
|
541
|
-
# @api
|
564
|
+
# @api public
|
542
565
|
#
|
543
|
-
# By default this method returns +false+.
|
544
|
-
# Override in subclasses to fit your needs.
|
566
|
+
# By default, this method returns +false+.
|
567
|
+
# Override it in subclasses to fit your needs.
|
545
568
|
#
|
546
|
-
# @note Only relevant for binary
|
569
|
+
# @note Only relevant for binary objects
|
547
570
|
# @see Scrivito::Configuration.default_image_transformation=
|
548
571
|
# @see Scrivito::Binary#transform
|
549
572
|
#
|
@@ -551,14 +574,14 @@ module Scrivito
|
|
551
574
|
false
|
552
575
|
end
|
553
576
|
|
554
|
-
# Returns true if this
|
577
|
+
# Returns true if this Obj is the root Obj.
|
555
578
|
# @api public
|
556
579
|
def root?
|
557
580
|
path == "/"
|
558
581
|
end
|
559
582
|
|
560
583
|
# Returns a list of children excluding the binary? ones unless :all is specfied.
|
561
|
-
# This is
|
584
|
+
# This is useful for creating navigations.
|
562
585
|
# @return [Array<Obj>]
|
563
586
|
# @api public
|
564
587
|
def toclist(*args)
|
@@ -568,15 +591,15 @@ module Scrivito
|
|
568
591
|
toclist
|
569
592
|
end
|
570
593
|
|
571
|
-
# @param objs_to_be_sorted [Array<Scrivito::BasicObj>] unsorted list of
|
572
|
-
# @param list [Array<Scrivito::BasicObj>] list of
|
573
|
-
# @return [Array<Scrivito::BasicObj>] a sorted list of
|
574
|
-
# +objs_to_be_sorted+ but not in +list+ are appended
|
594
|
+
# @param objs_to_be_sorted [Array<Scrivito::BasicObj>] unsorted list of CMS objects
|
595
|
+
# @param list [Array<Scrivito::BasicObj>] list of objects that defines the order
|
596
|
+
# @return [Array<Scrivito::BasicObj>] a sorted list of objects. Objects present in
|
597
|
+
# +objs_to_be_sorted+ but not in +list+ are appended to the end, sorted by +Obj#id+
|
575
598
|
def self.sort_by_list(objs_to_be_sorted, list)
|
576
599
|
(list & objs_to_be_sorted) + (objs_to_be_sorted - list).sort_by(&:id)
|
577
600
|
end
|
578
601
|
|
579
|
-
# This should be a
|
602
|
+
# This should be a Set, because it's faster in this particular case.
|
580
603
|
SYSTEM_KEYS = Set.new(%w[
|
581
604
|
body
|
582
605
|
_id
|
@@ -587,8 +610,8 @@ module Scrivito
|
|
587
610
|
title
|
588
611
|
])
|
589
612
|
|
590
|
-
# Returns the value of
|
591
|
-
# Passing an invalid key will not raise an error
|
613
|
+
# Returns the value of a system or custom attribute specified by its name.
|
614
|
+
# Passing an invalid key will not raise an error but return +nil+.
|
592
615
|
# @api public
|
593
616
|
def [](key)
|
594
617
|
key = key.to_s
|
@@ -609,8 +632,8 @@ module Scrivito
|
|
609
632
|
end
|
610
633
|
end
|
611
634
|
|
612
|
-
# Reloads the attributes of this
|
613
|
-
#
|
635
|
+
# Reloads the attributes of this Obj from the database.
|
636
|
+
# Note that the Ruby class of this Obj instance will NOT change,
|
614
637
|
# even if the obj_class in the database has changed.
|
615
638
|
# @api public
|
616
639
|
def reload
|
@@ -652,10 +675,10 @@ module Scrivito
|
|
652
675
|
end
|
653
676
|
end
|
654
677
|
|
655
|
-
#
|
678
|
+
# Similar to modification but faster if you are only interested in
|
656
679
|
# "new" and "deleted".
|
657
|
-
#
|
658
|
-
# ObjData instead.
|
680
|
+
# This method sometimes does not return a string, but an instance of
|
681
|
+
# ObjData instead. This indicates that the modification is either
|
659
682
|
# UNMODIFIED or EDITED. Which one it is can be determined by comparing
|
660
683
|
# the returned ObjData.
|
661
684
|
def quick_modification(revision)
|
@@ -669,7 +692,7 @@ module Scrivito
|
|
669
692
|
|
670
693
|
if data_for_comparison.present?
|
671
694
|
if modification_attr == 'deleted'
|
672
|
-
# Obj exists in comparison revision
|
695
|
+
# Obj exists in comparison revision but not in current
|
673
696
|
Modification::DELETED
|
674
697
|
else
|
675
698
|
# Obj exists in both revisions, leave the actual comparions
|
@@ -681,7 +704,7 @@ module Scrivito
|
|
681
704
|
# Obj does not exist in either revision
|
682
705
|
Modification::UNMODIFIED
|
683
706
|
else
|
684
|
-
# Obj exists in current
|
707
|
+
# Obj exists in current but not in comparision revision
|
685
708
|
Modification::NEW
|
686
709
|
end
|
687
710
|
end
|
@@ -707,16 +730,16 @@ module Scrivito
|
|
707
730
|
end
|
708
731
|
alias mime_type content_type
|
709
732
|
|
710
|
-
#
|
711
|
-
#
|
733
|
+
# Returns the name extension of the Obj (the part after the last dot).
|
734
|
+
# Returns an empty string if the name of the Obj doesn't have an extension.
|
712
735
|
# @return [String]
|
713
736
|
# @api public
|
714
737
|
def file_extension
|
715
738
|
File.extname(name)[1..-1] || ""
|
716
739
|
end
|
717
740
|
|
718
|
-
# Returns the body (main content) of the Obj for non-binary
|
719
|
-
# Returns +nil+ for binary
|
741
|
+
# Returns the body (main content) of the Obj for non-binary objects.
|
742
|
+
# Returns +nil+ for binary objects.
|
720
743
|
# @return [String]
|
721
744
|
# @api public
|
722
745
|
def body
|
@@ -728,11 +751,11 @@ module Scrivito
|
|
728
751
|
end
|
729
752
|
|
730
753
|
# @api public
|
731
|
-
# This method is intended for
|
732
|
-
# images or
|
754
|
+
# This method is intended for CMS objects that represent binary resources like
|
755
|
+
# images or PDF documents. If the Obj represents a binary file, an instance
|
733
756
|
# of {Binary} is returned.
|
734
757
|
#
|
735
|
-
# This method returns the
|
758
|
+
# This method returns the +blob+ attribute if its type is +binary+.
|
736
759
|
#
|
737
760
|
# @return [Binary, nil]
|
738
761
|
def binary
|
@@ -740,21 +763,21 @@ module Scrivito
|
|
740
763
|
end
|
741
764
|
|
742
765
|
# @api public
|
743
|
-
# This method returns the length
|
744
|
-
# @return [Fixnum] If no binary is set
|
766
|
+
# This method returns the byte length of the binary of the Obj.
|
767
|
+
# @return [Fixnum] If no binary is set, 0 is returned.
|
745
768
|
def binary_length
|
746
769
|
binary.try(:content_length) || 0
|
747
770
|
end
|
748
771
|
|
749
772
|
# @api public
|
750
|
-
# This method returns the content type of the binary of this
|
773
|
+
# This method returns the content type of the binary of this Obj if the binary is set.
|
751
774
|
# @return [String, nil]
|
752
775
|
def binary_content_type
|
753
776
|
binary.try(:content_type)
|
754
777
|
end
|
755
778
|
|
756
779
|
# @api public
|
757
|
-
# This method returns the
|
780
|
+
# This method returns the URL under which the content of this binary is
|
758
781
|
# available to the public if the binary is set.
|
759
782
|
#
|
760
783
|
# See {Binary#url} for details
|
@@ -796,7 +819,7 @@ module Scrivito
|
|
796
819
|
end
|
797
820
|
|
798
821
|
# @api public
|
799
|
-
# Allows accessing the {Scrivito::BasicWidget Widgets} of this Obj
|
822
|
+
# Allows accessing the {Scrivito::BasicWidget Widgets} of this Obj.
|
800
823
|
#
|
801
824
|
# @example Access a widget by its id
|
802
825
|
# obj.widgets['widget_id']
|
@@ -816,9 +839,9 @@ module Scrivito
|
|
816
839
|
#
|
817
840
|
# @api public
|
818
841
|
#
|
819
|
-
# @note This method does not support +Obj+s
|
842
|
+
# @note This method does not support +Obj+s that are +new+.
|
820
843
|
# Please use {Scrivito::BasicObj#destroy Obj#destroy} to destroy them.
|
821
|
-
# @note This method does not support +Obj+s
|
844
|
+
# @note This method does not support +Obj+s that are +deleted+.
|
822
845
|
# Please use {Scrivito::BasicObj.restore Obj.restore} to restore them.
|
823
846
|
#
|
824
847
|
# @raise [ScrivitoError] If the current workspace is +published+.
|
@@ -916,10 +939,6 @@ module Scrivito
|
|
916
939
|
ParentPath.of(path) unless root?
|
917
940
|
end
|
918
941
|
|
919
|
-
def as_client_json
|
920
|
-
data_from_cms.to_h.except(*GENERATED_ATTRIBUTES)
|
921
|
-
end
|
922
|
-
|
923
942
|
def outdated?
|
924
943
|
return false if workspace.published?
|
925
944
|
|
@@ -932,8 +951,64 @@ module Scrivito
|
|
932
951
|
cms_data_for_revision(base_revision) != cms_data_for_revision(published_revision)
|
933
952
|
end
|
934
953
|
|
954
|
+
def transfer_modifications_to(target_workspace)
|
955
|
+
return unless modification
|
956
|
+
if in_revision(target_workspace.revision).try(:modification)
|
957
|
+
raise TransferModificationsError, "Already modified in workspace #{target_workspace.id}"
|
958
|
+
end
|
959
|
+
copy_modifications_to(target_workspace)
|
960
|
+
reset_modifications
|
961
|
+
end
|
962
|
+
|
935
963
|
private
|
936
964
|
|
965
|
+
def copy_modifications_to(target_workspace)
|
966
|
+
case
|
967
|
+
when new? then create_in(target_workspace)
|
968
|
+
when deleted? then destroy_in(target_workspace)
|
969
|
+
else update_in(target_workspace)
|
970
|
+
end
|
971
|
+
end
|
972
|
+
|
973
|
+
def create_in(target_workspace)
|
974
|
+
target_workspace.api_request(:post, '/objs', obj: get_attributes)
|
975
|
+
end
|
976
|
+
|
977
|
+
def update_in(target_workspace)
|
978
|
+
update_attributes = fill_in_missing_attributes_as_nil(copyable_attributes)
|
979
|
+
target_workspace.api_request(:put, "/objs/#{id}", obj: update_attributes)
|
980
|
+
end
|
981
|
+
|
982
|
+
def destroy_in(target_workspace)
|
983
|
+
target_workspace.api_request(:delete, "/objs/#{id}")
|
984
|
+
end
|
985
|
+
|
986
|
+
def fill_in_missing_attributes_as_nil(attributes, type_computer=Obj.type_computer)
|
987
|
+
obj_class = type_computer.compute_type_without_fallback(attributes['_obj_class'])
|
988
|
+
missing_attributes = obj_class.attribute_definitions.map(&:name) - attributes.keys
|
989
|
+
|
990
|
+
if attributes['_widget_pool']
|
991
|
+
attributes['_widget_pool'].each do |id, widget_attributes|
|
992
|
+
attributes['_widget_pool'][id] = fill_in_missing_attributes_as_nil(
|
993
|
+
widget_attributes, Widget.type_computer)
|
994
|
+
end
|
995
|
+
end
|
996
|
+
|
997
|
+
missing_attributes.each do |attribute_name|
|
998
|
+
attributes[attribute_name] = nil
|
999
|
+
end
|
1000
|
+
|
1001
|
+
attributes
|
1002
|
+
end
|
1003
|
+
|
1004
|
+
def reset_modifications
|
1005
|
+
case
|
1006
|
+
when new? then destroy
|
1007
|
+
when deleted? then self.class.restore(id)
|
1008
|
+
else revert
|
1009
|
+
end
|
1010
|
+
end
|
1011
|
+
|
937
1012
|
def cms_data_for_revision(revision)
|
938
1013
|
return nil unless revision
|
939
1014
|
|
@@ -981,9 +1056,34 @@ module Scrivito
|
|
981
1056
|
end
|
982
1057
|
|
983
1058
|
def copyable_attributes
|
1059
|
+
get_attributes.except(*GENERATED_ATTRIBUTES).except(*UNIQ_ATTRIBUTES)
|
1060
|
+
end
|
1061
|
+
|
1062
|
+
def get_attributes
|
984
1063
|
workspace.api_request(:get, "/objs/#{id}")
|
985
|
-
|
986
|
-
|
1064
|
+
end
|
1065
|
+
|
1066
|
+
def copy_binaries(attributes)
|
1067
|
+
attribute_defintions = self.class.find_attribute_definitions(obj_class_name)
|
1068
|
+
destination_obj_id = attributes.fetch(:_id)
|
1069
|
+
|
1070
|
+
Hash[attributes.map do |name, value|
|
1071
|
+
if value && attribute_defintions[name].try(:type) == 'binary'
|
1072
|
+
binary = self[name]
|
1073
|
+
[name, ['binary', copy_binary(destination_obj_id, binary)]]
|
1074
|
+
else
|
1075
|
+
[name, value]
|
1076
|
+
end
|
1077
|
+
end]
|
1078
|
+
end
|
1079
|
+
|
1080
|
+
def copy_binary(destination_obj_id, binary)
|
1081
|
+
normalized_id = CmsRestApi.normalize_path_component(binary.id)
|
1082
|
+
CmsRestApi.put("/blobs/#{normalized_id}/copy", {
|
1083
|
+
destination_obj_id: destination_obj_id,
|
1084
|
+
filename: binary.filename,
|
1085
|
+
content_type: binary.content_type,
|
1086
|
+
})
|
987
1087
|
end
|
988
1088
|
|
989
1089
|
def assert_revertable
|
@@ -1039,10 +1139,14 @@ module Scrivito
|
|
1039
1139
|
Workspace.current.api_request(:post, '/objs', obj: obj_attributes)
|
1040
1140
|
end
|
1041
1141
|
|
1042
|
-
def prepare_attributes_for_rest_api(
|
1043
|
-
widget_pool_attributes = CmsRestApi::WidgetExtractor.call(
|
1142
|
+
def prepare_attributes_for_rest_api(attributes, obj = nil)
|
1143
|
+
widget_pool_attributes, obj_attributes = CmsRestApi::WidgetExtractor.call(attributes, obj)
|
1144
|
+
obj_id = obj ? obj.id : obj_attributes.fetch(:_id)
|
1044
1145
|
workspace = obj ? obj.revision.workspace : Workspace.current
|
1045
|
-
|
1146
|
+
|
1147
|
+
api_attributes = serialize_attributes(
|
1148
|
+
obj_attributes, widget_pool_attributes, workspace, obj_id
|
1149
|
+
)
|
1046
1150
|
|
1047
1151
|
if obj
|
1048
1152
|
widget_pool = api_attributes['_widget_pool']
|
@@ -1054,8 +1158,8 @@ module Scrivito
|
|
1054
1158
|
[api_attributes, widget_pool_attributes]
|
1055
1159
|
end
|
1056
1160
|
|
1057
|
-
def serialize_attributes(obj_attributes, widget_pool_attributes, workspace)
|
1058
|
-
serializer = AttributeSerializer.new(obj_attributes['_obj_class'] || name)
|
1161
|
+
def serialize_attributes(obj_attributes, widget_pool_attributes, workspace, obj_id)
|
1162
|
+
serializer = AttributeSerializer.new(obj_attributes['_obj_class'] || name, obj_id)
|
1059
1163
|
serialized_attributes = serialize_obj_attributes(serializer, obj_attributes)
|
1060
1164
|
serialized_attributes['_widget_pool'] =
|
1061
1165
|
serialize_widget_pool_attributes(serializer, widget_pool_attributes)
|
@@ -1080,6 +1184,10 @@ module Scrivito
|
|
1080
1184
|
def find_attribute_definitions(obj_class, basic_class = self)
|
1081
1185
|
basic_class.type_computer.compute_type(obj_class).attribute_definitions if obj_class
|
1082
1186
|
end
|
1187
|
+
|
1188
|
+
def with_default_id_attribute(attributes)
|
1189
|
+
attributes.reverse_merge(_id: SecureRandom.hex(8))
|
1190
|
+
end
|
1083
1191
|
end
|
1084
1192
|
end
|
1085
1193
|
end
|