locomotivecms_steam 1.2.0.beta1 → 1.2.0.rc1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +2 -1
- data/Gemfile.lock +36 -36
- data/lib/locomotive/steam/adapters/filesystem/yaml_loaders/content_entry.rb +9 -1
- data/lib/locomotive/steam/decorators/page_decorator.rb +20 -0
- data/lib/locomotive/steam/decorators/template_decorator.rb +0 -1
- data/lib/locomotive/steam/entities/content_entry.rb +5 -4
- data/lib/locomotive/steam/entities/content_type.rb +5 -0
- data/lib/locomotive/steam/entities/page.rb +1 -2
- data/lib/locomotive/steam/liquid/drops/base.rb +17 -13
- data/lib/locomotive/steam/liquid/drops/content_entry.rb +5 -1
- data/lib/locomotive/steam/liquid/drops/metafields.rb +8 -3
- data/lib/locomotive/steam/liquid/filters/misc.rb +1 -1
- data/lib/locomotive/steam/liquid/filters/resize.rb +1 -1
- data/lib/locomotive/steam/liquid/tags/with_scope.rb +12 -1
- data/lib/locomotive/steam/middlewares/entry_submission.rb +23 -4
- data/lib/locomotive/steam/middlewares/page.rb +12 -2
- data/lib/locomotive/steam/middlewares/renderer.rb +7 -6
- data/lib/locomotive/steam/middlewares/sitemap.rb +11 -0
- data/lib/locomotive/steam/middlewares/thread_safe.rb +4 -0
- data/lib/locomotive/steam/models/i18n_field.rb +1 -1
- data/lib/locomotive/steam/repositories/content_type_field_repository.rb +3 -1
- data/lib/locomotive/steam/server.rb +0 -1
- data/lib/locomotive/steam/services/external_api_service.rb +8 -1
- data/lib/locomotive/steam/services/image_resizer_service.rb +1 -1
- data/lib/locomotive/steam/services/page_finder_service.rb +4 -0
- data/lib/locomotive/steam/version.rb +1 -1
- data/locomotivecms_steam.gemspec +4 -5
- data/spec/fixtures/default/app/views/pages/all.liquid.haml +4 -1
- data/spec/fixtures/default/app/views/pages/contact.liquid.haml +8 -1
- data/spec/fixtures/default/app/views/pages/events.liquid.haml +7 -0
- data/spec/fixtures/default/app/views/pages/tags/nav_in_deep.liquid.haml +2 -2
- data/spec/fixtures/default/data/updates.yml +4 -2
- data/spec/integration/server/contact_form_spec.rb +13 -0
- data/spec/integration/server/nav_spec.rb +4 -0
- data/spec/integration/server/sitemap_spec.rb +2 -2
- data/spec/support/helpers.rb +2 -0
- data/spec/unit/adapters/filesystem/yaml_loaders/content_entry_spec.rb +17 -0
- data/spec/unit/decorators/page_decorator_spec.rb +36 -0
- data/spec/unit/decorators/template_decorator_spec.rb +1 -0
- data/spec/unit/entities/content_type_spec.rb +34 -0
- data/spec/unit/entities/page_spec.rb +0 -24
- data/spec/unit/liquid/drops/content_entry_spec.rb +10 -2
- data/spec/unit/liquid/drops/metafields_spec.rb +35 -6
- data/spec/unit/liquid/filters/resize_spec.rb +17 -0
- data/spec/unit/liquid/tags/with_scope_spec.rb +15 -0
- data/spec/unit/middlewares/page_spec.rb +63 -0
- data/spec/unit/middlewares/renderer_spec.rb +2 -4
- data/spec/unit/middlewares/sitemap_spec.rb +41 -1
- data/spec/unit/services/external_api_service_spec.rb +10 -0
- data/spec/unit/services/image_resizer_service_spec.rb +3 -3
- metadata +15 -24
@@ -11,6 +11,7 @@ module Locomotive::Steam
|
|
11
11
|
ENTRY_SUBMISSION_REGEXP = /^\/entry_submissions\/(\w+)/o
|
12
12
|
SUBMITTED_TYPE_PARAM = 'submitted_type_slug'
|
13
13
|
SUBMITTED_PARAM = 'submitted_entry_slug'
|
14
|
+
CONTENT_TYPE_PARAM = 'content_type_slug'
|
14
15
|
|
15
16
|
def _call
|
16
17
|
# we didn't go through the locale middleware yet,
|
@@ -72,8 +73,26 @@ module Locomotive::Steam
|
|
72
73
|
end
|
73
74
|
|
74
75
|
def entry_to_query_string(entry)
|
75
|
-
|
76
|
-
|
76
|
+
service_params = [
|
77
|
+
services.csrf_protection.field,
|
78
|
+
CONTENT_TYPE_PARAM,
|
79
|
+
SUBMITTED_TYPE_PARAM,
|
80
|
+
SUBMITTED_PARAM,
|
81
|
+
'success_callback',
|
82
|
+
'error_callback',
|
83
|
+
'content',
|
84
|
+
'entry'
|
85
|
+
]
|
86
|
+
|
87
|
+
[].tap do |list|
|
88
|
+
params.each do |key, value|
|
89
|
+
next if service_params.include?(key)
|
90
|
+
list << "#{key}=#{value}"
|
91
|
+
end
|
92
|
+
|
93
|
+
list << "#{SUBMITTED_TYPE_PARAM}=#{entry.content_type_slug}"
|
94
|
+
list << "#{SUBMITTED_PARAM}=#{entry._slug}"
|
95
|
+
end.join('&')
|
77
96
|
end
|
78
97
|
|
79
98
|
def with_locale(&block)
|
@@ -109,8 +128,8 @@ module Locomotive::Steam
|
|
109
128
|
# or from the presence of the content_type_slug param (model_form tag).
|
110
129
|
#
|
111
130
|
def get_content_type_slug
|
112
|
-
if request.post? && (request.path_info =~ ENTRY_SUBMISSION_REGEXP || params[
|
113
|
-
$1 || params[
|
131
|
+
if request.post? && (request.path_info =~ ENTRY_SUBMISSION_REGEXP || params[CONTENT_TYPE_PARAM])
|
132
|
+
$1 || params[CONTENT_TYPE_PARAM]
|
114
133
|
end
|
115
134
|
end
|
116
135
|
|
@@ -26,11 +26,21 @@ module Locomotive::Steam
|
|
26
26
|
protected
|
27
27
|
|
28
28
|
def fetch_page
|
29
|
-
|
29
|
+
page = page_finder.match(path).tap do |pages|
|
30
30
|
if pages.size > 1
|
31
31
|
self.log "Found multiple pages: #{pages.map(&:title).join(', ')}"
|
32
32
|
end
|
33
|
-
end.first
|
33
|
+
end.first
|
34
|
+
|
35
|
+
if page && (page.published? || page.not_found? || live_editing?)
|
36
|
+
page
|
37
|
+
else
|
38
|
+
page_finder.find('404')
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def page_finder
|
43
|
+
services.page_finder
|
34
44
|
end
|
35
45
|
|
36
46
|
end
|
@@ -16,7 +16,7 @@ module Locomotive::Steam
|
|
16
16
|
private
|
17
17
|
|
18
18
|
def render_page
|
19
|
-
if page.
|
19
|
+
if page.redirect?
|
20
20
|
redirect_to(page.redirect_url, page.redirect_type)
|
21
21
|
else
|
22
22
|
content = parse_and_render_liquid
|
@@ -73,7 +73,7 @@ module Locomotive::Steam
|
|
73
73
|
'today' => Date.today,
|
74
74
|
'mode' => Locomotive::Steam.configuration.mode,
|
75
75
|
'wagon' => Locomotive::Steam.configuration.mode == :test,
|
76
|
-
'live_editing' =>
|
76
|
+
'live_editing' => live_editing?
|
77
77
|
}
|
78
78
|
end
|
79
79
|
|
@@ -98,14 +98,15 @@ module Locomotive::Steam
|
|
98
98
|
|
99
99
|
def _request_liquid_assigns
|
100
100
|
{
|
101
|
-
'
|
101
|
+
'base_url' => request.base_url,
|
102
102
|
'fullpath' => request.fullpath,
|
103
|
-
'url' => request.url,
|
104
103
|
'ip_address' => request.ip,
|
104
|
+
'mounted_on' => mounted_on,
|
105
|
+
'path' => request.path,
|
105
106
|
'post?' => request.post?,
|
106
|
-
'
|
107
|
+
'referer' => request.referer,
|
108
|
+
'url' => request.url,
|
107
109
|
'user_agent' => request.user_agent,
|
108
|
-
'mounted_on' => mounted_on
|
109
110
|
}
|
110
111
|
end
|
111
112
|
|
@@ -53,6 +53,8 @@ module Locomotive::Steam
|
|
53
53
|
def build_templatized_page_xml(page, locale)
|
54
54
|
content_type = repositories.content_type.find(page.content_type_id)
|
55
55
|
|
56
|
+
return nil unless build_templatized_page_xml?(page, content_type, locale)
|
57
|
+
|
56
58
|
repositories.content_entry.with(content_type).all.map do |entry|
|
57
59
|
_entry = Locomotive::Steam::Decorators::I18nDecorator.new(entry, locale)
|
58
60
|
|
@@ -88,6 +90,15 @@ module Locomotive::Steam
|
|
88
90
|
services.url_builder.url_for(page, locale)
|
89
91
|
end
|
90
92
|
|
93
|
+
def build_templatized_page_xml?(page, content_type, locale)
|
94
|
+
return true if content_type.localized? || default_locale == locale
|
95
|
+
|
96
|
+
# does the templatized page have the same source
|
97
|
+
# (liquid template) as in the default locale?
|
98
|
+
# If so, no need to add a xml entry for this page
|
99
|
+
!page.source.blank?
|
100
|
+
end
|
101
|
+
|
91
102
|
def base_url
|
92
103
|
"#{request.scheme}://#{request.host_with_port}"
|
93
104
|
end
|
@@ -58,7 +58,9 @@ module Locomotive
|
|
58
58
|
end
|
59
59
|
|
60
60
|
def localized_names
|
61
|
-
query { where(localized: true) }.all.map
|
61
|
+
query { where(localized: true) }.all.map do |field|
|
62
|
+
field.type == :select ? [field.name, "#{field.name}_id"] : field.name
|
63
|
+
end.flatten
|
62
64
|
end
|
63
65
|
|
64
66
|
def default
|
@@ -16,6 +16,10 @@ module Locomotive
|
|
16
16
|
username, password = options.delete(:username), options.delete(:password)
|
17
17
|
options[:basic_auth] = { username: username, password: password } if username
|
18
18
|
|
19
|
+
# authorization header ?
|
20
|
+
header_auth = options.delete(:header_auth)
|
21
|
+
options[:headers] = { 'Authorization' => header_auth } if header_auth
|
22
|
+
|
19
23
|
perform_request_to(path, options)
|
20
24
|
end
|
21
25
|
|
@@ -37,7 +41,10 @@ module Locomotive
|
|
37
41
|
|
38
42
|
# sanitize the options
|
39
43
|
options[:format] = options[:format].gsub(/[\'\"]/, '').to_sym if options.has_key?(:format)
|
40
|
-
|
44
|
+
if options[:with_user_agent]
|
45
|
+
user_agent = { 'User-Agent' => 'LocomotiveCMS' }
|
46
|
+
options[:headers] ? options[:headers].merge!(user_agent) : options[:headers] = user_agent
|
47
|
+
end
|
41
48
|
|
42
49
|
response = self.class.get(path, options)
|
43
50
|
parsed_response = response.parsed_response
|
@@ -6,7 +6,7 @@ module Locomotive
|
|
6
6
|
attr_accessor_initialize :resizer, :asset_path
|
7
7
|
|
8
8
|
def resize(source, geometry)
|
9
|
-
return
|
9
|
+
return get_url_or_path(source) if disabled? || geometry.blank?
|
10
10
|
|
11
11
|
if file = fetch_file(source)
|
12
12
|
file.thumb(geometry).url
|
@@ -27,6 +27,10 @@ module Locomotive
|
|
27
27
|
|
28
28
|
private
|
29
29
|
|
30
|
+
def decorate(&block)
|
31
|
+
super(Decorators::PageDecorator, &block)
|
32
|
+
end
|
33
|
+
|
30
34
|
# Instead of hitting the DB each time we want a page from its handle,
|
31
35
|
# just get all the handles at once and cache the result. (up to 20% boost)
|
32
36
|
#
|
data/locomotivecms_steam.gemspec
CHANGED
@@ -18,10 +18,10 @@ Gem::Specification.new do |spec|
|
|
18
18
|
spec.add_development_dependency 'bundler', '~> 1.7'
|
19
19
|
spec.add_development_dependency 'rake', '~> 10.4.2'
|
20
20
|
|
21
|
-
spec.add_development_dependency 'mongo', '~> 2.2.
|
22
|
-
spec.add_development_dependency 'origin', '~> 2.
|
21
|
+
spec.add_development_dependency 'mongo', '~> 2.2.7'
|
22
|
+
spec.add_development_dependency 'origin', '~> 2.2.0'
|
23
23
|
|
24
|
-
spec.add_dependency 'nokogiri', '~> 1.6.
|
24
|
+
spec.add_dependency 'nokogiri', '~> 1.6.8'
|
25
25
|
spec.add_dependency 'sanitize', '~> 4.0.1'
|
26
26
|
spec.add_dependency 'morphine', '~> 0.1.1'
|
27
27
|
spec.add_dependency 'httparty', '~> 0.13.6'
|
@@ -40,8 +40,7 @@ Gem::Specification.new do |spec|
|
|
40
40
|
spec.add_dependency 'autoprefixer-rails', '~> 6.3.3.1'
|
41
41
|
|
42
42
|
spec.add_dependency 'kramdown', '~> 1.10.0'
|
43
|
-
spec.add_dependency 'RedCloth', '~> 4.2
|
44
|
-
spec.add_dependency 'haml', '~> 4.0.6'
|
43
|
+
spec.add_dependency 'RedCloth', '~> 4.3.2'
|
45
44
|
spec.add_dependency 'mimetype-fu', '~> 0.1.2'
|
46
45
|
spec.add_dependency 'mime-types', '~> 2.6.1'
|
47
46
|
spec.add_dependency 'duktape', '~> 1.3.0.6'
|
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
title: All the pages
|
3
3
|
listed: false
|
4
|
-
published:
|
4
|
+
published: true
|
5
5
|
---
|
6
6
|
{% extends parent %}
|
7
7
|
{% block content %}
|
@@ -10,4 +10,7 @@ published: false
|
|
10
10
|
<li>{{ page.title }}</li>
|
11
11
|
{% endfor %}
|
12
12
|
</ul>
|
13
|
+
|
14
|
+
<!-- TEST -->{{ site.index.children | map: 'title' | join: " - " }}<!-- TEST -->
|
15
|
+
|
13
16
|
{% endblock %}
|
@@ -13,10 +13,17 @@ position: 4
|
|
13
13
|
Ut imperdiet velit eu metus semper tristique. Vivamus risus nisi, tincidunt et euismod a, auctor pretium eros. Vestibulum sed magna et velit pulvinar euismod. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean sed velit quis nisl blandit vulputate id non tortor. Mauris nec placerat massa. Vivamus sed odio non ligula pharetra pretium. Ut convallis, purus et lobortis suscipit, mauris orci ullamcorper lectus, nec vulputate turpis mauris sed augue. Maecenas faucibus ultricies nisl, non ullamcorper justo bibendum nec. Duis vitae mauris condimentum risus commodo mattis vel sed libero. Fusce diam elit, porta id vestibulum ut, aliquet mattis neque.
|
14
14
|
{% endeditable_long_text %}
|
15
15
|
|
16
|
+
{% if message.errors %}
|
17
|
+
.text
|
18
|
+
%p Form with errors
|
19
|
+
{% endif %}
|
20
|
+
|
16
21
|
%form#contactform{ :name => 'contact', :action => '{{ contents.messages.public_submission_url }}.json', :method => 'post' }
|
17
22
|
/ %input{ type: 'hidden', name: 'success_callback', value: '/events' }
|
18
23
|
/ %input{ type: 'hidden', name: 'error_callback', value: '/contact' }
|
19
24
|
|
25
|
+
%input{ type: 'hidden', name: 'some_variable', value: '42' }
|
26
|
+
|
20
27
|
%p
|
21
28
|
%label{ :for => 'name' } Name
|
22
29
|
%input{ :type => 'text', :id => 'name', :name => 'content[name]', :placeholder => 'First and last name', :tabindex => '1', required: 'required', value: '{{ message.name }}' }
|
@@ -51,4 +58,4 @@ position: 4
|
|
51
58
|
});
|
52
59
|
});
|
53
60
|
|
54
|
-
{% endblock %}
|
61
|
+
{% endblock %}
|
@@ -5,8 +5,15 @@ position: 5
|
|
5
5
|
|
6
6
|
{% block content %}
|
7
7
|
|
8
|
+
{% if message.errors %}
|
9
|
+
.text
|
10
|
+
%p Form with errors
|
11
|
+
{% endif %}
|
12
|
+
|
8
13
|
%p Thank you {{ message.name }} !
|
9
14
|
|
15
|
+
%p Some variable: {{ params.some_variable }}
|
16
|
+
|
10
17
|
#events.unit.size2of3
|
11
18
|
%h2 Upcoming events
|
12
19
|
|
@@ -5,7 +5,9 @@
|
|
5
5
|
en: john posted a new post
|
6
6
|
fr: phrase FR
|
7
7
|
date: 2009/11/16
|
8
|
-
category:
|
8
|
+
category:
|
9
|
+
en: General
|
10
|
+
fr: Général
|
9
11
|
- "Update #5":
|
10
12
|
title:
|
11
13
|
fr: "Mise a jour #5"
|
@@ -45,4 +47,4 @@
|
|
45
47
|
en: added some free stuff
|
46
48
|
fr: phrase FR
|
47
49
|
date: 2009/05/12
|
48
|
-
category: General
|
50
|
+
category: General
|
@@ -78,6 +78,10 @@ describe 'ContactForm' do
|
|
78
78
|
expect(response.status).to eq 200
|
79
79
|
end
|
80
80
|
|
81
|
+
it 'displays a global error message' do
|
82
|
+
expect(response.body.to_s).to include "Form with errors"
|
83
|
+
end
|
84
|
+
|
81
85
|
it 'displays errors' do
|
82
86
|
expect(response.body.to_s).to include "can't be blank"
|
83
87
|
end
|
@@ -104,6 +108,10 @@ describe 'ContactForm' do
|
|
104
108
|
expect(response.status).to eq 200
|
105
109
|
end
|
106
110
|
|
111
|
+
it "doesn't display a global error message" do
|
112
|
+
expect(response.body.to_s).not_to include "Form with errors"
|
113
|
+
end
|
114
|
+
|
107
115
|
it 'displays a success message' do
|
108
116
|
expect(response.body.to_s).to include 'Thank you John'
|
109
117
|
end
|
@@ -130,6 +138,7 @@ describe 'ContactForm' do
|
|
130
138
|
let(:url) { '/events' }
|
131
139
|
let(:params) { {
|
132
140
|
'content_type_slug' => 'messages',
|
141
|
+
'some_variable' => '42',
|
133
142
|
'entry' => { 'name' => 'John', 'email' => 'j@doe.net', 'message' => 'Bla bla' } } }
|
134
143
|
let(:response) { post_contact_form(url, params) }
|
135
144
|
let(:status) { response.status }
|
@@ -160,6 +169,10 @@ describe 'ContactForm' do
|
|
160
169
|
expect(response.body.to_s).to include 'Thank you John'
|
161
170
|
end
|
162
171
|
|
172
|
+
it 'stores hidden fields from the form' do
|
173
|
+
expect(response.body.to_s).to include 'Some variable: 42'
|
174
|
+
end
|
175
|
+
|
163
176
|
end
|
164
177
|
|
165
178
|
context 'in a different locale' do
|
@@ -29,6 +29,10 @@ describe Locomotive::Steam::Server do
|
|
29
29
|
is_expected.to include('<li>A song template</li>')
|
30
30
|
end
|
31
31
|
|
32
|
+
it 'lists all the pages from the site liquid drop' do
|
33
|
+
is_expected.to include('<!-- TEST -->About Us - Music - Store - Contact Us - Events - Basic page - A sample contest - Various uses of the with_scope tag - Grunge leaders - Tags - Unlisted pages - Archives - All the pages - Layouts - Songs<!-- TEST -->')
|
34
|
+
end
|
35
|
+
|
32
36
|
describe 'with wrapper' do
|
33
37
|
|
34
38
|
subject { get '/tags/nav'; last_response.body }
|
@@ -21,7 +21,7 @@ describe Locomotive::Steam::Server do
|
|
21
21
|
|
22
22
|
it 'checks if it looks valid' do
|
23
23
|
expect(Nokogiri::XML(subject).errors.empty?).to eq true
|
24
|
-
expect(subject.scan(/<url>/).size).to eq
|
24
|
+
expect(subject.scan(/<url>/).size).to eq 40
|
25
25
|
expect(subject).to match("<loc>http://example.org/songs/song-number-2/band</loc>")
|
26
26
|
expect(subject).to match((<<-EOF
|
27
27
|
<url>
|
@@ -36,7 +36,7 @@ describe Locomotive::Steam::Server do
|
|
36
36
|
context 'existing sitemap page' do
|
37
37
|
|
38
38
|
let(:template) { %{<?xml version="1.0" encoding="utf-8"?>OK</xml>} }
|
39
|
-
let(:page) { instance_double('Page', liquid_source: template, templatized?: false,
|
39
|
+
let(:page) { instance_double('Page', liquid_source: template, templatized?: false, redirect?: false, to_liquid: template, not_found?: false, response_type: 'application/xml') }
|
40
40
|
let(:env) { { 'steam.page' => page } }
|
41
41
|
|
42
42
|
it 'renders the existing sitemap page' do
|
data/spec/support/helpers.rb
CHANGED
@@ -45,6 +45,23 @@ describe Locomotive::Steam::Adapters::Filesystem::YAMLLoaders::ContentEntry do
|
|
45
45
|
|
46
46
|
end
|
47
47
|
|
48
|
+
context 'a content type with a localized field' do
|
49
|
+
|
50
|
+
let(:options_scope) { instance_double('Scope', :locale= => true) }
|
51
|
+
let(:options) { instance_double('SelectOptionsRepository', scope: options_scope) }
|
52
|
+
let(:field) { instance_double('Field', name: 'category', type: :select, localized: true, select_options: options) }
|
53
|
+
let(:content_type) { instance_double('Updates', slug: 'updates', select_fields: [field], association_fields: [], file_fields: []) }
|
54
|
+
|
55
|
+
it 'adds a new localized attribute for the foreign key' do
|
56
|
+
option = instance_double('Option', _id: 'General')
|
57
|
+
allow(options).to receive(:by_name).with('General').and_return(option)
|
58
|
+
allow(options).to receive(:by_name).with('Général').and_return(option)
|
59
|
+
expect(subject.last[:category_id]).to eq({ en: 'General', fr: 'General' })
|
60
|
+
expect(subject.last[:category]).to eq nil
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
64
|
+
|
48
65
|
context 'a content type with a file field' do
|
49
66
|
|
50
67
|
let(:field) { instance_double('Field', name: 'cover', type: :file) }
|