locomotivecms_mounter 1.0.0.alpha1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (71) hide show
  1. data/lib/locomotive/mounter/config.rb +21 -0
  2. data/lib/locomotive/mounter/engine_api.rb +40 -0
  3. data/lib/locomotive/mounter/exceptions.rb +38 -0
  4. data/lib/locomotive/mounter/extensions/compass.rb +36 -0
  5. data/lib/locomotive/mounter/extensions/httmultiparty.rb +22 -0
  6. data/lib/locomotive/mounter/extensions/tilt/css.rb +31 -0
  7. data/lib/locomotive/mounter/extensions/tilt/haml.rb +27 -0
  8. data/lib/locomotive/mounter/extensions/tilt/liquid.rb +23 -0
  9. data/lib/locomotive/mounter/extensions/tilt/template.rb +11 -0
  10. data/lib/locomotive/mounter/fields.rb +250 -0
  11. data/lib/locomotive/mounter/models/base.rb +41 -0
  12. data/lib/locomotive/mounter/models/content_asset.rb +84 -0
  13. data/lib/locomotive/mounter/models/content_entry.rb +290 -0
  14. data/lib/locomotive/mounter/models/content_field.rb +128 -0
  15. data/lib/locomotive/mounter/models/content_select_option.rb +29 -0
  16. data/lib/locomotive/mounter/models/content_type.rb +217 -0
  17. data/lib/locomotive/mounter/models/editable_element.rb +27 -0
  18. data/lib/locomotive/mounter/models/page.rb +377 -0
  19. data/lib/locomotive/mounter/models/site.rb +27 -0
  20. data/lib/locomotive/mounter/models/snippet.rb +55 -0
  21. data/lib/locomotive/mounter/models/theme_asset.rb +135 -0
  22. data/lib/locomotive/mounter/models/translation.rb +28 -0
  23. data/lib/locomotive/mounter/mounting_point.rb +49 -0
  24. data/lib/locomotive/mounter/reader/api/base.rb +49 -0
  25. data/lib/locomotive/mounter/reader/api/content_assets_reader.rb +40 -0
  26. data/lib/locomotive/mounter/reader/api/content_entries_reader.rb +141 -0
  27. data/lib/locomotive/mounter/reader/api/content_types_reader.rb +74 -0
  28. data/lib/locomotive/mounter/reader/api/pages_reader.rb +174 -0
  29. data/lib/locomotive/mounter/reader/api/site_reader.rb +37 -0
  30. data/lib/locomotive/mounter/reader/api/snippets_reader.rb +59 -0
  31. data/lib/locomotive/mounter/reader/api/theme_assets_reader.rb +42 -0
  32. data/lib/locomotive/mounter/reader/api/translations_reader.rb +28 -0
  33. data/lib/locomotive/mounter/reader/api.rb +49 -0
  34. data/lib/locomotive/mounter/reader/file_system/base.rb +65 -0
  35. data/lib/locomotive/mounter/reader/file_system/content_assets_reader.rb +88 -0
  36. data/lib/locomotive/mounter/reader/file_system/content_entries_reader.rb +101 -0
  37. data/lib/locomotive/mounter/reader/file_system/content_types_reader.rb +88 -0
  38. data/lib/locomotive/mounter/reader/file_system/pages_reader.rb +206 -0
  39. data/lib/locomotive/mounter/reader/file_system/site_reader.rb +24 -0
  40. data/lib/locomotive/mounter/reader/file_system/snippets_reader.rb +78 -0
  41. data/lib/locomotive/mounter/reader/file_system/theme_assets_reader.rb +78 -0
  42. data/lib/locomotive/mounter/reader/file_system/translations_reader.rb +36 -0
  43. data/lib/locomotive/mounter/reader/file_system.rb +42 -0
  44. data/lib/locomotive/mounter/reader/runner.rb +89 -0
  45. data/lib/locomotive/mounter/utils/hash.rb +31 -0
  46. data/lib/locomotive/mounter/utils/string.rb +17 -0
  47. data/lib/locomotive/mounter/utils/yaml.rb +125 -0
  48. data/lib/locomotive/mounter/version.rb +8 -0
  49. data/lib/locomotive/mounter/writer/api/base.rb +323 -0
  50. data/lib/locomotive/mounter/writer/api/content_assets_writer.rb +74 -0
  51. data/lib/locomotive/mounter/writer/api/content_entries_writer.rb +223 -0
  52. data/lib/locomotive/mounter/writer/api/content_types_writer.rb +151 -0
  53. data/lib/locomotive/mounter/writer/api/pages_writer.rb +225 -0
  54. data/lib/locomotive/mounter/writer/api/site_writer.rb +164 -0
  55. data/lib/locomotive/mounter/writer/api/snippets_writer.rb +111 -0
  56. data/lib/locomotive/mounter/writer/api/theme_assets_writer.rb +152 -0
  57. data/lib/locomotive/mounter/writer/api/translations_writer.rb +83 -0
  58. data/lib/locomotive/mounter/writer/api.rb +62 -0
  59. data/lib/locomotive/mounter/writer/file_system/base.rb +61 -0
  60. data/lib/locomotive/mounter/writer/file_system/content_assets_writer.rb +33 -0
  61. data/lib/locomotive/mounter/writer/file_system/content_entries_writer.rb +29 -0
  62. data/lib/locomotive/mounter/writer/file_system/content_types_writer.rb +27 -0
  63. data/lib/locomotive/mounter/writer/file_system/pages_writer.rb +73 -0
  64. data/lib/locomotive/mounter/writer/file_system/site_writer.rb +25 -0
  65. data/lib/locomotive/mounter/writer/file_system/snippets_writer.rb +54 -0
  66. data/lib/locomotive/mounter/writer/file_system/theme_assets_writer.rb +35 -0
  67. data/lib/locomotive/mounter/writer/file_system/translations_writer.rb +22 -0
  68. data/lib/locomotive/mounter/writer/file_system.rb +69 -0
  69. data/lib/locomotive/mounter/writer/runner.rb +68 -0
  70. data/lib/locomotive/mounter.rb +97 -0
  71. metadata +487 -0
@@ -0,0 +1,49 @@
1
+ module Locomotive
2
+ module Mounter
3
+ module Reader
4
+ module Api
5
+
6
+ class Base
7
+
8
+ attr_accessor :runner, :items
9
+
10
+ def initialize(runner)
11
+ self.runner = runner
12
+ self.items = {}
13
+ end
14
+
15
+ def mounting_point
16
+ self.runner.mounting_point
17
+ end
18
+
19
+ def locales
20
+ self.mounting_point.locales
21
+ end
22
+
23
+ def get(resource_name, locale = nil, raw = false)
24
+ params = { query: {} }
25
+
26
+ params[:query][:locale] = locale if locale
27
+
28
+ response = Locomotive::Mounter::EngineApi.get("/#{resource_name}.json", params).parsed_response
29
+
30
+ return response if raw
31
+
32
+ case response
33
+ when Hash then response.to_hash.delete_if { |k, _| !self.safe_attributes.include?(k) }
34
+ when Array
35
+ response.map do |row|
36
+ # puts "#{row.inspect}\n---" # DEBUG
37
+ row.delete_if { |k, _| !self.safe_attributes.include?(k) }
38
+ end
39
+ else
40
+ response
41
+ end
42
+ end
43
+
44
+ end
45
+
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,40 @@
1
+ module Locomotive
2
+ module Mounter
3
+ module Reader
4
+ module Api
5
+
6
+ class ContentAssetsReader < Base
7
+
8
+ # Build the list of theme assets from the public folder with eager loading.
9
+ #
10
+ # @return [ Array ] The cached list of theme assets
11
+ #
12
+ def read
13
+ base_uri = self.runner.uri.split('/').first
14
+ base_uri = "http://#{base_uri}" unless base_uri =~ /^http:\/\//
15
+
16
+ self.get(:content_assets).each do |attributes|
17
+ url = attributes.delete('url')
18
+
19
+ attributes['folder'] = 'samples/assets'
20
+ attributes['uri'] = URI(url =~ /http:\/\// ? url : "#{base_uri}#{url}")
21
+
22
+ self.items[url] = Locomotive::Mounter::Models::ContentAsset.new(attributes)
23
+ end
24
+
25
+ self.items
26
+ end
27
+
28
+ protected
29
+
30
+ def safe_attributes
31
+ %w(_id url)
32
+ end
33
+
34
+ end
35
+
36
+ end
37
+
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,141 @@
1
+ module Locomotive
2
+ module Mounter
3
+ module Reader
4
+ module Api
5
+
6
+ class ContentEntriesReader < Base
7
+
8
+ attr_accessor :ids, :relationships
9
+
10
+ def initialize(runner)
11
+ self.ids, self.relationships = {}, []
12
+ super
13
+ end
14
+
15
+ # Build the list of content types from the folder on the file system.
16
+ #
17
+ # @return [ Array ] The un-ordered list of content types
18
+ #
19
+ def read
20
+ self.fetch
21
+
22
+ self.resolve_relationships
23
+
24
+ self.items
25
+ end
26
+
27
+ protected
28
+
29
+ def fetch
30
+ self.mounting_point.content_types.each do |slug, content_type|
31
+ entries = self.get("content_types/#{slug}/entries", nil, true)
32
+
33
+ entries.each do |attributes|
34
+ locales = attributes.delete('translated_in') || []
35
+
36
+ entry = self.add(content_type, attributes)
37
+
38
+ # get all the translated versions
39
+ locales.each do |locale|
40
+ _attributes = self.get("content_types/#{slug}/entries/#{entry._id}", locale, true)
41
+
42
+ Locomotive::Mounter.with_locale(locale) do
43
+ self.filter_attributes(content_type, _attributes).each do |key, value|
44
+ entry.send(:"#{key}=", value)
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
51
+
52
+ # Add a content entry for a content type.
53
+ #
54
+ # @param [ Object ] content_type The content type
55
+ # @param [ Hash ] attributes The attributes of the content entry
56
+ #
57
+ # @return [ Object] The newly created content entry
58
+ #
59
+ def add(content_type, attributes)
60
+ _attributes = self.filter_attributes(content_type, attributes)
61
+
62
+ # puts "_attributes = #{_attributes.inspect}" # DEBUG
63
+
64
+ entry = content_type.build_entry(_attributes)
65
+
66
+ key = File.join(content_type.slug, entry._slug)
67
+
68
+ self.items[key] = self.ids[entry._id] = entry
69
+ end
70
+
71
+ # Filter the attributes coming directly from an API call.
72
+ #
73
+ # @param [ Object ] content_type The content type
74
+ # @param [ Hash ] attributes The attributes of the content entry
75
+ #
76
+ # @return [ Object] The attributes understandable by the content entry
77
+ #
78
+ def filter_attributes(content_type, original_attributes)
79
+ attributes = original_attributes.clone.keep_if { |k, v| %w(_id _slug seo_title meta_keywords meta_description _position).include?(k) }
80
+
81
+ content_type.fields.each do |field|
82
+ value = (case field.type
83
+ when :string, :boolean
84
+ original_attributes[field.name]
85
+ when :text
86
+ self.replace_urls_by_content_assets(original_attributes[field.name])
87
+ when :select
88
+ field.name_for_select_option(original_attributes[field.name])
89
+ when :date
90
+ original_attributes["formatted_#{field.name}"]
91
+ when :belongs_to, :many_to_many
92
+ # push a relationship in the waiting line in order to be resolved at last
93
+ target_field_name = field.type == :belongs_to ? "#{field.name}_id" : "#{field.name}_ids"
94
+ self.relationships << { id: attributes['_id'], field: field.name, target_ids: original_attributes[target_field_name] }
95
+ nil
96
+ else
97
+ nil
98
+ end)
99
+
100
+ attributes[field.name] = value unless value.nil?
101
+ end
102
+
103
+ attributes
104
+ end
105
+
106
+ # Some entries have what it is called "relationships" field
107
+ # which can be only resolved once all the entries have been fetched
108
+ #
109
+ def resolve_relationships
110
+ self.relationships.each do |relationship|
111
+ source_entry, target_ids = self.ids[relationship[:id]], relationship[:target_ids]
112
+
113
+ target_entries = self.ids.select { |k, _| [*target_ids].include?(k) }.values
114
+
115
+ # single entry (belongs_to) or an array (many_to_many) ?
116
+ target_entries = target_entries.first unless target_ids.is_a?(Array)
117
+
118
+ source_entry.send(:"#{relationship[:field]}=", target_entries)
119
+ end
120
+ end
121
+
122
+ # For a given content, parse it and replace all the urls from content assets
123
+ # by their corresponding locale ones.
124
+ #
125
+ # @param [ String ] content The content to parse
126
+ #
127
+ # @return [ String ] The content with local urls
128
+ #
129
+ def replace_urls_by_content_assets(content)
130
+ self.mounting_point.content_assets.each do |path, asset|
131
+ content.gsub!(path, asset.local_filepath)
132
+ end
133
+ content
134
+ end
135
+
136
+ end
137
+
138
+ end
139
+ end
140
+ end
141
+ end
@@ -0,0 +1,74 @@
1
+ module Locomotive
2
+ module Mounter
3
+ module Reader
4
+ module Api
5
+
6
+ class ContentTypesReader < Base
7
+
8
+ # Build the list of content types from the folder in the file system.
9
+ #
10
+ # @return [ Array ] The un-ordered list of content types
11
+ #
12
+ def read
13
+ self.fetch
14
+
15
+ self.enable_relationships
16
+
17
+ self.items
18
+ end
19
+
20
+ protected
21
+
22
+ def fetch
23
+ self.get(:content_types).each do |attributes|
24
+ self.add(attributes)
25
+ end
26
+ end
27
+
28
+ # Add a new content type in the global hash of content types.
29
+ # If the content type exists, it returns it.
30
+ #
31
+ # @param [ Hash ] attributes The attributes of the content type
32
+ #
33
+ # @return [ Object ] A newly created content type or the existing one
34
+ #
35
+ def add(attributes)
36
+ slug = attributes['slug']
37
+
38
+ attributes.delete('entries_custom_fields').each do |_attributes|
39
+ _attributes = _attributes.delete_if { |k, v| v.blank? || %w(id updated_at created_at).include?(k) }
40
+
41
+ # TODO: select options
42
+
43
+ (attributes['fields'] ||= []) << _attributes
44
+ end
45
+
46
+ unless self.items.key?(slug)
47
+ self.items[slug] = Locomotive::Mounter::Models::ContentType.new(attributes)
48
+ end
49
+
50
+ self.items[slug]
51
+ end
52
+
53
+ # Make sure that each "relationship" field of a content type is
54
+ # correctly connected to the target content type.
55
+ def enable_relationships
56
+ self.items.each do |_, content_type|
57
+ content_type.fields.find_all(&:is_relationship?).each do |field|
58
+ # look for the target content type from its class name
59
+ target = self.items.values.find { |_content_type| _content_type.klass_name == field.class_name }
60
+ field.class_name = target.slug
61
+ end
62
+ end
63
+ end
64
+
65
+ def safe_attributes
66
+ %w(name slug description order_by order_direction label_field_name group_by_field_id public_submission_accounts entries_custom_fields klass_name)
67
+ end
68
+
69
+ end
70
+
71
+ end
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,174 @@
1
+ module Locomotive
2
+ module Mounter
3
+ module Reader
4
+ module Api
5
+
6
+ class PagesReader < Base
7
+
8
+ attr_accessor :pages
9
+
10
+ def initialize(runner)
11
+ self.pages = {}
12
+ super
13
+ end
14
+
15
+ # Build the tree of pages based on the filesystem structure
16
+ #
17
+ # @return [ Hash ] The pages organized as a Hash (using the fullpath as the key)
18
+ #
19
+ def read
20
+ self.fetch
21
+
22
+ index = self.pages['index']
23
+
24
+ self.build_relationships(index, self.pages_to_list)
25
+
26
+ # Locomotive::Mounter.with_locale(:fr) { self.to_s } # DEBUG
27
+ # self.to_s
28
+
29
+ self.pages
30
+ end
31
+
32
+ protected
33
+
34
+ # Create a ordered list of pages from the Hash
35
+ #
36
+ # @return [ Array ] An ordered list of pages
37
+ #
38
+ def pages_to_list
39
+ # sort by fullpath first
40
+ list = self.pages.values.sort { |a, b| a.fullpath <=> b.fullpath }
41
+ # sort finally by depth
42
+ list.sort { |a, b| a.depth <=> b.depth }
43
+ end
44
+
45
+ def build_relationships(parent, list)
46
+ list.dup.each do |page|
47
+ next unless self.is_subpage_of?(page.fullpath, parent.fullpath)
48
+
49
+ # attach the page to the parent (order by position), also set the parent
50
+ parent.add_child(page)
51
+
52
+ # remove the page from the list
53
+ list.delete(page)
54
+
55
+ # go under
56
+ self.build_relationships(page, list)
57
+ end
58
+ end
59
+
60
+ # Record pages found in file system
61
+ def fetch
62
+ self.get(:pages).each do |attributes|
63
+ page = self.add(attributes['fullpath'], attributes)
64
+
65
+ self.mounting_point.locales[1..-1].each do |locale|
66
+ # if not translated, no need to make an api call for that locale
67
+ next unless page.translated_in?(locale)
68
+
69
+ Locomotive::Mounter.with_locale(locale) do
70
+ localized_attributes = self.get("pages/#{page._id}", locale)
71
+
72
+ # delete useless attributes
73
+ localized_attributes.delete('target_klass_slug')
74
+
75
+ # isolate the editable elements
76
+ editable_elements = self.filter_editable_elements(localized_attributes.delete('editable_elements'))
77
+
78
+ page.attributes = localized_attributes
79
+
80
+ page.set_editable_elements(editable_elements)
81
+ end
82
+ end
83
+ end
84
+ end
85
+
86
+ # Add a new page in the global hash of pages.
87
+ # If the page exists, then do nothing.
88
+ #
89
+ # @param [ String ] fullpath The fullpath used as the key for the hash
90
+ # @param [ Hash ] attributes The attributes of the new page
91
+ #
92
+ # @return [ Object ] A newly created page or the existing one
93
+ #
94
+ def add(fullpath, attributes = {})
95
+ unless self.pages.key?(fullpath)
96
+ # editable elements
97
+ editable_elements = self.filter_editable_elements(attributes.delete('editable_elements'))
98
+
99
+ # content type
100
+ if content_type_slug = attributes.delete('target_klass_slug')
101
+ attributes['content_type'] = self.mounting_point.content_types[content_type_slug] #.values.find { |ct| ct._id == content_type_id }
102
+ end
103
+
104
+ self.pages[fullpath] = Locomotive::Mounter::Models::Page.new(attributes)
105
+
106
+ self.pages[fullpath].set_editable_elements(editable_elements)
107
+ end
108
+
109
+ self.pages[fullpath]
110
+ end
111
+
112
+ # Tell is a page described by its fullpath is a sub page of a parent page
113
+ # also described by its fullpath
114
+ #
115
+ # @param [ String ] fullpath The full path of the page to test
116
+ # @param [ String ] parent_fullpath The full path of the parent page
117
+ #
118
+ # @return [ Boolean] True if the page is a sub page of the parent one
119
+ #
120
+ def is_subpage_of?(fullpath, parent_fullpath)
121
+ return false if %w(index 404).include?(fullpath)
122
+
123
+ if parent_fullpath == 'index' && fullpath.split('/').size == 1
124
+ return true
125
+ end
126
+
127
+ File.dirname(fullpath.dasherize) == parent_fullpath.dasherize
128
+ end
129
+
130
+ # Only keep the minimal attributes from a list of
131
+ # editable elements hashes. It also replaces the url to
132
+ # content assets by their corresponding local ones.
133
+ #
134
+ # @param [ Array ] list The list of the editable elements with all the attributes
135
+ #
136
+ # @return [ Array ] The list of editable elements with the right attributes
137
+ #
138
+ def filter_editable_elements(list)
139
+ list.map do |attributes|
140
+ attributes.keep_if { |k, _| %w(_id block slug content).include?(k) }.tap do |hash|
141
+ self.mounting_point.content_assets.each do |path, asset|
142
+ hash['content'].gsub!(path, asset.local_filepath)
143
+ end
144
+ end
145
+ end
146
+ end
147
+
148
+ def safe_attributes
149
+ %w(_id title slug handle fullpath translated_in target_klass_slug
150
+ published listed templatized editable_elements
151
+ redirect_url cache_strategy response_type position
152
+ seo_title meta_keywords meta_description raw_template)
153
+ end
154
+
155
+ # Output simply the tree structure of the pages.
156
+ #
157
+ # Note: only for debug purpose
158
+ #
159
+ def to_s(page = nil)
160
+ page ||= self.pages['index']
161
+
162
+ return unless page.translated_in?(Locomotive::Mounter.locale)
163
+
164
+ puts "#{" " * (page.try(:depth) + 1)} #{page.fullpath.inspect} (#{page.title}, position=#{page.position})"
165
+
166
+ (page.children || []).each { |child| self.to_s(child) }
167
+ end
168
+
169
+ end
170
+
171
+ end
172
+ end
173
+ end
174
+ end
@@ -0,0 +1,37 @@
1
+ module Locomotive
2
+ module Mounter
3
+ module Reader
4
+ module Api
5
+
6
+ class SiteReader < Base
7
+
8
+ def read
9
+ # get the site from the API
10
+ site = self.get(:current_site)
11
+
12
+ # set the default locale first
13
+ Locomotive::Mounter.locale = site['locales'].first.to_sym
14
+
15
+ Locomotive::Mounter::Models::Site.new(site).tap do |site|
16
+ # fetch the information in other locales
17
+ site.locales[1..-1].each do |locale|
18
+ Locomotive::Mounter.with_locale(locale) do
19
+ self.get(:current_site, locale).each do |name, value|
20
+ next unless %w(seo_title meta_keywords meta_description).include?(name)
21
+ site.send(:"#{name}=", value)
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
27
+
28
+ def safe_attributes
29
+ %w(name locales seo_title meta_keywords meta_description domains subdomain)
30
+ end
31
+
32
+ end
33
+
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,59 @@
1
+ module Locomotive
2
+ module Mounter
3
+ module Reader
4
+ module Api
5
+
6
+ class SnippetsReader < Base
7
+
8
+ # Build the list of snippets from the folder on the file system.
9
+ #
10
+ # @return [ Array ] The un-ordered list of snippets
11
+ #
12
+ def read
13
+ self.fetch
14
+
15
+ self.items
16
+ end
17
+
18
+ protected
19
+
20
+ # Record snippets found in file system
21
+ def fetch
22
+ self.get(:snippets).each do |attributes|
23
+ snippet = self.add(attributes.delete('slug'), attributes)
24
+
25
+ self.mounting_point.locales[1..-1].each do |locale|
26
+ Locomotive::Mounter.with_locale(locale) do
27
+ localized_attributes = self.get("snippets/#{snippet._id}", locale)
28
+ snippet.attributes = localized_attributes
29
+ end
30
+ end
31
+ end
32
+ end
33
+
34
+ # Add a new snippet in the global hash of snippets.
35
+ # If the snippet exists, it returns it.
36
+
37
+ # @param [ String ] slug The slug of the snippet
38
+ # @param [ Hash ] attributes The attributes of the snippet
39
+ #
40
+ # @return [ Object ] A newly created snippet or the existing one
41
+ #
42
+ def add(slug, attributes)
43
+ unless self.items.key?(slug)
44
+ self.items[slug] = Locomotive::Mounter::Models::Snippet.new(attributes)
45
+ end
46
+
47
+ self.items[slug]
48
+ end
49
+
50
+ def safe_attributes
51
+ %w(_id name slug template)
52
+ end
53
+
54
+ end
55
+
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,42 @@
1
+ module Locomotive
2
+ module Mounter
3
+ module Reader
4
+ module Api
5
+
6
+ class ThemeAssetsReader < Base
7
+
8
+ def initialize(runner)
9
+ super
10
+ self.items = []
11
+ end
12
+
13
+ # Build the list of theme assets from the public folder with eager loading.
14
+ #
15
+ # @return [ Array ] The cached list of theme assets
16
+ #
17
+ def read
18
+ base_uri = self.runner.uri.split('/').first
19
+ base_uri = "http://#{base_uri}" unless base_uri =~ /^http:\/\//
20
+
21
+ self.items = self.get(:theme_assets).map do |attributes|
22
+ url = attributes.delete('url')
23
+
24
+ attributes['uri'] = URI(url =~ /http:\/\// ? url : "#{base_uri}#{url}")
25
+
26
+ Locomotive::Mounter::Models::ThemeAsset.new(attributes)
27
+ end
28
+ end
29
+
30
+ protected
31
+
32
+ def safe_attributes
33
+ %w(_id folder url)
34
+ end
35
+
36
+ end
37
+
38
+ end
39
+
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,28 @@
1
+ module Locomotive
2
+ module Mounter
3
+ module Reader
4
+ module Api
5
+
6
+ class TranslationsReader < Base
7
+
8
+ # Build the list of translations
9
+ #
10
+ # @return [ Array ] The cached list of theme assets
11
+ #
12
+ def read
13
+ self.items = get(:translations).map do |attributes|
14
+ Locomotive::Mounter::Models::Translation.new(attributes)
15
+ end
16
+ end
17
+
18
+ protected
19
+ def safe_attributes
20
+ %w[_id key values]
21
+ end
22
+ end
23
+
24
+ end
25
+
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,49 @@
1
+ module Locomotive
2
+ module Mounter
3
+ module Reader
4
+ module Api
5
+
6
+ # Build a singleton instance of the Runner class.
7
+ #
8
+ # @return [ Object ] A singleton instance of the Runner class
9
+ #
10
+ def self.instance
11
+ @@instance ||= Runner.new(:api)
12
+ end
13
+
14
+ class Runner < Locomotive::Mounter::Reader::Runner
15
+
16
+ attr_accessor :uri
17
+
18
+ # Call the LocomotiveCMS engine to get a token for
19
+ # the next API calls
20
+ def prepare
21
+ self.uri = self.parameters.delete(:uri)
22
+ email = self.parameters.delete(:email)
23
+ password = self.parameters.delete(:password)
24
+
25
+ if uri.blank? || email.blank? || password.blank?
26
+ raise Locomotive::Mounter::ReaderException.new("one or many API credentials (uri, email, password) are missing")
27
+ end
28
+
29
+ begin
30
+ Locomotive::Mounter::EngineApi.set_token(uri, email, password)
31
+ rescue Exception => e
32
+ raise Locomotive::Mounter::ReaderException.new("unable to get an API token: #{e.message}")
33
+ end
34
+ end
35
+
36
+ # Ordered list of atomic readers
37
+ #
38
+ # @return [ Array ] List of classes
39
+ #
40
+ def readers
41
+ [SiteReader, ContentAssetsReader, SnippetsReader, ContentTypesReader, ContentEntriesReader, PagesReader, ThemeAssetsReader, TranslationsReader]
42
+ end
43
+
44
+ end
45
+
46
+ end
47
+ end
48
+ end
49
+ end