contentful-management 0.0.1.pre

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 (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