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.
- checksums.yaml +7 -0
- data/LICENSE.md +21 -0
- data/README.md +617 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/lib/delivery/builders/image_transformation_builder.rb +272 -0
- data/lib/delivery/builders/url_builder.rb +123 -0
- data/lib/delivery/client/delivery_client.rb +184 -0
- data/lib/delivery/client/delivery_query.rb +308 -0
- data/lib/delivery/client/request_manager.rb +127 -0
- data/lib/delivery/models/content_item.rb +153 -0
- data/lib/delivery/models/content_type.rb +41 -0
- data/lib/delivery/models/language.rb +29 -0
- data/lib/delivery/models/pagination.rb +22 -0
- data/lib/delivery/models/taxonomy_group.rb +39 -0
- data/lib/delivery/query_parameters/filters.rb +201 -0
- data/lib/delivery/query_parameters/parameter_base.rb +56 -0
- data/lib/delivery/query_parameters/query_string.rb +78 -0
- data/lib/delivery/resolvers/content_link_resolver.rb +102 -0
- data/lib/delivery/resolvers/inline_content_item_resolver.rb +75 -0
- data/lib/delivery/resolvers/linked_item_resolver.rb +43 -0
- data/lib/delivery/responses/delivery_element_response.rb +34 -0
- data/lib/delivery/responses/delivery_item_listing_response.rb +54 -0
- data/lib/delivery/responses/delivery_item_response.rb +40 -0
- data/lib/delivery/responses/delivery_items_feed_response.rb +58 -0
- data/lib/delivery/responses/delivery_language_listing_response.rb +44 -0
- data/lib/delivery/responses/delivery_taxonomy_listing_response.rb +47 -0
- data/lib/delivery/responses/delivery_taxonomy_response.rb +33 -0
- data/lib/delivery/responses/delivery_type_listing_response.rb +46 -0
- data/lib/delivery/responses/delivery_type_response.rb +32 -0
- data/lib/delivery/responses/response_base.rb +39 -0
- data/lib/delivery/tests/401.json +6 -0
- data/lib/delivery/tests/429.json +5 -0
- data/lib/delivery/tests/fake_responder.rb +99 -0
- data/lib/delivery/tests/filtering/items_with_count.json +5385 -0
- data/lib/delivery/tests/filtering/pagination.json +762 -0
- data/lib/delivery/tests/generic/items/about_us.json +277 -0
- data/lib/delivery/tests/generic/items/aeropress_filters.json +156 -0
- data/lib/delivery/tests/generic/items/coffee_processing_techniques.json +566 -0
- data/lib/delivery/tests/generic/items/empty_rich_text.json +24 -0
- data/lib/delivery/tests/generic/items/rich_text_complex_tables.json +81 -0
- data/lib/delivery/tests/generic/items/where_does_coffee_come_from_.json +599 -0
- data/lib/delivery/tests/generic/items.json +5384 -0
- data/lib/delivery/tests/generic/languages.json +24 -0
- data/lib/delivery/tests/generic/taxonomies/manufacturer.json +30 -0
- data/lib/delivery/tests/generic/taxonomies.json +204 -0
- data/lib/delivery/tests/generic/types/brewer/elements/product_status.json +6 -0
- data/lib/delivery/tests/generic/types/brewer.json +89 -0
- data/lib/delivery/tests/generic/types.json +836 -0
- data/lib/delivery/tests/items_feed/articles_feed_1.json +39 -0
- data/lib/delivery/tests/items_feed/articles_feed_2.json +78 -0
- data/lib/delivery/tests/items_feed/articles_feed_3.json +104 -0
- data/lib/kontent-ai-delivery.rb +22 -0
- 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
|