contentful-management 0.0.1.pre

Sign up to get free protection for your applications and to get access to all the features.
Files changed (188) hide show
  1. data/.gitignore +24 -0
  2. data/.reek +3 -0
  3. data/.rspec +3 -0
  4. data/.rubocop.yml +16 -0
  5. data/.travis.yml +9 -0
  6. data/CHANGELOG.md +2 -0
  7. data/Gemfile +13 -0
  8. data/LICENSE.txt +22 -0
  9. data/README.md +408 -0
  10. data/Rakefile +37 -0
  11. data/bin/cma-console +8 -0
  12. data/contentful-management.gemspec +33 -0
  13. data/examples/blog.rb +82 -0
  14. data/examples/content_types.rb +45 -0
  15. data/examples/create_space.rb +35 -0
  16. data/lib/contentful/management.rb +12 -0
  17. data/lib/contentful/management/array.rb +35 -0
  18. data/lib/contentful/management/asset.rb +163 -0
  19. data/lib/contentful/management/client.rb +160 -0
  20. data/lib/contentful/management/content_type.rb +180 -0
  21. data/lib/contentful/management/dynamic_entry.rb +71 -0
  22. data/lib/contentful/management/entry.rb +213 -0
  23. data/lib/contentful/management/error.rb +62 -0
  24. data/lib/contentful/management/field.rb +34 -0
  25. data/lib/contentful/management/file.rb +15 -0
  26. data/lib/contentful/management/http_client.rb +22 -0
  27. data/lib/contentful/management/link.rb +23 -0
  28. data/lib/contentful/management/locale.rb +48 -0
  29. data/lib/contentful/management/location.rb +15 -0
  30. data/lib/contentful/management/request.rb +82 -0
  31. data/lib/contentful/management/resource.rb +166 -0
  32. data/lib/contentful/management/resource/array_like.rb +37 -0
  33. data/lib/contentful/management/resource/fields.rb +69 -0
  34. data/lib/contentful/management/resource/refresher.rb +21 -0
  35. data/lib/contentful/management/resource/system_properties.rb +56 -0
  36. data/lib/contentful/management/resource_builder.rb +269 -0
  37. data/lib/contentful/management/response.rb +72 -0
  38. data/lib/contentful/management/space.rb +159 -0
  39. data/lib/contentful/management/support.rb +24 -0
  40. data/lib/contentful/management/version.rb +6 -0
  41. data/spec/fixtures/vcr_cassettes/array_page_1.yml +1337 -0
  42. data/spec/fixtures/vcr_cassettes/asset/all.yml +611 -0
  43. data/spec/fixtures/vcr_cassettes/asset/archive.yml +228 -0
  44. data/spec/fixtures/vcr_cassettes/asset/archive_published.yml +177 -0
  45. data/spec/fixtures/vcr_cassettes/asset/archived_false.yml +228 -0
  46. data/spec/fixtures/vcr_cassettes/asset/archived_true.yml +228 -0
  47. data/spec/fixtures/vcr_cassettes/asset/create.yml +150 -0
  48. data/spec/fixtures/vcr_cassettes/asset/create_with_already_used_id.yml +56 -0
  49. data/spec/fixtures/vcr_cassettes/asset/create_with_custom_id.yml +150 -0
  50. data/spec/fixtures/vcr_cassettes/asset/destroy.yml +159 -0
  51. data/spec/fixtures/vcr_cassettes/asset/destroy_published.yml +175 -0
  52. data/spec/fixtures/vcr_cassettes/asset/find.yml +108 -0
  53. data/spec/fixtures/vcr_cassettes/asset/find_not_found.yml +64 -0
  54. data/spec/fixtures/vcr_cassettes/asset/image_url.yml +133 -0
  55. data/spec/fixtures/vcr_cassettes/asset/locale.yml +110 -0
  56. data/spec/fixtures/vcr_cassettes/asset/publish.yml +228 -0
  57. data/spec/fixtures/vcr_cassettes/asset/publish_already_published.yml +176 -0
  58. data/spec/fixtures/vcr_cassettes/asset/published_false.yml +228 -0
  59. data/spec/fixtures/vcr_cassettes/asset/published_true.yml +226 -0
  60. data/spec/fixtures/vcr_cassettes/asset/save_update.yml +242 -0
  61. data/spec/fixtures/vcr_cassettes/asset/set_locale.yml +110 -0
  62. data/spec/fixtures/vcr_cassettes/asset/unarchive.yml +228 -0
  63. data/spec/fixtures/vcr_cassettes/asset/unarchive_already_unarchive.yml +168 -0
  64. data/spec/fixtures/vcr_cassettes/asset/unarchive_already_unarchived.yml +168 -0
  65. data/spec/fixtures/vcr_cassettes/asset/unpublish.yml +228 -0
  66. data/spec/fixtures/vcr_cassettes/asset/unpublish_already_unpublished.yml +168 -0
  67. data/spec/fixtures/vcr_cassettes/asset/update_file.yml +207 -0
  68. data/spec/fixtures/vcr_cassettes/asset/update_to_specified_locale.yml +224 -0
  69. data/spec/fixtures/vcr_cassettes/asset/update_with_default_locale_without_file.yml +214 -0
  70. data/spec/fixtures/vcr_cassettes/content_type/activate.yml +246 -0
  71. data/spec/fixtures/vcr_cassettes/content_type/activate_with_invalid_version.yml +186 -0
  72. data/spec/fixtures/vcr_cassettes/content_type/activated_false.yml +246 -0
  73. data/spec/fixtures/vcr_cassettes/content_type/activated_true.yml +257 -0
  74. data/spec/fixtures/vcr_cassettes/content_type/all.yml +190 -0
  75. data/spec/fixtures/vcr_cassettes/content_type/create.yml +87 -0
  76. data/spec/fixtures/vcr_cassettes/content_type/create_content_type_with_id.yml +87 -0
  77. data/spec/fixtures/vcr_cassettes/content_type/create_with_Array_field.yml +94 -0
  78. data/spec/fixtures/vcr_cassettes/content_type/create_with_Boolean_field.yml +94 -0
  79. data/spec/fixtures/vcr_cassettes/content_type/create_with_Date_field.yml +94 -0
  80. data/spec/fixtures/vcr_cassettes/content_type/create_with_Integer_field.yml +94 -0
  81. data/spec/fixtures/vcr_cassettes/content_type/create_with_Link_field.yml +95 -0
  82. data/spec/fixtures/vcr_cassettes/content_type/create_with_Location_field.yml +94 -0
  83. data/spec/fixtures/vcr_cassettes/content_type/create_with_Number_field.yml +94 -0
  84. data/spec/fixtures/vcr_cassettes/content_type/create_with_Object_field.yml +94 -0
  85. data/spec/fixtures/vcr_cassettes/content_type/create_with_Symbol_field.yml +94 -0
  86. data/spec/fixtures/vcr_cassettes/content_type/create_with_Text_field.yml +94 -0
  87. data/spec/fixtures/vcr_cassettes/content_type/deactivate.yml +246 -0
  88. data/spec/fixtures/vcr_cassettes/content_type/deactivate_already_deactivated.yml +176 -0
  89. data/spec/fixtures/vcr_cassettes/content_type/deactivate_with_entries.yml +236 -0
  90. data/spec/fixtures/vcr_cassettes/content_type/deactivate_with_version_change.yml +248 -0
  91. data/spec/fixtures/vcr_cassettes/content_type/destroy.yml +148 -0
  92. data/spec/fixtures/vcr_cassettes/content_type/destroy_activated.yml +164 -0
  93. data/spec/fixtures/vcr_cassettes/content_type/entry/create.yml +1344 -0
  94. data/spec/fixtures/vcr_cassettes/content_type/entry/create_with_camel_case_id_to_multiple_locales.yml +235 -0
  95. data/spec/fixtures/vcr_cassettes/content_type/entry/create_with_entries.yml +398 -0
  96. data/spec/fixtures/vcr_cassettes/content_type/entry/create_with_entries_for_multiple_locales.yml +3157 -0
  97. data/spec/fixtures/vcr_cassettes/content_type/entry/create_with_multiple_locales.yml +230 -0
  98. data/spec/fixtures/vcr_cassettes/content_type/fields/add.yml +345 -0
  99. data/spec/fixtures/vcr_cassettes/content_type/fields/create.yml +353 -0
  100. data/spec/fixtures/vcr_cassettes/content_type/fields/create_array_with_params.yml +228 -0
  101. data/spec/fixtures/vcr_cassettes/content_type/fields/create_with_params.yml +221 -0
  102. data/spec/fixtures/vcr_cassettes/content_type/fields/destroy.yml +349 -0
  103. data/spec/fixtures/vcr_cassettes/content_type/fields/update_field.yml +358 -0
  104. data/spec/fixtures/vcr_cassettes/content_type/find.yml +180 -0
  105. data/spec/fixtures/vcr_cassettes/content_type/find_not_found.yml +64 -0
  106. data/spec/fixtures/vcr_cassettes/content_type/save_new.yml +876 -0
  107. data/spec/fixtures/vcr_cassettes/content_type/save_updated.yml +345 -0
  108. data/spec/fixtures/vcr_cassettes/content_type/save_with_added_field.yml +217 -0
  109. data/spec/fixtures/vcr_cassettes/content_type/update.yml +175 -0
  110. data/spec/fixtures/vcr_cassettes/content_type/update_change_field_name.yml +222 -0
  111. data/spec/fixtures/vcr_cassettes/content_type/update_remove_field.yml +231 -0
  112. data/spec/fixtures/vcr_cassettes/content_type/update_with_fields.yml +222 -0
  113. data/spec/fixtures/vcr_cassettes/content_type/update_with_one_new_field.yml +251 -0
  114. data/spec/fixtures/vcr_cassettes/entry/all.yml +139 -0
  115. data/spec/fixtures/vcr_cassettes/entry/archive.yml +222 -0
  116. data/spec/fixtures/vcr_cassettes/entry/archive_published.yml +187 -0
  117. data/spec/fixtures/vcr_cassettes/entry/archived_false.yml +178 -0
  118. data/spec/fixtures/vcr_cassettes/entry/archived_true.yml +248 -0
  119. data/spec/fixtures/vcr_cassettes/entry/create.yml +245 -0
  120. data/spec/fixtures/vcr_cassettes/entry/create_test.yml +150 -0
  121. data/spec/fixtures/vcr_cassettes/entry/create_with_asset.yml +403 -0
  122. data/spec/fixtures/vcr_cassettes/entry/create_with_assets.yml +419 -0
  123. data/spec/fixtures/vcr_cassettes/entry/create_with_entries.yml +418 -0
  124. data/spec/fixtures/vcr_cassettes/entry/create_with_entry.yml +493 -0
  125. data/spec/fixtures/vcr_cassettes/entry/create_with_location.yml +259 -0
  126. data/spec/fixtures/vcr_cassettes/entry/create_with_symbols.yml +271 -0
  127. data/spec/fixtures/vcr_cassettes/entry/destory_published.yml +172 -0
  128. data/spec/fixtures/vcr_cassettes/entry/destroy.yml +156 -0
  129. data/spec/fixtures/vcr_cassettes/entry/find.yml +129 -0
  130. data/spec/fixtures/vcr_cassettes/entry/find_not_found.yml +64 -0
  131. data/spec/fixtures/vcr_cassettes/entry/publish.yml +248 -0
  132. data/spec/fixtures/vcr_cassettes/entry/publish_already_published.yml +186 -0
  133. data/spec/fixtures/vcr_cassettes/entry/published_false.yml +248 -0
  134. data/spec/fixtures/vcr_cassettes/entry/published_true.yml +257 -0
  135. data/spec/fixtures/vcr_cassettes/entry/save_update.yml +211 -0
  136. data/spec/fixtures/vcr_cassettes/entry/unarchive.yml +248 -0
  137. data/spec/fixtures/vcr_cassettes/entry/unarchive_already_unarchived.yml +178 -0
  138. data/spec/fixtures/vcr_cassettes/entry/unpublish.yml +248 -0
  139. data/spec/fixtures/vcr_cassettes/entry/unpublish_already_unpublished.yml +178 -0
  140. data/spec/fixtures/vcr_cassettes/entry/update.yml +626 -0
  141. data/spec/fixtures/vcr_cassettes/entry/update_unlocalized_field.yml +308 -0
  142. data/spec/fixtures/vcr_cassettes/entry/update_with_custom_locale.yml +332 -0
  143. data/spec/fixtures/vcr_cassettes/get_request.yml +37 -0
  144. data/spec/fixtures/vcr_cassettes/locale/all_for_space.yml +321 -0
  145. data/spec/fixtures/vcr_cassettes/locale/create_for_space.yml +95 -0
  146. data/spec/fixtures/vcr_cassettes/locale/find.yml +95 -0
  147. data/spec/fixtures/vcr_cassettes/locale/find_for_space_not_found.yml +67 -0
  148. data/spec/fixtures/vcr_cassettes/space/all.yml +1201 -0
  149. data/spec/fixtures/vcr_cassettes/space/asset/all.yml +475 -0
  150. data/spec/fixtures/vcr_cassettes/space/asset/assets.yml +826 -0
  151. data/spec/fixtures/vcr_cassettes/space/asset/create.yml +508 -0
  152. data/spec/fixtures/vcr_cassettes/space/asset/create_with_multiple_locales.yml +1062 -0
  153. data/spec/fixtures/vcr_cassettes/space/asset/find.yml +634 -0
  154. data/spec/fixtures/vcr_cassettes/space/content_type/all.yml +470 -0
  155. data/spec/fixtures/vcr_cassettes/space/content_type/content_types.yml +341 -0
  156. data/spec/fixtures/vcr_cassettes/space/content_type/create.yml +425 -0
  157. data/spec/fixtures/vcr_cassettes/space/content_type/find.yml +493 -0
  158. data/spec/fixtures/vcr_cassettes/space/create.yml +85 -0
  159. data/spec/fixtures/vcr_cassettes/space/create_when_limit_has_been_reached.yml +67 -0
  160. data/spec/fixtures/vcr_cassettes/space/create_with_unknown_organization.yml +65 -0
  161. data/spec/fixtures/vcr_cassettes/space/create_without_organization.yml +83 -0
  162. data/spec/fixtures/vcr_cassettes/space/destory.yml +196 -0
  163. data/spec/fixtures/vcr_cassettes/space/entry/all.yml +634 -0
  164. data/spec/fixtures/vcr_cassettes/space/entry/entries.yml +498 -0
  165. data/spec/fixtures/vcr_cassettes/space/entry/find.yml +624 -0
  166. data/spec/fixtures/vcr_cassettes/space/find.yml +270 -0
  167. data/spec/fixtures/vcr_cassettes/space/find_not_found.yml +67 -0
  168. data/spec/fixtures/vcr_cassettes/space/locale/all.yml +690 -0
  169. data/spec/fixtures/vcr_cassettes/space/locale/create.yml +572 -0
  170. data/spec/fixtures/vcr_cassettes/space/locale/create_with_the_same_code.yml +585 -0
  171. data/spec/fixtures/vcr_cassettes/space/locale/find.yml +572 -0
  172. data/spec/fixtures/vcr_cassettes/space/locale/find_not_found.yml +580 -0
  173. data/spec/fixtures/vcr_cassettes/space/locale/locales.yml +480 -0
  174. data/spec/fixtures/vcr_cassettes/space/locale/update.yml +700 -0
  175. data/spec/fixtures/vcr_cassettes/space/save_new_space.yml +67 -0
  176. data/spec/fixtures/vcr_cassettes/space/save_update_space.yml +352 -0
  177. data/spec/fixtures/vcr_cassettes/space/update.yml +350 -0
  178. data/spec/fixtures/vcr_cassettes/space/update_with_the_same_data.yml +350 -0
  179. data/spec/lib/contentful/management/array_spec.rb +59 -0
  180. data/spec/lib/contentful/management/asset_spec.rb +321 -0
  181. data/spec/lib/contentful/management/client_spec.rb +80 -0
  182. data/spec/lib/contentful/management/content_type_spec.rb +455 -0
  183. data/spec/lib/contentful/management/entry_spec.rb +308 -0
  184. data/spec/lib/contentful/management/locale_spec.rb +53 -0
  185. data/spec/lib/contentful/management/space_spec.rb +317 -0
  186. data/spec/spec_helper.rb +10 -0
  187. data/spec/support/vcr.rb +17 -0
  188. metadata +554 -0
@@ -0,0 +1,37 @@
1
+ # -*- encoding: utf-8 -*-
2
+ module Contentful
3
+ module Management
4
+ module Resource
5
+ # Useful methods for array-like resources that can be included if an
6
+ # :items property exists
7
+ module ArrayLike
8
+ include Enumerable
9
+
10
+ # Returns true for array-like resources
11
+ def array?
12
+ true
13
+ end
14
+
15
+ # Delegates to items#each
16
+ def each_item(&block)
17
+ items.each(&block)
18
+ end
19
+
20
+ alias each each_item
21
+
22
+ # Delegates to items#empty?
23
+ def empty?
24
+ items.empty?
25
+ end
26
+
27
+ # Delegetes to items#size
28
+ def size
29
+ items.size
30
+ end
31
+
32
+ alias length size
33
+
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,69 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require_relative '../file'
3
+
4
+ module Contentful
5
+ module Management
6
+ module Resource
7
+ module Fields
8
+
9
+ def fields(wanted_locale = default_locale)
10
+ requested_locale = locale || wanted_locale
11
+ @fields[requested_locale] = {} unless @fields[requested_locale]
12
+ @fields[requested_locale]
13
+ end
14
+
15
+ def initialize(object = nil, *)
16
+ super
17
+ @fields = {}
18
+ extract_fields_from_object! object if object
19
+ end
20
+
21
+ def inspect(info = nil)
22
+ if fields.empty?
23
+ super(info)
24
+ else
25
+ super("#{ info } @fields=#{ fields.inspect }")
26
+ end
27
+ end
28
+
29
+ def self.included(base)
30
+ base.fields_coercions.keys.each { |name|
31
+ accessor_name = Contentful::Management::Support.snakify(name)
32
+ base.send :define_method, accessor_name do
33
+ fields[name.to_sym]
34
+ end
35
+ base.send :define_method, "#{ accessor_name }_with_locales" do
36
+ fields_for_query[name.to_sym]
37
+ end
38
+ base.send :define_method, "#{ accessor_name }=" do |value|
39
+ fields[name.to_sym] = value
40
+ end
41
+ base.send :define_method, "#{ accessor_name }_with_locales=" do |values|
42
+ values.each do |locale, value|
43
+ @fields[locale] = {} if @fields[locale].nil?
44
+ @fields[locale][name.to_sym] = value
45
+ end
46
+ end
47
+ }
48
+ end
49
+
50
+ private
51
+
52
+ def extract_fields_from_object!(object)
53
+ if nested_locale_fields? && !object['fields'].nil?
54
+ object['fields'].each do |field_name, nested_child_object|
55
+ nested_child_object.each do |object_locale, real_child_object|
56
+ @fields[object_locale] ||= {}
57
+ @fields[object_locale].merge! extract_from_object(
58
+ { field_name => real_child_object }, :fields
59
+ )
60
+ end
61
+ end
62
+ else
63
+ @fields[locale || default_locale] = extract_from_object object['fields'], :fields
64
+ end
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,21 @@
1
+ # -*- encoding: utf-8 -*-
2
+ module Contentful
3
+ module Management
4
+ module Resource
5
+ # Adds the feature to have properties and system data reload for Resource.
6
+ module Refresher
7
+
8
+ def refresh_data(resource)
9
+ if resource.is_a? Error
10
+ resource
11
+ else
12
+ @properties = resource.instance_variable_get(:@properties)
13
+ @fields = resource.instance_variable_get(:@fields) if self.is_a?(Contentful::Management::Entry)
14
+ @sys = resource.instance_variable_get(:@sys)
15
+ self
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,56 @@
1
+ # -*- encoding: utf-8 -*-
2
+ module Contentful
3
+ module Management
4
+ module Resource
5
+ # Adds the feature to have system properties to a Resource.
6
+ module SystemProperties
7
+ SYS_COERCIONS = {
8
+ type: :string,
9
+ id: :string,
10
+ space: nil,
11
+ contentType: nil,
12
+ linkType: :string,
13
+ revision: :integer,
14
+ createdAt: :date,
15
+ updatedAt: :date,
16
+ locale: :string
17
+ }
18
+ attr_reader :sys
19
+
20
+ def initialize(object = { 'sys' => nil }, *)
21
+ super
22
+ object ||= { 'sys' => nil }
23
+ @sys = extract_from_object object['sys'], :sys
24
+ end
25
+
26
+ def inspect(info = nil)
27
+ if sys.empty?
28
+ super(info)
29
+ else
30
+ super("#{ info } @sys=#{ sys.inspect }")
31
+ end
32
+ end
33
+
34
+ module ClassMethods
35
+ def sys_coercions
36
+ SYS_COERCIONS
37
+ end
38
+ end
39
+
40
+ def self.included(base)
41
+ base.extend(ClassMethods)
42
+
43
+ base.sys_coercions.keys.each { |name|
44
+ accessor_name = Contentful::Management::Support.snakify(name)
45
+ base.send :define_method, accessor_name do
46
+ sys[name.to_sym]
47
+ end
48
+ base.send :define_method, "#{ accessor_name }=" do |value|
49
+ sys[name.to_sym] = value
50
+ end
51
+ }
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,269 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require_relative 'error'
3
+ require_relative 'resource'
4
+ require_relative 'entry'
5
+ require_relative 'dynamic_entry'
6
+ require_relative 'array'
7
+ require_relative 'link'
8
+ require_relative 'space'
9
+ require_relative 'content_type'
10
+ require_relative 'asset'
11
+
12
+ module Contentful
13
+ module Management
14
+ # Transforms a Contentful::Response into a Contentful::Resource or a Contentful::Error
15
+ # See example/resource_mapping.rb for avanced usage
16
+ class ResourceBuilder
17
+ DEFAULT_RESOURCE_MAPPING = {
18
+ 'Space' => Contentful::Management::Space,
19
+ 'ContentType' => Contentful::Management::ContentType,
20
+ 'Entry' => :find_entry_class,
21
+ 'Asset' => Contentful::Management::Asset,
22
+ 'Array' => :array_or_sync_page,
23
+ 'Link' => Contentful::Management::Link
24
+ }
25
+ DEFAULT_ENTRY_MAPPING = {}
26
+
27
+ attr_reader :client, :response, :resource_mapping, :entry_mapping, :resource
28
+
29
+
30
+ def initialize(client, response, resource_mapping = {}, entry_mapping = {})
31
+ @response = response
32
+ @client = client
33
+ @included_resources = {}
34
+ @known_resources = Hash.new { |h, k| h[k] = {} }
35
+ @nested_locales = true
36
+ @default_locale = (Contentful::Management::Client.shared_instance.configuration || Contentful::Client::DEFAULT_CONFIGURATION)[:default_locale]
37
+ @resource_mapping = default_resource_mapping.merge(resource_mapping)
38
+ @entry_mapping = default_entry_mapping.merge(entry_mapping)
39
+ end
40
+
41
+ # Starts the parsing process.
42
+ # Either returns an Error, or the parsed Resource
43
+ def run
44
+ case response.status
45
+ when :contentful_error
46
+ Error[response.raw.status].new(response)
47
+ when :unparsable_json
48
+ UnparsableJson.new(response)
49
+ when :not_contentful
50
+ Error.new(response)
51
+ else
52
+ begin
53
+ create_all_resources!
54
+ rescue UnparsableResource => error
55
+ error
56
+ end
57
+ end
58
+ end
59
+
60
+ # PARSING MECHANISM
61
+ # - raise error if response not valid
62
+ # - look for included objects and parse them to resources
63
+ # - parse main object to resource
64
+ # - replace links in included resources with known resources
65
+ # - replace links in main resource with known resources
66
+ # - return main resource
67
+ def create_all_resources!
68
+ create_included_resources! response.object['includes']
69
+ @resource = create_resource(response.object)
70
+
71
+ unless @included_resources.empty?
72
+ replace_links_in_included_resources_with_known_resources
73
+ replace_links_with_known_resources @resource
74
+ end
75
+
76
+ @resource
77
+ end
78
+
79
+ # Creates a single resource from the response object
80
+ def create_resource(object)
81
+ res_class = detect_resource_class(object)
82
+ @nested_locales ||= res_class.nested_locale_fields?
83
+ res = res_class.new(object, response.request, client, @nested_locales, @default_locale)
84
+
85
+ add_to_known_resources res
86
+ replace_children res, object
87
+ replace_child_array res.items if res.array?
88
+
89
+ res
90
+ end
91
+
92
+ # Checks in a custom class for an entry was defined in entry_mapping
93
+ def find_entry_class(object)
94
+ entry_mapping[content_type_id_for_entry(object)] || try_dynamic_entry(object)
95
+ end
96
+
97
+ # Automatically converts Entry to DynamicEntry if in cache
98
+ def try_dynamic_entry(object)
99
+ get_dynamic_entry(object) || Contentful::Management::Entry
100
+ end
101
+
102
+ # Finds the proper DynamicEntry class for an entry
103
+ def get_dynamic_entry(object)
104
+ if content_id = content_type_id_for_entry(object)
105
+ client.dynamic_entry_cache[content_id.to_sym]
106
+ end
107
+ end
108
+
109
+ # Returns the id of the related ContentType, if there is one
110
+ def content_type_id_for_entry(object)
111
+ object['sys'] &&
112
+ object['sys']['contentType'] &&
113
+ object['sys']['contentType']['sys'] &&
114
+ object['sys']['contentType']['sys']['id']
115
+ end
116
+
117
+ # Detects if a resource is an Contentful::Array or a SyncPage
118
+ def array_or_sync_page(object)
119
+ if object['nextPageUrl'] || object['nextSyncUrl']
120
+ SyncPage
121
+ else
122
+ Array
123
+ end
124
+ end
125
+
126
+ # Uses the resource mapping to find the proper Resource class to initialize
127
+ # for this Response object type
128
+ #
129
+ # The mapping value can be a
130
+ # - Class
131
+ # - Proc: Will be called, expected to return the proper Class
132
+ # - Symbol: Will be called as method of the ResourceBuilder itself
133
+ def detect_resource_class(object)
134
+ type = object['sys'] && object['sys']['type']
135
+
136
+ case res_class = resource_mapping[type]
137
+ when Symbol
138
+ public_send(res_class, object)
139
+ when Proc
140
+ res_class[object]
141
+ when nil
142
+ raise UnparsableResource.new(response)
143
+ else
144
+ res_class
145
+ end
146
+ end
147
+
148
+ # The default mapping for #detect_resource_class
149
+ def default_resource_mapping
150
+ DEFAULT_RESOURCE_MAPPING.dup
151
+ end
152
+
153
+ # The default entry mapping
154
+ def default_entry_mapping
155
+ DEFAULT_ENTRY_MAPPING.dup
156
+ end
157
+
158
+
159
+ private
160
+
161
+ def detect_child_objects(object)
162
+ if object.is_a? Hash
163
+ object.select { |_, v| v.is_a?(Hash) && v.key?('sys') }
164
+ else
165
+ {}
166
+ end
167
+ end
168
+
169
+ def detect_child_arrays(object)
170
+ if object.is_a? Hash
171
+ object.select do |_, v|
172
+ v.is_a?(::Array) &&
173
+ v.first &&
174
+ v.first.is_a?(Hash) &&
175
+ v.first.key?('sys')
176
+ end
177
+ else
178
+ {}
179
+ end
180
+ end
181
+
182
+ def add_to_known_resources(res)
183
+ @known_resources[res.type][res.id] = res if res.sys && res.id && res.type != 'Link'
184
+ end
185
+
186
+ def replace_children(res, object)
187
+ object.each do |name, potential_objects|
188
+ detect_child_objects(potential_objects).each do |child_name, child_object|
189
+ res.public_send(name)[child_name.to_sym] = create_resource(child_object)
190
+ end
191
+ next if name == 'includes'
192
+ detect_child_arrays(potential_objects).each do |child_name, _child_array|
193
+ replace_child_array res.public_send(name)[child_name.to_sym]
194
+ end
195
+ end
196
+ end
197
+
198
+ def replace_child_array(child_array)
199
+ child_array.map! { |resource_object| create_resource(resource_object) }
200
+ end
201
+
202
+ def create_included_resources!(included_objects)
203
+ if included_objects
204
+ included_objects.each do |type, objects|
205
+ @included_resources[type] = Hash[
206
+ objects.map do |object|
207
+ res = create_resource(object)
208
+ [res.id, res]
209
+ end
210
+ ]
211
+ end
212
+ end
213
+ end
214
+
215
+ def replace_links_with_known_resources(res, seen_resource_ids = [])
216
+ seen_resource_ids << res.id
217
+
218
+ [:properties, :sys, :fields].map do |property_container_name|
219
+ res.public_send(property_container_name)
220
+ end.compact.each do |property_container|
221
+ replace_links_in_properties(property_container, seen_resource_ids)
222
+ end
223
+
224
+ if res.array?
225
+ replace_links_in_array res.items, seen_resource_ids
226
+ end
227
+ end
228
+
229
+ def replace_links_in_properties(property_container, seen_resource_ids)
230
+ property_container.each do |property_name, property_value|
231
+ if property_value.is_a? ::Array
232
+ replace_links_in_array property_value, seen_resource_ids
233
+ else
234
+ replace_link_or_check_recursively property_value, property_container, property_name, seen_resource_ids
235
+ end
236
+ end
237
+ end
238
+
239
+ def replace_links_in_array(property_container, seen_resource_ids)
240
+ property_container.each.with_index do |child_property, property_index|
241
+ replace_link_or_check_recursively child_property, property_container, property_index, seen_resource_ids
242
+ end
243
+ end
244
+
245
+ def replace_link_or_check_recursively(property_value, property_container, property_name, seen_resource_ids)
246
+ if property_value.is_a? Link
247
+ maybe_replace_link(property_value, property_container, property_name)
248
+ elsif property_value.is_a?(Resource) && property_value.sys && !seen_resource_ids.include?(property_value.id)
249
+ replace_links_with_known_resources(property_value, seen_resource_ids)
250
+ end
251
+ end
252
+
253
+ def maybe_replace_link(link, parent, key)
254
+ if @known_resources[link.link_type] &&
255
+ @known_resources[link.link_type].key?(link.id)
256
+ parent[key] = @known_resources[link.link_type][link.id]
257
+ end
258
+ end
259
+
260
+ def replace_links_in_included_resources_with_known_resources
261
+ @included_resources.each do |_, for_type|
262
+ for_type.each do |_, res|
263
+ replace_links_with_known_resources(res)
264
+ end
265
+ end
266
+ end
267
+ end
268
+ end
269
+ end