kontent-ai-delivery 3.0.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 (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