locomotivecms_steam 1.4.1 → 1.5.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (173) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +1 -1
  3. data/Gemfile.lock +31 -25
  4. data/Rakefile +2 -2
  5. data/config/locales/pt-BR.yml +43 -13
  6. data/lib/locomotive/steam.rb +9 -4
  7. data/lib/locomotive/steam/adapters/filesystem.rb +2 -7
  8. data/lib/locomotive/steam/adapters/filesystem/sanitizer.rb +0 -2
  9. data/lib/locomotive/steam/adapters/filesystem/sanitizers/page.rb +11 -0
  10. data/lib/locomotive/steam/adapters/filesystem/sanitizers/section.rb +37 -0
  11. data/lib/locomotive/steam/adapters/filesystem/sanitizers/site.rb +18 -0
  12. data/lib/locomotive/steam/adapters/filesystem/yaml_loaders/content_entry.rb +4 -3
  13. data/lib/locomotive/steam/adapters/filesystem/yaml_loaders/content_type.rb +4 -3
  14. data/lib/locomotive/steam/adapters/filesystem/yaml_loaders/section.rb +40 -0
  15. data/lib/locomotive/steam/adapters/filesystem/yaml_loaders/snippet.rb +0 -1
  16. data/lib/locomotive/steam/adapters/memory.rb +1 -1
  17. data/lib/locomotive/steam/entities/content_entry.rb +15 -3
  18. data/lib/locomotive/steam/entities/content_type.rb +2 -1
  19. data/lib/locomotive/steam/entities/page.rb +21 -19
  20. data/lib/locomotive/steam/entities/section.rb +24 -0
  21. data/lib/locomotive/steam/entities/site.rb +3 -1
  22. data/lib/locomotive/steam/liquid.rb +2 -0
  23. data/lib/locomotive/steam/liquid/drops/page.rb +4 -2
  24. data/lib/locomotive/steam/liquid/drops/params.rb +51 -0
  25. data/lib/locomotive/steam/liquid/drops/section.rb +56 -0
  26. data/lib/locomotive/steam/liquid/drops/section_block.rb +47 -0
  27. data/lib/locomotive/steam/liquid/drops/section_content_proxy.rb +97 -0
  28. data/lib/locomotive/steam/liquid/drops/section_editor_setting_data.rb +65 -0
  29. data/lib/locomotive/steam/liquid/drops/site.rb +2 -1
  30. data/lib/locomotive/steam/liquid/errors.rb +2 -0
  31. data/lib/locomotive/steam/liquid/filters/base.rb +3 -3
  32. data/lib/locomotive/steam/liquid/filters/date.rb +1 -1
  33. data/lib/locomotive/steam/liquid/filters/html.rb +7 -2
  34. data/lib/locomotive/steam/liquid/filters/json.rb +3 -1
  35. data/lib/locomotive/steam/liquid/tags/action.rb +2 -2
  36. data/lib/locomotive/steam/liquid/tags/alt_page_links.rb +63 -0
  37. data/lib/locomotive/steam/liquid/tags/concerns/i18n_page.rb +1 -1
  38. data/lib/locomotive/steam/liquid/tags/concerns/section.rb +117 -0
  39. data/lib/locomotive/steam/liquid/tags/global_section.rb +32 -0
  40. data/lib/locomotive/steam/liquid/tags/model_form.rb +1 -1
  41. data/lib/locomotive/steam/liquid/tags/section.rb +87 -0
  42. data/lib/locomotive/steam/liquid/tags/sections_dropzone.rb +56 -0
  43. data/lib/locomotive/steam/liquid/tags/snippet.rb +3 -2
  44. data/lib/locomotive/steam/liquid/template.rb +0 -5
  45. data/lib/locomotive/steam/middlewares.rb +1 -1
  46. data/lib/locomotive/steam/middlewares/auth.rb +29 -13
  47. data/lib/locomotive/steam/middlewares/concerns/helpers.rb +59 -0
  48. data/lib/locomotive/steam/middlewares/concerns/liquid_context.rb +94 -0
  49. data/lib/locomotive/steam/middlewares/encoded_link_redirection.rb +45 -0
  50. data/lib/locomotive/steam/middlewares/entry_submission.rb +1 -1
  51. data/lib/locomotive/steam/middlewares/favicon.rb +1 -1
  52. data/lib/locomotive/steam/middlewares/locale.rb +63 -15
  53. data/lib/locomotive/steam/middlewares/locale_redirection.rb +18 -6
  54. data/lib/locomotive/steam/middlewares/logging.rb +1 -1
  55. data/lib/locomotive/steam/middlewares/page.rb +35 -6
  56. data/lib/locomotive/steam/middlewares/path.rb +1 -1
  57. data/lib/locomotive/steam/middlewares/private_access.rb +1 -1
  58. data/lib/locomotive/steam/middlewares/redirection.rb +1 -1
  59. data/lib/locomotive/steam/middlewares/renderer.rb +2 -82
  60. data/lib/locomotive/steam/middlewares/robots.rb +1 -1
  61. data/lib/locomotive/steam/middlewares/section.rb +56 -0
  62. data/lib/locomotive/steam/middlewares/site.rb +1 -1
  63. data/lib/locomotive/steam/middlewares/sitemap.rb +58 -45
  64. data/lib/locomotive/steam/middlewares/templatized_page.rb +1 -1
  65. data/lib/locomotive/steam/middlewares/thread_safe.rb +85 -2
  66. data/lib/locomotive/steam/middlewares/timezone.rb +1 -1
  67. data/lib/locomotive/steam/middlewares/url_redirection.rb +1 -1
  68. data/lib/locomotive/steam/models/entity.rb +0 -2
  69. data/lib/locomotive/steam/models/mapper.rb +5 -3
  70. data/lib/locomotive/steam/models/scope.rb +8 -0
  71. data/lib/locomotive/steam/repositories.rb +4 -0
  72. data/lib/locomotive/steam/repositories/content_entry_repository.rb +6 -2
  73. data/lib/locomotive/steam/repositories/page_repository.rb +4 -1
  74. data/lib/locomotive/steam/repositories/section_repository.rb +14 -0
  75. data/lib/locomotive/steam/repositories/site_repository.rb +1 -1
  76. data/lib/locomotive/steam/repositories/snippet_repository.rb +0 -3
  77. data/lib/locomotive/steam/server.rb +3 -1
  78. data/lib/locomotive/steam/services.rb +17 -1
  79. data/lib/locomotive/steam/services/action_service.rb +10 -0
  80. data/lib/locomotive/steam/services/concerns/decorator.rb +0 -2
  81. data/lib/locomotive/steam/services/image_resizer_service.rb +1 -1
  82. data/lib/locomotive/steam/services/page_finder_service.rb +6 -0
  83. data/lib/locomotive/steam/services/section_finder_service.rb +17 -0
  84. data/lib/locomotive/steam/services/url_builder_service.rb +31 -17
  85. data/lib/locomotive/steam/services/url_finder_service.rb +87 -0
  86. data/lib/locomotive/steam/version.rb +2 -2
  87. data/locomotivecms_steam.gemspec +1 -1
  88. data/spec/fixtures/default/app/views/pages/tags/section.liquid.haml +11 -0
  89. data/spec/fixtures/default/app/views/sections/carousel.liquid +20 -0
  90. data/spec/fixtures/default/app/views/sections/footer.liquid +48 -0
  91. data/spec/fixtures/default/app/views/sections/header.liquid +54 -0
  92. data/spec/fixtures/default/config/deploy.yml +1 -1
  93. data/spec/fixtures/errors/section_bad_json_content.liquid +9 -0
  94. data/spec/fixtures/errors/section_bad_json_header.liquid +8 -0
  95. data/spec/fixtures/mongodb/locomotive_accounts.bson +0 -0
  96. data/spec/fixtures/mongodb/locomotive_accounts.metadata.json +1 -1
  97. data/spec/fixtures/mongodb/locomotive_activities.bson +0 -0
  98. data/spec/fixtures/mongodb/locomotive_activities.metadata.json +1 -1
  99. data/spec/fixtures/mongodb/locomotive_content_assets.bson +0 -0
  100. data/spec/fixtures/mongodb/locomotive_content_assets.metadata.json +1 -1
  101. data/spec/fixtures/mongodb/locomotive_content_entries.bson +0 -0
  102. data/spec/fixtures/mongodb/locomotive_content_entries.metadata.json +1 -1
  103. data/spec/fixtures/mongodb/locomotive_content_types.bson +0 -0
  104. data/spec/fixtures/mongodb/locomotive_content_types.metadata.json +1 -1
  105. data/spec/fixtures/mongodb/locomotive_pages.bson +0 -0
  106. data/spec/fixtures/mongodb/locomotive_pages.metadata.json +1 -1
  107. data/spec/fixtures/mongodb/locomotive_sections.bson +0 -0
  108. data/spec/fixtures/mongodb/{sessions.metadata.json → locomotive_sections.metadata.json} +1 -1
  109. data/spec/fixtures/mongodb/locomotive_sites.bson +0 -0
  110. data/spec/fixtures/mongodb/locomotive_sites.metadata.json +1 -1
  111. data/spec/fixtures/mongodb/locomotive_snippets.bson +0 -0
  112. data/spec/fixtures/mongodb/locomotive_snippets.metadata.json +1 -1
  113. data/spec/fixtures/mongodb/locomotive_theme_assets.bson +0 -0
  114. data/spec/fixtures/mongodb/locomotive_theme_assets.metadata.json +1 -1
  115. data/spec/fixtures/mongodb/locomotive_translations.bson +0 -0
  116. data/spec/fixtures/mongodb/locomotive_translations.metadata.json +1 -1
  117. data/spec/integration/repositories/content_entry_repository_spec.rb +1 -1
  118. data/spec/integration/repositories/page_repository_spec.rb +1 -1
  119. data/spec/integration/repositories/theme_asset_repository_spec.rb +1 -1
  120. data/spec/integration/server/auth_spec.rb +0 -4
  121. data/spec/integration/server/basic_spec.rb +8 -0
  122. data/spec/integration/server/contact_form_spec.rb +15 -2
  123. data/spec/integration/server/sitemap_spec.rb +5 -3
  124. data/spec/integration/services/content_entry_service_spec.rb +1 -1
  125. data/spec/support/helpers.rb +3 -3
  126. data/spec/unit/adapters/filesystem/sanitizers/section_spec.rb +65 -0
  127. data/spec/unit/adapters/filesystem/sanitizers/site_spec.rb +28 -2
  128. data/spec/unit/adapters/filesystem/yaml_loaders/content_entry_spec.rb +8 -4
  129. data/spec/unit/adapters/filesystem/yaml_loaders/content_type_spec.rb +2 -2
  130. data/spec/unit/adapters/filesystem/yaml_loaders/page_spec.rb +1 -1
  131. data/spec/unit/adapters/filesystem/yaml_loaders/section_spec.rb +27 -0
  132. data/spec/unit/entities/section_spec.rb +29 -0
  133. data/spec/unit/liquid/drops/params_spec.rb +38 -0
  134. data/spec/unit/liquid/drops/section_content_proxy_spec.rb +88 -0
  135. data/spec/unit/liquid/drops/section_spec.rb +26 -0
  136. data/spec/unit/liquid/filters/html_spec.rb +198 -170
  137. data/spec/unit/liquid/filters/json_spec.rb +7 -0
  138. data/spec/unit/liquid/tags/action_spec.rb +12 -2
  139. data/spec/unit/liquid/tags/alt_page_links_spec.rb +58 -0
  140. data/spec/unit/liquid/tags/global_section_spec.rb +130 -0
  141. data/spec/unit/liquid/tags/link_to_spec.rb +1 -1
  142. data/spec/unit/liquid/tags/locale_switcher_spec.rb +1 -1
  143. data/spec/unit/liquid/tags/model_form_spec.rb +8 -0
  144. data/spec/unit/liquid/tags/path_to_spec.rb +26 -3
  145. data/spec/unit/liquid/tags/section_spec.rb +231 -0
  146. data/spec/unit/liquid/tags/sections_dropzone_spec.rb +107 -0
  147. data/spec/unit/middlewares/auth_spec.rb +9 -2
  148. data/spec/unit/middlewares/encoded_link_redirection_spec.rb +73 -0
  149. data/spec/unit/middlewares/entry_submission_spec.rb +1 -1
  150. data/spec/unit/middlewares/helpers_spec.rb +3 -64
  151. data/spec/unit/middlewares/locale_redirection_spec.rb +13 -2
  152. data/spec/unit/middlewares/locale_spec.rb +52 -10
  153. data/spec/unit/middlewares/page_spec.rb +57 -16
  154. data/spec/unit/middlewares/private_access_spec.rb +1 -1
  155. data/spec/unit/middlewares/redirection_spec.rb +1 -1
  156. data/spec/unit/middlewares/renderer_spec.rb +2 -1
  157. data/spec/unit/middlewares/section_spec.rb +70 -0
  158. data/spec/unit/middlewares/site_spec.rb +1 -1
  159. data/spec/unit/middlewares/sitemap_spec.rb +4 -42
  160. data/spec/unit/middlewares/url_redirection_spec.rb +1 -1
  161. data/spec/unit/repositories/content_entry_repository_spec.rb +13 -13
  162. data/spec/unit/repositories/section_repository_spec.rb +38 -0
  163. data/spec/unit/repositories/snippet_repository_spec.rb +0 -3
  164. data/spec/unit/services/action_service_spec.rb +19 -1
  165. data/spec/unit/services/asset_host_service_spec.rb +8 -0
  166. data/spec/unit/services/parent_finder_service_spec.rb +1 -2
  167. data/spec/unit/services/section_finder_service_spec.rb +28 -0
  168. data/spec/unit/services/url_builder_service_spec.rb +14 -4
  169. data/spec/unit/services/url_finder_service_spec.rb +100 -0
  170. data/spec/unit/services_spec.rb +34 -20
  171. metadata +72 -11
  172. data/lib/locomotive/steam/middlewares/helpers.rb +0 -140
  173. data/spec/fixtures/mongodb/sessions.bson +0 -0
@@ -0,0 +1,56 @@
1
+ module Locomotive
2
+ module Steam
3
+ module Liquid
4
+
5
+ module Tags
6
+
7
+ class SectionsDropzone < ::Liquid::Tag
8
+
9
+ include Concerns::Section
10
+
11
+ def parse(tokens)
12
+ notify_on_parsing('_sections_dropzone_', is_dropzone: true)
13
+ end
14
+
15
+ def render(context)
16
+ sections_dropzone_content = context['page']&.sections_dropzone_content || []
17
+
18
+ html = sections_dropzone_content.each_with_index.map do |content, index|
19
+ # find the liquid source of the section
20
+ section = find_section(context, content['type'])
21
+
22
+ next if section.nil? # the section doesn't exist anymore?
23
+
24
+ # assign a new dom_id to the section
25
+ content['id'] = "dropzone-#{index}"
26
+
27
+ # parse the template of the section
28
+ template = build_template(section)
29
+
30
+ render_section(context, template, section, content)
31
+ end.join
32
+
33
+ %(<div class="locomotive-sections">#{html}</div>)
34
+ end
35
+
36
+ private
37
+
38
+ def find_section(context, type)
39
+ # TODO: add some cache (useful if there are sections with the same type)
40
+ context.registers[:services].section_finder.find(type)
41
+ end
42
+
43
+ def build_template(section)
44
+ # TODO: add some cache here (useful if there are sections with the same type)
45
+ ::Liquid::Template.parse(section.liquid_source, @options)
46
+ end
47
+
48
+ end
49
+
50
+ ::Liquid::Template.register_tag('sections_dropzone'.freeze, SectionsDropzone)
51
+
52
+ end
53
+
54
+ end
55
+ end
56
+ end
@@ -6,10 +6,11 @@ module Locomotive
6
6
  class Snippet < ::Liquid::Include
7
7
 
8
8
  def parse(tokens)
9
- ActiveSupport::Notifications.instrument('steam.parse.include', page: options[:page], name: @template_name)
9
+ name = evaluate_snippet_name
10
+
11
+ ActiveSupport::Notifications.instrument('steam.parse.include', page: options[:page], name: name)
10
12
 
11
13
  # look for editable elements
12
- name = evaluate_snippet_name
13
14
  if options[:snippet_finder] && snippet = options[:snippet_finder].find(name)
14
15
  options[:parser]._parse(snippet, options.merge(snippet: name))
15
16
  end
@@ -1,7 +1,6 @@
1
1
  module Locomotive
2
2
  module Steam
3
3
  module Liquid
4
-
5
4
  class Template < ::Liquid::Template
6
5
 
7
6
  # When we render a Locomotive template, we need to know what are
@@ -18,18 +17,14 @@ module Locomotive
18
17
  end
19
18
 
20
19
  class << self
21
-
22
20
  def parse(source, options = {})
23
21
  template = new
24
22
  template.parse(source, options.merge({
25
23
  line_numbers: true
26
24
  }))
27
25
  end
28
-
29
26
  end
30
-
31
27
  end
32
-
33
28
  end
34
29
  end
35
30
  end
@@ -1,6 +1,6 @@
1
1
  require_relative 'middlewares/thread_safe'
2
- require_relative 'middlewares/helpers'
3
2
 
3
+ require_relative_all 'middlewares/concerns'
4
4
  require_relative_all 'middlewares'
5
5
 
6
6
  module Locomotive::Steam
@@ -13,7 +13,7 @@ module Locomotive::Steam
13
13
  #
14
14
  class Auth < ThreadSafe
15
15
 
16
- include Helpers
16
+ include Concerns::Helpers
17
17
 
18
18
  def _call
19
19
  load_authenticated_entry
@@ -169,7 +169,7 @@ module Locomotive::Steam
169
169
  end
170
170
 
171
171
  def from
172
- params[:auth_email_from] || 'support@locomotivecms.com'
172
+ smtp_config['sender'] || 'support@locomotivecms.com'
173
173
  end
174
174
 
175
175
  def subject
@@ -188,23 +188,39 @@ module Locomotive::Steam
188
188
  params[:auth_entry]
189
189
  end
190
190
 
191
+ def smtp_config
192
+ @config ||= _read_smtp_config
193
+ end
194
+
191
195
  def smtp
192
- name = params[:auth_email_smtp_namespace] || 'smtp'
193
- namespace = site.metafields.try(:[], name)
196
+ if smtp_config.blank?
197
+ {}
198
+ else
199
+ {
200
+ address: smtp_config['address'],
201
+ port: smtp_config['port'],
202
+ user_name: smtp_config['user_name'],
203
+ password: smtp_config['password'],
204
+ authentication: smtp_config['authentication'] || 'plain',
205
+ enable_starttls_auto: (smtp_config['enable_starttls_auto'] || "0").to_bool,
206
+ }
207
+ end
208
+ end
194
209
 
195
- if namespace.blank?
210
+ private
211
+
212
+ def _read_smtp_config
213
+ name = params[:auth_email_smtp_namespace] || 'smtp'
214
+ config = site.metafields.try(:[], name)
215
+ if config.blank?
196
216
  Locomotive::Common::Logger.error "[Auth] Missing SMTP settings in the Site metafields. Namespace: #{name}".light_red
197
- return {}
217
+ {}
218
+ else
219
+ config
198
220
  end
199
-
200
- {
201
- address: namespace[params[:auth_email_smtp_address_alias] || 'address'],
202
- port: namespace[params[:auth_email_smtp_port_alias] || 'port'],
203
- user_name: namespace[params[:auth_email_smtp_user_name_alias] || 'user_name'],
204
- password: namespace[params[:auth_email_smtp_password_alias] || 'password']
205
- }
206
221
  end
207
222
 
223
+
208
224
  end
209
225
 
210
226
  end
@@ -0,0 +1,59 @@
1
+ module Locomotive::Steam
2
+ module Middlewares
3
+ module Concerns
4
+ module Helpers
5
+
6
+ def html?
7
+ ['text/html', 'application/x-www-form-urlencoded', 'multipart/form-data'].include?(self.request.media_type) &&
8
+ !self.request.xhr? &&
9
+ !self.json?
10
+ end
11
+
12
+ def json?
13
+ self.request.content_type == 'application/json' || File.extname(self.request.path) == '.json'
14
+ end
15
+
16
+ def render_response(content, code = 200, type = nil)
17
+ @next_response = [code, { 'Content-Type' => type || 'text/html' }, [content]]
18
+ end
19
+
20
+ def redirect_to(location, type = 301)
21
+ _location = mounted_on && !location.starts_with?(mounted_on) && (location =~ Locomotive::Steam::IsHTTP).nil? ? "#{mounted_on}#{location}" : location
22
+
23
+ self.log "Redirected to #{_location}".blue
24
+
25
+ @next_response = [type, { 'Content-Type' => 'text/html', 'Location' => _location }, []]
26
+ end
27
+
28
+ def modify_path(path = nil, &block)
29
+ path ||= env['steam.path']
30
+
31
+ segments = path.split('/')
32
+ yield(segments)
33
+ path = segments.join('/')
34
+
35
+ path = '/' if path.blank?
36
+ path += "?#{request.query_string}" unless request.query_string.empty?
37
+ path
38
+ end
39
+
40
+ # make sure the location passed in parameter doesn't
41
+ # include the "mounted_on" parameter.
42
+ # If so, returns the location without the "mounted_on" string.
43
+ def make_local_path(location)
44
+ return location if mounted_on.blank?
45
+ location.gsub(Regexp.new('^' + mounted_on), '')
46
+ end
47
+
48
+ def mounted_on
49
+ request.env['steam.mounted_on']
50
+ end
51
+
52
+ def log(msg, offset = 2)
53
+ Locomotive::Common::Logger.info (' ' * offset) + msg
54
+ end
55
+
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,94 @@
1
+ module Locomotive::Steam
2
+ module Middlewares
3
+ module Concerns
4
+ module LiquidContext
5
+
6
+ private
7
+
8
+ def liquid_context
9
+ ::Liquid::Context.new(liquid_assigns, {}, liquid_registers, true)
10
+ end
11
+
12
+ def liquid_registers
13
+ {
14
+ request: request,
15
+ locale: locale,
16
+ site: site,
17
+ page: page,
18
+ services: services,
19
+ repositories: services.repositories,
20
+ logger: Locomotive::Common::Logger,
21
+ live_editing: live_editing?,
22
+ params: params,
23
+ session: request.session,
24
+ cookies: request.cookies
25
+ }
26
+ end
27
+
28
+ def liquid_assigns
29
+ _default_liquid_assigns.merge(
30
+ _locale_liquid_assigns.merge(
31
+ _request_liquid_assigns.merge(
32
+ _http_actions_liquid_assigns.merge(
33
+ _steam_liquid_assigns))))
34
+ end
35
+
36
+ def _default_liquid_assigns
37
+ {
38
+ 'current_page' => params[:page],
39
+ 'params' => Locomotive::Steam::Liquid::Drops::Params.new(params),
40
+ 'now' => Time.zone.now,
41
+ 'today' => Date.today,
42
+ 'mode' => Locomotive::Steam.configuration.mode,
43
+ 'wagon' => Locomotive::Steam.configuration.mode == :test,
44
+ 'live_editing' => live_editing?
45
+ }
46
+ end
47
+
48
+ def _steam_liquid_assigns
49
+ {
50
+ 'site' => site.to_liquid,
51
+ 'page' => page.to_liquid,
52
+ 'models' => Locomotive::Steam::Liquid::Drops::ContentTypes.new,
53
+ 'contents' => Locomotive::Steam::Liquid::Drops::ContentTypes.new,
54
+ 'session' => Locomotive::Steam::Liquid::Drops::SessionProxy.new,
55
+ }.merge(env['steam.liquid_assigns'])
56
+ end
57
+
58
+ def _locale_liquid_assigns
59
+ {
60
+ 'locale' => locale.to_s,
61
+ 'default_locale' => site.default_locale.to_s,
62
+ 'locales' => site.locales.map(&:to_s)
63
+ }
64
+ end
65
+
66
+ def _request_liquid_assigns
67
+ {
68
+ 'base_url' => request.base_url,
69
+ 'fullpath' => request.fullpath,
70
+ 'http_method' => request.request_method,
71
+ 'ip_address' => request.ip,
72
+ 'mounted_on' => mounted_on,
73
+ 'path' => request.path,
74
+ 'referer' => request.referer,
75
+ 'url' => request.url,
76
+ 'user_agent' => request.user_agent,
77
+ 'host' => request.host_with_port
78
+ }
79
+ end
80
+
81
+ def _http_actions_liquid_assigns
82
+ {
83
+ 'head?' => request.head?,
84
+ 'get?' => request.get?,
85
+ 'post?' => request.post?,
86
+ 'put?' => request.put?,
87
+ 'delete?' => request.delete?
88
+ }
89
+ end
90
+
91
+ end
92
+ end
93
+ end
94
+ end
@@ -0,0 +1,45 @@
1
+ module Locomotive::Steam
2
+ module Middlewares
3
+
4
+ # Redirect to the resource (page, templatized page with a content entry)
5
+ # based on the encoded link in the url.
6
+ # The link is encoded by the UrlPicker component (engine).
7
+ #
8
+ # For SEO purpose, the encoded link shouldn't be shared. It's just for internal purposes.
9
+ #
10
+ # Example:
11
+ #
12
+ # /_locomotive-link/eyJ0eXBlIjoiX2V4dGVybmFsIiwidmFsdWUiOiJodHRwczovL3d3dy5ub2NvZmZlZS5mciIsImxhYmVsIjpbImV4dGVybmFsIiwiaHR0cHM6Ly93d3cubm9jb2ZmZWUuZnIiXX0
13
+ #
14
+ # will redirect (302) to https://www.nocoffee.fr
15
+ #
16
+ class EncodedLinkRedirection < ThreadSafe
17
+
18
+ include Concerns::Helpers
19
+
20
+ PATH_REGEXP = /\/_locomotive-link\/(?<link>[^\"]+)/mo.freeze
21
+
22
+ def _call
23
+ if env['PATH_INFO'] =~ PATH_REGEXP
24
+ resource = url_finder.decode_link($~[:link])
25
+
26
+ # set the locale
27
+ if resource && resource['locale']
28
+ services.locale = 'fr'
29
+ end
30
+
31
+ link, _ = url_finder.url_for(resource)
32
+
33
+ redirect_to link, 302
34
+ end
35
+ end
36
+
37
+ private
38
+
39
+ def url_finder
40
+ services.url_finder
41
+ end
42
+
43
+ end
44
+ end
45
+ end
@@ -5,7 +5,7 @@ module Locomotive::Steam
5
5
  #
6
6
  class EntrySubmission < ThreadSafe
7
7
 
8
- include Helpers
8
+ include Concerns::Helpers
9
9
 
10
10
  HTTP_REGEXP = /^https?:\/\//o
11
11
  ENTRY_SUBMISSION_REGEXP = /^\/entry_submissions\/(\w+)/o
@@ -5,7 +5,7 @@ module Locomotive::Steam
5
5
 
6
6
  attr_accessor_initialize :app
7
7
 
8
- include Helpers
8
+ include Concerns::Helpers
9
9
 
10
10
  def call(env)
11
11
  if env['PATH_INFO'] == '/favicon.ico'
@@ -9,16 +9,19 @@ module Locomotive::Steam
9
9
  # /fr/ => locale = :fr
10
10
  # /index => locale = :en (default one)
11
11
  #
12
- # The
12
+ # /en/index?locale=fr => locale = :fr
13
+ # /index => redirection to /en if the locale in session is :en
13
14
  #
14
15
  class Locale < ThreadSafe
15
16
 
16
- include Helpers
17
+ include Concerns::Helpers
17
18
 
18
19
  def _call
19
- locale = extract_locale
20
+ env['steam.path'] = request.path_info
20
21
 
21
- log "Detecting locale #{locale.upcase}"
22
+ env['steam.locale'] = session[session_key_name] = services.locale = extract_locale
23
+
24
+ log "Locale used: #{locale.upcase}"
22
25
 
23
26
  I18n.with_locale(locale) do
24
27
  self.next
@@ -28,24 +31,69 @@ module Locomotive::Steam
28
31
  protected
29
32
 
30
33
  def extract_locale
31
- _locale = locale_from_params || default_locale
32
- _path = request.path_info
34
+ # Regarding the index page (basically, "/"), we've to see if we could
35
+ # guess the locale from the headers the browser sends to us.
36
+ locale = if is_index_page?
37
+ locale_from_params || locale_from_session || locale_from_header
38
+ else
39
+ locale_from_path || locale_from_params
40
+ end
33
41
 
34
- if _path =~ /^\/(#{site.locales.join('|')})+(\/|$)/
35
- _locale = $1
36
- _path = _path.gsub($1 + $2, '')
42
+ # make sure, the locale is among the ones defined in the site,
43
+ # otherwise take the default one.
44
+ locale && locales.include?(locale) ? locale : default_locale
45
+ end
37
46
 
38
- # let the other middlewares that the locale was
39
- # extracted from the path.
47
+ def locale_from_params
48
+ params[:locale]&.to_sym.tap do |locale|
49
+ log 'Locale extracted from the params' unless locale.blank?
50
+ end
51
+ end
52
+
53
+ def locale_from_path
54
+ path = request.path_info
55
+
56
+ if path =~ /^\/(#{site.locales.join('|')})+(\/|$)/
57
+ locale = $1
58
+
59
+ # no need to keep the locale in the path used to fetch the page
60
+ env['steam.path'] = path.gsub($1 + $2, '')
40
61
  env['steam.locale_in_path'] = true
62
+
63
+ log 'Locale extracted from the path'
64
+
65
+ locale.to_sym
41
66
  end
67
+ end
42
68
 
43
- env['steam.path'] = _path
44
- env['steam.locale'] = services.locale = _locale
69
+ def locale_from_header
70
+ request.accept_language.lazy
71
+ .sort { |a, b| b[1] <=> a[1] }
72
+ .map { |lang, _| lang[0..1].to_sym }
73
+ .find { |lang| locales.include?(lang) }.tap do |locale|
74
+ log 'Locale extracted from the header' unless locale.blank?
75
+ end
45
76
  end
46
77
 
47
- def locale_from_params
48
- locales.include?(params[:locale]) ? params[:locale] : nil
78
+ def locale_from_session
79
+ if locale = session[session_key_name]
80
+ env['steam.locale_in_session'] = true
81
+
82
+ log 'Locale extracted from the session'
83
+
84
+ locale.to_sym
85
+ end
86
+ end
87
+
88
+ # The preview urls for all the sites share the same domain, so session[:locale]
89
+ # would be the same for all the preview urls and this is not good.
90
+ # This is why we need to use a different key.
91
+ def session_key_name
92
+ live_editing? ? "steam-locale-#{site.handle}" : 'steam-locale'
93
+ end
94
+
95
+ def is_index_page?
96
+ ['/', ''].include?(request.path_info)
49
97
  end
50
98
 
51
99
  end