infopark_cloud_connector 6.8.0.beta.200.621.4c8e1b0
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.
- data/README +71 -0
- data/lib/infopark_cloud_connector.rb +19 -0
- data/lib/rails_connector/attribute.rb +35 -0
- data/lib/rails_connector/blob.rb +66 -0
- data/lib/rails_connector/cache.rb +35 -0
- data/lib/rails_connector/cache_middleware.rb +17 -0
- data/lib/rails_connector/chain.rb +177 -0
- data/lib/rails_connector/cms_base_model.rb +61 -0
- data/lib/rails_connector/content_cache.rb +24 -0
- data/lib/rails_connector/controller_runtime.rb +35 -0
- data/lib/rails_connector/couch_blob.rb +44 -0
- data/lib/rails_connector/couchdb_views_source_path.rb +7 -0
- data/lib/rails_connector/date_attribute.rb +28 -0
- data/lib/rails_connector/default_search_request.rb +6 -0
- data/lib/rails_connector/elasticsearch_request.rb +78 -0
- data/lib/rails_connector/errors.rb +9 -0
- data/lib/rails_connector/link.rb +135 -0
- data/lib/rails_connector/log_subscriber.rb +29 -0
- data/lib/rails_connector/named_link.rb +72 -0
- data/lib/rails_connector/obj.rb +622 -0
- data/lib/rails_connector/obj_body.rb +60 -0
- data/lib/rails_connector/obj_class.rb +35 -0
- data/lib/rails_connector/path_conversion.rb +17 -0
- data/lib/rails_connector/permission.rb +39 -0
- data/lib/rails_connector/rack_middlewares.rb +6 -0
- data/lib/rails_connector/s3_blob.rb +67 -0
- data/lib/rails_connector/version.rb +39 -0
- data/lib/rails_connector/workspace.rb +139 -0
- data/lib/rails_connector/workspace_label.rb +10 -0
- data/lib/rails_connector/workspace_selection_middleware.rb +45 -0
- metadata +169 -0
@@ -0,0 +1,622 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'ostruct'
|
3
|
+
require 'kvom/model_identity'
|
4
|
+
|
5
|
+
module RailsConnector
|
6
|
+
# The CMS file class
|
7
|
+
class Obj
|
8
|
+
extend ActiveModel::Naming
|
9
|
+
include Kvom::ModelIdentity
|
10
|
+
|
11
|
+
include DateAttribute
|
12
|
+
include StringTagging
|
13
|
+
include SEO
|
14
|
+
include ObjBody
|
15
|
+
|
16
|
+
extend PathConversion
|
17
|
+
include PathConversion
|
18
|
+
|
19
|
+
# Create a new Obj instance with the given values and attributes.
|
20
|
+
# Normally this method should not be used.
|
21
|
+
# Instead Objs should be loaded from the cms database.
|
22
|
+
def initialize(values = {}, meta = {})
|
23
|
+
update_data(values, meta)
|
24
|
+
end
|
25
|
+
|
26
|
+
# instantiate an Obj instance from obj_data.
|
27
|
+
# May result in an instance of a subclass of Obj according to STI rules.
|
28
|
+
def self.instantiate(obj_data) # :nodoc:
|
29
|
+
obj_class = obj_data["values"]["obj_class"]
|
30
|
+
Obj.compute_type(obj_class).new(
|
31
|
+
obj_data["values"], obj_data
|
32
|
+
)
|
33
|
+
end
|
34
|
+
|
35
|
+
def id
|
36
|
+
@values["id"]
|
37
|
+
end
|
38
|
+
|
39
|
+
### FINDERS ####################
|
40
|
+
|
41
|
+
# Find an Obj by it's id.
|
42
|
+
# If the paremeter is an Array containing ids, return a list of corresponding Objs.
|
43
|
+
def self.find(id_or_list)
|
44
|
+
case id_or_list
|
45
|
+
when Array
|
46
|
+
find_objs_by(:id, id_or_list).map(&:first)
|
47
|
+
else
|
48
|
+
obj = find_objs_by(:id, [id_or_list.to_s]).first.first
|
49
|
+
obj or raise ResourceNotFound, "Could not find #{self} with id #{id_or_list}"
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
# (notice: not yet implemented)
|
54
|
+
# Returns a list of all Objs.
|
55
|
+
# If invoked on a subclass of Obj, the result will be restricted to Obj of that subclass.
|
56
|
+
def self.all # :nodoc:
|
57
|
+
raise "not yet implemented!"
|
58
|
+
end
|
59
|
+
|
60
|
+
# (notice: not yet implemented)
|
61
|
+
# returns an Array of all Objs with the given obj_class.
|
62
|
+
def self.find_all_by_obj_class(obj_class) # :nodoc:
|
63
|
+
raise "not yet implemented!"
|
64
|
+
end
|
65
|
+
|
66
|
+
# Find the Obj with the given path.
|
67
|
+
# Returns nil if no matching Obj exists.
|
68
|
+
def self.find_by_path(path)
|
69
|
+
find_objs_by(:path, [path]).first.first
|
70
|
+
end
|
71
|
+
|
72
|
+
def self.find_by_path_list(path_list) # :nodoc:
|
73
|
+
find_by_path(path_from_list(path_list))
|
74
|
+
end
|
75
|
+
|
76
|
+
def self.find_many_by_paths(pathes) # :nodoc:
|
77
|
+
find_objs_by(:path, pathes).map(&:first)
|
78
|
+
end
|
79
|
+
|
80
|
+
# (notice: not yet implemented)
|
81
|
+
# Find an Obj with the given name.
|
82
|
+
# If several Objs exist with the given name, one of them is chosen and returned.
|
83
|
+
# If no Obj with the name exits, nil is returned.
|
84
|
+
def self.find_by_name(name) # :nodoc:
|
85
|
+
raise "not yet implemented!"
|
86
|
+
end
|
87
|
+
|
88
|
+
# (notice: not yet implemented)
|
89
|
+
# Find all Objs with the given name.
|
90
|
+
def self.find_all_by_name(name) # :nodoc:
|
91
|
+
raise "not yet implemented!"
|
92
|
+
end
|
93
|
+
|
94
|
+
# Return the Obj with the given permalink or nil if no matching Obj exists.
|
95
|
+
def self.find_by_permalink(permalink)
|
96
|
+
find_objs_by(:permalink, [permalink]).first.first
|
97
|
+
end
|
98
|
+
|
99
|
+
# Return the Obj with the given permalink or raise ResourceNotFound if no matching Obj exists.
|
100
|
+
def self.find_by_permalink!(permalink)
|
101
|
+
find_by_permalink(permalink) or
|
102
|
+
raise ResourceNotFound, "Could not find #{self} with permalink '#{permalink}'"
|
103
|
+
end
|
104
|
+
|
105
|
+
# accepts the name of an "obj_by" - view and a list of keys.
|
106
|
+
# returns a list of lists of Objs: a list of Objs for each given keys.
|
107
|
+
def self.find_objs_by(view, keys) # :nodoc:
|
108
|
+
Workspace.current.find_obj_data_by(view, keys).map do |list|
|
109
|
+
list.map { |obj_data| Obj.instantiate(obj_data) }
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
def to_param # :nodoc:
|
114
|
+
id
|
115
|
+
end
|
116
|
+
|
117
|
+
def self.configure_for_content(mode) # :nodoc:
|
118
|
+
# this method exists only for compatibility with the fiona connector.
|
119
|
+
end
|
120
|
+
|
121
|
+
# A CMS administrator can specify the <tt>obj_class</tt> for a given CMS object.
|
122
|
+
# In Rails, this could be either:
|
123
|
+
#
|
124
|
+
# * A valid and existing model name
|
125
|
+
# * A valid and non-existing model name
|
126
|
+
# * An invalid model name
|
127
|
+
#
|
128
|
+
# Rails' STI mechanism only considers the first case.
|
129
|
+
# In any other case, RailsConnector::Obj is used, except when explicitely asked
|
130
|
+
# for a model in the RailsConnector namespace (RailsConnector::Permission etc.)
|
131
|
+
|
132
|
+
def self.compute_type(type_name) # :nodoc:
|
133
|
+
@compute_type_cache ||= {}
|
134
|
+
@compute_type_cache [type_name] ||= try_type { type_name.constantize } || self
|
135
|
+
end
|
136
|
+
|
137
|
+
# return the Obj that is the parent of this Obj.
|
138
|
+
# returns nil for the root Obj.
|
139
|
+
def parent
|
140
|
+
root? ? nil : Obj.find_by_path_list(path_list[0..-2])
|
141
|
+
end
|
142
|
+
|
143
|
+
# Returns an Array of all the ancestor objects, starting at the root and ending at this object's parent.
|
144
|
+
def ancestors
|
145
|
+
return [] if root?
|
146
|
+
ancestor_paths = path_list[0..-2].inject([""]) do |list, component|
|
147
|
+
list << list.last + "/#{component}"
|
148
|
+
end
|
149
|
+
ancestor_paths[0] = "/"
|
150
|
+
Obj.find_many_by_paths(ancestor_paths)
|
151
|
+
end
|
152
|
+
|
153
|
+
# return a list of all child Objs.
|
154
|
+
def children
|
155
|
+
Obj.find_objs_by(:ppath, [path]).first
|
156
|
+
end
|
157
|
+
|
158
|
+
### ATTRIBUTES #################
|
159
|
+
|
160
|
+
# returns the Obj's path as a String.
|
161
|
+
def path
|
162
|
+
path_from_list(path_list)
|
163
|
+
end
|
164
|
+
|
165
|
+
def path_list # :nodoc:
|
166
|
+
read_attribute(:path) || []
|
167
|
+
end
|
168
|
+
|
169
|
+
# returns the Obj's name, i.e. the last component of the path.
|
170
|
+
def name
|
171
|
+
path_list.last || ""
|
172
|
+
end
|
173
|
+
|
174
|
+
def permissions
|
175
|
+
# FIXME permissions
|
176
|
+
@permissions ||= OpenStruct.new({
|
177
|
+
:live => permitted_groups,
|
178
|
+
:read => [],
|
179
|
+
:write => [],
|
180
|
+
:root => [],
|
181
|
+
:create_children => [],
|
182
|
+
})
|
183
|
+
end
|
184
|
+
|
185
|
+
def permitted_for_user?(user)
|
186
|
+
if permitted_groups.blank?
|
187
|
+
true
|
188
|
+
else
|
189
|
+
if user
|
190
|
+
(permitted_groups & user.live_server_groups).any?
|
191
|
+
else
|
192
|
+
false
|
193
|
+
end
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
def object_id # :nodoc:
|
198
|
+
obj_id
|
199
|
+
end
|
200
|
+
|
201
|
+
# Returns the root Obj, i.e. the Obj with the path "/"
|
202
|
+
def self.root
|
203
|
+
Obj.find_by_path("/") or raise ResourceNotFound, "Obj.root not found: There is no Obj with path '/'."
|
204
|
+
end
|
205
|
+
|
206
|
+
# Returns the homepage object. This can be overwritten in your application's +ObjExtensions+.
|
207
|
+
# Use <tt>Obj#homepage?</tt> to check if an object is the homepage.
|
208
|
+
def self.homepage
|
209
|
+
root
|
210
|
+
end
|
211
|
+
|
212
|
+
# returns the obj's permalink.
|
213
|
+
def permalink
|
214
|
+
read_attribute(:permalink)
|
215
|
+
end
|
216
|
+
|
217
|
+
# This method determines the controller that should be invoked when the Obj is requested.
|
218
|
+
# By default a controller matching the Obj's obj_class will be used.
|
219
|
+
# If the controller does not exist, the CmsController will be used as a fallback.
|
220
|
+
# Overwrite this method to force a different controller to be used.
|
221
|
+
def controller_name
|
222
|
+
obj_class
|
223
|
+
end
|
224
|
+
|
225
|
+
# This method determines the action that should be invoked when the Obj is requested.
|
226
|
+
# The default action is 'index'.
|
227
|
+
# Overwrite this method to force a different action to be used.
|
228
|
+
def controller_action_name
|
229
|
+
"index"
|
230
|
+
end
|
231
|
+
|
232
|
+
# Returns true if the current object is the homepage object.
|
233
|
+
def homepage?
|
234
|
+
self == self.class.homepage
|
235
|
+
end
|
236
|
+
|
237
|
+
# Returns the title of the content or the name.
|
238
|
+
def display_title
|
239
|
+
self.title || name
|
240
|
+
end
|
241
|
+
|
242
|
+
def title
|
243
|
+
read_attribute(:title)
|
244
|
+
end
|
245
|
+
|
246
|
+
# Returns the type of the object: :document, :publication, :image or :generic
|
247
|
+
def object_type
|
248
|
+
read_attribute(:obj_type).to_sym
|
249
|
+
end
|
250
|
+
|
251
|
+
# Returns true if image? or generic?
|
252
|
+
def binary?
|
253
|
+
[:image, :generic].include? object_type
|
254
|
+
end
|
255
|
+
|
256
|
+
# Returns true if object_type == :image
|
257
|
+
def image?
|
258
|
+
object_type == :image
|
259
|
+
end
|
260
|
+
|
261
|
+
# Returns true if object_type == :generic
|
262
|
+
def generic?
|
263
|
+
object_type == :generic
|
264
|
+
end
|
265
|
+
|
266
|
+
# Returns true if object_type == :publication (for folders)
|
267
|
+
def publication?
|
268
|
+
object_type == :publication
|
269
|
+
end
|
270
|
+
|
271
|
+
# Returns true if object_type == :document
|
272
|
+
def document?
|
273
|
+
object_type == :document
|
274
|
+
end
|
275
|
+
|
276
|
+
# Returns true if this object is active (time_when is in object's time interval)
|
277
|
+
def active?(time_when = nil)
|
278
|
+
return false unless valid_from
|
279
|
+
time_then = time_when || Obj.preview_time
|
280
|
+
valid_from <= time_then && (!valid_until || time_then <= valid_until)
|
281
|
+
end
|
282
|
+
|
283
|
+
# compatibility with legacy apps.
|
284
|
+
def suppress_export # :nodoc:
|
285
|
+
suppressed? ? 1 : 0
|
286
|
+
end
|
287
|
+
|
288
|
+
# Returns true if the Obj is suppressed.
|
289
|
+
# A suppressed Obj does not represent an entire web page, but only a part of a page
|
290
|
+
# (for example a teaser) and will not be delivered by the rails application
|
291
|
+
# as a standalone web page.
|
292
|
+
def suppressed?
|
293
|
+
@values["suppress_export"] ? true : false
|
294
|
+
end
|
295
|
+
|
296
|
+
# Returns true if the export of the object is not suppressed and the content is active?
|
297
|
+
def exportable?(current_time = nil)
|
298
|
+
!suppressed? && active?(current_time)
|
299
|
+
end
|
300
|
+
|
301
|
+
# Returns the file name to which the Content.file_extension has been appended.
|
302
|
+
def filename
|
303
|
+
Rails.logger.warn(
|
304
|
+
"DEPRECATION WARNING: "\
|
305
|
+
"The Method Obj#filename is no longer supported. Please use Obj#name instead. "\
|
306
|
+
"From: #{caller[0]}"
|
307
|
+
)
|
308
|
+
|
309
|
+
name
|
310
|
+
end
|
311
|
+
|
312
|
+
# Returns an array with the names of groups that are permitted to access this Obj.
|
313
|
+
# This corresponds to the cms permission "permissionLiveServerRead".
|
314
|
+
def permitted_groups
|
315
|
+
# FIXME permissions not yet implemented in fiona 7
|
316
|
+
[]
|
317
|
+
end
|
318
|
+
|
319
|
+
# Returns true if this object is the root object.
|
320
|
+
def root?
|
321
|
+
path_list.empty?
|
322
|
+
end
|
323
|
+
|
324
|
+
# Returns a list of exportable? children excluding the binary? ones unless :all is specfied.
|
325
|
+
# This is mainly used for navigations.
|
326
|
+
def toclist(*args)
|
327
|
+
return [] unless publication?
|
328
|
+
time = args.detect {|value| value.kind_of? Time}
|
329
|
+
toclist = children.select{ |toc| toc.exportable?(time) }
|
330
|
+
toclist = toclist.reject { |toc| toc.binary? } unless args.include?(:all)
|
331
|
+
toclist
|
332
|
+
end
|
333
|
+
|
334
|
+
# Returns the sorted +toclist+, respecting sort order and type of this Obj.
|
335
|
+
def sorted_toclist(*args)
|
336
|
+
list = self.toclist(*args)
|
337
|
+
return [] if list.blank?
|
338
|
+
|
339
|
+
cached_sort_key1 = self.sort_key1
|
340
|
+
cached_sort_type1 = self.sort_type1
|
341
|
+
|
342
|
+
sorted_list =
|
343
|
+
if cached_sort_key1.blank?
|
344
|
+
list.sort { |left_obj, right_obj| left_obj.name <=> right_obj.name }
|
345
|
+
else
|
346
|
+
cached_sort_key2 = self.sort_key2
|
347
|
+
cached_sort_type2 = self.sort_type2
|
348
|
+
cached_sort_key3 = self.sort_key3
|
349
|
+
cached_sort_type3 = self.sort_type3
|
350
|
+
|
351
|
+
list.sort do |left_obj, right_obj|
|
352
|
+
compare = compare_on_sort_key(left_obj, right_obj, cached_sort_key1, cached_sort_type1)
|
353
|
+
if compare == 0 && cached_sort_key2
|
354
|
+
compare = compare_on_sort_key(left_obj, right_obj, cached_sort_key2, cached_sort_type2)
|
355
|
+
if compare == 0 && cached_sort_key3
|
356
|
+
compare = compare_on_sort_key(left_obj, right_obj, cached_sort_key3, cached_sort_type3)
|
357
|
+
end
|
358
|
+
end
|
359
|
+
compare
|
360
|
+
end
|
361
|
+
end
|
362
|
+
|
363
|
+
return self.sort_order == "descending" ? sorted_list.reverse : sorted_list
|
364
|
+
end
|
365
|
+
|
366
|
+
def sort_order # :nodoc:
|
367
|
+
read_attribute(:sort_order) == 1 ? "descending" : "ascending"
|
368
|
+
end
|
369
|
+
|
370
|
+
def sort_type1 # :nodoc:
|
371
|
+
converted_sort_type(:sort_type1)
|
372
|
+
end
|
373
|
+
|
374
|
+
def sort_type2 # :nodoc:
|
375
|
+
converted_sort_type(:sort_type2)
|
376
|
+
end
|
377
|
+
|
378
|
+
def sort_type3 # :nodoc:
|
379
|
+
converted_sort_type(:sort_type3)
|
380
|
+
end
|
381
|
+
|
382
|
+
def sort_key1 # :nodoc:
|
383
|
+
converted_sort_key(:sort_key1)
|
384
|
+
end
|
385
|
+
|
386
|
+
def sort_key2 # :nodoc:
|
387
|
+
converted_sort_key(:sort_key2)
|
388
|
+
end
|
389
|
+
|
390
|
+
def sort_key3 # :nodoc:
|
391
|
+
converted_sort_key(:sort_key3)
|
392
|
+
end
|
393
|
+
|
394
|
+
# Returns the Object with the given name next in the hierarchy
|
395
|
+
# returns nil if no object with the given name was found.
|
396
|
+
def find_nearest(name)
|
397
|
+
obj = self.class.find_by_path_list(path_list + [name])
|
398
|
+
return obj if obj and obj.active?
|
399
|
+
parent.find_nearest(name) unless self.root?
|
400
|
+
end
|
401
|
+
|
402
|
+
# Returns the value of the attribute specified by its name.
|
403
|
+
#
|
404
|
+
# Passing an invalid key will not raise an error, but return nil.
|
405
|
+
def [](raw_key)
|
406
|
+
key = raw_key.to_s
|
407
|
+
case key
|
408
|
+
when "name"
|
409
|
+
name
|
410
|
+
when "body"
|
411
|
+
body
|
412
|
+
else
|
413
|
+
read_attribute(key)
|
414
|
+
end
|
415
|
+
end
|
416
|
+
|
417
|
+
# Reloads the attributes of this object from the database.
|
418
|
+
# Notice that the ruby class of this Obj instance will NOT change,
|
419
|
+
# even if the obj_class in the database has changed.
|
420
|
+
def reload
|
421
|
+
obj_data = Workspace.current.find_obj_data_by(:id, [id.to_s]).first.first
|
422
|
+
update_data(obj_data["values"], obj_data)
|
423
|
+
end
|
424
|
+
|
425
|
+
def last_changed
|
426
|
+
self[:last_changed]
|
427
|
+
end
|
428
|
+
|
429
|
+
def valid_from
|
430
|
+
self[:valid_from]
|
431
|
+
end
|
432
|
+
|
433
|
+
def valid_until
|
434
|
+
self[:valid_until]
|
435
|
+
end
|
436
|
+
|
437
|
+
# For a binary Obj, the content_type is equal to the content_type of it's body (i.e. it's data).
|
438
|
+
# For non-binary Objs, a the default content_type is "text/html".
|
439
|
+
# Override this method in subclasses to define a different content_type.
|
440
|
+
# Note that only Objs with content_type "text/html"
|
441
|
+
# will be rendered with layout and templates by the DefaultCmsController.
|
442
|
+
def content_type
|
443
|
+
if binary?
|
444
|
+
body_content_type
|
445
|
+
else
|
446
|
+
"text/html"
|
447
|
+
end
|
448
|
+
end
|
449
|
+
alias mime_type content_type
|
450
|
+
|
451
|
+
# returns the extension (the part after the last dot) from the Obj's name.
|
452
|
+
# returns an empty string if no extension is present in the Obj's name.
|
453
|
+
def file_extension
|
454
|
+
File.extname(name)[1..-1] || ""
|
455
|
+
end
|
456
|
+
|
457
|
+
def to_liquid # :nodoc:
|
458
|
+
LiquidSupport::ObjDrop.new(self)
|
459
|
+
end
|
460
|
+
|
461
|
+
def respond_to?(method_id, include_private=false) # :nodoc:
|
462
|
+
if has_attribute?(method_id)
|
463
|
+
true
|
464
|
+
else
|
465
|
+
super
|
466
|
+
end
|
467
|
+
end
|
468
|
+
|
469
|
+
# Returns a list of the names of all custom attributes defined for this Obj as Symbols.
|
470
|
+
# A custom attribute is a user-defined attribute, i.e. one that is not built-in in the CMS.
|
471
|
+
def custom_attribute_names
|
472
|
+
@attributes.keys.map(&:to_sym)
|
473
|
+
end
|
474
|
+
|
475
|
+
def has_attribute?(name)
|
476
|
+
name_as_string = name.to_s
|
477
|
+
@values.has_key?(name_as_string) || @attributes.has_key?(name_as_string)
|
478
|
+
end
|
479
|
+
|
480
|
+
def self.preview_time=(t) # :nodoc:
|
481
|
+
Thread.current[:preview_time] = t
|
482
|
+
end
|
483
|
+
|
484
|
+
def self.preview_time # :nodoc:
|
485
|
+
Thread.current[:preview_time] || Time.now
|
486
|
+
end
|
487
|
+
|
488
|
+
def inspect
|
489
|
+
"<#{self.class} id=\"#{id}\" path=\"#{path}\">"
|
490
|
+
end
|
491
|
+
|
492
|
+
private
|
493
|
+
|
494
|
+
def update_data(values = {}, meta = {})
|
495
|
+
@values = values
|
496
|
+
@attributes = meta["attributes"] || {}
|
497
|
+
@attr_cache = {}
|
498
|
+
end
|
499
|
+
|
500
|
+
def read_attribute(name)
|
501
|
+
name = name.to_s
|
502
|
+
if name == "suppress_export"
|
503
|
+
suppress_export
|
504
|
+
else
|
505
|
+
raw = @values[name]
|
506
|
+
@attr_cache[name] ||= case type_of(name)
|
507
|
+
when :markdown
|
508
|
+
StringTagging.tag_as_markdown(raw, self)
|
509
|
+
when :html
|
510
|
+
StringTagging.tag_as_html(raw, self)
|
511
|
+
when :date
|
512
|
+
DateAttribute.parse raw if raw
|
513
|
+
when :linklist
|
514
|
+
if name == "text_links"
|
515
|
+
LinkList.new(raw.values)
|
516
|
+
else
|
517
|
+
LinkList.new(raw)
|
518
|
+
end
|
519
|
+
else
|
520
|
+
raw
|
521
|
+
end
|
522
|
+
end
|
523
|
+
end
|
524
|
+
|
525
|
+
def type_of(key)
|
526
|
+
key = key.to_s
|
527
|
+
case key
|
528
|
+
when "permission_live_server_read"
|
529
|
+
nil
|
530
|
+
when "text_links"
|
531
|
+
:linklist
|
532
|
+
when "valid_from"
|
533
|
+
:date
|
534
|
+
when "valid_until"
|
535
|
+
:date
|
536
|
+
when "last_changed"
|
537
|
+
:date
|
538
|
+
when "title"
|
539
|
+
:html
|
540
|
+
else
|
541
|
+
if attr_def = @attributes[key]
|
542
|
+
type = attr_def["type"]
|
543
|
+
type.to_sym if type
|
544
|
+
end
|
545
|
+
end
|
546
|
+
end
|
547
|
+
|
548
|
+
def as_date(value)
|
549
|
+
DateAttribute.parse(value) unless value.nil?
|
550
|
+
end
|
551
|
+
|
552
|
+
def method_missing(method_id, *args) # :nodoc:
|
553
|
+
if has_attribute?(method_id)
|
554
|
+
read_attribute(method_id)
|
555
|
+
else
|
556
|
+
super
|
557
|
+
end
|
558
|
+
end
|
559
|
+
|
560
|
+
def compare_on_sort_key(left_obj, right_obj, my_sort_key, my_sort_type)
|
561
|
+
left_value = left_obj[my_sort_key]
|
562
|
+
right_value = right_obj[my_sort_key]
|
563
|
+
|
564
|
+
if left_value.nil?
|
565
|
+
1
|
566
|
+
elsif right_value.nil?
|
567
|
+
-1
|
568
|
+
# hardcoded type check needed for speed
|
569
|
+
elsif left_value.is_a?(Time) && right_value.is_a?(Time)
|
570
|
+
left_value <=> right_value
|
571
|
+
else
|
572
|
+
if my_sort_type == "numeric"
|
573
|
+
(left_value.to_i rescue 0) <=> (right_value.to_i rescue 0)
|
574
|
+
else
|
575
|
+
left_value.to_s.downcase <=> right_value.to_s.downcase
|
576
|
+
end
|
577
|
+
end
|
578
|
+
end
|
579
|
+
|
580
|
+
def converted_sort_type(attribute)
|
581
|
+
read_attribute(attribute) == 1 ? "numeric" : "alphaNumeric"
|
582
|
+
end
|
583
|
+
|
584
|
+
def converted_sort_key(attribute)
|
585
|
+
key = read_attribute(attribute)
|
586
|
+
case key
|
587
|
+
when "validUntil"
|
588
|
+
"valid_until"
|
589
|
+
when "validFrom"
|
590
|
+
"valid_from"
|
591
|
+
when "lastChanged"
|
592
|
+
"last_changed"
|
593
|
+
when "contentType"
|
594
|
+
"content_type"
|
595
|
+
else
|
596
|
+
key
|
597
|
+
end
|
598
|
+
end
|
599
|
+
|
600
|
+
class << self
|
601
|
+
private
|
602
|
+
|
603
|
+
def try_type
|
604
|
+
result = yield
|
605
|
+
result if subclass_of_obj(result)
|
606
|
+
rescue NameError
|
607
|
+
nil
|
608
|
+
end
|
609
|
+
|
610
|
+
def subclass_of_obj(klass)
|
611
|
+
if klass == Obj
|
612
|
+
true
|
613
|
+
else
|
614
|
+
klass.superclass && subclass_of_obj(klass.superclass)
|
615
|
+
end
|
616
|
+
end
|
617
|
+
|
618
|
+
end
|
619
|
+
end
|
620
|
+
|
621
|
+
end
|
622
|
+
|
@@ -0,0 +1,60 @@
|
|
1
|
+
module RailsConnector
|
2
|
+
|
3
|
+
module ObjBody
|
4
|
+
# Returns the body (main content) of the Obj for non-binary Objs.
|
5
|
+
# Returns nil for binary Objs.
|
6
|
+
def body
|
7
|
+
if binary?
|
8
|
+
nil
|
9
|
+
else
|
10
|
+
StringTagging.tag_as_html(read_attribute(:blob), self)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
# for binary Objs body_length equals the file size
|
15
|
+
# for non-binary Objs body_length equals the number of characters in the body (main content)
|
16
|
+
def body_length
|
17
|
+
if binary?
|
18
|
+
blob = find_blob
|
19
|
+
blob ? blob.length : 0
|
20
|
+
else
|
21
|
+
(body || "").length
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
# returns an URL to retrieve the Obj's body for binary Objs.
|
26
|
+
# returns nil for non-binary Objs.
|
27
|
+
def body_data_url
|
28
|
+
if binary?
|
29
|
+
blob = find_blob
|
30
|
+
blob.url if blob
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def body_data_path # :nodoc:
|
35
|
+
# not needed/supported when using cloud connector.
|
36
|
+
nil
|
37
|
+
end
|
38
|
+
|
39
|
+
# returns the content type of the Obj's body for binary Objs.
|
40
|
+
# returns nil for non-binary Objs.
|
41
|
+
def body_content_type
|
42
|
+
if binary?
|
43
|
+
blob = find_blob
|
44
|
+
if blob
|
45
|
+
blob.content_type
|
46
|
+
else
|
47
|
+
"application/octet-stream"
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
private
|
53
|
+
|
54
|
+
def find_blob
|
55
|
+
blob_spec = read_attribute(:blob)
|
56
|
+
Blob.find(blob_spec["id"], :context => path) if blob_spec
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
end # module RailsConnector
|
@@ -0,0 +1,35 @@
|
|
1
|
+
#:enddoc:
|
2
|
+
module RailsConnector
|
3
|
+
|
4
|
+
class ObjClass < CmsBaseModel
|
5
|
+
def self.by_name(name)
|
6
|
+
obj_class_cache[name]
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.reset_cache
|
10
|
+
@obj_class_cache = nil
|
11
|
+
end
|
12
|
+
|
13
|
+
def name
|
14
|
+
obj_class_name
|
15
|
+
end
|
16
|
+
|
17
|
+
def has_attribute?(name)
|
18
|
+
@custom_attribute_names ||= custom_attributes.map(&:name)
|
19
|
+
@custom_attribute_names.include?(name.to_s)
|
20
|
+
end
|
21
|
+
|
22
|
+
module ClassMethods
|
23
|
+
private
|
24
|
+
|
25
|
+
def obj_class_cache
|
26
|
+
@obj_class_cache ||= find(:all).each_with_object({}) do |objclass, map|
|
27
|
+
map[objclass.name] = objclass
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
extend ClassMethods
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|