infopark_cloud_connector 6.9.4 → 6.9.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (61) hide show
  1. checksums.yaml +15 -0
  2. data/README +1 -3
  3. data/app/controllers/cms_controller.rb +7 -0
  4. data/app/controllers/rails_connector/default_cms_controller.rb +43 -0
  5. data/app/controllers/rails_connector/objs_controller.rb +29 -0
  6. data/app/controllers/rails_connector/widget_renderer.rb +1 -1
  7. data/app/controllers/rails_connector/workspaces_controller.rb +4 -0
  8. data/app/helpers/cms_helper.rb +7 -0
  9. data/app/helpers/cms_routing_helper.rb +7 -0
  10. data/app/helpers/rails_connector/cms_asset_helper.rb +24 -17
  11. data/app/helpers/rails_connector/cms_tag_helper.rb +9 -6
  12. data/app/helpers/rails_connector/default_cms_helper.rb +23 -0
  13. data/app/helpers/rails_connector/default_cms_routing_helper.rb +101 -0
  14. data/app/helpers/rails_connector/display_helper.rb +4 -30
  15. data/app/helpers/rails_connector/editing_helper.rb +3 -0
  16. data/app/helpers/rails_connector/layout_helper.rb +29 -0
  17. data/app/helpers/rails_connector/table_of_contents_helper.rb +22 -0
  18. data/app/models/named_link.rb +2 -0
  19. data/app/views/cms/_index.html.erb +7 -0
  20. data/app/views/cms/index.html.erb +1 -0
  21. data/app/views/errors/403_forbidden.html.erb +3 -0
  22. data/app/views/errors/410_gone.html.erb +7 -0
  23. data/app/views/rails_connector/_editing_javascript.html.erb +2 -0
  24. data/config/ca-bundle.crt +1 -1
  25. data/config/cms_routes.rb +14 -0
  26. data/config/locales/de.rails_connector.errors.yml +11 -0
  27. data/config/locales/de.rails_connector.lib.yml +6 -0
  28. data/config/locales/de.rails_connector.views.yml +9 -0
  29. data/config/locales/en.rails_connector.errors.yml +10 -0
  30. data/config/locales/en.rails_connector.lib.yml +6 -0
  31. data/config/locales/en.rails_connector.views.yml +9 -0
  32. data/config/routes.rb +4 -0
  33. data/lib/assets/javascripts/infopark_editing.js +689 -285
  34. data/lib/assets/stylesheets/infopark_editing.css +17 -0
  35. data/lib/infopark_cloud_connector.rb +22 -0
  36. data/lib/obj.rb +3 -0
  37. data/lib/rails_connector/attribute_content.rb +190 -0
  38. data/lib/rails_connector/authenticable.rb +30 -0
  39. data/lib/rails_connector/basic_obj.rb +25 -139
  40. data/lib/rails_connector/basic_widget.rb +35 -0
  41. data/lib/rails_connector/cms_accessible.rb +114 -0
  42. data/lib/rails_connector/cms_cache_storage.rb +1 -1
  43. data/lib/rails_connector/cms_dispatch_controller.rb +46 -0
  44. data/lib/rails_connector/cms_env.rb +68 -0
  45. data/lib/rails_connector/cms_test_request.rb +23 -0
  46. data/lib/rails_connector/configuration.rb +3 -2
  47. data/lib/rails_connector/core_extensions.rb +1 -0
  48. data/lib/rails_connector/core_extensions/time.rb +18 -0
  49. data/lib/rails_connector/date_attribute.rb +1 -17
  50. data/lib/rails_connector/engine.rb +57 -0
  51. data/lib/rails_connector/html_string.rb +19 -0
  52. data/lib/rails_connector/link.rb +102 -17
  53. data/lib/rails_connector/link_resolvable.rb +9 -0
  54. data/lib/rails_connector/migrations/migrator.rb +8 -4
  55. data/lib/rails_connector/migrations/workspace_lock.rb +3 -2
  56. data/lib/rails_connector/named_link.rb +1 -1
  57. data/lib/rails_connector/obj_data_from_service.rb +18 -0
  58. data/lib/rails_connector/string_tagging.rb +29 -0
  59. data/lib/rails_connector/type_computer.rb +30 -0
  60. data/lib/widget.rb +3 -0
  61. metadata +103 -18
@@ -368,6 +368,23 @@ html.ip_bottombar_on {
368
368
  color: #eee;
369
369
  text-shadow: 0 1px 0 #333;
370
370
  }
371
+ .ip_menu_box .ip_menu_item.disabled span:hover,
372
+ .ip_menu_box .ip_menu_item.disabled a:hover {
373
+ color: #fff;
374
+ cursor: help;
375
+ background-color: transparent;
376
+ background-image: none;
377
+ background-repeat: no-repeat;
378
+ filter: none;
379
+ color: #696969;
380
+ }
381
+ .ip_menu_box .ip_menu_item.disabled span,
382
+ .ip_menu_box .ip_menu_item.disabled a,
383
+ .ip_menu_box .ip_menu_item.disabled span .ip_icon,
384
+ .ip_menu_box .ip_menu_item.disabled a .ip_icon {
385
+ color: #696969;
386
+ cursor: help;
387
+ }
371
388
  .ip_topbar .ip_button_bar .ip_logo {
372
389
  display: block;
373
390
  padding: 0;
@@ -1,3 +1,24 @@
1
+ # @api public
2
+ module ::RailsConnector
3
+ PLATFORM_CLOUD = :cloud.freeze
4
+ PLATFORM_FIONA = :fiona.freeze
5
+
6
+ # return either <tt>:fiona</tt> or <tt>:cloud</tt> depending on the app's configuration.
7
+ # @return [Symbol]
8
+ def self.platform
9
+ PLATFORM_CLOUD
10
+ end
11
+
12
+ def self.platform_cloud?
13
+ true
14
+ end
15
+
16
+ def self.platform_fiona?
17
+ false
18
+ end
19
+ end
20
+
21
+ require 'rails_connector/core_extensions'
1
22
  require 'rails_connector/rack_middlewares'
2
23
  require "rails_connector/errors"
3
24
 
@@ -17,4 +38,5 @@ module RailsConnector
17
38
  autoload_all_sources
18
39
  end
19
40
 
41
+ require "rails_connector/engine" if defined?(Rails)
20
42
  require "rails_connector/cloud_engine" if defined?(Rails)
@@ -0,0 +1,3 @@
1
+ # empty implementation for Obj
2
+ # only unsed in case the app does not define Obj itself
3
+ ::Obj = Class.new(RailsConnector::BasicObj)
@@ -0,0 +1,190 @@
1
+ module RailsConnector
2
+
3
+ module AttributeContent
4
+ extend ActiveSupport::Concern
5
+
6
+ included do
7
+ private
8
+ attr_accessor :data_from_cms
9
+ end
10
+
11
+ def respond_to?(method_id, include_private=false)
12
+ if has_attribute?(method_id)
13
+ true
14
+ else
15
+ super
16
+ end
17
+ end
18
+
19
+ def method_missing(method_name, *args)
20
+ if has_attribute?(method_name)
21
+ read_attribute(method_name.to_s)
22
+ else
23
+ super
24
+ end
25
+ end
26
+
27
+ def widgets(attribute_name)
28
+ unless (type_of_attribute(attribute_name) == 'widget')
29
+ raise "Not a widget field: #{attribute_name}."
30
+ end
31
+
32
+ widgets = read_attribute(attribute_name.to_s, false)
33
+
34
+ return [] unless widgets.present?
35
+
36
+ output_objs = []
37
+ (widgets['layout'] || []).each do |widget_hash|
38
+ begin
39
+ widget_obj = self.class.find(widget_hash['widget'])
40
+ rescue RailsConnector::ResourceNotFound => e
41
+ end
42
+ if widget_obj.present? && widget_obj.path.start_with?("/_widgets/#{id}/")
43
+ output_objs << widget_obj
44
+ end
45
+ end
46
+
47
+ output_objs
48
+ end
49
+
50
+ def read_attribute(attribute_name, skip_widgets = true)
51
+ if skip_widgets && (type_of_attribute(attribute_name) == 'widget')
52
+ raise "Field #{attribute_name} not (yet) available, since it's a widget"
53
+ end
54
+ @attribute_cache.fetch(attribute_name) do
55
+ (raw_value, attribute_type) = data_from_cms.value_and_type_of(attribute_name)
56
+ @attribute_cache[attribute_name] =
57
+ prepare_attribute_value(raw_value, attribute_type)
58
+ end
59
+ end
60
+
61
+ def has_attribute?(name)
62
+ data_from_cms.has_custom_attribute?(name.to_s)
63
+ end
64
+
65
+ # @return [String]
66
+ def type_of_attribute(field_name)
67
+ data_from_cms.type_of(field_name.to_s)
68
+ end
69
+
70
+ # Returns the value of an internal or external attribute specified by its name.
71
+ # Passing an invalid key will not raise an error, but return +nil+.
72
+ # @api public
73
+ def [](key)
74
+ key = key.to_s
75
+ has_attribute?(key) ? read_attribute(key) : nil
76
+ end
77
+
78
+ # Hook method to control which widget classes should be avaiable for this page.
79
+ # Override it to allow only certain classes or none.
80
+ # Must return either {NilClass}, or {Array}.
81
+ #
82
+ # If {NilClass} is returned, then all widget classes will be available for this page.
83
+ # By default {NilClass} is returned.
84
+ #
85
+ # If {Array} is returned, then it should include desired class names.
86
+ # Each class name must be either a {String} or a {Symbol}.
87
+ # Only this class names will be available for this page.
88
+ # Order of the class names will be preserved.
89
+ #
90
+ # @param [String] field_name Name of the widget field.
91
+ # @return [NilClass, Array<Symbol, String>]
92
+ # @api public
93
+ def valid_widget_classes_for(field_name)
94
+ end
95
+
96
+ private
97
+
98
+ def update_data(data)
99
+ self.data_from_cms = data
100
+ @attribute_cache = {}
101
+ end
102
+
103
+ def prepare_attribute_value(attribute_value, attribute_type)
104
+ case attribute_type
105
+ when "html"
106
+ StringTagging.tag_as_html(convert_links(attribute_value), self)
107
+ when "date"
108
+ DateAttribute.parse(attribute_value) if attribute_value
109
+ when "linklist"
110
+ build_links(attribute_value)
111
+ when "reference"
112
+ self.class.find([attribute_value]).first
113
+ when "referencelist"
114
+ self.class.find(attribute_value).compact
115
+ else
116
+ attribute_value
117
+ end
118
+ end
119
+
120
+ def convert_links(html)
121
+ if html
122
+ html.gsub(%r{<?\binternallink:(\d+)\b>?(['"]?)}) do
123
+ link, postfix = text_link_map[$1], $2
124
+ link ? convert_link(link, postfix) : missing_link_url(postfix)
125
+ end
126
+ end
127
+ end
128
+
129
+ def convert_link(link, postfix)
130
+ link.internal? ? convert_internal_link(link, postfix) : convert_external_link(link, postfix)
131
+ end
132
+
133
+ def convert_internal_link(link, postfix)
134
+ link.obj ? decorate_link_url(link.internal_url, link, postfix) : missing_link_url(postfix)
135
+ end
136
+
137
+ def convert_external_link(link, postfix)
138
+ decorate_link_url(link.external_url, link, postfix)
139
+ end
140
+
141
+ def decorate_link_url(url, link, postfix)
142
+ "#{url}#{link.query_and_fragment}#{postfix} #{link.html_attribute_snippet}"
143
+ end
144
+
145
+ def missing_link_url(postfix)
146
+ "#{CmsRoutingHelper::LINK_TO_UNREACHABLE}#{postfix}"
147
+ end
148
+
149
+ def text_link_map
150
+ @_text_link_map ||= text_links.each_with_object({}) { |link, map| map[link.id] = link }
151
+ end
152
+
153
+ def build_links(link_definitions)
154
+ if link_definitions.present?
155
+ link_definitions = link_definitions.map(&:with_indifferent_access)
156
+
157
+ object_ids = link_definitions.map { |link_data| link_data[:destination] }.compact.uniq
158
+ objects = object_ids.empty? ? [] : Obj.find(object_ids)
159
+ link_definitions.each_with_object([]) do |link_data, links|
160
+ obj = objects.detect { |o| o && o.id == link_data[:destination] }
161
+ link = Link.new(link_data.merge(obj: obj))
162
+ links << link if link.active?
163
+ end
164
+ else
165
+ []
166
+ end
167
+ end
168
+
169
+ module ClassMethods
170
+ # instantiate an Obj instance from obj_data.
171
+ # May result in an instance of a subclass of Obj according to STI rules.
172
+ #
173
+ # A CMS administrator can specify the <tt>obj_class</tt> for a given CMS object.
174
+ # In Rails, this could be either:
175
+ #
176
+ # * A valid and existing model name
177
+ # * A valid and non-existing model name
178
+ # * An invalid model name
179
+ #
180
+ # Rails' STI mechanism only considers the first case.
181
+ # In any other case, RailsConnector::Obj is used, except when explicitly asked
182
+ # for a model in the RailsConnector namespace (RailsConnector::Permission etc.)
183
+ def instantiate(obj_data)
184
+ obj_class = obj_data.value_of('_obj_class')
185
+ type_computer.compute_type(obj_class).new(obj_data)
186
+ end
187
+ end
188
+ end
189
+
190
+ end
@@ -0,0 +1,30 @@
1
+ module RailsConnector
2
+ module Authenticable
3
+ def self.included(mod)
4
+ %w(logged_in? admin? current_user).each do |method_name|
5
+ unless instance_method_defined?(mod, method_name)
6
+ mod.class_eval do
7
+ private
8
+ define_method(method_name, InstanceMethods.method(method_name).to_proc)
9
+ end
10
+ end
11
+
12
+ mod.send(:helper_method, method_name)
13
+ end
14
+ end
15
+
16
+ module InstanceMethods
17
+ def self.logged_in?; false; end
18
+ def self.admin?; false; end
19
+ def self.current_user; nil; end
20
+ end
21
+
22
+ private
23
+
24
+ def self.instance_method_defined?(mod, method_name)
25
+ (
26
+ mod.instance_methods + mod.protected_instance_methods + mod.private_instance_methods
27
+ ).map(&:to_s).include?(method_name)
28
+ end
29
+ end
30
+ end
@@ -5,11 +5,21 @@ module RailsConnector
5
5
  # The CMS file class
6
6
  # @api public
7
7
  class BasicObj
8
+ WIDGET_POOL_ATTRIBUTE_NAME = '_widget_pool'.freeze
9
+
8
10
  extend ActiveModel::Naming
9
11
 
10
- include DateAttribute
12
+ include AttributeContent
11
13
  include ModelIdentity
12
14
 
15
+ def self.type_computer
16
+ @_type_computer ||= TypeComputer.new(RailsConnector::BasicObj, ::Obj)
17
+ end
18
+
19
+ def self.reset_type_computer!
20
+ @_type_computer = nil
21
+ end
22
+
13
23
  # Create a new Obj instance with the given values and attributes.
14
24
  # Normally this method should not be used.
15
25
  # Instead Objs should be loaded from the cms database.
@@ -21,13 +31,6 @@ module RailsConnector
21
31
  update_data(obj_data)
22
32
  end
23
33
 
24
- # instantiate an Obj instance from obj_data.
25
- # May result in an instance of a subclass of Obj according to STI rules.
26
- def self.instantiate(obj_data)
27
- obj_class = obj_data.value_of("_obj_class")
28
- BasicObj.compute_type(obj_class).new(obj_data)
29
- end
30
-
31
34
  # @api public
32
35
  def id
33
36
  read_attribute('_id')
@@ -168,26 +171,6 @@ module RailsConnector
168
171
  id
169
172
  end
170
173
 
171
- # A CMS administrator can specify the <tt>obj_class</tt> for a given CMS object.
172
- # In Rails, this could be either:
173
- #
174
- # * A valid and existing model name
175
- # * A valid and non-existing model name
176
- # * An invalid model name
177
- #
178
- # Rails' STI mechanism only considers the first case.
179
- # In any other case, RailsConnector::Obj is used, except when explicitly asked
180
- # for a model in the RailsConnector namespace (RailsConnector::Permission etc.)
181
-
182
- def self.compute_type(type_name)
183
- @compute_type_cache ||= {}
184
- @compute_type_cache[type_name] ||= try_type { type_name.constantize } || Obj
185
- end
186
-
187
- def self.reset_type_cache
188
- @compute_type_cache = {}
189
- end
190
-
191
174
  # return the Obj that is the parent of this Obj.
192
175
  # returns +nil+ for the root Obj.
193
176
  # @api public
@@ -394,11 +377,6 @@ module RailsConnector
394
377
  name
395
378
  end
396
379
 
397
- # @return [String]
398
- def type_of_attribute(field_name)
399
- data_from_cms.type_of(field_name.to_s)
400
- end
401
-
402
380
  # Returns an array with the names of groups that are permitted to access this Obj.
403
381
  # This corresponds to the cms permission "permissionLiveServerRead".
404
382
  def permitted_groups
@@ -531,10 +509,8 @@ module RailsConnector
531
509
  elsif key.start_with?('_') && OLD_INTERNAL_KEYS.include?(internal_key = key[1..-1])
532
510
  # For backwards compatibility reasons
533
511
  send(internal_key)
534
- elsif has_attribute?(key)
535
- read_attribute(key)
536
512
  else
537
- nil
513
+ super
538
514
  end
539
515
  end
540
516
 
@@ -651,45 +627,10 @@ module RailsConnector
651
627
  end
652
628
  end
653
629
 
654
- def respond_to?(method_id, include_private=false)
655
- if has_attribute?(method_id)
656
- true
657
- else
658
- super
659
- end
660
- end
661
-
662
630
  def inspect
663
631
  "<#{self.class} id=\"#{id}\" path=\"#{path}\">"
664
632
  end
665
633
 
666
- def has_attribute?(name)
667
- data_from_cms.has_custom_attribute?(name.to_s)
668
- end
669
-
670
- def widgets(attribute_name)
671
- unless (type_of_attribute(attribute_name) == 'widget')
672
- raise "Not a widget field: #{attribute_name}."
673
- end
674
-
675
- widgets = read_attribute(attribute_name.to_s, false)
676
-
677
- return [] unless widgets.present?
678
-
679
- output_objs = []
680
- (widgets['layout'] || []).each do |widget_hash|
681
- begin
682
- widget_obj = self.class.find(widget_hash['widget'])
683
- rescue RailsConnector::ResourceNotFound => e
684
- end
685
- if widget_obj.present? && widget_obj.path.start_with?("/_widgets/#{id}/")
686
- output_objs << widget_obj
687
- end
688
- end
689
-
690
- output_objs
691
- end
692
-
693
634
  def destroy
694
635
  if children.any?
695
636
  raise ClientError.new(I18n.t('rails_connector.errors.models.basic_obj.has_children'), 412)
@@ -702,62 +643,29 @@ module RailsConnector
702
643
  @widget_container ||= self.class.find(parent_path.split('/').last)
703
644
  end
704
645
 
705
- # Hook method to control which widget classes should be avaiable for this page.
706
- # Override it to allow only certain classes or none.
707
- # Must return either {NilClass}, or {Array}.
708
- #
709
- # If {NilClass} is returned, then all widget classes will be available for this page.
710
- # By default {NilClass} is returned.
711
- #
712
- # If {Array} is returned, then it should include desired class names.
713
- # Each class name must be either a {String} or a {Symbol}.
714
- # Only this class names will be available for this page.
715
- # Order of the class names will be preserved.
716
- #
717
- # @param [String] field_name Name of the widget field.
718
- # @return [NilClass, Array<Symbol, String>]
719
- # @api public
720
- def valid_widget_classes_for(field_name)
721
- end
722
-
723
646
  def edit_view_path
724
647
  "#{obj_class.underscore}/edit"
725
648
  end
726
649
 
727
- private
650
+ def widget_from_pool(widget_id)
651
+ widget_data = widget_data_from_pool(widget_id)
652
+ instantiate_widget(widget_id, widget_data) if widget_data
653
+ end
728
654
 
729
- attr_accessor :data_from_cms
655
+ private
730
656
 
731
- def update_data(data)
732
- self.data_from_cms = data
733
- @attribute_cache = {}
657
+ def widget_data_from_pool(widget_id)
658
+ read_widget_pool[widget_id]
734
659
  end
735
660
 
736
- def read_attribute(attribute_name, skip_widgets = true)
737
- if skip_widgets && (type_of_attribute(attribute_name) == 'widget')
738
- raise "Field #{attribute_name} not (yet) available, since it's a widget"
739
- end
740
- @attribute_cache.fetch(attribute_name) do
741
- (raw_value, attribute_type) = data_from_cms.value_and_type_of(attribute_name)
742
- @attribute_cache[attribute_name] =
743
- prepare_attribute_value(raw_value, attribute_type)
744
- end
661
+ def read_widget_pool
662
+ read_attribute(WIDGET_POOL_ATTRIBUTE_NAME)
745
663
  end
746
664
 
747
- def prepare_attribute_value(attribute_value, attribute_type)
748
- case attribute_type
749
- when "html"
750
- StringTagging.tag_as_html(attribute_value, self)
751
- when "date"
752
- DateAttribute.parse(attribute_value) if attribute_value
753
- when "linklist"
754
- LinkList.new(attribute_value)
755
- when "reference"
756
- self.class.find([attribute_value]).first
757
- when "referencelist"
758
- self.class.find(attribute_value).compact
759
- else
760
- attribute_value
665
+ def instantiate_widget(widget_id, widget_data)
666
+ BasicWidget.instantiate(widget_data).tap do |widget|
667
+ widget.id = widget_id
668
+ widget.obj = self
761
669
  end
762
670
  end
763
671
 
@@ -775,14 +683,6 @@ module RailsConnector
775
683
  Blob.find(blob_spec["id"]) if blob_spec
776
684
  end
777
685
 
778
- def method_missing(method_name, *args)
779
- if has_attribute?(method_name)
780
- read_attribute(method_name.to_s)
781
- else
782
- super
783
- end
784
- end
785
-
786
686
  def compare_on_sort_key(left_obj, right_obj, my_sort_key, my_sort_type)
787
687
  left_value = left_obj[my_sort_key]
788
688
  right_value = right_obj[my_sort_key]
@@ -806,20 +706,6 @@ module RailsConnector
806
706
  def converted_sort_type(attribute)
807
707
  read_attribute(attribute) == 1 ? "numeric" : "alphaNumeric"
808
708
  end
809
-
810
- class << self
811
- private
812
-
813
- def try_type
814
- klass = yield
815
- klass if klass.try(:descends_from_basic_obj?) # Descendants of BasicObj have this method
816
- rescue NameError
817
- end
818
-
819
- def descends_from_basic_obj?
820
- self != BasicObj
821
- end
822
- end
823
709
  end
824
710
 
825
711
  end