scrivito_sdk 1.5.5 → 1.6.0.rc1

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 (66) hide show
  1. checksums.yaml +4 -4
  2. data/.yardopts +1 -0
  3. data/app/controllers/scrivito/obj_class_controller.rb +27 -4
  4. data/app/controllers/scrivito/objs_controller.rb +0 -26
  5. data/app/controllers/scrivito/resolve_paths_controller.rb +1 -1
  6. data/app/controllers/scrivito/ui_configs_controller.rb +8 -0
  7. data/app/controllers/scrivito/users_controller.rb +11 -1
  8. data/app/helpers/scrivito_helper.rb +56 -5
  9. data/app/views/scrivito/page_details.html.erb +6 -1
  10. data/app/views/scrivito/ui/index.html.erb +4 -1
  11. data/app/views/scrivito/ui_configs/ui_configs.json.jbuilder +7 -0
  12. data/app/views/scrivito/users/publish_ability.json.jbuilder +1 -0
  13. data/app/views/scrivito/users/users.json.jbuilder +7 -0
  14. data/config/ca-bundle.crt +2 -32
  15. data/config/precedence_routes.rb +6 -3
  16. data/lib/assets/javascripts/scrivito.js +0 -11
  17. data/lib/assets/javascripts/scrivito_sdk.js +17921 -0
  18. data/lib/assets/javascripts/scrivito_ui.js +35583 -32542
  19. data/lib/assets/javascripts/scrivito_ui_redirect.js +10 -0
  20. data/lib/assets/stylesheets/scrivito.css +1 -1
  21. data/lib/assets/stylesheets/scrivito_ui.css +1 -1
  22. data/lib/generators/scrivito/install/templates/app/models/download.rb +1 -0
  23. data/lib/generators/scrivito/install/templates/app/models/image.rb +1 -0
  24. data/lib/generators/scrivito/install/templates/app/models/page.rb +1 -0
  25. data/lib/generators/scrivito/install/templates/app/views/download/details.html.erb +4 -0
  26. data/lib/generators/scrivito/install/templates/app/views/image/details.html.erb +4 -0
  27. data/lib/generators/scrivito/install/templates/app/views/page/details.html.erb +4 -0
  28. data/lib/generators/scrivito/page/templates/details.html.erb +4 -0
  29. data/lib/generators/scrivito/page/templates/model.erb +1 -0
  30. data/lib/scrivito/associations.rb +200 -0
  31. data/lib/scrivito/attribute_content.rb +18 -10
  32. data/lib/scrivito/attribute_definition.rb +1 -1
  33. data/lib/scrivito/attribute_serializer.rb +1 -1
  34. data/lib/scrivito/base_widget_tag.rb +4 -5
  35. data/lib/scrivito/basic_obj.rb +15 -2
  36. data/lib/scrivito/basic_widget.rb +8 -2
  37. data/lib/scrivito/binary.rb +12 -24
  38. data/lib/scrivito/binary_rewrite.rb +1 -1
  39. data/lib/scrivito/binary_routing.rb +1 -1
  40. data/lib/scrivito/cms_env.rb +2 -6
  41. data/lib/scrivito/cms_field_tag.rb +4 -0
  42. data/lib/scrivito/cms_rest_api.rb +1 -1
  43. data/lib/scrivito/configuration.rb +7 -4
  44. data/lib/scrivito/connection_manager.rb +1 -1
  45. data/lib/scrivito/editing_context.rb +9 -4
  46. data/lib/scrivito/float_conversion.rb +2 -3
  47. data/lib/scrivito/integer_conversion.rb +2 -3
  48. data/lib/scrivito/link.rb +2 -2
  49. data/lib/scrivito/link_parser.rb +7 -7
  50. data/lib/scrivito/meta_data_collection.rb +3 -2
  51. data/lib/scrivito/migrations/workspace_lock.rb +1 -1
  52. data/lib/scrivito/obj_collection.rb +4 -2
  53. data/lib/scrivito/obj_create_params_parser.rb +25 -1
  54. data/lib/scrivito/obj_search_enumerator.rb +79 -37
  55. data/lib/scrivito/obj_ui_config.rb +20 -0
  56. data/lib/scrivito/publish_ability.rb +14 -0
  57. data/lib/scrivito/sdk_engine.rb +2 -0
  58. data/lib/scrivito/ui_config.rb +1 -3
  59. data/lib/scrivito/user.rb +17 -1
  60. data/lib/scrivito/widget_collection.rb +1 -1
  61. data/lib/scrivito/workspace.rb +0 -16
  62. data/lib/scrivito/workspace/publish_checker.rb +3 -3
  63. metadata +13 -7
  64. data/app/views/scrivito/users/suggest.json.jbuilder +0 -1
  65. data/lib/scrivito/obj_params_parser.rb +0 -36
  66. data/lib/scrivito/obj_update_params_parser.rb +0 -28
@@ -142,7 +142,8 @@ class BasicWidget
142
142
  # @option context [Scrivito::User] :scrivito_user current visitor
143
143
  # @return [Widget] the newly created {Scrivito::BasicWidget Widget}
144
144
  #
145
- # @see Scrivito::BasicWidget.new
145
+ # @raise [ArgumentError] if called on +Widget+ without +_obj_class+ attribute.
146
+ #
146
147
  # @see Scrivito::AttributeContent::ClassMethods#default_for
147
148
  #
148
149
  def self.new(attributes = {}, context = {})
@@ -319,7 +320,8 @@ class BasicWidget
319
320
  end
320
321
  end
321
322
 
322
- # Returns the entity ({Scrivito::BasicObj} or {Scrivito::BasicWidget}) that references this widget.
323
+ # Returns the entity ({Scrivito::BasicObj} or {Scrivito::BasicWidget})
324
+ # that references this widget.
323
325
  # @api public
324
326
  #
325
327
  # @return [Scrivito::AttributeContent] the entity that references this widget.
@@ -365,6 +367,10 @@ class BasicWidget
365
367
  end
366
368
  end
367
369
 
370
+ # Returns the {Scrivito::BasicObj Obj} to which this widget belongs.
371
+ # @api public
372
+ #
373
+ # @return [Scrivito::BasicObj] - the Obj this widget belongs to.
368
374
  def obj
369
375
  if @obj
370
376
  @obj
@@ -107,7 +107,18 @@ class Binary
107
107
  # accessible hours or days after they have been generated.
108
108
  # @return [String] the URL at which this content is available.
109
109
  def url
110
- find_url('get')
110
+ blob_data = CmsBackend.find_blob_data(id, access_type, 'get',
111
+ transformation_definition: transformation_definition)
112
+ blob_data['url']
113
+ rescue ClientError => e
114
+ case e.backend_code
115
+ when /\Abinary\.unprocessable\.image\.transform\.source\./
116
+ raise TransformationSourceError.new(e.message, e.backend_code)
117
+ when 'binary.unprocessable.image.transform.config.invalid'
118
+ raise TransformationDefinitionError.new(e.message, e.backend_code)
119
+ else
120
+ raise e
121
+ end
111
122
  end
112
123
 
113
124
  def no_cache_url
@@ -311,33 +322,10 @@ class Binary
311
322
 
312
323
  private
313
324
 
314
- def public_content?
315
- !!@public_content
316
- end
317
-
318
325
  def raise_field_not_available(field_name)
319
326
  raise ScrivitoError, "#{field_name} is not available for transformed images"
320
327
  end
321
328
 
322
- def headers
323
- CmsBackend.find_blob_metadata(id, find_url('head'))
324
- end
325
-
326
- def find_url(verb)
327
- blob_data = CmsBackend.find_blob_data(id, access_type, verb,
328
- transformation_definition: transformation_definition)
329
- blob_data['url']
330
- rescue ClientError => e
331
- case e.backend_code
332
- when /\Abinary\.unprocessable\.image\.transform\.source\./
333
- raise TransformationSourceError.new(e.message, e.backend_code)
334
- when 'binary.unprocessable.image.transform.config.invalid'
335
- raise TransformationDefinitionError.new(e.message, e.backend_code)
336
- else
337
- raise e
338
- end
339
- end
340
-
341
329
  def access_type
342
330
  public? ? 'public_access' : 'private_access'
343
331
  end
@@ -24,7 +24,7 @@ module Scrivito
24
24
  # @example
25
25
  # Scrivito::BinaryRewrite.enable_for(request) do |binary_url|
26
26
  # binary_url.sub(
27
- # /https:\/\/.+\.scrvt\.com\//,
27
+ # "https://scrivito-public-cdn.s3-eu-west-1.amazonaws.com/",
28
28
  # "https://my.reverse.proxy.com/")
29
29
  # end
30
30
  #
@@ -6,7 +6,7 @@ class BinaryRouting < Struct.new(:request, :scrivito_engine)
6
6
  end
7
7
 
8
8
  def binary_obj_url(obj, binary, image_options = {})
9
- binary = if image_options.has_key?(:transform)
9
+ binary = if image_options.key?(:transform)
10
10
  apply_custom_transformation(binary, image_options[:transform])
11
11
  else
12
12
  apply_default_transformation(binary, obj)
@@ -31,7 +31,8 @@ module Scrivito
31
31
  if params[:id]
32
32
  Obj.find(params[:id])
33
33
  elsif params[:permalink].present?
34
- self.class.find_permalink_by_param(params[:permalink])
34
+ permalink = Array(params[:permalink]).join("/")
35
+ Obj.find_by_permalink!(permalink)
35
36
  else
36
37
  Scrivito::RequestHomepage.call(env)
37
38
  end
@@ -42,10 +43,5 @@ module Scrivito
42
43
  def params
43
44
  env["action_dispatch.request.path_parameters"]
44
45
  end
45
-
46
- def self.find_permalink_by_param(permalink_param)
47
- permalink = Array(permalink_param).join("/")
48
- Obj.find_by_permalink!(permalink)
49
- end
50
46
  end
51
47
  end
@@ -75,6 +75,10 @@ class CmsFieldTag < Struct.new(:view, :tag_name, :obj_or_widget, :editing_option
75
75
  options["private-field-widget-inner-tag"] = inner_tag
76
76
  options['private-field-widget-allowed-classes'] = build_valid_widget_classes.to_json
77
77
  options['private-field-widget-template'] = widget_render_context
78
+
79
+ if editing_options[:disable_margins]
80
+ options['private-field-widget-disable-margins'] = true
81
+ end
78
82
  end
79
83
 
80
84
  options
@@ -151,7 +151,6 @@ module Scrivito
151
151
 
152
152
  if response.code.start_with?('4')
153
153
  backend_code = error_body['code']
154
- message = "'#{specific_output}' on '#{resource_path}'"
155
154
  raise ClientError.new(specific_output,
156
155
  http_code: http_code, backend_code: backend_code)
157
156
  elsif response.code == '500' && specific_output
@@ -181,6 +180,7 @@ module Scrivito
181
180
 
182
181
  def upload_file(file, content_type, upload_permission)
183
182
  uri = URI.parse(upload_permission['url'])
183
+ uri.normalize!
184
184
 
185
185
  File.open(file) do |open_file|
186
186
  upload_io = UploadIO.new(open_file, content_type, File.basename(file))
@@ -120,7 +120,8 @@ module Scrivito
120
120
  # @example Use Memcached as the second level cache (https://rubygems.org/gems/dalli)
121
121
  #
122
122
  # Scrivito.configure do |config|
123
- # config.second_level_cache = ActiveSupport::Cache::DalliStore.new("localhost", "server-downstairs.localnetwork:8229")
123
+ # config.second_level_cache = ActiveSupport::Cache::DalliStore.new("localhost",
124
+ # "server-downstairs.localnetwork:8229")
124
125
  # end
125
126
  #
126
127
  def second_level_cache=(cache_store)
@@ -170,7 +171,9 @@ module Scrivito
170
171
  # e.g. Content Read Service.
171
172
  # @api public
172
173
  def ca_file=(path)
173
- File.read(path) if path # Try to read the given file and fail if it doesn't exist or is not readable.
174
+ if path # Try to read the given file and fail if it doesn't exist or is not readable.
175
+ File.read(path)
176
+ end
174
177
  @ca_file = path
175
178
  end
176
179
 
@@ -285,8 +288,8 @@ Please use the new scrivito_route api to replicate the legacy routes:
285
288
  # {Scrivito::BasicObj#apply_image_transformation? Obj#apply_image_transformation?} returns
286
289
  # +true+.
287
290
  #
288
- # If not changed the default image transformation is an empty transformation (an empty +Hash+).
289
- # Set it to +false+ to disabled the default image transformation completely.
291
+ # If not changed the default image transformation is an empty transformation (an empty
292
+ # +Hash+). Set it to +false+ to disabled the default image transformation completely.
290
293
  #
291
294
  # @param [Hash] value the {Scrivito::Binary#transform transformation definition}
292
295
  #
@@ -152,7 +152,7 @@ module Scrivito
152
152
  rescue IO::WaitReadable, IO::WaitWritable
153
153
  # these "errors" indicate the connection is still usable
154
154
  false
155
- rescue => e
155
+ rescue
156
156
  # other errors indicate the connection has a problem
157
157
  true
158
158
  end
@@ -2,10 +2,15 @@ module Scrivito
2
2
 
3
3
  class EditingContext
4
4
  # +options+:
5
- # +:selected_workspace_id+: The id of the selected workspace. If empty +published+ workspace is used.
6
- # +:display_mode+: Can be +view+, +editing+, +added+ or +deleted+. If empty +view+ is used.
7
- # +:editor+: A block, which is lazy evaluated on first access, to determine the editor (details see {Scrivito::Configuration.editing_auth})
8
- # +:workspace_changed+: A boolean, determining if the workspace has been changed with this request.
5
+ # +:selected_workspace_id+:
6
+ # The id of the selected workspace. If empty +published+ workspace is used.
7
+ # +:display_mode+:
8
+ # Can be +view+, +editing+, +added+ or +deleted+. If empty +view+ is used.
9
+ # +:editor+:
10
+ # A block, which is lazy evaluated on first access, to determine the editor
11
+ # (details see {Scrivito::Configuration.editing_auth})
12
+ # +:workspace_changed+:
13
+ # A boolean, determining if the workspace has been changed with this request.
9
14
  # @param [Hash] options
10
15
  def initialize(options = {})
11
16
  @selected_workspace_id = options[:selected_workspace_id]
@@ -1,15 +1,14 @@
1
1
  module Scrivito
2
2
  module FloatConversion
3
3
  FLOAT_STRING_REGEX = /\A-?\d+(\.\d+)?\z/.freeze
4
- DEFAULT_VALUE = 0.0
5
4
 
6
5
  def self.deserialize_from_backend(backend_value)
7
6
  case backend_value
8
7
  when Integer, Float, FLOAT_STRING_REGEX
9
8
  value = backend_value.to_f
10
- value.finite? ? value : DEFAULT_VALUE
9
+ value.finite? ? value : nil
11
10
  when nil, String
12
- DEFAULT_VALUE
11
+ nil
13
12
  else
14
13
  raise Scrivito::InternalError,
15
14
  "invalid value #{backend_value} (class: #{backend_value.class})"
@@ -1,16 +1,15 @@
1
1
  module Scrivito
2
2
  module IntegerConversion
3
3
  INTEGER_STRING_REGEX = /\A-?\d+\z/.freeze
4
- DEFAULT_VALUE = 0
5
4
  RANGE = Range.new(-(2**53 - 1), (2**53 - 1)).freeze
6
5
 
7
6
  def self.deserialize_from_backend(backend_value)
8
7
  case backend_value
9
8
  when Integer, Float, INTEGER_STRING_REGEX
10
9
  value = backend_value.to_i
11
- RANGE.include?(value) ? value : DEFAULT_VALUE
10
+ RANGE.include?(value) ? value : nil
12
11
  when nil, String
13
- DEFAULT_VALUE
12
+ nil
14
13
  else
15
14
  raise Scrivito::InternalError,
16
15
  "invalid value #{backend_value} (class: #{backend_value.class})"
data/lib/scrivito/link.rb CHANGED
@@ -2,8 +2,8 @@ require 'active_model/naming'
2
2
 
3
3
  module Scrivito
4
4
  # This class represents individual external or internal links Scrivito is able to identify and
5
- # to process.
6
- # To format a link for rendering on an HTML page, use the +scrivito_path+ or +scrivito_url+ methods.
5
+ # to process. To format a link for rendering on an HTML page, use the +scrivito_path+ or
6
+ # +scrivito_url+ methods.
7
7
  # @api public
8
8
  class Link
9
9
 
@@ -30,7 +30,7 @@ module Scrivito
30
30
  link_params[:url] = uri.to_s
31
31
  end
32
32
 
33
- link_params[:query] = remove_editing_context_params(uri.query)
33
+ link_params[:query] = remove_editing_context_params(uri.query_values)
34
34
  link_params[:fragment] = uri.fragment
35
35
 
36
36
  Link.new(link_params)
@@ -96,12 +96,12 @@ module Scrivito
96
96
  rescue ActionController::RoutingError
97
97
  end
98
98
 
99
- def remove_editing_context_params(query)
100
- if query
101
- params = Rack::Utils.parse_nested_query(query)
102
- params.delete('_scrivito_display_mode')
103
- params.delete('_scrivito_workspace_id')
104
- params.to_query
99
+ def remove_editing_context_params(query_values)
100
+ if query_values
101
+ query_values.delete('_scrivito_display_mode')
102
+ query_values.delete('_scrivito_workspace_id')
103
+ uri = Addressable::URI.new(query_values: query_values)
104
+ uri.query
105
105
  end
106
106
  end
107
107
  end
@@ -5,7 +5,7 @@ module Scrivito
5
5
  #
6
6
  # == Available meta data attributes
7
7
  # All binaries have the meta attributes +content_length+ and +content_type+, in addition, PDFs
8
- # and images have attributes specfic to their type.
8
+ # and images have attributes specific to their type.
9
9
  #
10
10
  # If not specified otherwise, the attributes contain +string+ values.
11
11
  #
@@ -59,7 +59,8 @@ class MetaDataCollection
59
59
  # Find value of a meta data attribute.
60
60
  #
61
61
  # @param name [Symbol, String] the name of the meta data attribute.
62
- # @return [String, Array, Fixnum, Date, nil] meta data attribute value if found or +nil+ otherwise.
62
+ # @return [String, Array, Fixnum, Date, nil] meta data attribute value if
63
+ # found or +nil+ otherwise.
63
64
  def [](name)
64
65
  @attributes[name]
65
66
  end
@@ -24,7 +24,7 @@ module Scrivito
24
24
  end
25
25
 
26
26
  def exists?
27
- File.exists?(filename)
27
+ File.exist?(filename)
28
28
  end
29
29
 
30
30
  private
@@ -63,9 +63,11 @@ module Scrivito
63
63
  find_by(:permalink, [permalink]).first.min_by(&:id)
64
64
  end
65
65
 
66
- # Returns an {ObjSearchEnumerator} with the given initial subquery consisting of the four arguments.
66
+ # Returns an {ObjSearchEnumerator} with the given initial subquery consisting of the
67
+ # four arguments.
67
68
  #
68
- # Note that +field+ and +value+ may also be arrays for searching several fields or searching for several values.
69
+ # Note that +field+ and +value+ may also be arrays for searching several fields or searching
70
+ # for several values.
69
71
  #
70
72
  # {ObjSearchEnumerator}s can be chained using one of the chainable methods
71
73
  # (e.g. {ObjSearchEnumerator#and} and {ObjSearchEnumerator#and_not}).
@@ -1,5 +1,11 @@
1
1
  module Scrivito
2
- class ObjCreateParamsParser < ObjParamsParser
2
+ class ObjCreateParamsParser < Struct.new(:host, :port, :context)
3
+ def parse(params)
4
+ params = params.deep_dup
5
+ convert_params(params)
6
+ params
7
+ end
8
+
3
9
  private
4
10
 
5
11
  def convert_params(params)
@@ -10,5 +16,23 @@ module Scrivito
10
16
  raise ArgumentError, 'Missing "_obj_class" param'
11
17
  end
12
18
  end
19
+
20
+ def convert_field_params(params, attribute_definitions)
21
+ params.each_pair do |key, value|
22
+ params[key] = case attribute_definitions[key.to_s].try(:type)
23
+ when 'binary' then parse_binary_params(value)
24
+ when 'html' then ContentConversion.convert_html_links(value, host, port)
25
+ when 'link' then ContentConversion.convert_link(value, host, port)
26
+ when 'linklist' then ContentConversion.convert_linklist_urls(value, host, port)
27
+ when 'date' then DateConversion.deserialize_from_client(value)
28
+ else value
29
+ end
30
+ end
31
+ end
32
+
33
+ def parse_binary_params(params)
34
+ return unless params
35
+ UploadedBinary.new(params)
36
+ end
13
37
  end
14
38
  end
@@ -2,7 +2,7 @@
2
2
  module Scrivito
3
3
  # Provides an enumerator for iterating over the results of searches for CMS objects to retrieve
4
4
  # instances of these objects. This is achieved through the
5
- # {http://ruby-doc.org/core/Enumerable.html +Enumerable+ mixin}, which provides methods such
5
+ # {https://ruby-doc.org/core/Enumerable.html +Enumerable+ mixin}, which provides methods such
6
6
  # as +map+, +select+ or +take+.
7
7
  #
8
8
  # This enumerator is lazy. If, for example, you are looking for {Scrivito::BasicObj Obj}s whose
@@ -77,7 +77,8 @@ module Scrivito
77
77
  #
78
78
  # [+:equals+] The +field+ value needs to be identical to the +value+ of this subquery.
79
79
  #
80
- # Applicable to +string+, +stringlist+, +enum+, +multienum+ and +date+ fields.
80
+ # Applicable to +string+, +stringlist+, +enum+, +multienum+,
81
+ # +float+, +integer+ and +date+ fields.
81
82
  #
82
83
  # Example subquery values:
83
84
  #
@@ -115,7 +116,7 @@ module Scrivito
115
116
  #
116
117
  # === +is_less_than+ and +is_greater_than+
117
118
  #
118
- # These operators are intended for comparing +date+ values or numerical metadata, for example the width of an image.
119
+ # These operators are intended for comparing +date+, +integer+, or +float+ values.
119
120
  # It only considers attributes of {Scrivito::BasicObj Obj}s and _not_ of {Scrivito::BasicWidget Widget}s.
120
121
  # Therefore, {Scrivito::BasicWidget Widget} attributes are not searchable using the +is_less_than+ and +is_greater_than+ operators.
121
122
  #
@@ -137,50 +138,84 @@ module Scrivito
137
138
  # ✔ +Time.new(2000,01,01,00,00,01)+ (is greater than)
138
139
  #
139
140
  # ✘ +Time.new(2000,01,01,00,00,00)+ (equal, not greater than)
140
- # === +refers_to+
141
141
  #
142
- # The +refers_to+ operator searches for CMS objects in which specific attributes
143
- # reference specific CMS objects. It works with individual +reference+ or +referencelist+
144
- # attributes and with a list of attributes of these types.
142
+ # For +is_less_than+ and +is_greater_than+, the examples are based on the following float value:
143
+ # +23.42+
145
144
  #
146
- # So the operator returns the CMS objects in which given attributes of the +reference+ or
147
- # +referencelist+ type reference the given CMS objects.
145
+ # [+:is_less_than+] Matches if the field value is less than the subquery numeric value.
148
146
  #
149
- # Using the "*" wildcard for the attributes to search causes all reference and referencelist
150
- # attributes of the searched CMS objects to be taken into account.
147
+ # Example subquery values:
148
+ #
149
+ # ✔ +23.41+ (is less than)
151
150
  #
152
- # Note that only attributes directly part of the CMS objects are searched.
153
- # Currently, attributes contained in widgets are not searched.
151
+ # +5+ (is less than)
154
152
  #
155
- # [+:refers_to+] Searches for CMS objects referencing given objects by means of specific attributes.
153
+ # +23.42+ (equal, not less than)
154
+ #
155
+ # [+:is_greater_than+] Matches if the field value is greater than the subquery numeric value.
156
156
  #
157
157
  # Example subquery values:
158
158
  #
159
- # ✔ myObj (an instance of {Scrivito::BasicObj Obj})
159
+ # ✔ +23.43+ (is greater than)
160
160
  #
161
- # "NameString" (not an instance of {Scrivito::BasicObj Obj})
161
+ # +42+ (is greater than)
162
162
  #
163
- # ✘ +Time.new(2000,01,01,00,00,00)+ (not an instance of {Scrivito::BasicObj Obj})
163
+ # ✘ +23.42+ (equal, not greater than)
164
164
  #
165
165
  # === +links_to+
166
166
  #
167
- # The +links_to+ operator searches for CMS objects containing one or more links pointing to
168
- # a specific CMS object.
169
- # So the operator returns the CMS objects in which an
170
- # +html+, +link+, +linklist+, +reference+ or +referencelist+ attribute links to the CMS object.
167
+ # The +links_to+ operator searches for CMS objects containing one or more attributes linking to
168
+ # specific CMS objects. So the operator returns the CMS objects in which at least one +html+,
169
+ # +link+, +linklist+, +reference+ or +referencelist+ attribute links to specific CMS objects.
170
+ #
171
+ # The operator can only be applied to all attributes, so the +"*"+ wildcard _must_ be specified
172
+ # for the attributes to search. If you want to search specific +reference+ or +referencelist+
173
+ # attributes, please use the +refers_to+ operator.
174
+ #
175
+ # Using +nil+ instead of an instance of {Scrivito::BasicObj Obj} raises an error.
176
+ #
177
+ # Note that, in contrast to the +refers_to+ operator, the +links_to+ operator searches the
178
+ # attributes directly part of the CMS objects _as_ _well_ _as_ the attributes contained in
179
+ # widgets.
180
+ #
181
+ # [+:links_to+] Searches for CMS objects linking to a specific CMS object.
182
+ #
183
+ # Example subquery values:
184
+ #
185
+ # ✔ +my_obj+ (an instance of {Scrivito::BasicObj Obj})
186
+ #
187
+ # ✔ +[my_obj1, my_obj2]+ (an +Array+ of instances of {Scrivito::BasicObj Obj})
171
188
  #
172
- # The operator can only be applied to all attributes, so the "*" wild card must be specified for
173
- # the attribute to search.
189
+ # +nil+ (not an instance of {Scrivito::BasicObj Obj})
174
190
  #
175
- # [+:links_to+] Searches for one or more linked objects.
191
+ # "some_string" (not an instance of {Scrivito::BasicObj Obj})
192
+ #
193
+ # === +refers_to+
194
+ #
195
+ # The +refers_to+ operator searches for CMS objects in which at least one of the specified
196
+ # +reference+ or +referencelist+ attributes refers to specific CMS objects.
197
+ #
198
+ # Using the +"*"+ wildcard for the attributes to search causes all +reference+ and +referencelist+
199
+ # attributes of the searched CMS objects to be taken into account.
200
+ #
201
+ # Using +nil+ instead of {Scrivito::BasicObj Objs} searches for all CMS objects in which none of
202
+ # the specified attributes refer to a CMS object.
203
+ #
204
+ # Note that, in contrast to the +links_to+ operator, the +refers_to+ operator only searches
205
+ # attributes _directly_ _part_ _of_ _the_ _CMS_ _objects_. Currently, attributes contained in
206
+ # widgets are _not_ searched.
207
+ #
208
+ # [+:refers_to+] Searches for CMS objects in which specific +reference+ or +referencelist+ attributes refer to specific CMS objects.
176
209
  #
177
210
  # Example subquery values:
178
211
  #
179
- # ✔ myObj (an instance of {Scrivito::BasicObj Obj})
212
+ # ✔ +my_obj+ (an instance of {Scrivito::BasicObj Obj})
213
+ #
214
+ # ✔ +[my_obj1, my_obj2]+ (an +Array+ of instances of {Scrivito::BasicObj Obj})
180
215
  #
181
- # "NameString" (not an instance of {Scrivito::BasicObj Obj})
216
+ # +nil+
182
217
  #
183
- # ✘ +Time.new(2000,01,01,00,00,00)+ (not an instance of {Scrivito::BasicObj Obj})
218
+ # ✘ "some_string" (not an instance of {Scrivito::BasicObj Obj})
184
219
  #
185
220
  # == Matching +multienum+ and +stringlist+
186
221
  #
@@ -189,8 +224,15 @@ module Scrivito
189
224
  # A search query matches a +multienum+ or +stringlist+, if at least one string in the list matches.
190
225
  # Example: A query using the operator +:equals+ and the value +"Eggs"+ matches an Obj containing +["Spam","Eggs"]+ in a +stringlist+ or +multienum+ attribute.
191
226
  #
227
+ # == Limits
228
+ #
229
+ # The number of chainable subqueries is limited. The limit depends on the number of values,
230
+ # fields, and boost parameters requested, as well as the number of words in a free text
231
+ # search.
232
+ #
192
233
  # @api public
193
234
  class ObjSearchEnumerator
235
+ INVALID_NEGATED_OPERATORS = [:contains, :contains_prefix].freeze
194
236
  include Enumerable
195
237
 
196
238
  attr_reader :workspace
@@ -212,7 +254,8 @@ module Scrivito
212
254
  # @param [Symbol, String, Array<Symbol, String>] field Name(s) of the field(s) to be searched.
213
255
  # For arrays, the subquery matches if one or more of these fields meet this criterion.
214
256
  # @param [Symbol, String] operator See "Currently available operators" above.
215
- # @param [String, Date, Time, Array<String, Date, Time>] value The value(s) to compare with the field value(s) using the
257
+ # @param [String, Integer, Float, Date, Time, Array<String, Date, Time, Float, Integer>]
258
+ # value The value(s) to compare with the field value(s) using the
216
259
  # +operator+ of this subquery. For arrays, the subquery matches if the condition is met for
217
260
  # one or more of the array elements.
218
261
  # @param [Hash] boost A hash where the keys are field names and their values are boosting
@@ -222,7 +265,7 @@ module Scrivito
222
265
  # @api public
223
266
  def and(field, operator, value, boost = nil)
224
267
  real_operator = operator_mapping(operator)
225
- subquery = {:field => field, :operator => real_operator, :value => convert_value(value)}
268
+ subquery = { field: field, operator: real_operator, value: convert_value(value) }
226
269
  if boost.present?
227
270
  valid_boost_operators = [:contains, :contains_prefix]
228
271
  if valid_boost_operators.include?(operator.to_sym)
@@ -246,21 +289,20 @@ module Scrivito
246
289
  # @param [Symbol, String, Array<Symbol, String>] field Name(s) of the field(s) to be searched.
247
290
  # For arrays, the subquery matches if one or more of these fields meet this criterion.
248
291
  # @param [Symbol, String] operator Must be one of: +equals+,
249
- # +starts_with+, +is_greater_than+, +is_less_than+.
292
+ # +starts_with+, +is_greater_than+, +is_less_than+, +links_to+, +refers_to+.
250
293
  # (See "Currently available operators" above).
251
- # @param [String, Date, Time, Array<String, Date, Time>] value The value(s) to compare with the field value(s) using the
294
+ # @param [String, Date, Time, Integer, Float Array<String, Date, Time, Integer, Float>] value The value(s) to compare with the field value(s) using the
252
295
  # +operator+ of this subquery. For arrays, the subquery matches if the condition is met for
253
296
  # one or more of the array elements.
254
297
  # @return [Scrivito::ObjSearchEnumerator]
255
298
  # @api public
256
299
  def and_not(field, operator, value)
257
- real_operator = operator_mapping(operator)
258
- valid_negated_operators = [:equals, :starts_with, :is_greater_than, :is_less_than]
259
- unless valid_negated_operators.include?(operator.to_sym)
300
+ if INVALID_NEGATED_OPERATORS.include?(operator.to_sym)
260
301
  raise "Negating operator '#{operator}' is not valid."
261
302
  end
262
- subquery = {:field => field, :operator => real_operator, :value => convert_value(value),
263
- :negate => true}
303
+ real_operator = operator_mapping(operator)
304
+ subquery = { field: field, operator: real_operator, value: convert_value(value),
305
+ negate: true }
264
306
  reset_for_changed_query
265
307
  @query = (query || []) + [subquery]
266
308
 
@@ -269,7 +311,7 @@ module Scrivito
269
311
 
270
312
  # Orders the results by +field_name+.
271
313
  #
272
- # Applicable to the attribute types +string+, +enum+ and +date+.
314
+ # Applicable to the attribute types +string+, +enum+, +integer+, +float+ and +date+.
273
315
  #
274
316
  # There is a precision limit when sorting string values:
275
317
  # Only the first 50 characters of a string are guaranteed to be considered when sorting search results.