kontent-ai-delivery 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (54) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE.md +21 -0
  3. data/README.md +617 -0
  4. data/bin/console +14 -0
  5. data/bin/setup +8 -0
  6. data/lib/delivery/builders/image_transformation_builder.rb +272 -0
  7. data/lib/delivery/builders/url_builder.rb +123 -0
  8. data/lib/delivery/client/delivery_client.rb +184 -0
  9. data/lib/delivery/client/delivery_query.rb +308 -0
  10. data/lib/delivery/client/request_manager.rb +127 -0
  11. data/lib/delivery/models/content_item.rb +153 -0
  12. data/lib/delivery/models/content_type.rb +41 -0
  13. data/lib/delivery/models/language.rb +29 -0
  14. data/lib/delivery/models/pagination.rb +22 -0
  15. data/lib/delivery/models/taxonomy_group.rb +39 -0
  16. data/lib/delivery/query_parameters/filters.rb +201 -0
  17. data/lib/delivery/query_parameters/parameter_base.rb +56 -0
  18. data/lib/delivery/query_parameters/query_string.rb +78 -0
  19. data/lib/delivery/resolvers/content_link_resolver.rb +102 -0
  20. data/lib/delivery/resolvers/inline_content_item_resolver.rb +75 -0
  21. data/lib/delivery/resolvers/linked_item_resolver.rb +43 -0
  22. data/lib/delivery/responses/delivery_element_response.rb +34 -0
  23. data/lib/delivery/responses/delivery_item_listing_response.rb +54 -0
  24. data/lib/delivery/responses/delivery_item_response.rb +40 -0
  25. data/lib/delivery/responses/delivery_items_feed_response.rb +58 -0
  26. data/lib/delivery/responses/delivery_language_listing_response.rb +44 -0
  27. data/lib/delivery/responses/delivery_taxonomy_listing_response.rb +47 -0
  28. data/lib/delivery/responses/delivery_taxonomy_response.rb +33 -0
  29. data/lib/delivery/responses/delivery_type_listing_response.rb +46 -0
  30. data/lib/delivery/responses/delivery_type_response.rb +32 -0
  31. data/lib/delivery/responses/response_base.rb +39 -0
  32. data/lib/delivery/tests/401.json +6 -0
  33. data/lib/delivery/tests/429.json +5 -0
  34. data/lib/delivery/tests/fake_responder.rb +99 -0
  35. data/lib/delivery/tests/filtering/items_with_count.json +5385 -0
  36. data/lib/delivery/tests/filtering/pagination.json +762 -0
  37. data/lib/delivery/tests/generic/items/about_us.json +277 -0
  38. data/lib/delivery/tests/generic/items/aeropress_filters.json +156 -0
  39. data/lib/delivery/tests/generic/items/coffee_processing_techniques.json +566 -0
  40. data/lib/delivery/tests/generic/items/empty_rich_text.json +24 -0
  41. data/lib/delivery/tests/generic/items/rich_text_complex_tables.json +81 -0
  42. data/lib/delivery/tests/generic/items/where_does_coffee_come_from_.json +599 -0
  43. data/lib/delivery/tests/generic/items.json +5384 -0
  44. data/lib/delivery/tests/generic/languages.json +24 -0
  45. data/lib/delivery/tests/generic/taxonomies/manufacturer.json +30 -0
  46. data/lib/delivery/tests/generic/taxonomies.json +204 -0
  47. data/lib/delivery/tests/generic/types/brewer/elements/product_status.json +6 -0
  48. data/lib/delivery/tests/generic/types/brewer.json +89 -0
  49. data/lib/delivery/tests/generic/types.json +836 -0
  50. data/lib/delivery/tests/items_feed/articles_feed_1.json +39 -0
  51. data/lib/delivery/tests/items_feed/articles_feed_2.json +78 -0
  52. data/lib/delivery/tests/items_feed/articles_feed_3.json +104 -0
  53. data/lib/kontent-ai-delivery.rb +22 -0
  54. metadata +221 -0
@@ -0,0 +1,308 @@
1
+ require 'rubygems'
2
+ require 'delivery/builders/url_builder'
3
+ require 'delivery/query_parameters/query_string'
4
+
5
+ module Kontent
6
+ module Ai
7
+ module Delivery
8
+ # Responsible for executing REST requests to Kontent.ai.
9
+ class DeliveryQuery
10
+ ERROR_PREVIEW = 'Preview is enabled for the query, but the key is null. '\
11
+ 'You can set the preview_key attribute of the query, or '\
12
+ 'when you initialize the client. See '\
13
+ 'https://github.com/kontent-ai/delivery-sdk-ruby#previewing-unpublished-content'.freeze
14
+ ERROR_PARAMS = 'Only filters may be passed in the .item or .items methods'\
15
+ '. See https://github.com/kontent-ai/delivery-sdk-ruby#filtering'.freeze
16
+ HEADER_WAIT_FOR_CONTENT = 'X-KC-Wait-For-Loading-New-Content'.freeze
17
+ HEADER_SDK_ID = 'X-KC-SDKID'.freeze
18
+ HEADER_CONTINUATION = 'X-Continuation'.freeze
19
+ attr_accessor :use_preview,
20
+ :preview_key,
21
+ :project_id,
22
+ :code_name,
23
+ :secure_key,
24
+ :content_link_url_resolver,
25
+ :inline_content_item_resolver,
26
+ :query_type,
27
+ :query_string,
28
+ :content_type,
29
+ :with_retry_policy,
30
+ :default_rendition_preset
31
+
32
+ # Setter for a custom URL.
33
+ #
34
+ # * *Args*:
35
+ # - *url* (+string+) _optional_ Custom URL to use for the query
36
+ #
37
+ # * *Returns*:
38
+ # - +self+
39
+ def url(url = nil)
40
+ @url = url unless url.nil?
41
+ self
42
+ end
43
+
44
+ # Constructor. Queries should not be instantiated using the constructor, but
45
+ # using one of the Kontent::Ai::Delivery::DeliveryClient methods instead.
46
+ #
47
+ # * *Args*:
48
+ # - *config* (+Hash+) A hash in which each key automatically has its value paired with the corresponding attribute
49
+ def initialize(config)
50
+ @headers = {}
51
+
52
+ # Map each hash value to attr with corresponding key
53
+ # from https://stackoverflow.com/a/2681014/5656214
54
+ config.each do |k, v|
55
+ instance_variable_set("@#{k}", v) unless v.nil?
56
+ end
57
+ self.query_string = Kontent::Ai::Delivery::QueryParameters::QueryString.new
58
+ return if config.fetch(:qp, nil).nil?
59
+
60
+ # Query parameters were passed, parse and validate
61
+ validate_params config.fetch(:qp)
62
+ end
63
+
64
+ # Executes the REST request.
65
+ #
66
+ # * *Returns*:
67
+ # - Kontent::Ai::Delivery::Responses::ResponseBase or a class extending it
68
+ def execute
69
+ resp = Kontent::Ai::Delivery::RequestManager.start self, headers
70
+ yield resp if block_given?
71
+ resp
72
+ end
73
+
74
+ # Determines whether the query should use preview mode.
75
+ #
76
+ # * *Returns*:
77
+ # - +boolean+ Whether preview mode should be used for the query
78
+ #
79
+ # * *Raises*:
80
+ # - +StandardError+ if +use_preview+ is true, but +preview_key+ is +nil+
81
+ def should_preview
82
+ raise ERROR_PREVIEW if use_preview && preview_key.nil?
83
+
84
+ use_preview && !preview_key.nil?
85
+ end
86
+
87
+ # Enables the total_count attribute of the pagination object, which specifies
88
+ # the total number of items returned by the query regardless of paging. See
89
+ # https://docs.kontent.ai/reference/delivery-api#operation/list-content-items
90
+ #
91
+ # * *Returns*:
92
+ # - +self+
93
+ def include_total_count
94
+ query_string.set_param('includeTotalCount', 1)
95
+ self
96
+ end
97
+
98
+ # Sets a content link resolver to render links contained in rich text. See
99
+ # https://github.com/kontent-ai/delivery-sdk-ruby#resolving-links
100
+ #
101
+ # * *Args*:
102
+ # - *resolver* ( Kontent::Ai::Delivery::Resolvers::ContentLinkResolver ) The resolver. Replaces a resolver registered during +DeliveryClient+ instantiation, for this query only.
103
+ #
104
+ # * *Returns*:
105
+ # - +self+
106
+ def with_link_resolver(resolver)
107
+ self.content_link_url_resolver = resolver
108
+ self
109
+ end
110
+
111
+ # Sets an inline content itme to render content items and components in rich text.
112
+ # See https://github.com/kontent-ai/delivery-sdk-ruby#resolving-inline-content
113
+ #
114
+ # * *Args*:
115
+ # - *resolver* ( Kontent::Ai::Delivery::Resolvers::InlineContentItemResolver ) The resolver. Replaces a resolver registered during +DeliveryClient+ instantiation, for this query only.
116
+ #
117
+ # * *Returns*:
118
+ # - +self+
119
+ def with_inline_content_item_resolver(resolver)
120
+ self.inline_content_item_resolver = resolver
121
+ self
122
+ end
123
+
124
+ def with_default_rendition_preset(rendition)
125
+ self.default_rendition_preset = rendition
126
+ self
127
+ end
128
+
129
+ # Sets the 'order' query string parameter
130
+ #
131
+ # * *Args*:
132
+ # - *value* (+string+) The value to order by
133
+ # - *sort* (+string+) _optional_ The direction of the order, surrounded by brackets. The default value is '[asc]'
134
+ #
135
+ # * *Returns*:
136
+ # - +self+
137
+ def order_by(value, sort = '[asc]')
138
+ query_string.set_param('order', value + sort)
139
+ self
140
+ end
141
+
142
+ # Sets the 'skip' query string parameter for paging results.
143
+ # See https://kontent.ai/learn/reference/delivery-api/#operation/list-content-items
144
+ #
145
+ # * *Args*:
146
+ # - *value* (+integer+) The number to skip by
147
+ #
148
+ # * *Returns*:
149
+ # - +self+
150
+ def skip(value)
151
+ query_string.set_param('skip', value) unless query_type.eql? Kontent::Ai::Delivery::QUERY_TYPE_ITEMS_FEED
152
+ self
153
+ end
154
+
155
+ # Sets the 'language' query string parameter. Language fallbacks will be used
156
+ # if untranslated content items are found.
157
+ # See https://kontent.ai/learn/tutorials/develop-apps/get-content/localized-content-items/
158
+ #
159
+ # * *Args*:
160
+ # - *value* (+string+) The code name of the desired language
161
+ #
162
+ # * *Returns*:
163
+ # - +self+
164
+ def language(value)
165
+ query_string.set_param('language', value)
166
+ self
167
+ end
168
+
169
+ # Sets the 'limit' query string parameter for paging results, or just to
170
+ # return a specific number of content items.
171
+ # See https://kontent.ai/learn/reference/delivery-api/#operation/list-content-items
172
+ #
173
+ # * *Args*:
174
+ # - *value* (+integer+) The number of content items to return
175
+ #
176
+ # * *Returns*:
177
+ # - +self+
178
+ def limit(value)
179
+ query_string.set_param('limit', value) unless query_type.eql? Kontent::Ai::Delivery::QUERY_TYPE_ITEMS_FEED
180
+ self
181
+ end
182
+
183
+ # Sets the 'elements' query string parameter to limit the elements returned
184
+ # by the query.
185
+ # See https://kontent.ai/learn/reference/delivery-api/#tag/Projection
186
+ #
187
+ # * *Args*:
188
+ # - *value* (+Array+) A single string or array of strings specifying the desired elements, e.g. %w[price product_name image]
189
+ #
190
+ # * *Returns*:
191
+ # - +self+
192
+ def elements(value)
193
+ query_string.set_param('elements', value)
194
+ self
195
+ end
196
+
197
+ # Sets the 'depth' query string parameter to determine how many levels of
198
+ # linked content items should be returned. By default, only 1 level of depth
199
+ # is used.
200
+ # See https://kontent.ai/learn/reference/delivery-api/#tag/Linked-content-and-components/linked-content-depth
201
+ #
202
+ # * *Args*:
203
+ # - *value* (+integer+) Level of linked items to be returned
204
+ #
205
+ # * *Returns*:
206
+ # - +self+
207
+ def depth(value)
208
+ query_string.set_param('depth', value) unless query_type.eql? Kontent::Ai::Delivery::QUERY_TYPE_ITEMS_FEED
209
+ self
210
+ end
211
+
212
+ # Allows the request to bypass caching and return the latest content
213
+ # directly from Kontent.ai.
214
+ # See https://github.com/kontent-ai/delivery-sdk-ruby#requesting-the-latest-content
215
+ #
216
+ # * *Returns*:
217
+ # - +self+
218
+ def request_latest_content
219
+ @headers[HEADER_WAIT_FOR_CONTENT] = true
220
+ self
221
+ end
222
+
223
+ # Uses Kontent::Ai::Delivery::Builders::UrlBuilder.provide_url to set
224
+ # the URL for the query. The +UrlBuilder+ also validates the URL.
225
+ #
226
+ # * *Raises*:
227
+ # - +UriFormatException+ if the URL is 65,519 characters or more
228
+ #
229
+ # * *Returns*:
230
+ # - +string+ The full URL for this query
231
+ def provide_url
232
+ @url = Kontent::Ai::Delivery::Builders::UrlBuilder.provide_url self if @url.nil?
233
+ Kontent::Ai::Delivery::Builders::UrlBuilder.validate_url @url
234
+ @url
235
+ end
236
+
237
+ # Allows providing custom headers for client requests.
238
+ # See https://github.com/kontent-ai/delivery-sdk-ruby#providing-custom-headers
239
+ #
240
+ # * *Args*:
241
+ # - *headers* (+Hash+) A hash that corresponds to provided headers
242
+ #
243
+ # * *Returns*:
244
+ # - +self+
245
+ def custom_headers(headers)
246
+ @custom_headers = headers
247
+ self
248
+ end
249
+
250
+ def update_continuation(token)
251
+ @headers[HEADER_CONTINUATION] = token
252
+ self
253
+ end
254
+
255
+ def continuation_exists?
256
+ !continuation_token.nil?
257
+ end
258
+
259
+ def continuation_token
260
+ @headers[HEADER_CONTINUATION]
261
+ end
262
+
263
+ private
264
+
265
+ # Returns request headers that are extended with custom headers.
266
+ # Custom headers do not override existing headers.
267
+ #
268
+ # * *Returns*
269
+ # - +Hash+
270
+ def headers
271
+ headers = @headers.clone
272
+ headers[HEADER_SDK_ID] = provide_sdk_header
273
+ headers['Authorization'] = "Bearer #{preview_key}" if should_preview
274
+ headers['Authorization'] = "Bearer #{secure_key}" if !should_preview && secure_key
275
+
276
+ if @custom_headers
277
+ headers.merge!(@custom_headers) { |key, v1, v2| v1 }
278
+ end
279
+
280
+ headers
281
+ end
282
+
283
+ # Initializes the +query_string+ attribute with the passed array of
284
+ # Kontent::Ai::Delivery::QueryParameters::Filter objects.
285
+ #
286
+ # * *Raises*:
287
+ # - +ArgumentError+ if one the passed objects is not a +Filter+
288
+ def validate_params(query_parameters)
289
+ params = if query_parameters.is_a? Array
290
+ query_parameters
291
+ else
292
+ [query_parameters]
293
+ end
294
+ params.each do |p|
295
+ query_string.set_param p
296
+ unless p.is_a? Kontent::Ai::Delivery::QueryParameters::Filter
297
+ raise ArgumentError, ERROR_PARAMS
298
+ end
299
+ end
300
+ end
301
+
302
+ def provide_sdk_header
303
+ 'rubygems.org;delivery-sdk-ruby;'
304
+ end
305
+ end
306
+ end
307
+ end
308
+ end
@@ -0,0 +1,127 @@
1
+ require 'rest-client'
2
+
3
+ module Kontent
4
+ module Ai
5
+ module Delivery
6
+ class RequestManager
7
+ class << self
8
+ MAX_ATTEMPTS = 6
9
+ MAX_DELAY_SECONDS = 30
10
+ INITIAL_DELAY = 1
11
+ RETRY_WHEN_CODE = [408, 429, 500, 502, 503, 504].freeze
12
+ CODES_WITH_POSSIBLE_RETRY_HEADER = [429, 503].freeze
13
+
14
+ def start(query, headers)
15
+ @query = query
16
+ @headers = headers
17
+ @times_run = 1
18
+ @delay = INITIAL_DELAY
19
+ @url = @query.provide_url
20
+ @total_delay = 0
21
+ continue
22
+ end
23
+
24
+ private
25
+
26
+ def should_retry(potential_response)
27
+ return potential_response if @times_run == MAX_ATTEMPTS ||
28
+ !RETRY_WHEN_CODE.include?(potential_response.http_code) ||
29
+ !@query.with_retry_policy ||
30
+ @total_delay >= MAX_DELAY_SECONDS
31
+
32
+ next_delay
33
+ sleep(@delay)
34
+ @total_delay += @delay
35
+ continue
36
+ end
37
+
38
+ # Generates a random delay based on times_run, then increases times_run
39
+ def next_delay
40
+ min = 0.8 * INITIAL_DELAY
41
+ max = (1.2 * INITIAL_DELAY) * (2**@times_run)
42
+ @delay = rand(min..max)
43
+ @times_run += 1
44
+ end
45
+
46
+ def continue
47
+ if ENV['TEST'] == '1'
48
+ resp = Kontent::Ai::Delivery::Tests::FakeResponder.get_response @query, @url, @headers
49
+ return should_retry(resp) if resp.is_a? Kontent::Ai::Delivery::Responses::ResponseBase
50
+
51
+ make_response resp # resp is pure JSON
52
+ else
53
+ begin
54
+ resp = RestClient.get @url, @headers
55
+ rescue RestClient::ExceptionWithResponse => err
56
+ should_retry Kontent::Ai::Delivery::Responses::ResponseBase.new err.http_code, err.response
57
+ rescue RestClient::SSLCertificateNotVerified => err
58
+ should_retry Kontent::Ai::Delivery::Responses::ResponseBase.new 500, err
59
+ rescue SocketError => err
60
+ should_retry Kontent::Ai::Delivery::Responses::ResponseBase.new 500, err.message
61
+ else
62
+ make_response resp
63
+ end
64
+ end
65
+ end
66
+
67
+ # Converts a standard REST response based on the type of query.
68
+ #
69
+ # * *Returns*:
70
+ # - An object derived from the Kontent::Ai::Delivery::Responses::ResponseBase class
71
+ def make_response(response)
72
+ case @query.query_type
73
+ when Kontent::Ai::Delivery::QUERY_TYPE_ITEMS_FEED
74
+ Kontent::Ai::Delivery::Responses::DeliveryItemsFeedResponse.new(
75
+ response.headers,
76
+ response.body,
77
+ @query
78
+ )
79
+ when Kontent::Ai::Delivery::QUERY_TYPE_ITEMS
80
+ respond_item response
81
+ when Kontent::Ai::Delivery::QUERY_TYPE_TYPES
82
+ respond_type response
83
+ when Kontent::Ai::Delivery::QUERY_TYPE_TAXONOMIES
84
+ respond_taxonomy response
85
+ when Kontent::Ai::Delivery::QUERY_TYPE_ELEMENT
86
+ Kontent::Ai::Delivery::Responses::DeliveryElementResponse.new response.headers, response.body
87
+ when Kontent::Ai::Delivery::QUERY_TYPE_LANGUAGES
88
+ Kontent::Ai::Delivery::Responses::DeliveryLanguageListingResponse.new response.headers, response.body
89
+ end
90
+ end
91
+
92
+ def respond_type(response)
93
+ if @query.code_name.nil?
94
+ Kontent::Ai::Delivery::Responses::DeliveryTypeListingResponse.new response.headers, response.body
95
+ else
96
+ Kontent::Ai::Delivery::Responses::DeliveryTypeResponse.new response.headers, response.body
97
+ end
98
+ end
99
+
100
+ def respond_taxonomy(response)
101
+ if @query.code_name.nil?
102
+ Kontent::Ai::Delivery::Responses::DeliveryTaxonomyListingResponse.new response.headers, response.body
103
+ else
104
+ Kontent::Ai::Delivery::Responses::DeliveryTaxonomyResponse.new response.headers, response.body
105
+ end
106
+ end
107
+
108
+ def respond_item(response)
109
+ if @query.code_name.nil?
110
+ Kontent::Ai::Delivery::Responses::DeliveryItemListingResponse.new(
111
+ response.headers,
112
+ response.body,
113
+ @query
114
+ )
115
+ else
116
+ Kontent::Ai::Delivery::Responses::DeliveryItemResponse.new(
117
+ response.headers,
118
+ response.body,
119
+ @query
120
+ )
121
+ end
122
+ end
123
+ end
124
+ end
125
+ end
126
+ end
127
+ end
@@ -0,0 +1,153 @@
1
+ require 'ostruct'
2
+ require 'nokogiri'
3
+
4
+ module Kontent
5
+ module Ai
6
+ module Delivery
7
+ class ContentItem
8
+ attr_accessor :content_link_url_resolver,
9
+ :inline_content_item_resolver
10
+
11
+ # Parses the 'elements' JSON object as a dynamic OpenStruct object.
12
+ #
13
+ # * *Returns*:
14
+ # - +OpenStruct+ The elements of the content item
15
+ def elements
16
+ @elements unless @elements.nil?
17
+ @elements = JSON.parse(
18
+ JSON.generate(@source['elements']),
19
+ object_class: OpenStruct
20
+ )
21
+ end
22
+
23
+ # Parses the 'system' JSON object as a dynamic OpenStruct object.
24
+ #
25
+ # * *Returns*:
26
+ # - +OpenStruct+ The system properties of the content item
27
+ def system
28
+ @system unless @system.nil?
29
+ @system = JSON.parse(
30
+ JSON.generate(@source['system']),
31
+ object_class: OpenStruct
32
+ )
33
+ end
34
+
35
+ # Constructor.
36
+ #
37
+ # * *Args*:
38
+ # - *source* (+JSON+) The response from a REST request for content items. The item may be on the root or under the 'item' node
39
+ # - *content_link_url_resolver* ( Kontent::Ai::Delivery::Resolvers::ContentLinkResolver )
40
+ # - *inline_content_item_resolver* ( Kontent::Ai::Delivery::Resolvers::InlineContentItemResolver )
41
+ # - *linked_items_resolver* ( Kontent::Ai::Delivery::Resolvers::LinkedItemResolver )
42
+ def initialize(source, content_link_url_resolver, inline_content_item_resolver, linked_items_resolver)
43
+ @source =
44
+ if source['item'].nil?
45
+ source
46
+ else
47
+ source['item']
48
+ end
49
+ @linked_items_resolver = linked_items_resolver
50
+ self.content_link_url_resolver = content_link_url_resolver
51
+ self.inline_content_item_resolver = inline_content_item_resolver
52
+ end
53
+
54
+ # Gets a string representation of the data stored in the element. Using this
55
+ # method instead of directly accessing the +elements+ collection causes
56
+ # the content to be resolved using the resolvers passed during instantiation.
57
+ # See https://github.com/kontent-ai/delivery-sdk-ruby#resolving-links
58
+ #
59
+ # * *Args*:
60
+ # - *code_name* (+string+) The code name of the desired element
61
+ #
62
+ # * *Returns*:
63
+ # - +string+ The data converted to a string, resolved if the element is a 'rich_text' element
64
+ def get_string(code_name)
65
+ element = get_element code_name
66
+ content = element['value']
67
+
68
+ if element['type'] == 'rich_text'
69
+ content = content_link_url_resolver.resolve content, element['links'] if should_resolve_links element
70
+ inline_items = get_inline_items code_name
71
+ content = inline_content_item_resolver.resolve content, inline_items if should_resolve_inline_content element
72
+ end
73
+ content.to_s
74
+ end
75
+
76
+ # Returns an array of assets inserted into the specified element of the
77
+ # 'asset' type.
78
+ #
79
+ # * *Args*:
80
+ # - *code_name* (+string+) The code name of the desired element
81
+ #
82
+ # * *Returns*:
83
+ # - +Array+ The element's assets parsed as +OpenStruct+ objects
84
+ def get_assets(code_name)
85
+ element = get_element code_name
86
+ element['value'].map { |n| OpenStruct.new(n) }
87
+ end
88
+
89
+ # Returns an array of ContentItems that are linked in a 'modular_content'
90
+ # element.
91
+ #
92
+ # * *Args*:
93
+ # - *code_name* (+string+) The code name of the desired element
94
+ #
95
+ # * *Returns*:
96
+ # - +Array+ The element's linked items parsed as +ContentItem+ objects
97
+ def get_links(code_name)
98
+ element = get_element code_name
99
+ get_linked_items element['value']
100
+ end
101
+
102
+ # Returns an array of ContentItems that are inserted as inline content
103
+ # items or componenets of a 'rich_text' element.
104
+ #
105
+ # * *Args*:
106
+ # - *code_name* (+string+) The code name of the desired element
107
+ #
108
+ # * *Returns*:
109
+ # - +Array+ The element's inline content items parsed as +ContentItem+ objects
110
+ def get_inline_items(code_name)
111
+ element = get_element code_name
112
+ get_linked_items element['modular_content']
113
+ end
114
+
115
+ private
116
+
117
+ def should_resolve_links(element)
118
+ !element['links'].nil? && !content_link_url_resolver.nil?
119
+ end
120
+
121
+ def should_resolve_inline_content(element)
122
+ !element['modular_content'].nil? && !inline_content_item_resolver.nil?
123
+ end
124
+
125
+ # Gets the JSON object from the 'elements' collection with the specified key
126
+ #
127
+ # * *Args*:
128
+ # - *code_name* (+string+, +symbol+) The code name or symbol of the desired element
129
+ #
130
+ # * *Returns*:
131
+ # - +JSON+ The element as a JSON object
132
+ #
133
+ # * *Raises*:
134
+ # - +ArgumentError+ if +code_name+ is +nil+
135
+ def get_element(code_name)
136
+ raise ArgumentError, "Argument 'code_name' cannot be null" if code_name.nil?
137
+
138
+ code_name = code_name.to_s if code_name.is_a? Symbol
139
+ @source['elements'][code_name]
140
+ end
141
+
142
+ def get_linked_items(codenames)
143
+ return [] unless codenames.class == Array
144
+
145
+ codenames.each_with_object([]) do |codename, items|
146
+ item = @linked_items_resolver.resolve codename
147
+ items << item if item
148
+ end
149
+ end
150
+ end
151
+ end
152
+ end
153
+ end
@@ -0,0 +1,41 @@
1
+ require 'ostruct'
2
+
3
+ module Kontent
4
+ module Ai
5
+ module Delivery
6
+ class ContentType
7
+ # Parses the 'elements' JSON object as a dynamic OpenStruct object.
8
+ #
9
+ # * *Returns*:
10
+ # - +OpenStruct+ The elements of the content type
11
+ def elements
12
+ @elements unless @elements.nil?
13
+ @elements = JSON.parse(
14
+ JSON.generate(@source['elements']),
15
+ object_class: OpenStruct
16
+ )
17
+ end
18
+
19
+ # Parses the 'system' JSON object as a dynamic OpenStruct object.
20
+ #
21
+ # * *Returns*:
22
+ # - +OpenStruct+ The system properties of the content type
23
+ def system
24
+ @system unless @system.nil?
25
+ @system = JSON.parse(
26
+ JSON.generate(@source['system']),
27
+ object_class: OpenStruct
28
+ )
29
+ end
30
+
31
+ # Constructor.
32
+ #
33
+ # * *Args*:
34
+ # - *source* (+JSON+) The response from a REST request for content types
35
+ def initialize(source)
36
+ @source = source
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,29 @@
1
+ require 'ostruct'
2
+
3
+ module Kontent
4
+ module Ai
5
+ module Delivery
6
+ class Language
7
+ # Parses the 'system' JSON object as a dynamic OpenStruct object.
8
+ #
9
+ # * *Returns*:
10
+ # - +OpenStruct+ The system properties of the language
11
+ def system
12
+ @system unless @system.nil?
13
+ @system = JSON.parse(
14
+ JSON.generate(@source['system']),
15
+ object_class: OpenStruct
16
+ )
17
+ end
18
+
19
+ # Constructor.
20
+ #
21
+ # * *Args*:
22
+ # - *source* (+JSON+) The response from a REST request for a language
23
+ def initialize(source)
24
+ @source = source
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,22 @@
1
+ module Kontent
2
+ module Ai
3
+ module Delivery
4
+ # Holds pagination data from listing responses
5
+ class Pagination
6
+ attr_accessor :skip, :limit, :count, :next_page, :total_count
7
+
8
+ # Constructor.
9
+ #
10
+ # * *Args*:
11
+ # - *json* (+JSON+) The 'pagination' node of a listing reponse's JSON object
12
+ def initialize(json)
13
+ self.skip = json['skip']
14
+ self.limit = json['limit']
15
+ self.count = json['count']
16
+ self.next_page = json['next_page']
17
+ self.total_count = json['total_count']
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end