scrivito_sdk 0.12.0

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.
Files changed (123) hide show
  1. checksums.yaml +7 -0
  2. data/.yardopts +5 -0
  3. data/README +6 -0
  4. data/app/controllers/cms_controller.rb +7 -0
  5. data/app/controllers/scrivito/blobs_controller.rb +10 -0
  6. data/app/controllers/scrivito/default_cms_controller.rb +61 -0
  7. data/app/controllers/scrivito/objs_controller.rb +200 -0
  8. data/app/controllers/scrivito/tasks_controller.rb +11 -0
  9. data/app/controllers/scrivito/webservice_controller.rb +36 -0
  10. data/app/controllers/scrivito/workspaces_controller.rb +41 -0
  11. data/app/helpers/cms_helper.rb +7 -0
  12. data/app/helpers/cms_routing_helper.rb +7 -0
  13. data/app/helpers/scrivito/cms_asset_helper.rb +103 -0
  14. data/app/helpers/scrivito/cms_tag_helper.rb +231 -0
  15. data/app/helpers/scrivito/default_cms_helper.rb +21 -0
  16. data/app/helpers/scrivito/default_cms_routing_helper.rb +130 -0
  17. data/app/helpers/scrivito/display_helper.rb +71 -0
  18. data/app/helpers/scrivito/editing_helper.rb +26 -0
  19. data/app/helpers/scrivito/layout_helper.rb +28 -0
  20. data/app/models/named_link.rb +2 -0
  21. data/app/views/cms/_index.html.erb +7 -0
  22. data/app/views/cms/index.html.erb +1 -0
  23. data/app/views/scrivito/_editing_javascript.html.erb +7 -0
  24. data/app/views/scrivito/default_cms/show_widget.html.erb +1 -0
  25. data/app/views/scrivito/objs/copy_widget.html.erb +1 -0
  26. data/app/views/scrivito/objs/create_widget.html.erb +1 -0
  27. data/app/views/scrivito/widget_thumbnail.html.erb +9 -0
  28. data/config/ca-bundle.crt +3509 -0
  29. data/config/cms_routes.rb +17 -0
  30. data/config/locales/de.scrivito.errors.yml +7 -0
  31. data/config/locales/de.scrivito.lib.yml +6 -0
  32. data/config/locales/de.scrivito.models.yml +6 -0
  33. data/config/locales/en.scrivito.errors.yml +7 -0
  34. data/config/locales/en.scrivito.lib.yml +6 -0
  35. data/config/locales/en.scrivito.models.yml +6 -0
  36. data/config/routes.rb +37 -0
  37. data/lib/assets/images/180x120.gif +0 -0
  38. data/lib/assets/images/scrivito/image_placeholder.png +0 -0
  39. data/lib/assets/javascripts/scrivito_editing.js +14642 -0
  40. data/lib/assets/stylesheets/scrivito.css +180 -0
  41. data/lib/assets/stylesheets/scrivito_editing.css +2213 -0
  42. data/lib/generators/cms/migration/USAGE +9 -0
  43. data/lib/generators/cms/migration/migration_generator.rb +21 -0
  44. data/lib/generators/cms/migration/templates/migration.erb +10 -0
  45. data/lib/obj.rb +3 -0
  46. data/lib/scrivito/access_denied.rb +6 -0
  47. data/lib/scrivito/attribute_content.rb +194 -0
  48. data/lib/scrivito/backend_error.rb +4 -0
  49. data/lib/scrivito/basic_obj.rb +840 -0
  50. data/lib/scrivito/basic_widget.rb +238 -0
  51. data/lib/scrivito/blob.rb +48 -0
  52. data/lib/scrivito/cache.rb +41 -0
  53. data/lib/scrivito/cache_garbage_collector.rb +83 -0
  54. data/lib/scrivito/cache_middleware.rb +17 -0
  55. data/lib/scrivito/client_config.rb +62 -0
  56. data/lib/scrivito/client_error.rb +12 -0
  57. data/lib/scrivito/cms_accessible.rb +30 -0
  58. data/lib/scrivito/cms_backend.rb +238 -0
  59. data/lib/scrivito/cms_cache_storage.rb +51 -0
  60. data/lib/scrivito/cms_dispatch_controller.rb +46 -0
  61. data/lib/scrivito/cms_env.rb +63 -0
  62. data/lib/scrivito/cms_field_tag.rb +112 -0
  63. data/lib/scrivito/cms_rest_api.rb +151 -0
  64. data/lib/scrivito/cms_rest_api/attribute_serializer.rb +98 -0
  65. data/lib/scrivito/cms_rest_api/blob_uploader.rb +18 -0
  66. data/lib/scrivito/cms_rest_api/widget_extractor.rb +42 -0
  67. data/lib/scrivito/cms_test_request.rb +23 -0
  68. data/lib/scrivito/communication_error.rb +17 -0
  69. data/lib/scrivito/comparison.rb +67 -0
  70. data/lib/scrivito/configuration.rb +221 -0
  71. data/lib/scrivito/connection_manager.rb +100 -0
  72. data/lib/scrivito/content_conversion.rb +43 -0
  73. data/lib/scrivito/content_service.rb +118 -0
  74. data/lib/scrivito/content_state.rb +109 -0
  75. data/lib/scrivito/content_state_caching.rb +47 -0
  76. data/lib/scrivito/content_state_visitor.rb +19 -0
  77. data/lib/scrivito/controller_runtime.rb +35 -0
  78. data/lib/scrivito/date_attribute.rb +16 -0
  79. data/lib/scrivito/deprecation.rb +21 -0
  80. data/lib/scrivito/diff.rb +110 -0
  81. data/lib/scrivito/editing_context.rb +106 -0
  82. data/lib/scrivito/editing_context_middleware.rb +60 -0
  83. data/lib/scrivito/engine.rb +65 -0
  84. data/lib/scrivito/errors.rb +11 -0
  85. data/lib/scrivito/html_string.rb +18 -0
  86. data/lib/scrivito/link.rb +187 -0
  87. data/lib/scrivito/link_parser.rb +81 -0
  88. data/lib/scrivito/log_subscriber.rb +29 -0
  89. data/lib/scrivito/migration.rb +2 -0
  90. data/lib/scrivito/migrations.rb +12 -0
  91. data/lib/scrivito/migrations/cms_backend.rb +94 -0
  92. data/lib/scrivito/migrations/installer.rb +45 -0
  93. data/lib/scrivito/migrations/migration.rb +93 -0
  94. data/lib/scrivito/migrations/migration_dsl.rb +143 -0
  95. data/lib/scrivito/migrations/migration_store.rb +23 -0
  96. data/lib/scrivito/migrations/migrator.rb +135 -0
  97. data/lib/scrivito/migrations/workspace_lock.rb +39 -0
  98. data/lib/scrivito/model_identity.rb +13 -0
  99. data/lib/scrivito/modification.rb +8 -0
  100. data/lib/scrivito/named_link.rb +75 -0
  101. data/lib/scrivito/network_error.rb +11 -0
  102. data/lib/scrivito/obj_data.rb +140 -0
  103. data/lib/scrivito/obj_data_from_hash.rb +31 -0
  104. data/lib/scrivito/obj_data_from_service.rb +84 -0
  105. data/lib/scrivito/obj_params_parser.rb +61 -0
  106. data/lib/scrivito/obj_search_builder.rb +62 -0
  107. data/lib/scrivito/obj_search_enumerator.rb +374 -0
  108. data/lib/scrivito/rate_limit_exceeded.rb +5 -0
  109. data/lib/scrivito/revision.rb +9 -0
  110. data/lib/scrivito/string_tagging.rb +18 -0
  111. data/lib/scrivito/text_link.rb +52 -0
  112. data/lib/scrivito/text_link_conversion.rb +52 -0
  113. data/lib/scrivito/type_computer.rb +34 -0
  114. data/lib/scrivito/widget_field_params.rb +61 -0
  115. data/lib/scrivito/widget_garbage_collection.rb +97 -0
  116. data/lib/scrivito/workspace.rb +222 -0
  117. data/lib/scrivito/workspace_data_from_service.rb +80 -0
  118. data/lib/scrivito/workspace_selection_middleware.rb +23 -0
  119. data/lib/scrivito_sdk.rb +19 -0
  120. data/lib/tasks/cache.rake +12 -0
  121. data/lib/tasks/migration.rake +35 -0
  122. data/lib/widget.rb +3 -0
  123. metadata +291 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 24c7dcabf5aef63eb33bcdd0a13f588c3be4c524
4
+ data.tar.gz: 1461028fb468bed23183f63921081cb0560d213c
5
+ SHA512:
6
+ metadata.gz: 0251875fb48fdabcd26e4d0cef5e743218e8f4606c47cbc778a7d0bf02a83e278c3b3aafbc6ec647830c8b0c99e22abe32f6b8b6b2c01d794864596485317027
7
+ data.tar.gz: ebfe1320eaf24a181166a5d40620e31580ec4249795150da9a86ee2c4e6eb918e4fc3f6b58820254a25657cc56f34930d51d33c9cc1aa1502795024a52c0fea9
data/.yardopts ADDED
@@ -0,0 +1,5 @@
1
+ --hide-void-return
2
+ --protected
3
+ --private
4
+ --non-transitive-tag api
5
+ --api public
data/README ADDED
@@ -0,0 +1,6 @@
1
+ = Scrivito SDK
2
+
3
+ The Scrivito SDK makes CMS objects maintained by means of the cloud-based Scrivito CMS available to your Rails application.
4
+ It offers easy-to-use functionality for rendering CMS content, doing searches, etc.
5
+
6
+ For more information about Scrivito, please visit {http://scrivito.com/}.
@@ -0,0 +1,7 @@
1
+ # This controller inherits all of its behavior from
2
+ # {Scrivito::DefaultCmsController}.
3
+ #
4
+ # {CmsController} is referenced by the Scrivito routes.
5
+ # @api public
6
+ class CmsController < Scrivito::DefaultCmsController
7
+ end
@@ -0,0 +1,10 @@
1
+ module Scrivito
2
+
3
+ class BlobsController < WebserviceController
4
+ def upload_permission
5
+ permission = CmsRestApi.task_unaware_request(:get, 'blobs/upload_permission')
6
+ render json: permission
7
+ end
8
+ end
9
+
10
+ end
@@ -0,0 +1,61 @@
1
+ module Scrivito
2
+
3
+ # This controller provides some default includes ({CmsAccessible}),
4
+ # before filters (+load_object+, among others), and actions to simplify
5
+ # CMS object handling. It should never be used directly, but only as a
6
+ # super class to {CmsController}.
7
+ # @api public
8
+ class DefaultCmsController < ApplicationController
9
+ include CmsAccessible
10
+
11
+ before_filter :load_object
12
+ before_filter :authorize_editor, only: [:show_widget, :widget_details]
13
+
14
+ # Default Action. Delivers files directly if {BasicObj#binary?}.
15
+ # Otherwise the view is rendered.
16
+ # @api public
17
+ def index
18
+ deliver_file if @obj.binary?
19
+ end
20
+
21
+ def show_widget
22
+ widget = load_widget
23
+ render layout: false, locals: {widget: widget}
24
+ end
25
+
26
+ def widget_details
27
+ widget = load_widget
28
+ template_path = "#{widget.obj_class_name.underscore}/details"
29
+ render template_path, layout: false, locals: {widget: widget}
30
+ end
31
+
32
+ # This method indicates if this controller should be used automatically when an Obj is
33
+ # requested via the Scrivito's standard routes. It returns true by default.
34
+ #
35
+ # Overwrite it to return false if you do want your controller to be excluded from Obj dispatching.
36
+ #
37
+ # You may also implement a method with the name {use_for_obj_dispatch?} in controllers not
38
+ # descending from {DefaultCmsController} to include them in Obj dispatching.
39
+ #
40
+ # @see Obj#controller_name
41
+ # @api public
42
+ def self.use_for_obj_dispatch?
43
+ true
44
+ end
45
+
46
+ private
47
+
48
+ def authorize_editor
49
+ head(:forbidden) unless editing_context.authenticated_editor?
50
+ end
51
+
52
+ def editing_context
53
+ request.env[EditingContextMiddleware::ENVKEY] || EditingContext.new
54
+ end
55
+
56
+ def load_widget
57
+ @obj.widget_from_pool(params[:widget_id])
58
+ end
59
+ end
60
+
61
+ end
@@ -0,0 +1,200 @@
1
+ module Scrivito
2
+
3
+ class ObjsController < WebserviceController
4
+ before_filter :ensure_identical_selected_and_visible_workspace, only: [:create, :update, :copy,
5
+ :duplicate, :page_class_selection, :create_widget, :widget_class_selection, :copy_widget]
6
+
7
+ def create
8
+ created_obj = task_unaware_request(:post,
9
+ "workspaces/#{Workspace.current.id}/objs",
10
+ {obj: obj_params}
11
+ )
12
+ render json: created_obj
13
+ end
14
+
15
+ def details
16
+ load_object
17
+ render json: {markup: render_to_string(@obj.details_view_path, layout: false)}
18
+ end
19
+
20
+ def update
21
+ load_object
22
+ changed_obj = task_unaware_request(:put,
23
+ "workspaces/#{Workspace.current.id}/objs/#{params[:id]}",
24
+ {obj: obj_params}
25
+ )
26
+ render json: changed_obj
27
+ end
28
+
29
+ def destroy
30
+ in_selected_workspace { load_object.destroy }
31
+ render_empty_json
32
+ end
33
+
34
+ def revert
35
+ in_selected_workspace { load_object.revert }
36
+ render_empty_json
37
+ end
38
+
39
+ def restore
40
+ in_selected_workspace { Obj.restore(params[:id]) }
41
+ render_empty_json
42
+ end
43
+
44
+ def mark_resolved
45
+ in_selected_workspace { load_object.mark_resolved }
46
+ render_empty_json
47
+ end
48
+
49
+ def copy
50
+ render json: copy_obj(get_obj_attributes(params[:id]), params[:parent_path])
51
+ end
52
+
53
+ def duplicate
54
+ attributes = get_obj_attributes(params[:id])
55
+
56
+ render json: copy_obj(attributes, parent_path(attributes['_path']))
57
+ end
58
+
59
+ def page_class_selection
60
+ valid_page_classes = Obj.valid_page_classes_beneath(params[:parent_path]) ||
61
+ Obj.descendants
62
+ valid_page_classes.map!(&:to_s)
63
+
64
+ page_class_names = valid_page_classes.map do |page_class_name|
65
+ begin
66
+ markup = render_to_string("#{page_class_name.underscore}/thumbnail")
67
+ {name: page_class_name, markup: markup}
68
+ rescue ActionView::MissingTemplate
69
+ end
70
+ end
71
+
72
+ render json: page_class_names.compact
73
+ end
74
+
75
+ def widget_class_selection
76
+ load_object
77
+ valid_widget_classes = @obj.valid_widget_classes_for(params[:field_name]) ||
78
+ Widget.descendants
79
+ valid_widget_classes.map!(&:to_s)
80
+
81
+ widgets_classes = valid_widget_classes.map do |widget_class_name|
82
+ template_path = "#{widget_class_name.underscore}/thumbnail"
83
+ markup = begin
84
+ render_to_string(template_path, layout: false)
85
+ rescue ActionView::MissingTemplate
86
+ render_to_string('scrivito/widget_thumbnail', layout: false,
87
+ locals: {widget_class_name: widget_class_name, template_path: template_path})
88
+ end
89
+ {name: widget_class_name, markup: markup}
90
+ end
91
+
92
+ render json: widgets_classes
93
+ end
94
+
95
+ def create_widget
96
+ load_object
97
+ widget_pool_id = BasicObj.generate_widget_pool_id
98
+
99
+ task_unaware_request(:put, "workspaces/#{Workspace.current.id}/objs/#{params[:id]}",
100
+ {obj: {_widget_pool: {widget_pool_id => {_obj_class: params[:obj_class]}}}})
101
+
102
+ Workspace.reload
103
+ @obj.reload
104
+
105
+ @widget = @obj.widget_from_pool(widget_pool_id)
106
+
107
+ render json: {markup: render_to_string(layout: false)}
108
+ end
109
+
110
+ def copy_widget
111
+ load_object
112
+ new_widget_id = @obj.copy_widget_from(params[:src_obj_id], params[:src_widget_id])
113
+
114
+ Workspace.reload
115
+ @obj.reload
116
+
117
+ @widget = @obj.widget_from_pool(new_widget_id)
118
+
119
+ render json: {markup: render_to_string(layout: false)}
120
+ end
121
+
122
+ def search
123
+ in_selected_workspace do
124
+ query = MultiJson.decode(params[:query]).with_indifferent_access
125
+ search_builder = ObjSearchBuilder.new(query)
126
+ enumerator = search_builder.build
127
+
128
+ if params[:query_action] == 'size'
129
+ result = { total: enumerator.size }
130
+ else
131
+ batch = enumerator.load_batch
132
+
133
+ result = {
134
+ total: enumerator.size,
135
+ hits: batch
136
+ }
137
+ end
138
+
139
+ render json: result
140
+ end
141
+ rescue ObjSearchEnumerator::UnregisteredObjFormat => e
142
+ render json: { error: e.message }, status: :not_found
143
+ end
144
+
145
+ private
146
+
147
+ def load_object
148
+ @obj = Obj.find(params[:id])
149
+ end
150
+
151
+ def ensure_identical_selected_and_visible_workspace
152
+ if editing_context.selected_workspace != editing_context.visible_workspace
153
+ raise ScrivitoError, "selected and visible workspace are not identical"
154
+ end
155
+ end
156
+
157
+ def obj_params
158
+ @obj_params ||= ObjParamsParser.new(request.host, request.port).parse(@obj, params[:obj])
159
+ end
160
+
161
+ def copy_obj(attributes, target_path=nil)
162
+ copied_attributes = attributes.except!('id', '_id', '_permalink')
163
+ copied_attributes['_path'] = "#{target_path}/#{SecureRandom.hex(6)}"
164
+
165
+ task_unaware_request(:post, "workspaces/#{Workspace.current.id}/objs", obj: copied_attributes)
166
+ end
167
+
168
+ def get_obj_attributes(id)
169
+ task_unaware_request(:get, "workspaces/#{Workspace.current.id}/objs/#{id}")
170
+ end
171
+
172
+ def parent_path(path)
173
+ path.split('/')[0..-2].join('/')
174
+ end
175
+
176
+ def current_page
177
+ Obj.find(params[:current_page_id]) if params[:current_page_id].present?
178
+ end
179
+ helper_method :current_page
180
+
181
+ delegate :task_unaware_request, to: CmsRestApi
182
+
183
+ private
184
+
185
+ def editing_context
186
+ request.env[EditingContextMiddleware::ENVKEY] || EditingContext.new
187
+ end
188
+
189
+ def in_selected_workspace
190
+ editing_context.selected_workspace.as_current do
191
+ yield
192
+ end
193
+ end
194
+
195
+ def render_empty_json
196
+ render json: {}
197
+ end
198
+ end
199
+
200
+ end
@@ -0,0 +1,11 @@
1
+ module Scrivito
2
+
3
+ class TasksController < WebserviceController
4
+
5
+ def show
6
+ render json: CmsRestApi.task_unaware_request(:get, "tasks/#{params[:id]}")
7
+ end
8
+
9
+ end
10
+
11
+ end
@@ -0,0 +1,36 @@
1
+ module Scrivito
2
+
3
+ class WebserviceController < ActionController::Base
4
+ rescue_from ClientError do |exception|
5
+ render json: {error: exception.message}, status: exception.http_code
6
+ end
7
+
8
+ before_filter :merge_correctly_parsed_json_params
9
+ before_filter :authorize
10
+
11
+ private
12
+
13
+ def authorize
14
+ unless allow_access?
15
+ render text: 'Forbidden', status: 403
16
+ end
17
+ end
18
+
19
+ # If +true+, allow access to ObjsController, else deny access.
20
+ # See {Scrivito::Configuration.editing_auth} for details.
21
+ # @return [Bool]
22
+ def allow_access?
23
+ Configuration.editing_auth_callback.call(request.env)
24
+ end
25
+
26
+ # Workaround for https://github.com/rails/rails/issues/8832
27
+ def merge_correctly_parsed_json_params
28
+ if request.format.json?
29
+ body = request.body.read
30
+ request.body.rewind
31
+ params.merge!(ActiveSupport::JSON.decode(body)) if body.present?
32
+ end
33
+ end
34
+ end
35
+
36
+ end
@@ -0,0 +1,41 @@
1
+ module Scrivito
2
+
3
+ class WorkspacesController < WebserviceController
4
+ def index
5
+ render json: CmsRestApi.task_unaware_request(:get, 'workspaces')
6
+ end
7
+
8
+ def create
9
+ render json: CmsRestApi.task_unaware_request(:post, 'workspaces', {
10
+ workspace: workspace_params,
11
+ })
12
+ end
13
+
14
+ def update
15
+ render json: CmsRestApi.task_unaware_request(:put, "workspaces/#{params[:id]}", {
16
+ workspace: workspace_params,
17
+ })
18
+ end
19
+
20
+ def destroy
21
+ render json: CmsRestApi.task_unaware_request(:delete, "workspaces/#{params[:id]}")
22
+ end
23
+
24
+ def publish
25
+ render json: CmsRestApi.task_unaware_request(:put, "workspaces/#{params[:id]}/publish", {})
26
+ end
27
+
28
+ def rebase
29
+ render json: CmsRestApi.task_unaware_request(:put, "workspaces/#{params[:id]}/rebase", {})
30
+ end
31
+
32
+ private
33
+
34
+ def workspace_params
35
+ raise "Required parameter 'workspace' is missing." unless params[:workspace].present?
36
+ raise "Parameter 'workspace' is not a hash." unless params[:workspace].is_a?(Hash)
37
+ params[:workspace]
38
+ end
39
+ end
40
+
41
+ end
@@ -0,0 +1,7 @@
1
+ # {CmsHelper} is a wrapper around {Scrivito::DefaultCmsHelper}.
2
+ # It can be replaced in your application in order to add or
3
+ # modify helpers.
4
+ # @api public
5
+ module CmsHelper
6
+ include Scrivito::DefaultCmsHelper
7
+ end
@@ -0,0 +1,7 @@
1
+ # {CmsRoutingHelper} is a wrapper around {Scrivito::DefaultCmsRoutingHelper}.
2
+ # It can be replaced in your application in order to add or
3
+ # modify helpers.
4
+ # @api public
5
+ module CmsRoutingHelper
6
+ include Scrivito::DefaultCmsRoutingHelper
7
+ end
@@ -0,0 +1,103 @@
1
+ module Scrivito
2
+
3
+ # This module contains helpers that can be used to reference images and other assets stored in the CMS.
4
+ #
5
+ # @api public
6
+ module CmsAssetHelper
7
+
8
+ # Calculates an HTML image tag for an image stored in the CMS.
9
+ #
10
+ # @note There are two different signatures of this method: the first one generates an HTML image tag with no
11
+ # inplace editing possible, the second one generated an HTML image tag for inplace editing.
12
+ #
13
+ # @overload cms_image_tag target, tag_options={}
14
+ # @note If you do not specify an HTML +alt+ attribute, the helper method will use +target+'s +display_title+.
15
+ # Calculates HTML image tag (no inplace editing possible).
16
+ #
17
+ # @param [Obj, Link] target Target containing image stored in CMS.
18
+ # @param [Hash] tag_options Additional HTML attributes for the tag.
19
+ #
20
+ # @example
21
+ # cms_image_tag @target
22
+ # cms_image_tag @target, alt: 'Interesting picture', class: 'my_image'
23
+ #
24
+ # @overload cms_image_tag obj, linklist, tag_options={}, editing_options={}
25
+ # @note If you do not specify an HTML +alt+ attribute, the helper method will use +display_title+ of the target object.
26
+ # Calculates HTML image tag for inplace editing.
27
+ #
28
+ # @param [Obj] obj Obj with an attribute of type +LinkList+.
29
+ # @param [String, Symbol] linklist Name of +LinkList+ attribute, which contains the image.
30
+ # @param [Hash] tag_options Additional HTML attributes for the tag.
31
+ #
32
+ # @param [Hash] editing_options Additional options for inplace editing.
33
+ # @option editing_options [String] :placeholder ('/assets/scrivito/image_placeholder.png') URL or path to image to be displayed if target is missing.
34
+ #
35
+ # @example
36
+ # cms_image_tag @obj, :my_linklist
37
+ # cms_image_tag @obj, :my_linklist, alt: 'Interesting picture', class: 'my_image'
38
+ # cms_image_tag @obj, :my_linklist, {}, placeholder: image_path('my_placeholder.png')
39
+ # cms_image_tag @obj, :my_linklist, {class: 'my_image'}, placeholder: 'http://placehold.it/350x150'
40
+ #
41
+ # @return [String] HTML image tag
42
+ # @api public
43
+ def cms_image_tag(*args)
44
+ if args.second.nil? || args.second.is_a?(Hash)
45
+ # Backwards compatibility.
46
+ target = args.first
47
+
48
+ tag_options = args.second || {}
49
+ tag_options.symbolize_keys!
50
+ tag_options[:src] = cms_path(target)
51
+ tag_options[:alt] ||= display_title(target)
52
+
53
+ tag('img', tag_options)
54
+ else
55
+ obj = args.first
56
+ field_name = args.second
57
+ tag_options = args.third || {}
58
+ editing_options = args.fourth || {}
59
+
60
+ cms_tag('img', obj, field_name, cms_image_tag_options(obj, field_name,
61
+ tag_options.symbolize_keys, editing_options.symbolize_keys))
62
+ end
63
+
64
+ end
65
+
66
+ private
67
+
68
+ def cms_image_tag_options(obj, field_name, tag_options, editing_options)
69
+ tag_options.reverse_merge(src: cms_image_tag_src(obj, field_name, editing_options),
70
+ alt: cms_image_tag_alt(obj, field_name))
71
+ end
72
+
73
+ def cms_image_tag_src(obj, field_name, editing_options)
74
+ cms_image_tag_path(obj, field_name) || editing_options[:placeholder] ||
75
+ image_path('scrivito/image_placeholder.png')
76
+ end
77
+
78
+ def cms_image_tag_alt(obj, field_name)
79
+ display_title(obj[field_name])
80
+ end
81
+
82
+ def cms_image_tag_path(obj, field_name)
83
+ field_type = obj.type_of_attribute(field_name)
84
+ field_value = obj[field_name]
85
+
86
+ case field_type
87
+ when 'reference' then field_value && cms_path(field_value)
88
+ when 'linklist'
89
+ path = cms_path(field_value)
90
+ path == DefaultCmsRoutingHelper::LINK_TO_EMPTY_LINKLIST ? nil : path
91
+ end
92
+ end
93
+
94
+ def display_title(target)
95
+ if target.respond_to?(:display_title)
96
+ return target.display_title
97
+ elsif target.respond_to?(:first) && target.first.respond_to?(:display_title)
98
+ return target.first.display_title
99
+ end
100
+ end
101
+
102
+ end
103
+ end