scrivito_sdk 1.5.5 → 1.6.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
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.