infopark_fiona7 1.5.5.3.1 → 1.5.5.4.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: f0590fa89cace0547e0dbf261e5acf5946c37cc8
4
- data.tar.gz: f88431937133bfb08439d6d2ee1f9bc3441e9524
3
+ metadata.gz: 4e1b268827386ff36463ab06a15afdee261a1273
4
+ data.tar.gz: edfd0fb11950038b68c440457f7d7a20a5c2afce
5
5
  SHA512:
6
- metadata.gz: 9883ff71077c343ba7f33c4f6bae47e2c19ef83a2489ec1d8cf28848be9b9a66a409adea54ed110161ba1be73e655db3cdfc7bba9ee5e41b4cb325727284440f
7
- data.tar.gz: 07179e47fe6f27c1cc31bc279f4121e6e0e79cfd4413ee7697b69bc51432315fc87dfda28835344f861adb78d41d622cb6cd9f61a38268aa0752eee6a34e7eb2
6
+ metadata.gz: cf9a981a212c5a2527986e4f6d298d000b243fc883ecc017208fc9e378df22e89de7784aa97c56e65942fbd09cf8d1390bb0601ee90678e7fe7d44dde7d5903c
7
+ data.tar.gz: bf3d33be89c1d3afafc7b28a5992ff29e5c5a7ff637640615ab522697a8415458082095a11fd35c6a507fd572b347bd923402d39604005f0ce7fba40c4850e68
@@ -219,38 +219,16 @@ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Cons
219
219
  return result;
220
220
  }
221
221
 
222
- var _iteratorNormalCompletion = true;
223
- var _didIteratorError = false;
224
- var _iteratorError = undefined;
225
-
226
- try {
227
- for (var _iterator = Object.keys(objParams)[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
228
- var k = _step.value;
229
-
230
- // if params[k] is an array
231
- if (objParams[k].pop) {
232
- // file uploads require form data
233
- result = objParams[k][1] && (scrivito.BinaryUtils.isFile(objParams[k][1]) || scrivito.BinaryUtils.isBlob(objParams[k][1]) || scrivito.BinaryUtils.isBlobWithName(objParams[k][1]));
234
- if (result) {
235
- return result;
236
- }
237
- }
238
- }
239
- } catch (err) {
240
- _didIteratorError = true;
241
- _iteratorError = err;
242
- } finally {
243
- try {
244
- if (!_iteratorNormalCompletion && _iterator['return']) {
245
- _iterator['return']();
246
- }
247
- } finally {
248
- if (_didIteratorError) {
249
- throw _iteratorError;
222
+ for (var k in objParams) {
223
+ // if objParams[k] is an array
224
+ if (objParams.hasOwnProperty(k) && objParams[k] && typeof objParams[k] === 'object' && objParams[k].pop) {
225
+ // file uploads require form data
226
+ result = objParams[k][1] && (scrivito.BinaryUtils.isFile(objParams[k][1]) || scrivito.BinaryUtils.isBlob(objParams[k][1]) || scrivito.BinaryUtils.isBlobWithName(objParams[k][1]));
227
+ if (result) {
228
+ return result;
250
229
  }
251
230
  }
252
231
  }
253
-
254
232
  return result;
255
233
  }
256
234
 
@@ -281,189 +259,92 @@ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Cons
281
259
  fd.append('verb', verb);
282
260
  fd.append('path', path);
283
261
 
284
- var _iteratorNormalCompletion2 = true;
285
- var _didIteratorError2 = false;
286
- var _iteratorError2 = undefined;
262
+ for (var attr in objParams) {
263
+ // attr is a [type, value] pair
264
+ if (objParams.hasOwnProperty(attr) && objParams[attr] && typeof objParams[attr] === 'object' && objParams[attr].pop) {
265
+ var _objParams$attr = _slicedToArray(objParams[attr], 2);
287
266
 
288
- try {
289
- for (var _iterator2 = Object.keys(objParams)[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
290
- var attr = _step2.value;
291
-
292
- // attr is a [type, value] pair
293
- if (objParams[attr] && typeof objParams[attr] === 'object' && objParams[attr].pop) {
294
- var _objParams$attr = _slicedToArray(objParams[attr], 2);
267
+ var type = _objParams$attr[0];
268
+ var value = _objParams$attr[1];
295
269
 
296
- var type = _objParams$attr[0];
297
- var value = _objParams$attr[1];
298
-
299
- if (value.pop) {
300
- // multienum / stringlist / widgetlist
301
- fd.append('params[obj][' + attr + '[]', type);
302
- for (var i = 0; i < value.length; ++i) {
303
- fd.append('params[obj][' + attr + '[][formdata$workaround][]', value[i]);
304
- }
305
- } else if (scrivito.BinaryUtils.isFile(value) || scrivito.BinaryUtils.isBlob(value)) {
306
- // upload
307
- fd.append('params[obj][' + attr + '][]', type);
308
- fd.append('params[obj][' + attr + '][]', value);
309
- } else if (scrivito.BinaryUtils.isBlobWithName(value)) {
310
- fd.append('params[obj][' + attr + '][]', type);
311
- fd.append('params[obj][' + attr + '][]', value.blob_to_upload, value.filename);
312
- } else if (value && typeof value === 'object') {
313
- // blob/copy rename
314
- fd.append('params[obj][' + attr + '[]', type);
315
- var _iteratorNormalCompletion3 = true;
316
- var _didIteratorError3 = false;
317
- var _iteratorError3 = undefined;
318
-
319
- try {
320
- for (var _iterator3 = Object.keys(value)[Symbol.iterator](), _step3; !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) {
321
- var l = _step3.value;
322
-
323
- fd.append('params[obj][' + attr + '][][' + l + ']', value[l]);
324
- }
325
- } catch (err) {
326
- _didIteratorError3 = true;
327
- _iteratorError3 = err;
328
- } finally {
329
- try {
330
- if (!_iteratorNormalCompletion3 && _iterator3['return']) {
331
- _iterator3['return']();
332
- }
333
- } finally {
334
- if (_didIteratorError3) {
335
- throw _iteratorError3;
336
- }
337
- }
270
+ if (typeof value === 'object' && value && value.pop) {
271
+ // multienum / stringlist / widgetlist
272
+ fd.append('params[obj][' + attr + '[]', type);
273
+ for (var i = 0; i < value.length; ++i) {
274
+ fd.append('params[obj][' + attr + '[][formdata$workaround][]', value[i]);
275
+ }
276
+ } else if (scrivito.BinaryUtils.isFile(value) || scrivito.BinaryUtils.isBlob(value)) {
277
+ // upload
278
+ fd.append('params[obj][' + attr + '][]', type);
279
+ fd.append('params[obj][' + attr + '][]', value);
280
+ } else if (scrivito.BinaryUtils.isBlobWithName(value)) {
281
+ fd.append('params[obj][' + attr + '][]', type);
282
+ fd.append('params[obj][' + attr + '][]', value.blob_to_upload, value.filename);
283
+ } else if (value && typeof value === 'object') {
284
+ // blob/copy rename
285
+ fd.append('params[obj][' + attr + '[]', type);
286
+ for (var l in value) {
287
+ if (value.hasOwnProperty(l)) {
288
+ fd.append('params[obj][' + attr + '][][' + l + ']', value[l]);
338
289
  }
339
- } else if (typeof value !== 'undefined') {
340
- fd.append('params[obj][' + attr + '][]', type);
341
- fd.append('params[obj][' + attr + '][]', value);
342
290
  }
343
- // special handling for widget pool
344
- } else if (attr === '_widget_pool') {
345
- var value = objParams[attr];
346
- var _iteratorNormalCompletion4 = true;
347
- var _didIteratorError4 = false;
348
- var _iteratorError4 = undefined;
349
-
350
- try {
351
- for (var _iterator4 = Object.keys(value)[Symbol.iterator](), _step4; !(_iteratorNormalCompletion4 = (_step4 = _iterator4.next()).done); _iteratorNormalCompletion4 = true) {
352
- var widgetId = _step4.value;
353
-
354
- var widget = value[widgetId];
355
- var _iteratorNormalCompletion5 = true;
356
- var _didIteratorError5 = false;
357
- var _iteratorError5 = undefined;
358
-
359
- try {
360
- for (var _iterator5 = Object.keys(widget)[Symbol.iterator](), _step5; !(_iteratorNormalCompletion5 = (_step5 = _iterator5.next()).done); _iteratorNormalCompletion5 = true) {
361
- var widgetAttr = _step5.value;
362
-
363
- if (widget[widgetAttr].pop) {
364
- var _widget$widgetAttr = _slicedToArray(widget[widgetAttr], 2);
365
-
366
- var widgetAttrType = _widget$widgetAttr[0];
367
- var widgetValue = _widget$widgetAttr[1];
368
-
369
- // FIXME: Duplication
370
- if (widgetValue.pop) {
371
- // multienum / stringlist / widgetlist
372
- fd.append('params[obj][' + attr + '][' + widgetId + '][' + widgetAttr + '][]', widgetAttrType);
373
- for (var i = 0; i < widgetValue.length; ++i) {
374
- fd.append('params[obj][' + attr + '][' + widgetId + '][' + widgetAttr + '][][formdata$workaround][]', widgetValue[i]);
375
- }
376
- } else if (scrivito.BinaryUtils.isFile(widgetValue) || scrivito.BinaryUtils.isBlob(widgetValue)) {
377
- // upload
378
- fd.append('params[obj][' + attr + '][' + widgetId + '][' + widgetAttr + '][]', widgetAttrType);
379
- fd.append('params[obj][' + attr + '][' + widgetId + '][' + widgetAttr + '][]', widgetValue);
380
- } else if (scrivito.BinaryUtils.isBlobWithName(widgetValue)) {
381
- fd.append('params[obj][' + attr + '][' + widgetId + '][' + widgetAttr + '][]', widgetAttrType);
382
- fd.append('params[obj][' + attr + '][' + widgetId + '][' + widgetAttr + '][]', widgetValue.blob_to_upload, widgetValue.filename);
383
- } else if (widgetValue && typeof widgetValue === 'object') {
384
- // blob/copy rename
385
- fd.append('params[obj][' + attr + '][' + widgetId + '][' + widgetAttr + '][]', widgetAttrType);
386
- var _iteratorNormalCompletion6 = true;
387
- var _didIteratorError6 = false;
388
- var _iteratorError6 = undefined;
389
-
390
- try {
391
- for (var _iterator6 = Object.keys(widgetValue)[Symbol.iterator](), _step6; !(_iteratorNormalCompletion6 = (_step6 = _iterator6.next()).done); _iteratorNormalCompletion6 = true) {
392
- var l = _step6.value;
393
-
394
- fd.append('params[obj][' + attr + '][' + widgetId + '][' + widgetAttr + '][][' + l + ']', widgetValue[l]);
395
- }
396
- } catch (err) {
397
- _didIteratorError6 = true;
398
- _iteratorError6 = err;
399
- } finally {
400
- try {
401
- if (!_iteratorNormalCompletion6 && _iterator6['return']) {
402
- _iterator6['return']();
403
- }
404
- } finally {
405
- if (_didIteratorError6) {
406
- throw _iteratorError6;
407
- }
408
- }
291
+ } else if (typeof value !== 'undefined') {
292
+ fd.append('params[obj][' + attr + '][]', type);
293
+ fd.append('params[obj][' + attr + '][]', value);
294
+ }
295
+ // special handling for widget pool
296
+ } else if (attr === '_widget_pool') {
297
+ var value = objParams[attr];
298
+ for (var widgetId in value) {
299
+ if (value.hasOwnProperty(widgetId)) {
300
+ var widget = value[widgetId];
301
+ for (var widgetAttr in widget) {
302
+ if (widget.hasOwnProperty(widgetAttr)) {
303
+ if (widget[widgetAttr] && widget[widgetAttr].pop) {
304
+ var _widget$widgetAttr = _slicedToArray(widget[widgetAttr], 2);
305
+
306
+ var widgetAttrType = _widget$widgetAttr[0];
307
+ var widgetValue = _widget$widgetAttr[1];
308
+
309
+ // FIXME: Duplication
310
+ if (widgetValue && typeof widgetValue === 'object' && widgetValue.pop) {
311
+ // multienum / stringlist / widgetlist
312
+ fd.append('params[obj][' + attr + '][' + widgetId + '][' + widgetAttr + '][]', widgetAttrType);
313
+ for (var i = 0; i < widgetValue.length; ++i) {
314
+ fd.append('params[obj][' + attr + '][' + widgetId + '][' + widgetAttr + '][][formdata$workaround][]', widgetValue[i]);
315
+ }
316
+ } else if (scrivito.BinaryUtils.isFile(widgetValue) || scrivito.BinaryUtils.isBlob(widgetValue)) {
317
+ // upload
318
+ fd.append('params[obj][' + attr + '][' + widgetId + '][' + widgetAttr + '][]', widgetAttrType);
319
+ fd.append('params[obj][' + attr + '][' + widgetId + '][' + widgetAttr + '][]', widgetValue);
320
+ } else if (scrivito.BinaryUtils.isBlobWithName(widgetValue)) {
321
+ fd.append('params[obj][' + attr + '][' + widgetId + '][' + widgetAttr + '][]', widgetAttrType);
322
+ fd.append('params[obj][' + attr + '][' + widgetId + '][' + widgetAttr + '][]', widgetValue.blob_to_upload, widgetValue.filename);
323
+ } else if (widgetValue && typeof widgetValue === 'object') {
324
+ // blob/copy rename
325
+ fd.append('params[obj][' + attr + '][' + widgetId + '][' + widgetAttr + '][]', widgetAttrType);
326
+ for (var l in widgetValue) {
327
+ if (widgetValue.hasOwnProperty(l)) {
328
+ fd.append('params[obj][' + attr + '][' + widgetId + '][' + widgetAttr + '][][' + l + ']', widgetValue[l]);
409
329
  }
410
- } else {
411
- // normal value
412
- fd.append('params[obj][' + attr + '][' + widgetId + '][' + widgetAttr + '][]', widgetAttrType);
413
- fd.append('params[obj][' + attr + '][' + widgetId + '][' + widgetAttr + '][]', widgetValue);
414
330
  }
415
331
  } else {
416
- // hopefully a built-in attribute :-)
417
- fd.append('params[obj][' + attr + '][' + widgetId + '][' + widgetAttr + ']', widget[widgetAttr]);
418
- }
419
- }
420
- } catch (err) {
421
- _didIteratorError5 = true;
422
- _iteratorError5 = err;
423
- } finally {
424
- try {
425
- if (!_iteratorNormalCompletion5 && _iterator5['return']) {
426
- _iterator5['return']();
427
- }
428
- } finally {
429
- if (_didIteratorError5) {
430
- throw _iteratorError5;
332
+ // normal value
333
+ fd.append('params[obj][' + attr + '][' + widgetId + '][' + widgetAttr + '][]', widgetAttrType);
334
+ fd.append('params[obj][' + attr + '][' + widgetId + '][' + widgetAttr + '][]', widgetValue);
431
335
  }
336
+ } else {
337
+ // hopefully a built-in attribute :-)
338
+ fd.append('params[obj][' + attr + '][' + widgetId + '][' + widgetAttr + ']', widget[widgetAttr]);
432
339
  }
433
340
  }
434
341
  }
435
- } catch (err) {
436
- _didIteratorError4 = true;
437
- _iteratorError4 = err;
438
- } finally {
439
- try {
440
- if (!_iteratorNormalCompletion4 && _iterator4['return']) {
441
- _iterator4['return']();
442
- }
443
- } finally {
444
- if (_didIteratorError4) {
445
- throw _iteratorError4;
446
- }
447
- }
342
+ } else {
343
+ // hopefully a built-in attribute :-)
344
+ fd.append('params[obj][' + attr + ']', objParams[attr]);
448
345
  }
449
- } else {
450
- // hopefully a built-in attribute :-)
451
- fd.append('params[obj][' + attr + ']', objParams[attr]);
452
346
  }
453
- }
454
- } catch (err) {
455
- _didIteratorError2 = true;
456
- _iteratorError2 = err;
457
- } finally {
458
- try {
459
- if (!_iteratorNormalCompletion2 && _iterator2['return']) {
460
- _iterator2['return']();
461
- }
462
- } finally {
463
- if (_didIteratorError2) {
464
- throw _iteratorError2;
465
347
  }
466
- }
467
348
  }
468
349
 
469
350
  return fd;
@@ -1,3 +1,5 @@
1
+ require 'fiona7/widget_gc/garbage_collector'
2
+
1
3
  module Fiona7
2
4
  class ReleaseController < ActionController::Base
3
5
  helper_method :current_locale
@@ -52,6 +54,14 @@ module Fiona7
52
54
  end
53
55
 
54
56
  def carefully_release(errors, obj, comment=nil)
57
+ # NOTE: widget garbage collection may be required on release
58
+ # but only for objects which actually contain widgets.
59
+ #
60
+ # TODO: refactor this code!
61
+ if obj.attr_values["X_widget_pool"].present?
62
+ WidgetGc::GarbageCollector.new(obj.id, :release).gc!
63
+ end
64
+
55
65
  if obj.really_edited?
56
66
  # we don't care much if this fails
57
67
  obj.take
@@ -16,6 +16,8 @@ require 'fiona7/prefetch/obj_prefetch'
16
16
 
17
17
  require 'fiona7/attribute_writers/factory'
18
18
 
19
+ require 'fiona7/widget_gc/garbage_collector'
20
+
19
21
 
20
22
  module Fiona7
21
23
  module Builder
@@ -79,6 +81,8 @@ module Fiona7
79
81
  write_widget_pool
80
82
  store_attributes
81
83
 
84
+ widgets_gc
85
+
82
86
  @obj
83
87
  end
84
88
 
@@ -100,7 +104,7 @@ module Fiona7
100
104
  @obj_class = @values.delete(:_obj_class)
101
105
  @real_obj_class = Fiona7::ObjClassNameMangler.new(@obj_class).mangle
102
106
  @widget_pool = @values.delete(:_widget_pool)
103
- @permalink = @values.delete(:_permalink)
107
+ @permalink = @values.key?(:_permalink) ? (@values.delete(:_permalink) || "") : nil
104
108
 
105
109
  @path = "/#{@path}" unless @path.start_with?('/')
106
110
  @name, parent_path = name_and_parent_path_from_path(@path)
@@ -171,9 +175,36 @@ module Fiona7
171
175
 
172
176
  @obj.save!
173
177
 
174
- #if !@values.empty? || !@new_widget_pool.nil?
175
- @obj.edit! unless @obj.really_edited?
176
- #end
178
+ @obj.edit! unless @obj.really_edited?
179
+ end
180
+
181
+ def widgets_gc
182
+ if self.trigger_widget_gc?
183
+ WidgetGc::GarbageCollector.new(@obj.id, :update).gc!
184
+ end
185
+ end
186
+
187
+ def trigger_widget_gc?
188
+ # NOTE: there is actually only one case when we need
189
+ # to trigger widget gc: when a widget has been deleted
190
+ #
191
+ # Sadly deleting widgets has been deprecated from the
192
+ # SDK - now only the references to a widget are
193
+ # !implicitely! removed.
194
+ #
195
+ # It could be possible to guess which widget was deleted
196
+ # but its tricky and complicates things.
197
+ #
198
+ # Therefore we use a simple heuristic: if a widgetlist
199
+ # attribute has been provided as an input, then
200
+ # widgets have been added/rearanged/deleted which
201
+ # triggers widget garbage collection.
202
+ #
203
+ # The overhead of useless widget garbage collection pass
204
+ # is equal to two database queries, so it isn't too bad.
205
+ params_contain_widgetlist = @values.present? && @values.any? {|name, pair| pair.is_a?(Array) && pair[0] == "widgetlist" }
206
+ pool_contains_widgetlist = @widget_pool.present? && @widget_pool.any? {|widget_id, values| values.nil? || values.any? {|name, pair| pair.is_a?(Array) && pair[0] == "widgetlist" } }
207
+ params_contain_widgetlist || pool_contains_widgetlist
177
208
  end
178
209
 
179
210
 
@@ -18,7 +18,8 @@ module Fiona7
18
18
  @obj = WriteObj.find(obj_id)
19
19
  @path = @values.delete(:_path)
20
20
  @widget_pool = @values.delete(:_widget_pool)
21
- @permalink = @values.delete(:_permalink)
21
+ @permalink = @values.key?(:_permalink) ? (@values.delete(:_permalink) || "") : nil
22
+
22
23
 
23
24
  # revert command sends this info. which is silly.
24
25
  @values.delete(:_last_changed)
@@ -14,6 +14,14 @@ module Fiona7
14
14
  false
15
15
  end
16
16
 
17
+ def write_widget_pool
18
+ true
19
+ end
20
+
21
+ def widgets_gc
22
+ true
23
+ end
24
+
17
25
  def prepare_object
18
26
  @path = self.generate_widget_path
19
27
  @obj_class = @values.delete(:_obj_class)
data/lib/fiona7/engine.rb CHANGED
@@ -128,6 +128,10 @@ module Fiona7
128
128
  end
129
129
  end
130
130
 
131
+ def self.widget_gc_strategy
132
+ self.read_config.features.widget_gc_strategy
133
+ end
134
+
131
135
  def self.workflows_enabled?
132
136
  !!self.read_config.features.workflows_enabled
133
137
  end
@@ -143,8 +147,8 @@ module Fiona7
143
147
  end
144
148
  end
145
149
 
146
- class Features < Struct.new("Features", :workflows_enabled, :facetting_enabled)
147
- def initialize(workflows_enabled=true, facetting_enabled=true)
150
+ class Features < Struct.new("Features", :workflows_enabled, :facetting_enabled, :widget_gc_strategy)
151
+ def initialize(workflows_enabled=true, facetting_enabled=true, widget_gc_strategy=nil)
148
152
  super
149
153
  end
150
154
  end
@@ -1,5 +1,6 @@
1
1
  require 'fiona7/prefetch/obj_prefetch'
2
2
  require 'fiona7/widget_resolver'
3
+ require 'fiona7/widget_object_id_collector'
3
4
 
4
5
  module Fiona7
5
6
  module Prefetch
@@ -26,9 +27,7 @@ module Fiona7
26
27
 
27
28
  def collect_widget_object_ids(objects)
28
29
  objects.map do |object|
29
- (object.attr_values["X_widget_pool"]||[]).map do |widget_hash|
30
- widget_hash["destination"].try(:to_i)
31
- end
30
+ WidgetObjectIdCollector.new(object.attr_values["X_widget_pool"]).call
32
31
  end.flatten.compact
33
32
  end
34
33
  end
@@ -17,7 +17,7 @@ module Fiona7
17
17
  when :live
18
18
  live(obj)
19
19
  else
20
- raise ArgumentError, "Uknown type #{type.inspect} expected :preview or :ive"
20
+ raise ArgumentError, "Uknown type #{type.inspect} expected :preview or :live"
21
21
  end
22
22
  end
23
23
 
@@ -1,3 +1,3 @@
1
1
  module Fiona7
2
- VERSION = "1.5.5.3.1"
2
+ VERSION = "1.5.5.4.0"
3
3
  end
@@ -0,0 +1,32 @@
1
+ require 'fiona7/prefetch/obj_prefetch'
2
+ require 'fiona7/prefetch/widget_resolver_prefetch'
3
+
4
+ require 'fiona7/widget_gc/sweep_strategies/factory'
5
+ require 'fiona7/widget_gc/marker'
6
+
7
+ module Fiona7
8
+ module WidgetGc
9
+ class GarbageCollector
10
+ def initialize(object_id, mode)
11
+ self.object_id = object_id
12
+ self.mode = mode
13
+ self.klass = Fiona7::WriteObj
14
+ end
15
+
16
+ def gc!
17
+ if (sweep_strategy = SweepStrategies::Factory.for(self.mode, Fiona7.widget_gc_strategy))
18
+ object = Prefetch::ObjPrefetch.new(self.klass, [self.object_id]).find_one(self.object_id)
19
+ widget_resolver = Prefetch::WidgetResolverPrefetch.new(self.klass, [object]).widget_resolver(object)
20
+ marker = Marker.new(object, widget_resolver)
21
+
22
+ if marker.garbage?
23
+ sweep_strategy.new(object, widget_resolver).sweep!(marker.garbage)
24
+ end
25
+ end
26
+ end
27
+
28
+ protected
29
+ attr_accessor :object_id, :mode, :klass
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,45 @@
1
+ require 'fiona7/widget_object_id_collector'
2
+ require 'fiona7/widgetlist_enumerator'
3
+
4
+ module Fiona7
5
+ module WidgetGc
6
+ class Marker
7
+ def initialize(object, widget_resolver)
8
+ self.object = object
9
+ self.widgets = widget_resolver.all
10
+
11
+ self.mark
12
+ end
13
+
14
+ def garbage
15
+ self.available - self.referenced
16
+ end
17
+
18
+ def garbage?
19
+ self.garbage.any?
20
+ end
21
+
22
+ attr_reader :object, :widgets, :available, :referenced
23
+
24
+ protected
25
+ attr_writer :object, :widgets, :available, :referenced
26
+
27
+
28
+ def mark
29
+ ref_from_obj = self.object_ids_of_widgets(object)
30
+ ref_from_widgets = widgets.map do |widget_object|
31
+ # TODO: check if widget_object referenced from object
32
+ self.object_ids_of_widgets(widget_object)
33
+ end.flatten
34
+
35
+ # TODO: maybe use widgets.map(&:id) instead?
36
+ self.available = Set.new(WidgetObjectIdCollector.new(self.object.attr_values["X_widget_pool"]).call).freeze
37
+ self.referenced = Set.new(ref_from_obj + ref_from_widgets).freeze
38
+ end
39
+
40
+ def object_ids_of_widgets(object)
41
+ WidgetlistEnumerator.new(object).to_enum.map {|attr_name, attr_value| WidgetObjectIdCollector.new(attr_value).call }.flatten
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,42 @@
1
+ module Fiona7
2
+ module WidgetGc
3
+ module SweepStrategies
4
+ # This garbage collection strategy deletes BOTH working
5
+ # and released versions of garbage widget objects
6
+ # This effecively nukes the widget object.
7
+ # NOTE: It normally requires permissionRoot
8
+ # on all garbage widget objects. But since it is meant
9
+ # to be used during release process, which only requires
10
+ # permissionWrite permission elevation is used
11
+ #
12
+ # This strategy should be only used shortly
13
+ # before releasing the page
14
+ class ArchiveSweep
15
+ def initialize(object, widget_resolver)
16
+ self.object = object
17
+ self.widget_resolver = widget_resolver
18
+ end
19
+
20
+ def sweep!(garbage)
21
+ # NOTE: this emulates permission elevation:
22
+ # permissionWrite -> permissionRoot
23
+ return unless self.object.permission.write?
24
+
25
+ garbage.each do |widget_object_id|
26
+ # TODO: improve performance here
27
+ widget_object = self.widget_resolver.all.find {|w| w.id == widget_object_id }
28
+ archive!(widget_object)
29
+ end
30
+ end
31
+
32
+ protected
33
+ attr_accessor :object, :widget_resolver
34
+ def archive!(widget_object)
35
+ Reactor::Sudo.su(Fiona7.root) do
36
+ widget_object.send(:crul_obj).remove_active_contents!
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,21 @@
1
+ require 'fiona7/widget_gc/sweep_strategies/revert_sweep'
2
+ require 'fiona7/widget_gc/sweep_strategies/archive_sweep'
3
+
4
+ module Fiona7
5
+ module WidgetGc
6
+ module SweepStrategies
7
+ module Factory
8
+ def self.for(mode, name=Fiona7.widget_gc_strategy)
9
+ case [mode, name]
10
+ when [:update, :revert_archive]
11
+ RevertSweep
12
+ when [:release, :revert_archive]
13
+ ArchiveSweep
14
+ else
15
+ nil
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,33 @@
1
+ module Fiona7
2
+ module WidgetGc
3
+ module SweepStrategies
4
+ # This garbage collection strategy deletes working versions
5
+ # of garbage widget objects
6
+ # Its usefulness is limited to objects which hasn't been released yet
7
+ # or gained links in working version
8
+ #
9
+ # This strategy should be only used
10
+ # after deleting widgets
11
+ class RevertSweep
12
+ def initialize(object, widget_resolver)
13
+ self.object = object
14
+ self.widget_resolver = widget_resolver
15
+ end
16
+
17
+ def sweep!(garbage)
18
+ garbage.each do |widget_object_id|
19
+ # TODO: improve performance here
20
+ widget_object = self.widget_resolver.all.find {|w| w.id == widget_object_id }
21
+ revert!(widget_object)
22
+ end
23
+ end
24
+
25
+ protected
26
+ attr_accessor :object, :widget_resolver
27
+ def revert!(widget_object)
28
+ widget_object.revert! if widget_object.really_edited?
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,22 @@
1
+ module Fiona7
2
+ # Extracts widget object IDs from a widgetlist attribute read from
3
+ # Fiona7::WriteObj#attr_values[]
4
+ #
5
+ # The array contains integer IDs of the objects representing
6
+ # the widgets within given attr_value.
7
+ # For nil values it returns an empty array.
8
+ class WidgetObjectIdCollector
9
+ def initialize(attr_value)
10
+ self.attr_value = attr_value
11
+ end
12
+
13
+ def call
14
+ (attr_value || []).map do |widget_hash|
15
+ widget_hash["destination"].try(:to_i)
16
+ end.compact
17
+ end
18
+
19
+ protected
20
+ attr_accessor :attr_value
21
+ end
22
+ end
@@ -9,6 +9,10 @@ module Fiona7
9
9
 
10
10
  attr_reader :id_map, :path_map, :instance_map
11
11
 
12
+ def all
13
+ self.instance_map.values
14
+ end
15
+
12
16
  protected
13
17
  attr_accessor :value, :obj_repository
14
18
  attr_writer :id_map, :path_map, :instance_map
@@ -0,0 +1,30 @@
1
+ module Fiona7
2
+ # Takes a Fiona7::WriteObj as input and iterates over each
3
+ # widgetlist attribute that it has.
4
+ #
5
+ # This is very low-level class hence it returns mangled attribute names
6
+ class WidgetlistEnumerator
7
+ def initialize(object)
8
+ self.object = object
9
+ end
10
+
11
+ def each
12
+ self.object.attr_values.each do |attr_name, attr_value|
13
+ next unless attr_name != "X_widget_pool"
14
+ next unless self.widgetlist?(object, attr_name)
15
+
16
+ yield(attr_name, attr_value)
17
+ end
18
+ end
19
+
20
+ protected
21
+ attr_accessor :object
22
+
23
+ def widgetlist?(object, attr_name)
24
+ attr_def = object.attr_defs[attr_name] || {}
25
+ type_tag = (attr_def["help_texts"]||{})["de"]||""
26
+
27
+ type_tag =~ /"widgetlist"/
28
+ end
29
+ end
30
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: infopark_fiona7
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.5.5.3.1
4
+ version: 1.5.5.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tomasz Przedmojski
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-01-05 00:00:00.000000000 Z
11
+ date: 2017-01-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -331,7 +331,14 @@ files:
331
331
  - lib/fiona7/verity_search_engine.rb
332
332
  - lib/fiona7/version.rb
333
333
  - lib/fiona7/version_helper.rb
334
+ - lib/fiona7/widget_gc/garbage_collector.rb
335
+ - lib/fiona7/widget_gc/marker.rb
336
+ - lib/fiona7/widget_gc/sweep_strategies/archive_sweep.rb
337
+ - lib/fiona7/widget_gc/sweep_strategies/factory.rb
338
+ - lib/fiona7/widget_gc/sweep_strategies/revert_sweep.rb
339
+ - lib/fiona7/widget_object_id_collector.rb
334
340
  - lib/fiona7/widget_resolver.rb
341
+ - lib/fiona7/widgetlist_enumerator.rb
335
342
  - lib/fiona7/workspace.rb
336
343
  - lib/infopark_fiona7.rb
337
344
  - lib/tasks/fiona7_tasks.rake