kontent-ai-delivery 3.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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,39 @@
|
|
1
|
+
module Kontent
|
2
|
+
module Ai
|
3
|
+
module Delivery
|
4
|
+
class TaxonomyGroup
|
5
|
+
# Parses the 'terms' JSON node as a dynamic OpenStruct object.
|
6
|
+
#
|
7
|
+
# * *Returns*:
|
8
|
+
# - +OpenStruct+ The terms of the taxonomy group as a dynamic object
|
9
|
+
def terms
|
10
|
+
@terms unless @terms.nil?
|
11
|
+
@terms = JSON.parse(
|
12
|
+
JSON.generate(@source['terms']),
|
13
|
+
object_class: OpenStruct
|
14
|
+
)
|
15
|
+
end
|
16
|
+
|
17
|
+
# Parses the 'system' JSON node as a dynamic OpenStruct object.
|
18
|
+
#
|
19
|
+
# * *Returns*:
|
20
|
+
# - +OpenStruct+ The system properties of the taxonomy group
|
21
|
+
def system
|
22
|
+
@system unless @system.nil?
|
23
|
+
@system = JSON.parse(
|
24
|
+
JSON.generate(@source['system']),
|
25
|
+
object_class: OpenStruct
|
26
|
+
)
|
27
|
+
end
|
28
|
+
|
29
|
+
# Constructor.
|
30
|
+
#
|
31
|
+
# * *Args*:
|
32
|
+
# - *json* (+JSON+) A JSON node representing a taxonomy group
|
33
|
+
def initialize(source)
|
34
|
+
@source = source
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,201 @@
|
|
1
|
+
require 'delivery/query_parameters/parameter_base'
|
2
|
+
|
3
|
+
module Kontent
|
4
|
+
module Ai
|
5
|
+
module Delivery
|
6
|
+
module QueryParameters
|
7
|
+
# Provides the base class for filter implementations.
|
8
|
+
# See https://kontent.ai/learn/reference/delivery-api/#tag/Filtering-content
|
9
|
+
class Filter < ParameterBase
|
10
|
+
# Constructor.
|
11
|
+
#
|
12
|
+
# * *Args*:
|
13
|
+
# - *key* (+string+) The field to filter upon
|
14
|
+
# - *operator* (+string+) The Kontent.ai filter being applied to the field, in brackets
|
15
|
+
# - *values* (+Object+) One or more values which will appear as the value of the query string parameter
|
16
|
+
# - *eq_sign* (+boolean+) If false, the equals sign is not generated in the parameter
|
17
|
+
def initialize(key, operator, values, eq_sign = true)
|
18
|
+
super(key, operator, values, eq_sign)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
# Extend String class to allow semantic typing of filters
|
27
|
+
class String
|
28
|
+
# Represents a filter that matches a content item if the specified content
|
29
|
+
# element or system attribute has a value that contains all the specified
|
30
|
+
# values. This filter is applicable to array values only, such as sitemap
|
31
|
+
# location or value of Linked Items, Taxonomy and Multiple choice content elements.
|
32
|
+
#
|
33
|
+
# * *Args*:
|
34
|
+
# - +Object+ One or more objects representing the values that must appear in the field
|
35
|
+
#
|
36
|
+
# * *Returns*:
|
37
|
+
# - Kontent::Ai::Delivery::QueryParameters::Filter
|
38
|
+
def all(*args)
|
39
|
+
Kontent::Ai::Delivery::QueryParameters::Filter.new(self, '[all]', *args)
|
40
|
+
end
|
41
|
+
|
42
|
+
# Represents a filter that matches a content item if the specified content
|
43
|
+
# element or system attribute has a value that contains any the specified
|
44
|
+
# values. This filter is applicable to array values only, such as sitemap
|
45
|
+
# location or value of Linked Items, Taxonomy and Multiple choice content elements.
|
46
|
+
#
|
47
|
+
# * *Args*:
|
48
|
+
# - +Object+ One or more objects representing the values that may appear in the field
|
49
|
+
#
|
50
|
+
# * *Returns*:
|
51
|
+
# - Kontent::Ai::Delivery::QueryParameters::Filter
|
52
|
+
def any(*args)
|
53
|
+
Kontent::Ai::Delivery::QueryParameters::Filter.new(self, '[any]', *args)
|
54
|
+
end
|
55
|
+
|
56
|
+
# Represents a filter that matches a content item if the specified content element
|
57
|
+
# or system attribute has a value that contains the specified value.
|
58
|
+
# This filter is applicable to array values only, such as sitemap location or value
|
59
|
+
# of Linked Items, Taxonomy and Multiple choice content elements.
|
60
|
+
#
|
61
|
+
# * *Args*:
|
62
|
+
# - +Object+ An object representing the value that must appear in the field
|
63
|
+
#
|
64
|
+
# * *Returns*:
|
65
|
+
# - Kontent::Ai::Delivery::QueryParameters::Filter
|
66
|
+
def contains(*args)
|
67
|
+
Kontent::Ai::Delivery::QueryParameters::Filter.new(self, '[contains]', *args)
|
68
|
+
end
|
69
|
+
|
70
|
+
# Represents a filter that matches a content item if the specified
|
71
|
+
# content element or system attribute has the specified value.
|
72
|
+
#
|
73
|
+
# * *Args*:
|
74
|
+
# - +Object+ An object representing the value that must equal the value in the field
|
75
|
+
#
|
76
|
+
# * *Returns*:
|
77
|
+
# - Kontent::Ai::Delivery::QueryParameters::Filter
|
78
|
+
def eq(*args)
|
79
|
+
Kontent::Ai::Delivery::QueryParameters::Filter.new(self, '', *args)
|
80
|
+
end
|
81
|
+
|
82
|
+
# Represents a filter that matches a content item if the specified
|
83
|
+
# content element or system attribute does not have the specified value.
|
84
|
+
#
|
85
|
+
# * *Args*:
|
86
|
+
# - +Object+ An object representing the value that cannot exist in the element
|
87
|
+
#
|
88
|
+
# * *Returns*:
|
89
|
+
# - Kontent::Ai::Delivery::QueryParameters::Filter
|
90
|
+
def not_eq(*args)
|
91
|
+
Kontent::Ai::Delivery::QueryParameters::Filter.new(self, '[neq]', *args)
|
92
|
+
end
|
93
|
+
|
94
|
+
# Represents a filter that matches a content item if the specified
|
95
|
+
# content element or system attribute does not have any value.
|
96
|
+
#
|
97
|
+
# * *Returns*:
|
98
|
+
# - Kontent::Ai::Delivery::QueryParameters::Filter
|
99
|
+
def empty
|
100
|
+
Kontent::Ai::Delivery::QueryParameters::Filter.new(self, '[empty]', nil, false)
|
101
|
+
end
|
102
|
+
|
103
|
+
# Represents a filter that matches a content item if the specified
|
104
|
+
# content element or system attribute has any value.
|
105
|
+
#
|
106
|
+
# * *Returns*:
|
107
|
+
# - Kontent::Ai::Delivery::QueryParameters::Filter
|
108
|
+
def not_empty
|
109
|
+
Kontent::Ai::Delivery::QueryParameters::Filter.new(self, '[nempty]', nil, false)
|
110
|
+
end
|
111
|
+
|
112
|
+
# Represents a filter that matches a content item if the specified
|
113
|
+
# content element or system attribute does not have the specified value.
|
114
|
+
#
|
115
|
+
# * *Args*:
|
116
|
+
# - +Object+ An object representing the value that cannot exist in the element
|
117
|
+
#
|
118
|
+
# * *Returns*:
|
119
|
+
# - Kontent::Ai::Delivery::QueryParameters::Filter
|
120
|
+
def not_in(*args)
|
121
|
+
Kontent::Ai::Delivery::QueryParameters::Filter.new(self, '[nin]', *args)
|
122
|
+
end
|
123
|
+
|
124
|
+
# Represents a filter that matches a content item if the specified content
|
125
|
+
# element or system attribute has a value that is greater than the
|
126
|
+
# specified value.
|
127
|
+
#
|
128
|
+
# * *Args*:
|
129
|
+
# - +Object+ An object representing the lowest possible value of the field, non-inclusive
|
130
|
+
#
|
131
|
+
# * *Returns*:
|
132
|
+
# - Kontent::Ai::Delivery::QueryParameters::Filter
|
133
|
+
def gt(*args)
|
134
|
+
Kontent::Ai::Delivery::QueryParameters::Filter.new(self, '[gt]', *args)
|
135
|
+
end
|
136
|
+
|
137
|
+
# Represents a filter that matches a content item if the specified content
|
138
|
+
# element or system attribute has a value that is greater than or equal to
|
139
|
+
# the specified value.
|
140
|
+
#
|
141
|
+
# * *Args*:
|
142
|
+
# - +Object+ An object representing the lowest possible value of the field
|
143
|
+
#
|
144
|
+
# * *Returns*:
|
145
|
+
# - Kontent::Ai::Delivery::QueryParameters::Filter
|
146
|
+
def gt_or_eq(*args)
|
147
|
+
Kontent::Ai::Delivery::QueryParameters::Filter.new(self, '[gte]', *args)
|
148
|
+
end
|
149
|
+
|
150
|
+
# Represents a filter that matches a content item if the specified
|
151
|
+
# content element or system attribute has a value that matches a
|
152
|
+
# value in the specified list.
|
153
|
+
#
|
154
|
+
# * *Args*:
|
155
|
+
# - +Object+ One or more objects representing the required values of the field
|
156
|
+
#
|
157
|
+
# * *Returns*:
|
158
|
+
# - Kontent::Ai::Delivery::QueryParameters::Filter
|
159
|
+
def in(*args)
|
160
|
+
Kontent::Ai::Delivery::QueryParameters::Filter.new(self, '[in]', *args)
|
161
|
+
end
|
162
|
+
|
163
|
+
# Represents a filter that matches a content item if the specified content
|
164
|
+
# element or system attribute has a value that is less than the
|
165
|
+
# specified value.
|
166
|
+
#
|
167
|
+
# * *Args*:
|
168
|
+
# - +Object+ An object representing the highest possible value of the field, non-inclusive
|
169
|
+
#
|
170
|
+
# * *Returns*:
|
171
|
+
# - Kontent::Ai::Delivery::QueryParameters::Filter
|
172
|
+
def lt(*args)
|
173
|
+
Kontent::Ai::Delivery::QueryParameters::Filter.new(self, '[lt]', *args)
|
174
|
+
end
|
175
|
+
|
176
|
+
# Represents a filter that matches a content item if the specified content
|
177
|
+
# element or system attribute has a value that is less than or equal to
|
178
|
+
# the specified value.
|
179
|
+
#
|
180
|
+
# * *Args*:
|
181
|
+
# - +Object+ An object representing the highest possible value of the field
|
182
|
+
#
|
183
|
+
# * *Returns*:
|
184
|
+
# - Kontent::Ai::Delivery::QueryParameters::Filter
|
185
|
+
def lt_or_eq(*args)
|
186
|
+
Kontent::Ai::Delivery::QueryParameters::Filter.new(self, '[lte]', *args)
|
187
|
+
end
|
188
|
+
|
189
|
+
# Represents a filter that matches a content item if the specified
|
190
|
+
# content element or system attribute has a value that falls within
|
191
|
+
# the specified range of values (both inclusive).
|
192
|
+
#
|
193
|
+
# * *Args*:
|
194
|
+
# - +Object+ An object representing the lowest and highest possible values of the field
|
195
|
+
#
|
196
|
+
# * *Returns*:
|
197
|
+
# - Kontent::Ai::Delivery::QueryParameters::Filter
|
198
|
+
def range(*args)
|
199
|
+
Kontent::Ai::Delivery::QueryParameters::Filter.new(self, '[range]', *args)
|
200
|
+
end
|
201
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'cgi'
|
2
|
+
|
3
|
+
module Kontent
|
4
|
+
module Ai
|
5
|
+
module Delivery
|
6
|
+
module QueryParameters
|
7
|
+
# Base class for all parameters added to a DeliveryQuery. All
|
8
|
+
# QueryParameters will appear in the query string.
|
9
|
+
class ParameterBase
|
10
|
+
attr_accessor :key
|
11
|
+
SEPARATOR = CGI::escape(',')
|
12
|
+
|
13
|
+
# Constructor.
|
14
|
+
#
|
15
|
+
# * *Args*:
|
16
|
+
# - *key* (+string+) The field to filter upon
|
17
|
+
# - *operator* (+string+) The Kontent.ai filter being applied to the field, in brackets
|
18
|
+
# - *values* (+Object+) One or more values which will appear as the value of the query string parameter
|
19
|
+
# - *eq_sign* (+boolean+) If false, the equals sign is not generated in the parameter
|
20
|
+
def initialize(key, operator, values, eq_sign = true)
|
21
|
+
self.key = key
|
22
|
+
values = [values] unless values.respond_to? :each
|
23
|
+
@values = values
|
24
|
+
@operator = operator
|
25
|
+
@eq_sign = eq_sign
|
26
|
+
end
|
27
|
+
|
28
|
+
# Converts the object into a valid query string parameter for use in
|
29
|
+
# a request to Delivery. The key, operator, and values are all escaped
|
30
|
+
# and if there are multiple values, they are joined with commas.
|
31
|
+
#
|
32
|
+
# * *Returns*:
|
33
|
+
# - +string+ A query string parameter without any additional characters (e.g. '&')
|
34
|
+
def provide_query_string_parameter
|
35
|
+
escaped_values = []
|
36
|
+
@values.each { |n| escaped_values << CGI.escape(n.to_s) }
|
37
|
+
if @eq_sign
|
38
|
+
format(
|
39
|
+
'%<k>s%<o>s=%<v>s',
|
40
|
+
k: CGI.escape(key),
|
41
|
+
o: CGI.escape(@operator),
|
42
|
+
v: escaped_values.join(SEPARATOR)
|
43
|
+
)
|
44
|
+
else
|
45
|
+
format(
|
46
|
+
'%<k>s%<o>s',
|
47
|
+
k: CGI.escape(key),
|
48
|
+
o: CGI.escape(@operator)
|
49
|
+
)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
require 'delivery/query_parameters/parameter_base'
|
2
|
+
|
3
|
+
module Kontent
|
4
|
+
module Ai
|
5
|
+
module Delivery
|
6
|
+
module QueryParameters
|
7
|
+
# Represents the entire query string for a request to Delivery.
|
8
|
+
class QueryString
|
9
|
+
def initialize
|
10
|
+
@params = []
|
11
|
+
end
|
12
|
+
|
13
|
+
# Adds a parameter to the query string
|
14
|
+
#
|
15
|
+
# * *Args*:
|
16
|
+
# - *param* (+Object+) Either a string representing the key for the parameter, or a complete Kontent::Ai::Delivery::QueryParameters::ParameterBase object
|
17
|
+
# - *values* (+string+) A string or array of strings representing the values for the parameter
|
18
|
+
# - *operator* (+string+) Kontent.ai filtering parameter, placed after the key, before the equal sign
|
19
|
+
def set_param(param, values = '', operator = '')
|
20
|
+
parameter_base =
|
21
|
+
if param.is_a? String
|
22
|
+
Kontent::Ai::Delivery::QueryParameters::ParameterBase.new(
|
23
|
+
param,
|
24
|
+
operator,
|
25
|
+
values
|
26
|
+
)
|
27
|
+
else
|
28
|
+
param
|
29
|
+
end
|
30
|
+
# Ensure we have a ParameterBase object
|
31
|
+
return unless parameter_base.respond_to? 'provide_query_string_parameter'
|
32
|
+
|
33
|
+
remove_param parameter_base.key
|
34
|
+
@params << parameter_base
|
35
|
+
end
|
36
|
+
|
37
|
+
# Removes all parameters from the query string with a matching key.
|
38
|
+
#
|
39
|
+
# * *Args*:
|
40
|
+
# - *key* (+string+) Parameter key
|
41
|
+
def remove_param(key)
|
42
|
+
@params.delete_if { |i| i.key.eql? key }
|
43
|
+
end
|
44
|
+
|
45
|
+
# Returns all parameters from the query string with a matching key.
|
46
|
+
#
|
47
|
+
# * *Args*:
|
48
|
+
# - *key* (+string+) Parameter key
|
49
|
+
#
|
50
|
+
# * *Returns*:
|
51
|
+
# - +Object+ One or more Kontent::Ai::Delivery::QueryParameters::ParameterBase objects
|
52
|
+
def param(key)
|
53
|
+
@params.select { |p| p.key.eql? key }
|
54
|
+
end
|
55
|
+
|
56
|
+
# Checks whether there are any parameters defined.
|
57
|
+
#
|
58
|
+
# * *Returns*:
|
59
|
+
# - +bool+ True if there are no parameters set.
|
60
|
+
def empty?
|
61
|
+
@params.empty?
|
62
|
+
end
|
63
|
+
|
64
|
+
# Generates a full query string based on the set parameters, with the
|
65
|
+
# required '?' character at the start. Accomplished by calling the
|
66
|
+
# Kontent::Ai::Delivery::QueryParameters::ParameterBase.provide_query_string_parameter
|
67
|
+
# method for each parameter.
|
68
|
+
#
|
69
|
+
# * *Returns*:
|
70
|
+
# - +string+ A complete query string
|
71
|
+
def to_s
|
72
|
+
'?' + @params.map(&:provide_query_string_parameter).join('&')
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
@@ -0,0 +1,102 @@
|
|
1
|
+
require 'nokogiri'
|
2
|
+
|
3
|
+
module Kontent
|
4
|
+
module Ai
|
5
|
+
module Delivery
|
6
|
+
module Resolvers
|
7
|
+
# Locates <a data-item-id=""> tags in content and calls a user-defined method
|
8
|
+
# to supply the href for content item links.
|
9
|
+
# See https://github.com/kontent-ai/delivery-sdk-ruby#resolving-links
|
10
|
+
class ContentLinkResolver
|
11
|
+
# Constructor.
|
12
|
+
#
|
13
|
+
# * *Args*:
|
14
|
+
# - *found_handler* (+lambda+) _optional_ Method to be called when resolving a content link and the content item is present in the response
|
15
|
+
# - *not_found_handler* (+lambda+) _optional_ Method to be called when resolving a content link and the content item isn't present in the response
|
16
|
+
def initialize(found_handler = nil, not_found_handler = nil)
|
17
|
+
@found_handler = found_handler
|
18
|
+
@not_found = not_found_handler
|
19
|
+
end
|
20
|
+
|
21
|
+
# Resolves all links in the content.
|
22
|
+
#
|
23
|
+
# * *Args*:
|
24
|
+
# - *content* (+string+) The string value stored in the element
|
25
|
+
# - *links* (+Array+) The collection of links from an element's 'links' JSON node
|
26
|
+
#
|
27
|
+
# * *Returns*:
|
28
|
+
# - +string+ The original content passed, with all links resolved
|
29
|
+
def resolve(content, links)
|
30
|
+
doc = Nokogiri::HTML.parse(content).xpath('//body')
|
31
|
+
links = links.map { |link| ContentLink.new link }
|
32
|
+
tags = doc.xpath('//a[@data-item-id]')
|
33
|
+
# This line performs the link resolving and replaces the tags in doc
|
34
|
+
tags.map { |tag| resolve_tag tag, links }
|
35
|
+
doc.to_xhtml
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
# Accepts a tag found in the content and tries to locate matching
|
41
|
+
# source link from JSON response. If found, resolves URL and returns
|
42
|
+
# the tag with generated HREF.
|
43
|
+
#
|
44
|
+
# * *Args*:
|
45
|
+
# - *tag* (+string+) A <a data-item-id=""> tag found in the content
|
46
|
+
# - *links* (+Array+) The collection of links from an element's 'links' JSON node, converted to Kontent::Ai::Delivery::Resolvers::ContentLink objects
|
47
|
+
#
|
48
|
+
# * *Returns*:
|
49
|
+
# - +string+ The <a data-item-id=""> tag with an HREF generated by the +provide_url+ method
|
50
|
+
def resolve_tag(tag, links)
|
51
|
+
matches = links.select { |link| link.id == tag['data-item-id'].to_s }
|
52
|
+
url = provide_url matches, tag['data-item-id']
|
53
|
+
tag['href'] = url
|
54
|
+
tag
|
55
|
+
end
|
56
|
+
|
57
|
+
# Uses the +resolve_link+ method to generate a URL for a ContentLink
|
58
|
+
# object, or +resolve_404+ if the content item was not present in the
|
59
|
+
# response.
|
60
|
+
#
|
61
|
+
# * *Args*:
|
62
|
+
# - *matches* (+Array+) The ContentLink objects with an ID matching a particular <a data-item-id=""> tag
|
63
|
+
# - *id* (+string+) The ID of the <a data-item-id=""> tag being resolved
|
64
|
+
#
|
65
|
+
# * *Returns*:
|
66
|
+
# - +string+ A url to the item or 404 page
|
67
|
+
def provide_url(matches, id)
|
68
|
+
if matches.empty?
|
69
|
+
if @not_found_handler.nil?
|
70
|
+
resolve_404 id
|
71
|
+
else
|
72
|
+
@not_found_handler.call id
|
73
|
+
end
|
74
|
+
else
|
75
|
+
if @found_handler.nil?
|
76
|
+
resolve_link matches[0]
|
77
|
+
else
|
78
|
+
@found_handler.call matches[0]
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
# Model for links from the JSON response
|
85
|
+
class ContentLink
|
86
|
+
attr_accessor :code_name, :type, :url_slug, :id
|
87
|
+
|
88
|
+
# Constructor.
|
89
|
+
#
|
90
|
+
# * *Args*:
|
91
|
+
# - *link* (+JSON+) One link from an element's 'links' JSON node
|
92
|
+
def initialize(link)
|
93
|
+
self.id = link[0]
|
94
|
+
self.code_name = link[1]['codename']
|
95
|
+
self.type = link[1]['type']
|
96
|
+
self.url_slug = link[1]['url_slug']
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
require 'nokogiri'
|
2
|
+
|
3
|
+
module Kontent
|
4
|
+
module Ai
|
5
|
+
module Delivery
|
6
|
+
module Resolvers
|
7
|
+
# Locates <object data-type="item"> tags in content and calls a user-defined
|
8
|
+
# method to supply the output for the content item.
|
9
|
+
# See https://github.com/kontent-ai/delivery-sdk-ruby#resolving-inline-content
|
10
|
+
class InlineContentItemResolver
|
11
|
+
def initialize(callback = nil)
|
12
|
+
@callback = callback
|
13
|
+
end
|
14
|
+
|
15
|
+
# Resolves all inline content items in the content.
|
16
|
+
#
|
17
|
+
# * *Args*:
|
18
|
+
# - *content* (+string+) The string value stored in the element
|
19
|
+
# - *inline_items* (+Array+) ContentItems referenced by the content from the 'modular_content' JSON node
|
20
|
+
#
|
21
|
+
# * *Returns*:
|
22
|
+
# - +string+ The original content passed, with all <object data-type="item"> replaced with custom output
|
23
|
+
def resolve(content, inline_items)
|
24
|
+
doc = Nokogiri::HTML.parse(content).xpath('//body')
|
25
|
+
tags = doc.xpath('//object[@type="application/kenticocloud"][@data-type="item"]')
|
26
|
+
tags.each do |tag|
|
27
|
+
output = resolve_tag tag, inline_items
|
28
|
+
el = doc.at_xpath(
|
29
|
+
'//object[@type="application/kenticocloud"][@data-type="item"][@data-codename=$value]',
|
30
|
+
nil,
|
31
|
+
value: tag['data-codename']
|
32
|
+
)
|
33
|
+
el.swap(output) unless output.nil?
|
34
|
+
end
|
35
|
+
doc.inner_html
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
# Accepts a tag found in the content and tries to locate matching
|
41
|
+
# ContentItem from JSON response.
|
42
|
+
#
|
43
|
+
# * *Args*:
|
44
|
+
# - *tag* (+string+) A <object data-type="item"> tag found in the content
|
45
|
+
# - *inline_items* (+Array+) ContentItems referenced by the content from the 'modular_content' JSON node
|
46
|
+
#
|
47
|
+
# * *Returns*:
|
48
|
+
# - +string+ The custom output generated by the +provide_output+ method
|
49
|
+
def resolve_tag(tag, inline_items)
|
50
|
+
matches = inline_items.select { |item| item.system.codename == tag['data-codename'].to_s }
|
51
|
+
provide_output matches
|
52
|
+
end
|
53
|
+
|
54
|
+
# Generates custom output for a content item using the +resolve_item+
|
55
|
+
# method.
|
56
|
+
#
|
57
|
+
# * *Args*:
|
58
|
+
# - *matches* (+Array+) The ContentItems from the 'modular_content' JSON node which match the code name of a particular <object data-type="item"> tag
|
59
|
+
#
|
60
|
+
# * *Returns*:
|
61
|
+
# - +string+ The custom output generated by the +resolve_item+ method
|
62
|
+
def provide_output(matches)
|
63
|
+
if !matches.empty?
|
64
|
+
if @callback.nil?
|
65
|
+
resolve_item matches[0]
|
66
|
+
else
|
67
|
+
@callback.call matches[0]
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module Kontent
|
2
|
+
module Ai
|
3
|
+
module Delivery
|
4
|
+
module Resolvers
|
5
|
+
# Resolves a content item by its codename. It contains the modular content
|
6
|
+
# of item/items response.
|
7
|
+
class LinkedItemResolver
|
8
|
+
def initialize(modular_content, content_link_url_resolver, inline_content_item_resolver)
|
9
|
+
@modular_content = modular_content
|
10
|
+
@content_link_url_resolver = content_link_url_resolver
|
11
|
+
@inline_content_item_resolver = inline_content_item_resolver
|
12
|
+
@resolved_items = {}
|
13
|
+
end
|
14
|
+
|
15
|
+
# Resolves a content item. If the link for a codename was resolved
|
16
|
+
# before, it returns the same instance of ContentItem.
|
17
|
+
#
|
18
|
+
# * *Args*:
|
19
|
+
# - *codename* (+string+) Codename of the content item
|
20
|
+
#
|
21
|
+
# * *Return*:
|
22
|
+
# - Kontent::Ai::Delivery::ContentItem
|
23
|
+
def resolve(codename)
|
24
|
+
@resolved_items[codename] ||= resolve_item(codename)
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def resolve_item(codename)
|
30
|
+
item = @modular_content.values.find { |i| i['system']['codename'] == codename }
|
31
|
+
unless item.nil?
|
32
|
+
return ContentItem.new(JSON.parse(JSON.generate(item)),
|
33
|
+
@content_link_url_resolver,
|
34
|
+
@inline_content_item_resolver,
|
35
|
+
self)
|
36
|
+
end
|
37
|
+
nil
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'delivery/responses/response_base'
|
2
|
+
|
3
|
+
module Kontent
|
4
|
+
module Ai
|
5
|
+
module Delivery
|
6
|
+
module Responses
|
7
|
+
# The response of a successful query of a content type's element
|
8
|
+
# See https://github.com/kontent-ai/delivery-sdk-ruby#retrieving-content-type-elements
|
9
|
+
class DeliveryElementResponse < ResponseBase
|
10
|
+
# An element's definition from a
|
11
|
+
# Kontent::Ai::Delivery::DeliveryClient.element call
|
12
|
+
#
|
13
|
+
# * *Returns*:
|
14
|
+
# - +OpenStruct+ The element of a content item
|
15
|
+
def element
|
16
|
+
@element unless @element.nil?
|
17
|
+
@element = JSON.parse(
|
18
|
+
JSON.generate(@response),
|
19
|
+
object_class: OpenStruct
|
20
|
+
)
|
21
|
+
end
|
22
|
+
|
23
|
+
def initialize(headers, body)
|
24
|
+
@response = JSON.parse(body)
|
25
|
+
super 200,
|
26
|
+
"Success, '#{element.codename}' returned",
|
27
|
+
headers,
|
28
|
+
JSON.generate(@response)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'delivery/models/content_item'
|
2
|
+
require 'delivery/models/pagination'
|
3
|
+
require 'delivery/responses/response_base'
|
4
|
+
|
5
|
+
module Kontent
|
6
|
+
module Ai
|
7
|
+
module Delivery
|
8
|
+
module Responses
|
9
|
+
# The response of a successful query for content items.
|
10
|
+
# See https://github.com/kontent-ai/delivery-sdk-ruby#listing-items
|
11
|
+
class DeliveryItemListingResponse < ResponseBase
|
12
|
+
# Parses the 'pagination' JSON node of the response.
|
13
|
+
#
|
14
|
+
# * *Returns*:
|
15
|
+
# - Kontent::Ai::Delivery::Pagination
|
16
|
+
def pagination
|
17
|
+
@pagination unless @pagination.nil?
|
18
|
+
@pagination = Pagination.new @response['pagination']
|
19
|
+
end
|
20
|
+
|
21
|
+
# A collection of Kontent::Ai::Delivery::ContentItem objects from
|
22
|
+
# a Kontent::Ai::Delivery::DeliveryClient.items call.
|
23
|
+
#
|
24
|
+
# * *Returns*:
|
25
|
+
# - +Array+ One or more Kontent::Ai::Delivery::ContentItem objects
|
26
|
+
def items
|
27
|
+
@items unless @items.nil?
|
28
|
+
linked_items_resolver = Kontent::Ai::Delivery::Resolvers::LinkedItemResolver.new @response['modular_content'], @content_link_url_resolver, @inline_content_item_resolver
|
29
|
+
items = []
|
30
|
+
@response['items'].each do |n|
|
31
|
+
items << Kontent::Ai::Delivery::ContentItem.new(
|
32
|
+
n,
|
33
|
+
@content_link_url_resolver,
|
34
|
+
@inline_content_item_resolver,
|
35
|
+
linked_items_resolver
|
36
|
+
)
|
37
|
+
end
|
38
|
+
@items = items
|
39
|
+
end
|
40
|
+
|
41
|
+
def initialize(headers, body, query)
|
42
|
+
@response = JSON.parse(body)
|
43
|
+
@content_link_url_resolver = query.content_link_url_resolver
|
44
|
+
@inline_content_item_resolver = query.inline_content_item_resolver
|
45
|
+
super 200,
|
46
|
+
"Success, #{items.length} items returned",
|
47
|
+
headers,
|
48
|
+
JSON.generate(@response)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|