scrivito_sdk 1.0.0 → 1.1.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (77) hide show
  1. checksums.yaml +4 -4
  2. data/.yardopts +1 -0
  3. data/README.md +1 -1
  4. data/app/controllers/scrivito/legacy_redirect_controller.rb +11 -0
  5. data/app/controllers/scrivito/objs_controller.rb +15 -5
  6. data/app/controllers/scrivito/webservice_controller.rb +4 -3
  7. data/app/controllers/scrivito/workspaces_controller.rb +24 -29
  8. data/app/helpers/scrivito_helper.rb +82 -37
  9. data/app/views/scrivito/objs/binary_no_cache.json.jbuilder +1 -0
  10. data/app/views/scrivito/objs/search.json.jbuilder +5 -5
  11. data/app/views/scrivito/webservice/error.json.jbuilder +2 -2
  12. data/config/ca-bundle.crt +1 -1
  13. data/config/precedence_routes.rb +51 -48
  14. data/config/routes.rb +1 -14
  15. data/lib/assets/javascripts/scrivito_ui.js +2447 -266
  16. data/lib/assets/stylesheets/scrivito.css +1 -1
  17. data/lib/assets/stylesheets/scrivito_ui.css +1 -1
  18. data/lib/generators/scrivito/install/install_generator.rb +12 -0
  19. data/lib/generators/scrivito/install/templates/config/initializers/scrivito.rb +3 -0
  20. data/lib/scrivito/attribute_definition.rb +13 -1
  21. data/lib/scrivito/attribute_deserializer.rb +4 -4
  22. data/lib/scrivito/attribute_value_renderer.rb +79 -0
  23. data/lib/scrivito/backend/obj_data_cache.rb +15 -15
  24. data/lib/scrivito/backend/obj_data_from_rest.rb +1 -21
  25. data/lib/scrivito/backend/obj_query.rb +2 -2
  26. data/lib/scrivito/basic_obj.rb +17 -6
  27. data/lib/scrivito/binary.rb +13 -5
  28. data/lib/scrivito/cache/chainable.rb +10 -5
  29. data/lib/scrivito/cache/file_store.rb +4 -0
  30. data/lib/scrivito/cache/ram_store.rb +4 -0
  31. data/lib/scrivito/child_list_tag.rb +16 -14
  32. data/lib/scrivito/client_error.rb +10 -0
  33. data/lib/scrivito/cms_backend.rb +66 -291
  34. data/lib/scrivito/cms_data_cache.rb +7 -9
  35. data/lib/scrivito/cms_dispatch_controller.rb +1 -10
  36. data/lib/scrivito/cms_field_tag.rb +2 -1
  37. data/lib/scrivito/cms_rest_api.rb +2 -0
  38. data/lib/scrivito/cms_routing.rb +26 -22
  39. data/lib/scrivito/configuration.rb +38 -0
  40. data/lib/scrivito/connection_manager.rb +69 -0
  41. data/lib/scrivito/controller_actions.rb +2 -2
  42. data/lib/scrivito/controller_helper.rb +2 -2
  43. data/lib/scrivito/date_attribute.rb +4 -1
  44. data/lib/scrivito/deprecation.rb +5 -4
  45. data/lib/scrivito/editing_context.rb +2 -2
  46. data/lib/scrivito/errors.rb +17 -0
  47. data/lib/scrivito/image_tag.rb +2 -2
  48. data/lib/scrivito/link_parser.rb +10 -5
  49. data/lib/scrivito/meta_data_collection.rb +11 -0
  50. data/lib/scrivito/obj_collection.rb +1 -1
  51. data/lib/scrivito/obj_facet_value.rb +19 -7
  52. data/lib/scrivito/obj_params_parser.rb +43 -14
  53. data/lib/scrivito/obj_search_builder.rb +1 -2
  54. data/lib/scrivito/obj_search_enumerator/batch.rb +22 -0
  55. data/lib/scrivito/obj_search_enumerator/batch_iterator.rb +36 -0
  56. data/lib/scrivito/obj_search_enumerator/query_executor.rb +35 -0
  57. data/lib/scrivito/obj_search_enumerator.rb +218 -93
  58. data/lib/scrivito/obj_update_params_parser.rb +1 -0
  59. data/lib/scrivito/preset_routes.rb +25 -0
  60. data/lib/scrivito/revision.rb +13 -11
  61. data/lib/scrivito/route.rb +62 -0
  62. data/lib/scrivito/routing_extensions.rb +92 -0
  63. data/lib/scrivito/sdk_engine.rb +4 -0
  64. data/lib/scrivito/task.rb +77 -0
  65. data/lib/scrivito/type_computer.rb +3 -3
  66. data/lib/scrivito/ui_config.rb +4 -0
  67. data/lib/scrivito/user.rb +24 -18
  68. data/lib/scrivito/workspace/publish_checker.rb +2 -3
  69. data/lib/scrivito/workspace.rb +38 -6
  70. data/lib/scrivito/workspace_data.rb +0 -14
  71. metadata +14 -10
  72. data/lib/scrivito/content_service.rb +0 -121
  73. data/lib/scrivito/content_state.rb +0 -109
  74. data/lib/scrivito/content_state_caching.rb +0 -47
  75. data/lib/scrivito/content_state_visitor.rb +0 -19
  76. data/lib/scrivito/obj_data_from_service.rb +0 -63
  77. data/lib/scrivito/workspace_data_from_service.rb +0 -43
@@ -1,51 +1,4 @@
1
- require 'addressable/uri'
2
-
3
1
  module Scrivito
4
-
5
- class ContentServiceObjQueries
6
- def initialize(queries)
7
- @queries = queries
8
- @open_queries = queries.dup
9
- @results = {}
10
- end
11
-
12
- def open_queries
13
- @open_queries[0..99]
14
- end
15
-
16
- def handle_response(response)
17
- objs = {}
18
- response["objs"].each do |obj|
19
- objs[obj["_id"].first] = obj
20
- end
21
-
22
- queries_to_delete = []
23
- response["results"].each_with_index do |response, i|
24
- query = @open_queries[i]
25
- if response["continuation_handle"]
26
- query[:continuation_handle] = response["continuation_handle"]
27
- else
28
- queries_to_delete << i
29
- end
30
- result = (@results[query.__id__] ||= [])
31
- response["refs"].each do |obj_ref|
32
- id = obj_ref["id"]
33
- # TODO fetch missing ObjData from Service
34
- result << (objs[id] or raise "Data for Obj with id #{id} missing!")
35
- end
36
- end
37
- queries_to_delete.reverse_each {|i| @open_queries.delete_at(i) }
38
- end
39
-
40
- def results
41
- @queries.map {|query| @results[query.__id__] || [] }
42
- end
43
-
44
- def finished?
45
- open_queries.empty?
46
- end
47
- end
48
-
49
2
  class CmsBackend
50
3
  VALID_INDEX_NAMES = %w[id path ppath permalink].freeze
51
4
 
@@ -55,12 +8,9 @@ module Scrivito
55
8
  end
56
9
  end
57
10
 
58
- attr_accessor :die_content_service
59
-
60
11
  def initialize
61
12
  @query_counter = 0
62
13
  @caching = true
63
- @die_content_service = true
64
14
  end
65
15
 
66
16
  def begin_caching
@@ -68,12 +18,12 @@ module Scrivito
68
18
  end
69
19
 
70
20
  def end_caching
71
- CmsDataCache.cache.clear
21
+ CmsDataCache.clear_request_cache
72
22
  @caching = false
73
23
  end
74
24
 
75
25
  def clear_cache
76
- CmsDataCache.cache.clear
26
+ CmsDataCache.clear_request_cache
77
27
  end
78
28
 
79
29
  def caching?
@@ -90,125 +40,76 @@ module Scrivito
90
40
  end
91
41
 
92
42
  def find_workspace_data_from_cache(id)
93
- if die_content_service
94
- cached_workspace_state = CmsDataCache.read_workspace_state(id)
95
- cached_data_tag = cached_workspace_state.try(:second)
96
- cached_content_state_id = cached_workspace_state.try(:first)
97
-
98
- if cached_data_tag && cached_content_state_id
99
- if raw_workspace_data = fetch_cached_data_by_tag(cached_data_tag)
100
- build_workspace_data(raw_workspace_data, cached_content_state_id)
101
- end
43
+ cached_workspace_state = CmsDataCache.read_workspace_state(id)
44
+ cached_data_tag = cached_workspace_state.try(:second)
45
+ cached_content_state_id = cached_workspace_state.try(:first)
46
+
47
+ if cached_data_tag && cached_content_state_id
48
+ if raw_workspace_data = fetch_cached_data_by_tag(cached_data_tag)
49
+ build_workspace_data(raw_workspace_data, cached_content_state_id)
102
50
  end
103
- else
104
- WorkspaceDataFromService.find_from_cache(id)
105
51
  end
106
52
  end
107
53
 
108
54
  def find_workspace_data_by_id(id, timeout=nil)
109
55
  options = timeout ? {timeout: timeout} : {}
110
56
 
111
- if die_content_service
112
- begin
113
- cached_workspace_state = CmsDataCache.read_workspace_state(id)
57
+ cached_workspace_state = CmsDataCache.read_workspace_state(id)
114
58
 
115
- cached_csid = cached_workspace_state.try(:first)
116
- cached_workspace_data_tag = cached_workspace_state.try(:second)
59
+ cached_csid = cached_workspace_state.try(:first)
60
+ cached_workspace_data_tag = cached_workspace_state.try(:second)
117
61
 
118
- changes = CmsRestApi.get("/workspaces/#{id}/changes", {from: cached_csid}, options)
62
+ changes = CmsRestApi.get("/workspaces/#{id}/changes", {from: cached_csid}, options)
119
63
 
120
- update_obj_cache(id, cached_csid, changes)
64
+ update_obj_cache(id, cached_csid, changes)
121
65
 
122
- raw_workspace_data, workspace_data_tag = update_workspace_cache(
123
- id, cached_workspace_data_tag, changes["workspace"], options)
124
-
125
- current_csid = changes["current"]
126
- current_workspace_state = [current_csid, workspace_data_tag]
127
-
128
- if current_workspace_state != cached_workspace_state
129
- CmsDataCache.write_workspace_state(id, current_workspace_state)
130
- end
66
+ raw_workspace_data, workspace_data_tag = update_workspace_cache(
67
+ id, cached_workspace_data_tag, changes["workspace"], options)
131
68
 
132
- return build_workspace_data(raw_workspace_data, current_csid)
69
+ current_csid = changes["current"]
70
+ current_workspace_state = [current_csid, workspace_data_tag]
133
71
 
134
- rescue Scrivito::ClientError => client_error
135
- if client_error.http_code == 404
136
- return nil
137
- else
138
- raise
139
- end
140
- end
72
+ if current_workspace_state != cached_workspace_state
73
+ CmsDataCache.write_workspace_state(id, current_workspace_state)
141
74
  end
142
75
 
143
- workspace_data_from_cache = find_workspace_data_from_cache(id)
144
- from_content_state_id = workspace_data_from_cache.try(:content_state_id)
145
-
146
- request_params = {:workspace_id => id}
147
- request_params[:content_state_id] = from_content_state_id if from_content_state_id
148
-
149
- raw_data = ContentService.query('workspaces/query', request_params, options)
150
-
151
- if raw_workspace_data = raw_data['workspace']
152
- workspace_data = WorkspaceDataFromService.new(raw_workspace_data)
153
- if from_content_state_id != workspace_data.content_state_id
154
- workspace_data.store_in_cache_and_create_content_state
155
- end
156
- workspace_data
76
+ build_workspace_data(raw_workspace_data, current_csid)
77
+ rescue Scrivito::ClientError => client_error
78
+ if client_error.http_code == 404
79
+ nil
80
+ else
81
+ raise
157
82
  end
158
83
  end
159
84
 
160
85
  def find_obj_data_by(revision, index, keys)
161
86
  index = index.to_s
162
87
 
163
- if die_content_service
164
- obj_datas =
165
- if index == "id"
166
- obj_datas = Backend::ObjLoad.load(revision, keys)
167
- obj_datas.map { |obj_data| obj_data ? [obj_data] : [] }
168
- else
169
- index_implementation = Backend::Index.by_name(index)
170
- Backend::ObjQuery.query(revision, index_implementation, keys)
171
- end
172
-
173
- return obj_datas
174
- end
175
-
176
- assert_valid_index_name(index)
177
- raw_data = find_raw_data_from_cache_or_database_by(revision, index, keys)
178
-
179
- raw_data.map do |raw_result|
180
- raw_result.each_with_object([]) do |raw_data, result|
181
- result << ObjDataFromService.new(raw_data)
182
- end
88
+ if index == "id"
89
+ obj_datas = Backend::ObjLoad.load(revision, keys)
90
+ obj_datas.map { |obj_data| obj_data ? [obj_data] : [] }
91
+ else
92
+ index_implementation = Backend::Index.by_name(index)
93
+ Backend::ObjQuery.query(revision, index_implementation, keys)
183
94
  end
184
95
  end
185
96
 
186
- def find_blob_data(id, access, verb, transformation_definition)
187
- if blob_data = find_blob_data_from_cache(id, access, verb, transformation_definition)
97
+ def find_blob_data(id, access, verb, options = {})
98
+ if blob_data = find_blob_data_from_cache(id, access, verb, options)
188
99
  blob_data
189
100
  else
190
101
  id = normalize_blob_id(id)
191
- blob_datas = request_blob_datas_from_backend(id, transformation_definition)
192
- store_blob_datas_in_cache(id, transformation_definition, blob_datas)
102
+ blob_datas = request_blob_datas_from_backend(id, options)
103
+ store_blob_datas_in_cache(id, options, blob_datas)
193
104
  blob_datas[access][verb]
194
105
  end
195
106
  end
196
107
 
197
- def find_blob_data_from_cache(id, access, verb, transformation_definition)
198
- cache_key = blob_data_cache_key(normalize_blob_id(id), access, verb, transformation_definition)
108
+ def find_blob_data_from_cache(id, access, verb, options)
109
+ cache_key = blob_data_cache_key(normalize_blob_id(id), access, verb, options)
199
110
  CmsDataCache.cache.read(cache_key)
200
111
  end
201
112
 
202
- def find_blob_metadata(id, url)
203
- if blob_metadata = fetch_blob_metadata_from_cache(id)
204
- blob_metadata
205
- else
206
- blob_metadata = request_blob_metadata_from_s3(url)
207
- store_blob_metadata_in_cache(id, blob_metadata)
208
- blob_metadata
209
- end
210
- end
211
-
212
113
  def find_binary_meta_data(blob_id)
213
114
  blob_id = normalize_blob_id(blob_id)
214
115
  cache_key = "binary_meta_data/#{blob_id}"
@@ -224,30 +125,16 @@ module Scrivito
224
125
  def search_objs(workspace, params)
225
126
  cache_index = 'search'
226
127
  cache_key = params.to_param
128
+ cache = Backend::ObjDataCache.view_for_revision(workspace.revision)
227
129
 
228
- if die_content_service
229
- cache = Backend::ObjDataCache.view_for_revision(workspace.revision)
230
-
231
- if hit = cache.read_index(cache_index, cache_key)
232
- return hit
233
- end
234
-
235
- result = request_search_result_from_backend(workspace, params)
236
-
237
- cache.write_index_not_updatable(cache_index, cache_key, result)
238
-
239
- return result
130
+ if hit = cache.read_index(cache_index, cache_key)
131
+ return hit
240
132
  end
241
133
 
242
- content_state = workspace.revision.content_state
243
-
244
- if result = fetch_search_result_from_cache(content_state, cache_index, cache_key)
245
- result
246
- else
247
- request_search_result_from_backend(workspace, params).tap do |result|
248
- store_search_result_in_cache(content_state, cache_index, cache_key, result)
249
- end
250
- end
134
+ result = request_search_result_from_backend(workspace, params)
135
+ persistent = !result.delete('tentative')
136
+ cache.write_index_not_updatable(cache_index, cache_key, result, persistent: persistent)
137
+ result
251
138
  end
252
139
 
253
140
  def create_obj(workspace_id, attributes)
@@ -303,164 +190,52 @@ module Scrivito
303
190
  end
304
191
  end
305
192
 
306
- def fetch_search_result_from_cache(content_state, cache_index, cache_key)
307
- content_state.find_obj_data(cache_index, cache_key) if caching?
308
- end
309
-
310
193
  def request_search_result_from_backend(workspace, params)
194
+ params = params.merge(consistent_with: workspace.content_state_id)
311
195
  CmsRestApi.get("workspaces/#{workspace.id}/objs/search", params)
312
196
  end
313
197
 
314
- def store_search_result_in_cache(content_state, cache_index, cache_key, result)
315
- content_state.save_obj_data(cache_index, cache_key, result) if caching?
316
- end
317
-
318
- def request_blob_datas_from_backend(id, transformation_definition)
198
+ def request_blob_datas_from_backend(id, options)
319
199
  @query_counter += 1
320
- if transformation_definition
200
+ case
201
+ when transformation_definition = options[:transformation_definition]
321
202
  CmsRestApi.get("blobs/#{id}/transform", transformation: transformation_definition)
203
+ when options[:no_cache]
204
+ CmsRestApi.get("blobs/#{id}/no_cache")
322
205
  else
323
206
  CmsRestApi.get("blobs/#{id}")
324
207
  end
325
208
  end
326
209
 
327
- def store_blob_datas_in_cache(id, transformation_definition, blob_datas)
210
+ def store_blob_datas_in_cache(id, options, blob_datas)
328
211
  %w[public_access private_access].each do |access|
329
212
  %w[get head].each do |verb|
330
- blob_data = blob_datas[access][verb]
331
- cache_key = blob_data_cache_key(id, access, verb, transformation_definition)
332
- CmsDataCache.cache.write(cache_key, blob_data, blob_data['maxage'])
213
+ if access_blob_data = blob_datas[access]
214
+ if blob_data = access_blob_data[verb]
215
+ cache_key = blob_data_cache_key(id, access, verb, options)
216
+ CmsDataCache.cache.write(cache_key, blob_data, expires_in: blob_data['maxage'])
217
+ end
218
+ end
333
219
  end
334
220
  end
335
221
  end
336
222
 
337
- def blob_data_cache_key(id, access, verb, transformation_definition)
223
+ def blob_data_cache_key(id, access, verb, options)
338
224
  cache_key = "blob_data/#{id}/#{access}/#{verb}"
339
- cache_key << "/#{transformation_definition.to_query}" if transformation_definition
340
- cache_key
341
- end
342
-
343
- def normalize_blob_id(id)
344
- CmsRestApi.normalize_path_component(id)
345
- end
346
225
 
347
- def fetch_blob_metadata_from_cache(id)
348
- CmsDataCache.cache.read(blob_metadata_cache_key(id))
349
- end
350
-
351
- def request_blob_metadata_from_s3(url)
352
- uri = URI.parse(url)
353
- retried = false
354
- begin
355
- response = ConnectionManager.request(uri, Net::HTTP::Head.new(uri))
356
- @query_counter += 1
357
- rescue NetworkError
358
- raise if retried
359
- retried = true
360
- retry
226
+ if transformation_definition = options[:transformation_definition]
227
+ cache_key << "/#{transformation_definition.to_query}"
361
228
  end
362
229
 
363
- raise ScrivitoError, "S3 responded with #{response.code}" unless response.code == '200'
364
-
365
- {
366
- content_length: response['content-length'],
367
- content_type: response['content-type'],
368
- cache_control: response['cache-control'],
369
- }
370
- end
371
-
372
- def store_blob_metadata_in_cache(id, blob_metadata)
373
- max_age = blob_metadata.delete(:cache_control) =~ /max-age=(.*),/ && $1
374
- max_age = max_age.to_i if max_age
375
- CmsDataCache.cache.write(blob_metadata_cache_key(id), blob_metadata, max_age)
376
- end
377
-
378
- def blob_metadata_cache_key(id)
379
- "blob_metadata/#{id}"
380
- end
381
-
382
- def find_raw_data_from_cache_or_database_by(revision, index, keys)
383
- keys_from_database = []
384
- # load results from cache
385
- results_from_cache = keys.map do |key|
386
- find_raw_data_from_cache_by(revision, index, key).tap do |objs|
387
- keys_from_database << key unless objs
388
- end
230
+ if options[:no_cache]
231
+ cache_key << '/no_cache'
389
232
  end
390
233
 
391
- # load cache misses from database and store them in cache
392
- results_from_database =
393
- find_raw_data_from_database_by(revision, index, keys_from_database)
394
- keys_from_database.each_with_index do |key, key_number|
395
- store_raw_data_list_in_cache(revision, index, key, results_from_database[key_number])
396
- end
397
-
398
- # combine the results
399
- results_from_cache.map do |objs_from_cache|
400
- objs_from_cache || results_from_database.shift
401
- end
402
- end
403
-
404
- def find_raw_data_from_cache_by(revision, index, key)
405
- ContentStateCaching.find_obj_data(revision.content_state, index, key) if caching?
406
- end
407
-
408
- def find_raw_data_from_database_by(revision, index, keys)
409
- return [] if keys.blank?
410
- instrumenter = ActiveSupport::Notifications.instrumenter
411
- instrumenter.instrument(
412
- "cms_load.scrivito", :name => "Obj Load", :index => index, :keys => keys
413
- ) do
414
- @query_counter += 1
415
- queries = ContentServiceObjQueries.new(keys.map {|key| {:type => index, :param => key} })
416
- queries.handle_response(request_content_service(queries, revision)) until queries.finished?
417
- queries.results
418
- end
419
- end
420
-
421
- def request_content_service(queries, revision)
422
- ContentService.query('objs/query', content_service_request_params(queries, revision))
423
- end
424
-
425
- def content_service_request_params(queries, revision)
426
- params = {
427
- queries: queries.open_queries,
428
- revision_id: revision.id,
429
- include_deleted: true
430
- }
431
-
432
- # A base revision doesn't have a directly corresponding workspace. Instead it uses its
433
- # derivative workspace as fallback to access the contents. Thus fallback workspace of a base
434
- # revision may not be used for backend requests.
435
- params[:workspace_id] = revision.workspace.id unless revision.base?
436
-
437
- params
438
- end
439
-
440
- UNIQUE_INDICES = [:id, :path, :permalink].freeze
441
-
442
- def store_raw_data_list_in_cache(revision, index, key, raw_data_list)
443
- raw_data_list.each do |values|
444
- UNIQUE_INDICES.each do |unique_index|
445
- unique_index_values = values["_#{unique_index}"]
446
- if unique_index_values.present?
447
- store_item_in_cache(revision, unique_index, unique_index_values.first, [values])
448
- end
449
- end
450
- end
451
- unless UNIQUE_INDICES.include?(index)
452
- store_item_in_cache(revision, index, key, raw_data_list)
453
- end
454
- end
455
-
456
- def store_item_in_cache(revision, index, key, item)
457
- ContentStateCaching.store_obj_data(revision.content_state, index, key, item)
234
+ cache_key
458
235
  end
459
236
 
460
- def assert_valid_index_name(index)
461
- raise ArgumentError, "invalid index name '#{index}'" unless VALID_INDEX_NAMES.include?(index)
237
+ def normalize_blob_id(id)
238
+ CmsRestApi.normalize_path_component(id)
462
239
  end
463
-
464
240
  end
465
-
466
241
  end
@@ -21,19 +21,17 @@ module CmsDataCache
21
21
  @first_level_cache ||= Cache::FileStore.new(path: @cache_path, next_store: second_level_cache)
22
22
  end
23
23
 
24
+ def clear_request_cache
25
+ cache.clear
26
+ end
27
+
24
28
  def second_level_cache=(cache_store)
25
29
  clear_cache_chain
26
30
  @second_level_cache = cache_store
27
31
  end
28
32
 
29
33
  SCHEMA = {
30
- # CONTENT SERVICE
31
- content_state: 'content/#{content_state_id}',
32
- obj_data: 'content/#{content_state_id}/obj/#{index}/#{key}',
33
- workspace_data: 'workspace/#{workspace_id}',
34
-
35
- # REST API
36
- obj_data_rest: 'obj/#{cache_id}/#{index}/#{key}',
34
+ obj_data: 'obj/#{cache_id}/#{index}/#{key}',
37
35
  content_state_node: 'csn/#{content_state_id}',
38
36
  workspace_state: 'wrkstt/#{workspace_id}',
39
37
  tag_data: 'tagd/#{tag}'
@@ -51,11 +49,11 @@ module CmsDataCache
51
49
  END
52
50
 
53
51
  class_eval(<<-END, __FILE__, __LINE__ + 1)
54
- def write_#{name}(#{params_code}, data)
52
+ def write_#{name}(#{params_code}, data, **options)
55
53
  if data == nil
56
54
  raise InternalError, "tried to write nil into #{schema}"
57
55
  end
58
- cache.write("#{schema}", data)
56
+ cache.write("#{schema}", data, **options)
59
57
  end
60
58
  END
61
59
 
@@ -8,17 +8,8 @@ module Scrivito
8
8
  def process(action)
9
9
  CmsEnv.new(env).load
10
10
 
11
- if !obj_not_found? && action == 'legacy'
12
- if Scrivito::Configuration.legacy_routing
13
- action = 'index'
14
- else
15
- redirect_to scrivito_path(loaded_obj), status: :moved_permanently
16
- return self.response
17
- end
18
- end
19
-
20
11
  if obj_not_found? && editing_context.workspace_changed?
21
- redirect_to :scrivito_root
12
+ redirect_to "/"
22
13
  return self.response
23
14
  end
24
15
 
@@ -33,7 +33,8 @@ class CmsFieldTag < Struct.new(:view, :tag_name, :obj_or_widget, :editing_option
33
33
  end
34
34
  view.safe_join(rendered_widgets)
35
35
  else
36
- block_given? ? view.capture { yield } : view.scrivito_value(default_content)
36
+ attribute_renderer = AttributeValueRenderer.new(view)
37
+ block_given? ? view.capture { yield } : attribute_renderer.render(default_content, field_type)
37
38
  end
38
39
  end
39
40
 
@@ -1,3 +1,5 @@
1
+ require 'addressable/uri'
2
+
1
3
  module Scrivito
2
4
 
3
5
  # Provides a simple wrapper for the CMS Rest API.
@@ -1,13 +1,9 @@
1
1
  module Scrivito
2
2
 
3
- class CmsRouting < Struct.new(:request, :main_app, :scrivito_engine, :image_options)
3
+ class CmsRouting < Struct.new(:request, :context, :scrivito_engine, :image_options)
4
4
  LINK_TO_EMPTY_LINKLIST = "#__empty_linklist"
5
5
  LINK_TO_EMPTY_BLOB = "#__empty_blob"
6
6
 
7
- def self.match_protocol(url, request)
8
- request.ssl? && !url.starts_with?('https') ? url.gsub(/^http/, 'https') : url
9
- end
10
-
11
7
  def path_or_url(target, path_or_url, options = {})
12
8
  if needs_editing_context?(target)
13
9
  path_or_url_needs_editing_context(target, path_or_url, options)
@@ -26,13 +22,14 @@ class CmsRouting < Struct.new(:request, :main_app, :scrivito_engine, :image_opti
26
22
  begin
27
23
  uri = URI.parse($2)
28
24
  options.merge!(extract_query(uri))
29
- options['anchor'] = uri.fragment
25
+ options[:anchor] = uri.fragment
30
26
  rescue
31
27
  end
32
28
  end
33
29
 
34
30
  if editing_context.display_mode == 'editing'
35
- id_path_or_url_for_objs(obj, :path, options)
31
+ options[:id] = obj.id
32
+ scrivito_engine.base_id_path(options)
36
33
  else
37
34
  path_or_url(obj, :path, options)
38
35
  end
@@ -70,41 +67,48 @@ class CmsRouting < Struct.new(:request, :main_app, :scrivito_engine, :image_opti
70
67
  end
71
68
 
72
69
  def path_or_url_for_links(link, path_or_url, options)
73
- url = basic_url_or_path_for_link(link, path_or_url,
74
- Rack::Utils.parse_nested_query(link.query).merge(options))
70
+ parsed_options = Rack::Utils.parse_nested_query(link.query)
71
+ combined_options = parsed_options.symbolize_keys.merge(options)
72
+
73
+ url = basic_url_or_path_for_link(link, path_or_url, combined_options)
75
74
  url = url + "##{link.fragment}" if link.fragment.present?
76
75
  url
77
76
  end
78
77
 
79
78
  def path_or_url_for_objs(obj, path_or_url, options)
80
79
  permalink = obj.permalink
81
- if permalink
82
- main_app
83
- .public_send("scrivito_permalink_#{path_or_url}", options.merge(:permalink => permalink))
84
- elsif homepage?(obj)
85
- main_app.public_send("scrivito_root_#{path_or_url}", options)
80
+ if permalink && route_defined?(:permalink)
81
+ use_route(:permalink, path_or_url, options.merge(:permalink => permalink))
82
+ elsif homepage?(obj) && route_defined?(:homepage)
83
+ use_route(:homepage, path_or_url, options)
86
84
  elsif obj.binary?
87
85
  binary_obj_url(obj) || LINK_TO_EMPTY_BLOB
88
- else
86
+ elsif route_defined?(:slug_id)
89
87
  slug = obj.slug.present? ? obj.slug.sub(/^\//, '') : nil
90
88
  id_path_or_url_for_objs(obj, path_or_url, options.merge(slug: slug))
89
+ else
90
+ raise ScrivitoError, "The required scrivito route 'slug_id' is not defined. "\
91
+ "Please add a 'slug_id' definition to your routes.rb. See the documentation"\
92
+ " of 'scrivito_route' for further details."
91
93
  end
92
94
  end
93
95
 
94
96
  def id_path_or_url_for_objs(obj, path_or_url, options)
95
- method_name = if Scrivito::Configuration.legacy_routing
96
- "cms_legacy_id_#{path_or_url}"
97
- else
98
- "cms_id_#{path_or_url}"
99
- end
100
-
101
97
  options[:id] = obj.id
102
98
 
103
99
  # Options must have the key slug.
104
100
  # Otherwise Rails will use the slug from current request params.
105
101
  options[:slug] ||= nil
106
102
 
107
- main_app.public_send(method_name, options)
103
+ use_route(:slug_id, path_or_url, options)
104
+ end
105
+
106
+ def route_defined?(name)
107
+ Route.defined?(context._routes, name)
108
+ end
109
+
110
+ def use_route(name, path_or_url, options)
111
+ Route.find(context._routes, name).generate(context, path_or_url, options)
108
112
  end
109
113
 
110
114
  def homepage?(obj)