locomotivecms_mounter 1.0.0.alpha1
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/locomotive/mounter/config.rb +21 -0
- data/lib/locomotive/mounter/engine_api.rb +40 -0
- data/lib/locomotive/mounter/exceptions.rb +38 -0
- data/lib/locomotive/mounter/extensions/compass.rb +36 -0
- data/lib/locomotive/mounter/extensions/httmultiparty.rb +22 -0
- data/lib/locomotive/mounter/extensions/tilt/css.rb +31 -0
- data/lib/locomotive/mounter/extensions/tilt/haml.rb +27 -0
- data/lib/locomotive/mounter/extensions/tilt/liquid.rb +23 -0
- data/lib/locomotive/mounter/extensions/tilt/template.rb +11 -0
- data/lib/locomotive/mounter/fields.rb +250 -0
- data/lib/locomotive/mounter/models/base.rb +41 -0
- data/lib/locomotive/mounter/models/content_asset.rb +84 -0
- data/lib/locomotive/mounter/models/content_entry.rb +290 -0
- data/lib/locomotive/mounter/models/content_field.rb +128 -0
- data/lib/locomotive/mounter/models/content_select_option.rb +29 -0
- data/lib/locomotive/mounter/models/content_type.rb +217 -0
- data/lib/locomotive/mounter/models/editable_element.rb +27 -0
- data/lib/locomotive/mounter/models/page.rb +377 -0
- data/lib/locomotive/mounter/models/site.rb +27 -0
- data/lib/locomotive/mounter/models/snippet.rb +55 -0
- data/lib/locomotive/mounter/models/theme_asset.rb +135 -0
- data/lib/locomotive/mounter/models/translation.rb +28 -0
- data/lib/locomotive/mounter/mounting_point.rb +49 -0
- data/lib/locomotive/mounter/reader/api/base.rb +49 -0
- data/lib/locomotive/mounter/reader/api/content_assets_reader.rb +40 -0
- data/lib/locomotive/mounter/reader/api/content_entries_reader.rb +141 -0
- data/lib/locomotive/mounter/reader/api/content_types_reader.rb +74 -0
- data/lib/locomotive/mounter/reader/api/pages_reader.rb +174 -0
- data/lib/locomotive/mounter/reader/api/site_reader.rb +37 -0
- data/lib/locomotive/mounter/reader/api/snippets_reader.rb +59 -0
- data/lib/locomotive/mounter/reader/api/theme_assets_reader.rb +42 -0
- data/lib/locomotive/mounter/reader/api/translations_reader.rb +28 -0
- data/lib/locomotive/mounter/reader/api.rb +49 -0
- data/lib/locomotive/mounter/reader/file_system/base.rb +65 -0
- data/lib/locomotive/mounter/reader/file_system/content_assets_reader.rb +88 -0
- data/lib/locomotive/mounter/reader/file_system/content_entries_reader.rb +101 -0
- data/lib/locomotive/mounter/reader/file_system/content_types_reader.rb +88 -0
- data/lib/locomotive/mounter/reader/file_system/pages_reader.rb +206 -0
- data/lib/locomotive/mounter/reader/file_system/site_reader.rb +24 -0
- data/lib/locomotive/mounter/reader/file_system/snippets_reader.rb +78 -0
- data/lib/locomotive/mounter/reader/file_system/theme_assets_reader.rb +78 -0
- data/lib/locomotive/mounter/reader/file_system/translations_reader.rb +36 -0
- data/lib/locomotive/mounter/reader/file_system.rb +42 -0
- data/lib/locomotive/mounter/reader/runner.rb +89 -0
- data/lib/locomotive/mounter/utils/hash.rb +31 -0
- data/lib/locomotive/mounter/utils/string.rb +17 -0
- data/lib/locomotive/mounter/utils/yaml.rb +125 -0
- data/lib/locomotive/mounter/version.rb +8 -0
- data/lib/locomotive/mounter/writer/api/base.rb +323 -0
- data/lib/locomotive/mounter/writer/api/content_assets_writer.rb +74 -0
- data/lib/locomotive/mounter/writer/api/content_entries_writer.rb +223 -0
- data/lib/locomotive/mounter/writer/api/content_types_writer.rb +151 -0
- data/lib/locomotive/mounter/writer/api/pages_writer.rb +225 -0
- data/lib/locomotive/mounter/writer/api/site_writer.rb +164 -0
- data/lib/locomotive/mounter/writer/api/snippets_writer.rb +111 -0
- data/lib/locomotive/mounter/writer/api/theme_assets_writer.rb +152 -0
- data/lib/locomotive/mounter/writer/api/translations_writer.rb +83 -0
- data/lib/locomotive/mounter/writer/api.rb +62 -0
- data/lib/locomotive/mounter/writer/file_system/base.rb +61 -0
- data/lib/locomotive/mounter/writer/file_system/content_assets_writer.rb +33 -0
- data/lib/locomotive/mounter/writer/file_system/content_entries_writer.rb +29 -0
- data/lib/locomotive/mounter/writer/file_system/content_types_writer.rb +27 -0
- data/lib/locomotive/mounter/writer/file_system/pages_writer.rb +73 -0
- data/lib/locomotive/mounter/writer/file_system/site_writer.rb +25 -0
- data/lib/locomotive/mounter/writer/file_system/snippets_writer.rb +54 -0
- data/lib/locomotive/mounter/writer/file_system/theme_assets_writer.rb +35 -0
- data/lib/locomotive/mounter/writer/file_system/translations_writer.rb +22 -0
- data/lib/locomotive/mounter/writer/file_system.rb +69 -0
- data/lib/locomotive/mounter/writer/runner.rb +68 -0
- data/lib/locomotive/mounter.rb +97 -0
- metadata +487 -0
@@ -0,0 +1,151 @@
|
|
1
|
+
module Locomotive
|
2
|
+
module Mounter
|
3
|
+
module Writer
|
4
|
+
module Api
|
5
|
+
|
6
|
+
# Push content types to a remote LocomotiveCMS engine.
|
7
|
+
#
|
8
|
+
# In a first time, create the content types without any relationships fields.
|
9
|
+
# Then, add the relationships one by one.
|
10
|
+
#
|
11
|
+
# If the :force option is passed, the remote fields not defined in the mounter version
|
12
|
+
# of the content type will be destroyed when pushed. The options of
|
13
|
+
# a select field will be pushed as well, otherwise they won't unless if
|
14
|
+
# it is a brand new content type.
|
15
|
+
#
|
16
|
+
class ContentTypesWriter < Base
|
17
|
+
|
18
|
+
def prepare
|
19
|
+
super
|
20
|
+
|
21
|
+
# assign an _id to a local content type if possible
|
22
|
+
self.get(:content_types, nil, true).each do |attributes|
|
23
|
+
content_type = self.content_types[attributes['slug']]
|
24
|
+
|
25
|
+
self.apply_response(content_type, attributes)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def write
|
30
|
+
done = {}
|
31
|
+
|
32
|
+
# first new content types
|
33
|
+
self.not_persisted.each do |content_type|
|
34
|
+
self.create_content_type(content_type)
|
35
|
+
|
36
|
+
done[content_type.slug] = content_type.with_relationships? ? :todo : :done
|
37
|
+
end
|
38
|
+
|
39
|
+
# then update the others
|
40
|
+
self.content_types.values.each do |content_type|
|
41
|
+
next unless done[content_type.slug].nil?
|
42
|
+
|
43
|
+
self.update_content_type(content_type)
|
44
|
+
end
|
45
|
+
|
46
|
+
# finally, update the newly created embedding a relationship field
|
47
|
+
done.each do |slug, status|
|
48
|
+
next if status == :done
|
49
|
+
|
50
|
+
content_type = self.content_types[slug]
|
51
|
+
|
52
|
+
self.update_content_type(content_type)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
protected
|
57
|
+
|
58
|
+
# Persist a content type by calling the API. It is enhanced then
|
59
|
+
# by the response if no errors occured.
|
60
|
+
#
|
61
|
+
# @param [ Object ] content_type The content type to create
|
62
|
+
#
|
63
|
+
def create_content_type(content_type)
|
64
|
+
self.output_resource_op content_type
|
65
|
+
|
66
|
+
response = self.post :content_types, content_type.to_params, nil, true
|
67
|
+
|
68
|
+
self.apply_response(content_type, response)
|
69
|
+
|
70
|
+
# status = self.response_to_status(response)
|
71
|
+
|
72
|
+
self.output_resource_op_status content_type, :success
|
73
|
+
rescue Exception => e
|
74
|
+
self.output_resource_op_status content_type, :error, e.message
|
75
|
+
end
|
76
|
+
|
77
|
+
# Update a content type by calling the API.
|
78
|
+
#
|
79
|
+
# @param [ Object ] content_type The content type to update
|
80
|
+
#
|
81
|
+
def update_content_type(content_type)
|
82
|
+
self.output_resource_op content_type
|
83
|
+
|
84
|
+
params = self.content_type_to_params(content_type)
|
85
|
+
|
86
|
+
# make a call to the API for the update
|
87
|
+
self.put :content_types, content_type._id, params
|
88
|
+
|
89
|
+
self.output_resource_op_status content_type, :success
|
90
|
+
rescue Exception => e
|
91
|
+
self.output_resource_op_status content_type, :error, e.message
|
92
|
+
end
|
93
|
+
|
94
|
+
def content_types
|
95
|
+
self.mounting_point.content_types
|
96
|
+
end
|
97
|
+
|
98
|
+
# Return the content types not persisted yet.
|
99
|
+
#
|
100
|
+
# @return [ Array ] The list of non persisted content types.
|
101
|
+
#
|
102
|
+
def not_persisted
|
103
|
+
self.content_types.values.find_all { |content_type| !content_type.persisted? }
|
104
|
+
end
|
105
|
+
|
106
|
+
# Enhance the content type with the information returned by an API call.
|
107
|
+
#
|
108
|
+
# @param [ Object ] content_type The content type instance
|
109
|
+
# @param [ Hash ] response The API response
|
110
|
+
#
|
111
|
+
def apply_response(content_type, response)
|
112
|
+
return if content_type.nil? || response.nil?
|
113
|
+
|
114
|
+
content_type._id = response['id']
|
115
|
+
content_type.klass_name = response['klass_name']
|
116
|
+
|
117
|
+
response['entries_custom_fields'].each do |remote_field|
|
118
|
+
field = content_type.find_field(remote_field['name'])
|
119
|
+
_id = remote_field['id']
|
120
|
+
|
121
|
+
if field.nil?
|
122
|
+
if self.force?
|
123
|
+
content_type.fields << Locomotive::Mounter::Models::ContentField.new(_id: _id, _destroy: true)
|
124
|
+
end
|
125
|
+
else
|
126
|
+
field._id = _id
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
# Get the params of a content type for an update.
|
132
|
+
# Delete the select_options unless the force flag is true.
|
133
|
+
#
|
134
|
+
# @param [ Object ] content_type The ContentType
|
135
|
+
#
|
136
|
+
# @return [ Hash ] The params of the ContentType ready to be used in the API
|
137
|
+
#
|
138
|
+
def content_type_to_params(content_type)
|
139
|
+
content_type.to_params(all_fields: true).tap do |params|
|
140
|
+
params[:entries_custom_fields].each do |attributes|
|
141
|
+
attributes.delete(:select_options) unless self.force?
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
end
|
147
|
+
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
@@ -0,0 +1,225 @@
|
|
1
|
+
module Locomotive
|
2
|
+
module Mounter
|
3
|
+
module Writer
|
4
|
+
module Api
|
5
|
+
|
6
|
+
# Push pages to a remote LocomotiveCMS engine.
|
7
|
+
#
|
8
|
+
# New pages are created and existing ones are partially updated.
|
9
|
+
#
|
10
|
+
# If the :force option is passed, the existing pages are fully updated (title, ...etc).
|
11
|
+
# But in any cases, the content of the page will be destroyed, unless the layout of the page
|
12
|
+
# changes.
|
13
|
+
#
|
14
|
+
class PagesWriter < Base
|
15
|
+
|
16
|
+
attr_accessor :new_pages
|
17
|
+
attr_accessor :remote_translations
|
18
|
+
|
19
|
+
def prepare
|
20
|
+
super
|
21
|
+
|
22
|
+
self.new_pages, self.remote_translations = [], {}
|
23
|
+
|
24
|
+
# set the unique identifier to each local page
|
25
|
+
self.get(:pages, nil, true).each do |attributes|
|
26
|
+
page = self.pages[attributes['fullpath'].dasherize]
|
27
|
+
|
28
|
+
self.remote_translations[attributes['fullpath']] = attributes['translated_in']
|
29
|
+
|
30
|
+
page._id = attributes['id'] if page
|
31
|
+
end
|
32
|
+
|
33
|
+
# assign the parent_id and the content_type_id to all the pages
|
34
|
+
self.pages.values.each do |page|
|
35
|
+
next if page.index_or_404?
|
36
|
+
|
37
|
+
page.parent_id = page.parent._id
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
# Write all the pages to the remote destination
|
42
|
+
def write
|
43
|
+
self.each_locale do |locale|
|
44
|
+
self.output_locale
|
45
|
+
|
46
|
+
# first write the pages which are layouts for others
|
47
|
+
self.layouts.each { |page| self.write_page(page) }
|
48
|
+
|
49
|
+
# and proceed the others
|
50
|
+
self.other_than_layouts.each { |page| self.write_page(page) }
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
protected
|
55
|
+
|
56
|
+
def write_page(page)
|
57
|
+
locale = Locomotive::Mounter.locale
|
58
|
+
|
59
|
+
return unless page.translated_in?(locale)
|
60
|
+
|
61
|
+
self.output_resource_op page
|
62
|
+
|
63
|
+
success = page.persisted? ? self.update_page(page) : self.create_page(page)
|
64
|
+
|
65
|
+
self.output_resource_op_status page, success ? :success : :error
|
66
|
+
self.flush_log_buffer
|
67
|
+
end
|
68
|
+
|
69
|
+
# Persist a page by calling the API. The returned _id
|
70
|
+
# is then set to the page itself.
|
71
|
+
#
|
72
|
+
# @param [ Object ] page The page to create
|
73
|
+
#
|
74
|
+
# @return [ Boolean ] True if the call to the API succeeded
|
75
|
+
#
|
76
|
+
def create_page(page)
|
77
|
+
if !page.index_or_404? && page.parent_id.nil?
|
78
|
+
raise Mounter::WriterException.new("We are unable to find the parent page for #{page.fullpath}")
|
79
|
+
end
|
80
|
+
|
81
|
+
params = self.buffer_log { page_to_params(page) }
|
82
|
+
|
83
|
+
# make a call to the API to create the page, no need to set
|
84
|
+
# the locale since it first happens for the default locale.
|
85
|
+
response = self.post :pages, params, nil, true
|
86
|
+
|
87
|
+
if response
|
88
|
+
page._id = response['id']
|
89
|
+
self.new_pages << page._id
|
90
|
+
end
|
91
|
+
|
92
|
+
!response.nil?
|
93
|
+
end
|
94
|
+
|
95
|
+
# Update a page by calling the API.
|
96
|
+
#
|
97
|
+
# @param [ Object ] page The page to persist
|
98
|
+
#
|
99
|
+
# @return [ Boolean ] True if the call to the API succeeded
|
100
|
+
#
|
101
|
+
def update_page(page)
|
102
|
+
locale = Locomotive::Mounter.locale
|
103
|
+
|
104
|
+
# All the attributes of the page or just some of them
|
105
|
+
params = self.buffer_log do
|
106
|
+
self.page_to_params(page, self.data? || !self.already_translated?(page))
|
107
|
+
end
|
108
|
+
|
109
|
+
# make a call to the API for the update
|
110
|
+
response = self.put :pages, page._id, params, locale
|
111
|
+
|
112
|
+
!response.nil?
|
113
|
+
end
|
114
|
+
|
115
|
+
# Shortcut to get pages.
|
116
|
+
#
|
117
|
+
# @return [ Hash ] The hash whose key is the fullpath and the value is the page itself
|
118
|
+
#
|
119
|
+
def pages
|
120
|
+
self.mounting_point.pages
|
121
|
+
end
|
122
|
+
|
123
|
+
# Return the pages which are layouts for others.
|
124
|
+
# They are sorted by the depth.
|
125
|
+
#
|
126
|
+
# @return [ Array ] The list of layouts
|
127
|
+
#
|
128
|
+
def layouts
|
129
|
+
self.pages.values.find_all do |page|
|
130
|
+
self.safely_translated?(page) && page.is_layout?
|
131
|
+
end.sort { |a, b| a.depth <=> b.depth }
|
132
|
+
end
|
133
|
+
|
134
|
+
# Return the pages wich are not layouts for others.
|
135
|
+
# They are sorted by both the depth and the position.
|
136
|
+
#
|
137
|
+
# @return [ Array ] The list of non-layout pages
|
138
|
+
#
|
139
|
+
def other_than_layouts
|
140
|
+
list = (self.pages.values - self.layouts)
|
141
|
+
|
142
|
+
# get only the translated ones in the current locale
|
143
|
+
list.delete_if do |page|
|
144
|
+
# if (!page.parent.nil? && !page.translated_in?(self.mounting_point.default_locale)) ||
|
145
|
+
# !page.translated_in?(Locomotive::Mounter.locale)
|
146
|
+
if !self.safely_translated?(page)
|
147
|
+
self.output_resource_op page
|
148
|
+
self.output_resource_op_status page, :not_translated
|
149
|
+
true
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
# sort them
|
154
|
+
list.sort { |a, b| a.depth_and_position <=> b.depth_and_position }
|
155
|
+
end
|
156
|
+
|
157
|
+
# Tell if the page passed in parameter has already been
|
158
|
+
# translated on the remote engine for the locale passed
|
159
|
+
# as the second parameter.
|
160
|
+
#
|
161
|
+
# @param [ Object ] page The page
|
162
|
+
# @param [ String / Symbol ] locale The locale. Use the current locale by default
|
163
|
+
#
|
164
|
+
# @return [ Boolean] True if already translated.
|
165
|
+
#
|
166
|
+
def already_translated?(page, locale = nil)
|
167
|
+
locale ||= Locomotive::Mounter.locale
|
168
|
+
|
169
|
+
(@remote_translations[page.fullpath] || []).include?(locale.to_s)
|
170
|
+
end
|
171
|
+
|
172
|
+
# Tell if the page is correctly localized, meaning it is localized itself
|
173
|
+
# as well as its parent.
|
174
|
+
#
|
175
|
+
# @param [ Object ] page The page
|
176
|
+
#
|
177
|
+
# @return [ Boolean] True if safely translated.
|
178
|
+
#
|
179
|
+
def safely_translated?(page)
|
180
|
+
if page.parent.nil?
|
181
|
+
page.translated_in?(Locomotive::Mounter.locale)
|
182
|
+
else
|
183
|
+
page.parent.translated_in?(Locomotive::Mounter.locale) &&
|
184
|
+
page.translated_in?(Locomotive::Mounter.locale)
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
# Return the parameters of a page sent by the API.
|
189
|
+
# It includes the editable_elements if the data option is enabled or
|
190
|
+
# if the page is a new one.
|
191
|
+
#
|
192
|
+
# @param [ Object ] page The page
|
193
|
+
# @param [ Boolean ] safe If true the to_safe_params is called, otherwise to_params is applied.
|
194
|
+
#
|
195
|
+
# @return [ Hash ] The parameters of the page
|
196
|
+
#
|
197
|
+
def page_to_params(page, safe = false)
|
198
|
+
(safe ? page.to_safe_params : page.to_params).tap do |params|
|
199
|
+
# raw template
|
200
|
+
params[:raw_template] = self.replace_content_assets!(params[:raw_template])
|
201
|
+
|
202
|
+
if self.data? || self.new_pages.include?(page._id)
|
203
|
+
params[:editable_elements] = (page.editable_elements || []).map(&:to_params)
|
204
|
+
end
|
205
|
+
|
206
|
+
# editable elements
|
207
|
+
(params[:editable_elements] || []).each do |element|
|
208
|
+
if element[:content] =~ /$\/samples\//
|
209
|
+
element[:source] = self.path_to_file(element.delete(:content))
|
210
|
+
elsif element[:content] =~ %r($http://)
|
211
|
+
element[:source_url] = element.delete(:content)
|
212
|
+
else
|
213
|
+
# string / text elements
|
214
|
+
element[:content] = self.replace_content_assets!(element[:content])
|
215
|
+
end
|
216
|
+
end
|
217
|
+
end
|
218
|
+
end
|
219
|
+
|
220
|
+
end
|
221
|
+
|
222
|
+
end
|
223
|
+
end
|
224
|
+
end
|
225
|
+
end
|
@@ -0,0 +1,164 @@
|
|
1
|
+
module Locomotive
|
2
|
+
module Mounter
|
3
|
+
module Writer
|
4
|
+
module Api
|
5
|
+
|
6
|
+
class SiteWriter < Base
|
7
|
+
|
8
|
+
attr_accessor :remote_site
|
9
|
+
|
10
|
+
# Check if the site has to be created before.
|
11
|
+
def prepare
|
12
|
+
super
|
13
|
+
|
14
|
+
self.fetch_site
|
15
|
+
|
16
|
+
# if self.fetch_site.nil?
|
17
|
+
# Mounter.logger.warn 'The site does not exist. Trying to create it.'
|
18
|
+
|
19
|
+
# unless self.has_admin_rights?
|
20
|
+
# raise Mounter::WriterException.new('Your account does not own admin rights.')
|
21
|
+
# end
|
22
|
+
# else
|
23
|
+
# self.check_locales
|
24
|
+
# end
|
25
|
+
end
|
26
|
+
|
27
|
+
# Create the site if it does not exist
|
28
|
+
def write
|
29
|
+
if self.site.persisted?
|
30
|
+
self.check_locales! unless self.force? # requirements
|
31
|
+
|
32
|
+
self.update_site
|
33
|
+
else
|
34
|
+
self.create_site
|
35
|
+
end
|
36
|
+
|
37
|
+
|
38
|
+
# unless self.site.persisted?
|
39
|
+
# # create it in the default locale
|
40
|
+
# Mounter.with_locale(self.default_locale) do
|
41
|
+
# self.output_locale
|
42
|
+
|
43
|
+
# self.output_resource_op self.site
|
44
|
+
|
45
|
+
# if (site = self.post(:sites, self.site.to_hash(false), Mounter.locale)).nil?
|
46
|
+
# raise Mounter::WriterException.new('Sorry, we are unable to create the site.')
|
47
|
+
# else
|
48
|
+
# self.site._id = site['id']
|
49
|
+
|
50
|
+
# self.output_resource_op_status self.site
|
51
|
+
# end
|
52
|
+
# end
|
53
|
+
|
54
|
+
# # update it in other locales
|
55
|
+
# self.site.translated_in.each do |locale|
|
56
|
+
# next if locale.to_s == self.default_locale.to_s
|
57
|
+
# Mounter.with_locale(locale) do
|
58
|
+
# self.output_locale
|
59
|
+
|
60
|
+
# self.output_resource_op self.site
|
61
|
+
|
62
|
+
# self.put(:sites, self.site._id, self.site.to_hash(false), Mounter.locale)
|
63
|
+
|
64
|
+
# self.output_resource_op_status self.site
|
65
|
+
# end
|
66
|
+
# end
|
67
|
+
# else
|
68
|
+
# self.output_resource_op self.site
|
69
|
+
# self.output_resource_op_status self.site, :skipped
|
70
|
+
# end
|
71
|
+
end
|
72
|
+
|
73
|
+
protected
|
74
|
+
|
75
|
+
# Create the current site in all the locales
|
76
|
+
#
|
77
|
+
def create_site
|
78
|
+
# create it in the default locale
|
79
|
+
Mounter.with_locale(self.default_locale) do
|
80
|
+
self.output_locale
|
81
|
+
|
82
|
+
self.output_resource_op self.site
|
83
|
+
|
84
|
+
if (site = self.post(:sites, self.site.to_hash(false), Mounter.locale)).nil?
|
85
|
+
raise Mounter::WriterException.new('Sorry, we are unable to create the site.')
|
86
|
+
else
|
87
|
+
self.site._id = site['id']
|
88
|
+
self.output_resource_op_status self.site
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
# update it in other locales
|
93
|
+
self.update_site(true)
|
94
|
+
end
|
95
|
+
|
96
|
+
# Update the current site in all the locales
|
97
|
+
#
|
98
|
+
# @param [ Boolean ] exclude_current_locale Update the site for all the locales other than the default one.
|
99
|
+
#
|
100
|
+
def update_site(exclude_current_locale = false)
|
101
|
+
self.each_locale do |locale|
|
102
|
+
next if exclude_current_locale && locale.to_s == self.default_locale.to_s
|
103
|
+
|
104
|
+
self.output_locale
|
105
|
+
|
106
|
+
begin
|
107
|
+
self.output_resource_op self.site
|
108
|
+
|
109
|
+
self.put(:sites, self.site._id, self.site.to_hash(false), locale)
|
110
|
+
|
111
|
+
self.output_resource_op_status self.site
|
112
|
+
rescue Exception => e
|
113
|
+
self.output_resource_op_status self.site, :error, e.message
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
def safe_attributes
|
119
|
+
%w(id locales)
|
120
|
+
end
|
121
|
+
|
122
|
+
def fetch_site
|
123
|
+
self.get(:current_site).tap do |_site|
|
124
|
+
if _site
|
125
|
+
self.remote_site = _site
|
126
|
+
self.site._id = _site['id']
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
# To push all the other resources, the big requirement is to
|
132
|
+
# have the same locales between the local site and the remote one.
|
133
|
+
#
|
134
|
+
def check_locales!
|
135
|
+
default_locale = self.mounting_point.default_locale.to_s
|
136
|
+
locales = self.site.locales.map(&:to_s)
|
137
|
+
remote_locales = self.remote_site['locales']
|
138
|
+
message = nil
|
139
|
+
|
140
|
+
unless locales.all? { |l| remote_locales.include?(l) }
|
141
|
+
message = "Your site locales (#{locales.join(', ')}) do not match exactly the ones of your target (#{remote_locales.join(', ')})"
|
142
|
+
end
|
143
|
+
|
144
|
+
if default_locale != remote_locales.first
|
145
|
+
message = "Your default site locale (#{default_locale.inspect}) is not the same as the one of your target (#{remote_locales.first.inspect})"
|
146
|
+
end
|
147
|
+
|
148
|
+
if message
|
149
|
+
self.output_resource_op self.site
|
150
|
+
self.output_resource_op_status self.site, :error, message
|
151
|
+
raise Mounter::WriterException.new('Use the force option in order to force your locale settings.')
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
def has_admin_rights?
|
156
|
+
self.get(:my_account, nil, true)['admin']
|
157
|
+
end
|
158
|
+
|
159
|
+
end
|
160
|
+
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
@@ -0,0 +1,111 @@
|
|
1
|
+
module Locomotive
|
2
|
+
module Mounter
|
3
|
+
module Writer
|
4
|
+
module Api
|
5
|
+
|
6
|
+
# Push snippets to a remote LocomotiveCMS engine.
|
7
|
+
#
|
8
|
+
# The force option is not used.
|
9
|
+
#
|
10
|
+
class SnippetsWriter < Base
|
11
|
+
|
12
|
+
def prepare
|
13
|
+
super
|
14
|
+
|
15
|
+
# set the unique identifier to each local snippet
|
16
|
+
self.get(:snippets, nil, true).each do |attributes|
|
17
|
+
snippet = self.snippets[attributes['slug']]
|
18
|
+
|
19
|
+
snippet._id = attributes['id'] if snippet
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
# Write all the snippets to the remote destination
|
24
|
+
def write
|
25
|
+
self.each_locale do |locale|
|
26
|
+
self.output_locale
|
27
|
+
|
28
|
+
self.snippets.values.each { |snippet| self.write_snippet(snippet) }
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
protected
|
33
|
+
|
34
|
+
# Write a snippet by calling the API.
|
35
|
+
#
|
36
|
+
# @param [ Object ] snippet The snippet
|
37
|
+
#
|
38
|
+
def write_snippet(snippet)
|
39
|
+
locale = Locomotive::Mounter.locale
|
40
|
+
|
41
|
+
return unless snippet.translated_in?(locale)
|
42
|
+
|
43
|
+
self.output_resource_op snippet
|
44
|
+
|
45
|
+
success = snippet.persisted? ? self.update_snippet(snippet) : self.create_snippet(snippet)
|
46
|
+
|
47
|
+
self.output_resource_op_status snippet, success ? :success : :error
|
48
|
+
self.flush_log_buffer
|
49
|
+
end
|
50
|
+
|
51
|
+
# Persist a snippet by calling the API. The returned id
|
52
|
+
# is then set to the snippet itself.
|
53
|
+
#
|
54
|
+
# @param [ Object ] snippet The snippet to create
|
55
|
+
#
|
56
|
+
# @return [ Boolean ] True if the call to the API succeeded
|
57
|
+
#
|
58
|
+
def create_snippet(snippet)
|
59
|
+
params = self.buffer_log { snippet_to_params(snippet) }
|
60
|
+
|
61
|
+
# make a call to the API to create the snippet, no need to set
|
62
|
+
# the locale since it first happens for the default locale.
|
63
|
+
response = self.post :snippets, params, nil, true
|
64
|
+
|
65
|
+
snippet._id = response['id'] if response
|
66
|
+
|
67
|
+
!response.nil?
|
68
|
+
end
|
69
|
+
|
70
|
+
# Update a snippet by calling the API.
|
71
|
+
#
|
72
|
+
# @param [ Object ] snippet The snippet to persist
|
73
|
+
#
|
74
|
+
# @return [ Boolean ] True if the call to the API succeeded
|
75
|
+
#
|
76
|
+
def update_snippet(snippet)
|
77
|
+
params = self.buffer_log { snippet_to_params(snippet) }
|
78
|
+
|
79
|
+
locale = Locomotive::Mounter.locale
|
80
|
+
|
81
|
+
# make a call to the API for the update
|
82
|
+
response = self.put :snippets, snippet._id, params, locale
|
83
|
+
|
84
|
+
!response.nil?
|
85
|
+
end
|
86
|
+
|
87
|
+
# Shortcut to get all the local snippets.
|
88
|
+
#
|
89
|
+
# @return [ Hash ] The hash whose key is the slug and the value is the snippet itself
|
90
|
+
#
|
91
|
+
def snippets
|
92
|
+
self.mounting_point.snippets
|
93
|
+
end
|
94
|
+
|
95
|
+
# Return the parameters of a snippet sent by the API.
|
96
|
+
#
|
97
|
+
# @param [ Object ] snippet The snippet
|
98
|
+
#
|
99
|
+
# @return [ Hash ] The parameters of the page
|
100
|
+
#
|
101
|
+
def snippet_to_params(snippet)
|
102
|
+
snippet.to_params.tap do |params|
|
103
|
+
params[:template] = self.replace_content_assets!(params[:template])
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|