contentful_middleman 1.1.1 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +7 -3
- data/CHANGELOG.md +10 -0
- data/CONTRIBUTING.md +1 -1
- data/Gemfile +1 -2
- data/Guardfile +5 -0
- data/README.md +122 -8
- data/contentful_middleman.gemspec +9 -3
- data/lib/contentful_middleman/commands/contentful.rb +0 -1
- data/lib/contentful_middleman/core.rb +18 -0
- data/lib/contentful_middleman/helpers.rb +29 -0
- data/lib/contentful_middleman/import_task.rb +6 -3
- data/lib/contentful_middleman/instance.rb +26 -5
- data/lib/contentful_middleman/mappers/base.rb +10 -2
- data/lib/contentful_middleman/version.rb +1 -1
- data/lib/contentful_middleman/webhook_handler.rb +33 -0
- data/spec/contentful_middleman/commands/context_spec.rb +22 -0
- data/spec/contentful_middleman/core_spec.rb +89 -0
- data/spec/contentful_middleman/helpers_spec.rb +99 -0
- data/spec/contentful_middleman/import_task_spec.rb +41 -0
- data/spec/contentful_middleman/instance_spec.rb +71 -0
- data/spec/contentful_middleman/local_data/file_spec.rb +34 -0
- data/spec/contentful_middleman/local_data/store_spec.rb +47 -0
- data/spec/contentful_middleman/mappers/base_spec.rb +88 -0
- data/spec/contentful_middleman/tools/backup_spec.rb +113 -0
- data/spec/contentful_middleman/version_hash_spec.rb +58 -0
- data/spec/contentful_middleman/webhook_handler_spec.rb +32 -0
- data/spec/fixtures/backup_fixtures/.tmp/backups/.gitkeep +0 -0
- data/spec/fixtures/backup_fixtures/baz +0 -0
- data/spec/fixtures/space_hash_fixtures/.blah-space-hash +1 -0
- data/spec/fixtures/space_hash_fixtures/.foo-space-hash +1 -0
- data/spec/fixtures/space_hash_fixtures/.foobar-space-hash +1 -0
- data/spec/fixtures/space_hash_fixtures/.my_space-space-hash +1 -0
- data/spec/fixtures/vcr_fixtures/instance/entries_1.yml +93 -0
- data/spec/fixtures/vcr_fixtures/instance/entries_2.yml +293 -0
- data/spec/fixtures/vcr_fixtures/mappers/entries.yml +913 -0
- data/spec/fixtures/vcr_fixtures/mappers/entries_localized.yml +996 -0
- data/spec/spec_helper.rb +57 -2
- metadata +153 -14
- data/TODO +0 -15
- data/spec/contentful_middleman_spec.rb +0 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 25dc16eb8eaa65244fc568404d2e3cf413c8dd34
|
4
|
+
data.tar.gz: e0ab36f581ddb8e6848e4aa3e9b0e4dd0611c70a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8f46e858aa74ed09a603e7e16b27d18d8c62dae561c7952e75fc30f106a8768b0e1363b5dff5905301cbb98b9d37149fab6cb1382188c67112cd1af4f08ce5fe
|
7
|
+
data.tar.gz: 4a1948b0b9a1e0a40ca1afbf76413b4ad86275ee61590fa63ee1c71fc4bc04cc3360c5ee690a1bed9e7103506307fed28608c05eb97fbe237ea10ca40edbbf40
|
data/.travis.yml
CHANGED
@@ -1,8 +1,12 @@
|
|
1
1
|
rvm:
|
2
|
-
- 1.9.3
|
3
2
|
- 2.0.0
|
4
|
-
-
|
3
|
+
- 2.1.2
|
4
|
+
- 2.2.3
|
5
|
+
- jruby
|
5
6
|
|
6
7
|
script: "bundle exec rake test"
|
7
8
|
|
8
|
-
env: TEST=true
|
9
|
+
env: TEST=true JRUBY_OPTS='--2.0'
|
10
|
+
notifications:
|
11
|
+
slack:
|
12
|
+
secure: MMWxqKMT4m2UhZ+Ix4wgCs1nLvu9hUFCbyV/qJWmIFif7V4GUKXi6h9krMqGqBAd3YV3pP/InPlw3QoKBUGIAIr5GzDpSnU5ACv7E61v548qViEvPBqsfhRHha2M164rUHn32tpejJnIizVUyND/hIzNviIrab+G8uOaZXUtB5I=
|
data/CHANGELOG.md
CHANGED
@@ -1,4 +1,14 @@
|
|
1
1
|
# Change Log
|
2
|
+
## Unreleased
|
3
|
+
|
4
|
+
## 1.2.0
|
5
|
+
### Added
|
6
|
+
* Include `:all_entries` option to `activate` block for getting over 1000 entries[#45](https://github.com/contentful-labs/contentful_middleman/issues/45)
|
7
|
+
* Update `middleman-core` required version
|
8
|
+
* Removes `middleman-blog` dependency[#9](https://github.com/contentful-labs/contentful_middleman/issues/9)
|
9
|
+
* Add Webhook Integration[#55](https://github.com/contentful-labs/contentful_middleman/pull/55)
|
10
|
+
* Clarify that `:all_entries` may need an `:order` attribute in the `:cda_query` for avoiding entry skipping and provided a sane default[#60](https://github.com/contentful/contentful_middleman/issues/60)
|
11
|
+
* Add Localize Helpers
|
2
12
|
|
3
13
|
## 1.1.1
|
4
14
|
### Changed
|
data/CONTRIBUTING.md
CHANGED
@@ -16,7 +16,7 @@ Here are some ways *you* can contribute:
|
|
16
16
|
* by closing [issues][]
|
17
17
|
* by reviewing patches
|
18
18
|
|
19
|
-
[issues]: https://github.com/
|
19
|
+
[issues]: https://github.com/contentful-labs/contentful_middleman/issues
|
20
20
|
|
21
21
|
## Submitting an Issue
|
22
22
|
We use the [GitHub issue tracker][issues] to track bugs and features. Before
|
data/Gemfile
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
# the following line to use "https"
|
3
3
|
source 'http://rubygems.org'
|
4
4
|
|
5
|
-
gem "middleman-core",
|
5
|
+
gem "middleman-core", '~> 3.4'
|
6
6
|
|
7
7
|
# Specify your gem's dependencies in contentful_middleman.gemspec
|
8
8
|
gemspec
|
@@ -15,4 +15,3 @@ gem "rspec"
|
|
15
15
|
gem "simplecov"
|
16
16
|
|
17
17
|
gem "cane", :platforms => [:mri_19, :mri_20], :require => false
|
18
|
-
gem 'coveralls', :require => false
|
data/Guardfile
ADDED
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# Contentful Middleman
|
2
2
|
|
3
|
-
[![Build Status](https://travis-ci.org/contentful
|
3
|
+
[![Build Status](https://travis-ci.org/contentful/contentful_middleman.svg?branch=master)](https://travis-ci.org/contentful/contentful_middleman)
|
4
4
|
|
5
5
|
Contentful Middleman is a [Middleman](http://middlemanapp.com/) extension to use the Middleman static site generator together with the API-driven [Contentful CMS](https://www.contentful.com). It is powered by the [Contentful Ruby Gem](https://github.com/contentful/contentful.rb).
|
6
6
|
|
@@ -44,15 +44,19 @@ activate :contentful do |f|
|
|
44
44
|
end
|
45
45
|
```
|
46
46
|
|
47
|
-
Parameter
|
48
|
-
----------
|
49
|
-
space
|
50
|
-
access_token
|
51
|
-
cda_query
|
52
|
-
content_types
|
53
|
-
use_preview_api
|
47
|
+
Parameter | Description
|
48
|
+
---------- | ------------
|
49
|
+
space | Hash with an user choosen name for the space as key and the space id as value
|
50
|
+
access_token | Contentful Delivery API access token
|
51
|
+
cda_query | Hash describing query configuration. See [contentful.rb](https://github.com/contentful/contentful.rb) for more info (look for filter options there). Note that by default only 100 entries will be fetched, this can be configured to up to 1000 entries using the `limit` option. Example: `f.cda_query = { limit: 1000 }`
|
52
|
+
content_types | Hash describing the mapping applied to entries of the imported content types
|
53
|
+
use_preview_api | Boolean to toggle the used API. Set it to `false` to use `cdn.contentful.com` (default value). Set it to `true` to use `preview.contentful.com`. More info in [the documentation](https://www.contentful.com/developers/documentation/content-delivery-api/#preview-api)
|
54
|
+
all_entries | Boolean to toggle multiple requests to the API for getting over 1000 entries. This uses a naive approach and can get rate limited. When using this, have in mind adding an `order` in your `:cda_query` . Default order is `order: 'sys.createdAt'`
|
55
|
+
rebuild_on_webhook | Boolean to toggle Webhook server. Server will run in port 5678, and will be expecting to receive Contentful Webhook calls on `/receive`
|
56
|
+
webhook_timeout | Integer (in seconds) for wait time after Webhook received for rebuilding. Only used if `:rebuild_on_webhook` is true. Defaults to 300 seconds
|
54
57
|
|
55
58
|
You can activate the extension multiple times to import entries from different spaces.
|
59
|
+
|
56
60
|
## Entry mapping
|
57
61
|
|
58
62
|
The extension will transform every fetched entry before storing it as a yaml file in the local
|
@@ -94,6 +98,44 @@ end
|
|
94
98
|
|
95
99
|
There's also an example back-reference mapper in the examples directory for adding back-references onto entries that are linked to by other entries.
|
96
100
|
|
101
|
+
#### Multiple Mappers
|
102
|
+
|
103
|
+
If you want to process a Content Type with multiple mappers, you can use the [Composite Design Pattern](https://en.wikipedia.org/wiki/Composite_pattern).
|
104
|
+
The Mapper code should look something similar to the following.
|
105
|
+
|
106
|
+
Then you can attach as many Custom Mappers as you want to that one.
|
107
|
+
|
108
|
+
```ruby
|
109
|
+
class CompositeMapper < ContentfulMiddleman::Mapper::Base
|
110
|
+
@@mappers = []
|
111
|
+
def self.mappers
|
112
|
+
@@mappers
|
113
|
+
end
|
114
|
+
|
115
|
+
def map(context, entry)
|
116
|
+
super
|
117
|
+
mappers.each do |m|
|
118
|
+
m.map(context, entry)
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
```
|
123
|
+
|
124
|
+
Then in your config.rb file:
|
125
|
+
|
126
|
+
```ruby
|
127
|
+
CompositeMapper.mappers << YourMapper.new
|
128
|
+
CompositeMapper.mappers << OtherMapper.new
|
129
|
+
|
130
|
+
activate :contentful do |f|
|
131
|
+
'... your config here ...'
|
132
|
+
f.content_types = {content_type_name_you_want_to_map: {mapper: CompositeMapper, id: 'content_type_id'}}
|
133
|
+
end
|
134
|
+
```
|
135
|
+
|
136
|
+
*NOTE*: This kind of Composite Mapper is static, therefore if you want to have multiple combinations of mappers
|
137
|
+
for multiple entries, you'd need to write code a bit differently.
|
138
|
+
|
97
139
|
## Configuration: examples
|
98
140
|
|
99
141
|
```ruby
|
@@ -104,6 +146,7 @@ activate :contentful do |f|
|
|
104
146
|
f.content_types = { partner: 'content-type-id'}
|
105
147
|
end
|
106
148
|
```
|
149
|
+
|
107
150
|
The above configuration does the following:
|
108
151
|
|
109
152
|
* Sets the alias `partners` to the space with id _some-id_
|
@@ -158,3 +201,74 @@ For Kramdown this would be:
|
|
158
201
|
```
|
159
202
|
<%= Kramdown::Document.new(data).to_html %>
|
160
203
|
```
|
204
|
+
|
205
|
+
### Locales
|
206
|
+
|
207
|
+
If you have localized entries, and want to display content for multiple locales.
|
208
|
+
You can now include `locale: '*'` in your CDA query.
|
209
|
+
|
210
|
+
Then you have the following methods of accessing locales:
|
211
|
+
|
212
|
+
* **Manual access**
|
213
|
+
|
214
|
+
You can access your localized fields by fetching the locale directly from the data
|
215
|
+
|
216
|
+
```html
|
217
|
+
<h1>Partners</h1>
|
218
|
+
<ol>
|
219
|
+
<% data.partners.partner.each do |id, partner| %>
|
220
|
+
<li><%= partner["name"]['en-US'] %></li>
|
221
|
+
<% end %>
|
222
|
+
</ol>
|
223
|
+
```
|
224
|
+
|
225
|
+
* **Entry Helper**
|
226
|
+
|
227
|
+
You can also map an specific locale for all entry fields using `localize_entry`
|
228
|
+
|
229
|
+
```html
|
230
|
+
<h1>Partners</h1>
|
231
|
+
<ol>
|
232
|
+
<% data.partners.partner.each do |id, partner| %>
|
233
|
+
<% localized_partner = localize_entry(partner, 'es') %>
|
234
|
+
<li><%= localized_partner["name"] %></li>
|
235
|
+
<% end %>
|
236
|
+
</ol>
|
237
|
+
```
|
238
|
+
|
239
|
+
* **Generic Field Helper**
|
240
|
+
|
241
|
+
The `localize` helper will map an specific locale to a field of your entry
|
242
|
+
|
243
|
+
```html
|
244
|
+
<h1>Partners</h1>
|
245
|
+
<ol>
|
246
|
+
<% data.partners.partner.each do |id, partner| %>
|
247
|
+
<li>Value Field: <%= localize(partner, 'name', 'en-US') %></li>
|
248
|
+
<li>Array Field: <%= localize(partner, 'phones', 'es') %></li>
|
249
|
+
<% end %>
|
250
|
+
</ol>
|
251
|
+
```
|
252
|
+
|
253
|
+
* **Specific Field Type Helper**
|
254
|
+
|
255
|
+
Or, you can use `localize_value` or `localize_array` if you want more granularity.
|
256
|
+
|
257
|
+
> This method is discouraged, as `localize` achieves the same goal and is a field-type
|
258
|
+
agnostic wrapper of these methods.
|
259
|
+
|
260
|
+
```html
|
261
|
+
<h1>Partners</h1>
|
262
|
+
<ol>
|
263
|
+
<% data.partners.partner.each do |id, partner| %>
|
264
|
+
<li>Value Field: <%= localize_value(partner['name'], 'en-US') %></li>
|
265
|
+
<li>Array Field: <%= localize_array(partner['phones'], 'es') %></li>
|
266
|
+
<% end %>
|
267
|
+
</ol>
|
268
|
+
```
|
269
|
+
|
270
|
+
If your fields are not localized, the value of the field will be returned.
|
271
|
+
|
272
|
+
In case of the field being localized but no value being set for a given entry, it will use
|
273
|
+
a fallback locale, by default is `en-US` but can be specified as an additional
|
274
|
+
parameter in all the mentioned calls.
|
@@ -21,10 +21,16 @@ Gem::Specification.new do |s|
|
|
21
21
|
# The version of middleman-core your extension depends on
|
22
22
|
s.add_dependency("middleman-core", ["~> 3.3"])
|
23
23
|
|
24
|
-
s.add_dependency("middleman-blog", ["~> 3.5"])
|
25
|
-
|
26
24
|
# Additional dependencies
|
27
|
-
s.add_dependency("contentful")
|
25
|
+
s.add_dependency("contentful", '~> 0.8')
|
26
|
+
s.add_dependency("contentful-webhook-listener", '~> 0.1')
|
28
27
|
|
29
28
|
s.add_development_dependency 'rubygems-tasks', '~> 0.2'
|
29
|
+
s.add_development_dependency "guard"
|
30
|
+
s.add_development_dependency "guard-rspec"
|
31
|
+
s.add_development_dependency "bundler", "~> 1.6"
|
32
|
+
s.add_development_dependency "rake"
|
33
|
+
s.add_development_dependency "rspec"
|
34
|
+
s.add_development_dependency "vcr"
|
35
|
+
s.add_development_dependency "webmock"
|
30
36
|
end
|
@@ -1,8 +1,11 @@
|
|
1
|
+
require 'logger'
|
1
2
|
require 'middleman-core'
|
2
3
|
require 'contentful'
|
4
|
+
require 'contentful/webhook/listener'
|
3
5
|
require_relative 'mappers/base'
|
4
6
|
require_relative 'helpers'
|
5
7
|
require_relative 'instance'
|
8
|
+
require_relative 'webhook_handler'
|
6
9
|
|
7
10
|
# The Contentful Middleman extensions allows to load managed content into Middleman projects through the Contentful Content Management Platform.
|
8
11
|
module ContentfulMiddleman
|
@@ -28,6 +31,15 @@ module ContentfulMiddleman
|
|
28
31
|
option :use_preview_api, false,
|
29
32
|
'Use the Preview API when fetching content'
|
30
33
|
|
34
|
+
option :all_entries, false,
|
35
|
+
'Allow multiple requests to the API for getting over 1000 entries'
|
36
|
+
|
37
|
+
option :rebuild_on_webhook, false,
|
38
|
+
"Run `middleman contentful --rebuild` upon receiving a Webhook on http://0.0.0.0:5678/receive"
|
39
|
+
|
40
|
+
option :webhook_timeout, 300,
|
41
|
+
"Wait time before rebuild after receiving a Webhook call"
|
42
|
+
|
31
43
|
|
32
44
|
helpers ContentfulMiddleman::Helpers
|
33
45
|
|
@@ -38,6 +50,8 @@ module ContentfulMiddleman
|
|
38
50
|
massage_options
|
39
51
|
|
40
52
|
ContentfulMiddleman.instances << (ContentfulMiddleman::Instance.new self)
|
53
|
+
|
54
|
+
webhook_options
|
41
55
|
end
|
42
56
|
|
43
57
|
private
|
@@ -70,5 +84,9 @@ module ContentfulMiddleman
|
|
70
84
|
|
71
85
|
options.content_types = new_content_types_options
|
72
86
|
end
|
87
|
+
|
88
|
+
def webhook_options
|
89
|
+
::ContentfulMiddleman::WebhookHandler.start(options) if options.rebuild_on_webhook
|
90
|
+
end
|
73
91
|
end
|
74
92
|
end
|
@@ -3,5 +3,34 @@ module ContentfulMiddleman
|
|
3
3
|
def contentful_instances
|
4
4
|
ContentfulMiddleman.instances
|
5
5
|
end
|
6
|
+
|
7
|
+
def localize_entry(entry, locale, fallback_locale='en-US')
|
8
|
+
localized_entry = {}
|
9
|
+
entry.each do |field, value|
|
10
|
+
localized_entry[field] = localize(entry, field, locale, fallback_locale)
|
11
|
+
end
|
12
|
+
localized_entry
|
13
|
+
end
|
14
|
+
|
15
|
+
def localize(entry, field, locale, fallback_locale='en-US')
|
16
|
+
value = entry.fetch(field)
|
17
|
+
|
18
|
+
return localize_array(value, locale, fallback_locale) if value.is_a? ::Array
|
19
|
+
localize_value(value, locale, fallback_locale)
|
20
|
+
end
|
21
|
+
|
22
|
+
def localize_array(value, locale, fallback_locale='en-US')
|
23
|
+
value.map do |v|
|
24
|
+
localize_value(v, locale, fallback_locale)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def localize_value(value, locale, fallback_locale='en-US')
|
29
|
+
if value.respond_to? :fetch
|
30
|
+
return value.fetch(locale) if value.key? locale
|
31
|
+
return value.fetch(fallback_locale)
|
32
|
+
end
|
33
|
+
value
|
34
|
+
end
|
6
35
|
end
|
7
36
|
end
|
@@ -25,15 +25,18 @@ module ContentfulMiddleman
|
|
25
25
|
private
|
26
26
|
def local_data_files
|
27
27
|
entries.map do |entry|
|
28
|
-
content_type_mapper_class = @content_type_mappers.fetch(entry.content_type.id)
|
28
|
+
content_type_mapper_class = @content_type_mappers.fetch(entry.content_type.id, nil)
|
29
|
+
|
30
|
+
next unless content_type_mapper_class
|
31
|
+
|
29
32
|
content_type_name = @content_type_names.fetch(entry.content_type.id).to_s
|
30
33
|
context = ContentfulMiddleman::Context.new
|
31
34
|
|
32
|
-
content_type_mapper = content_type_mapper_class.new(entries)
|
35
|
+
content_type_mapper = content_type_mapper_class.new(entries, @contentful.options)
|
33
36
|
content_type_mapper.map(context, entry)
|
34
37
|
|
35
38
|
LocalData::File.new(context.to_yaml, File.join(@space_name, content_type_name, entry.id))
|
36
|
-
end
|
39
|
+
end.compact
|
37
40
|
end
|
38
41
|
|
39
42
|
def entries
|
@@ -7,7 +7,11 @@ module ContentfulMiddleman
|
|
7
7
|
end
|
8
8
|
|
9
9
|
def entries
|
10
|
-
|
10
|
+
if options.all_entries
|
11
|
+
all_entries(options.cda_query)
|
12
|
+
else
|
13
|
+
client.entries(options.cda_query)
|
14
|
+
end
|
11
15
|
end
|
12
16
|
|
13
17
|
def space_name
|
@@ -30,7 +34,28 @@ module ContentfulMiddleman
|
|
30
34
|
end
|
31
35
|
end
|
32
36
|
|
37
|
+
def options
|
38
|
+
@extension.options
|
39
|
+
end
|
40
|
+
|
33
41
|
private
|
42
|
+
|
43
|
+
def all_entries(cda_query)
|
44
|
+
all = []
|
45
|
+
query = cda_query.clone
|
46
|
+
query[:order] = 'sys.createdAt' unless query.key?(:order)
|
47
|
+
num_entries = client.entries(limit: 1).total
|
48
|
+
|
49
|
+
((num_entries / 1000) + 1).times do |i|
|
50
|
+
query[:limit] = 1000
|
51
|
+
query[:skip] = i * 1000
|
52
|
+
page = client.entries(query)
|
53
|
+
page.each { |entry| all << entry }
|
54
|
+
end
|
55
|
+
|
56
|
+
all
|
57
|
+
end
|
58
|
+
|
34
59
|
def client
|
35
60
|
@client ||= Contentful::Client.new(client_options)
|
36
61
|
end
|
@@ -46,9 +71,5 @@ module ContentfulMiddleman
|
|
46
71
|
client_options[:api_url] = API_PREVIEW_URL if options.use_preview_api
|
47
72
|
client_options
|
48
73
|
end
|
49
|
-
|
50
|
-
def options
|
51
|
-
@extension.options
|
52
|
-
end
|
53
74
|
end
|
54
75
|
end
|
@@ -5,8 +5,9 @@ module ContentfulMiddleman
|
|
5
5
|
class Base
|
6
6
|
attr_reader :entries
|
7
7
|
|
8
|
-
def initialize(entries)
|
8
|
+
def initialize(entries, options)
|
9
9
|
@entries = entries
|
10
|
+
@options = options
|
10
11
|
@children = {}
|
11
12
|
end
|
12
13
|
|
@@ -24,6 +25,10 @@ module ContentfulMiddleman
|
|
24
25
|
|
25
26
|
private
|
26
27
|
|
28
|
+
def has_multiple_locales?
|
29
|
+
@options.cda_query.fetch(:locale, nil) == '*'
|
30
|
+
end
|
31
|
+
|
27
32
|
def map_field(context, field_name, field_value)
|
28
33
|
value_mapping = map_value(field_value)
|
29
34
|
context.set(field_name, value_mapping)
|
@@ -56,7 +61,10 @@ module ContentfulMiddleman
|
|
56
61
|
|
57
62
|
def map_entry_full(entry, context)
|
58
63
|
context.id = entry.id
|
59
|
-
|
64
|
+
|
65
|
+
fields = has_multiple_locales? ? entry.fields_with_locales : entry.fields
|
66
|
+
|
67
|
+
fields.each {|k, v| map_field context, k, v}
|
60
68
|
end
|
61
69
|
|
62
70
|
def map_entry(entry)
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'contentful/webhook/listener'
|
2
|
+
|
3
|
+
module ContentfulMiddleman
|
4
|
+
class WebhookHandler < Contentful::Webhook::Listener::Controllers::Wait
|
5
|
+
def perform(*)
|
6
|
+
logger.info 'Webhook Received - Waiting for rebuild'
|
7
|
+
super
|
8
|
+
logger.info 'Rebuilding'
|
9
|
+
system('bundle exec middleman contentful --rebuild')
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.start(options)
|
13
|
+
Contentful::Webhook::Listener::Server.start do |config|
|
14
|
+
config[:endpoints] = [{
|
15
|
+
endpoint: '/receive',
|
16
|
+
timeout: options.webhook_timeout,
|
17
|
+
controller: ::ContentfulMiddleman::WebhookHandler
|
18
|
+
}]
|
19
|
+
logger = Logger.new(STDOUT)
|
20
|
+
logger.level = Logger::INFO
|
21
|
+
logger.formatter = proc do |severity, datetime, progname, msg|
|
22
|
+
date_format = datetime.strftime("%Y-%m-%d %H:%M:%S")
|
23
|
+
if severity == "INFO"
|
24
|
+
"Webhook Server: #{msg}\n"
|
25
|
+
else
|
26
|
+
"[#{date_format}] #{severity} (#{progname}): #{msg}\n"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
config[:logger] = logger
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe ContentfulMiddleman::Context do
|
4
|
+
describe 'instance methods' do
|
5
|
+
it '#set' do
|
6
|
+
subject.set('foo', 'bar')
|
7
|
+
expect(subject.foo).to eq 'bar'
|
8
|
+
end
|
9
|
+
|
10
|
+
it '#get' do
|
11
|
+
subject.set('foo', 'bar')
|
12
|
+
expect(subject.get('foo')).to eq 'bar'
|
13
|
+
end
|
14
|
+
|
15
|
+
describe '#method_missing' do
|
16
|
+
it 'when :something= is called it uses #set(something, value)' do
|
17
|
+
subject.foo = 'bar'
|
18
|
+
expect(subject.foo).to eq 'bar'
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
class MapperDouble
|
4
|
+
end
|
5
|
+
|
6
|
+
describe ContentfulMiddleman::Core do
|
7
|
+
subject { described_class.new Middleman::Application }
|
8
|
+
let(:options) { subject.options }
|
9
|
+
|
10
|
+
before(:each) do
|
11
|
+
ContentfulMiddleman.instance_variable_set(:@contentful_middleman_instances, [])
|
12
|
+
end
|
13
|
+
|
14
|
+
describe 'options' do
|
15
|
+
it 'defaults' do
|
16
|
+
expect(options.space).to eq(nil)
|
17
|
+
expect(options.access_token).to eq(nil)
|
18
|
+
expect(options.cda_query).to eq({})
|
19
|
+
expect(options.content_types).to eq({})
|
20
|
+
expect(options.use_preview_api).to eq(false)
|
21
|
+
expect(options.all_entries).to eq(false)
|
22
|
+
expect(options.rebuild_on_webhook).to eq(false)
|
23
|
+
expect(options.webhook_timeout).to eq(300)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
describe 'hooks' do
|
28
|
+
describe '#after_configuration' do
|
29
|
+
before do
|
30
|
+
options.space = {some_name: 'some_id'}
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'updates space data from original hash' do
|
34
|
+
subject.after_configuration
|
35
|
+
|
36
|
+
expect(options.space).to match(name: :some_name, id: 'some_id')
|
37
|
+
end
|
38
|
+
|
39
|
+
describe 'updates content type data' do
|
40
|
+
it 'uses base mapper when only id is set' do
|
41
|
+
options.content_types = {
|
42
|
+
some_content_type_name: 'some_id'
|
43
|
+
}
|
44
|
+
|
45
|
+
subject.after_configuration
|
46
|
+
|
47
|
+
expect(options.content_types).to match('some_id' => {name: :some_content_type_name, mapper: ContentfulMiddleman::Mapper::Base})
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'uses custom mapper' do
|
51
|
+
options.content_types = {
|
52
|
+
some_content_type_name: {
|
53
|
+
id: 'some_id',
|
54
|
+
mapper: MapperDouble
|
55
|
+
}
|
56
|
+
}
|
57
|
+
|
58
|
+
subject.after_configuration
|
59
|
+
|
60
|
+
expect(options.content_types).to match('some_id' => {name: :some_content_type_name, mapper: MapperDouble})
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
it 'sets up instances' do
|
65
|
+
expect(ContentfulMiddleman.instances.size).to eq(0)
|
66
|
+
|
67
|
+
subject.after_configuration
|
68
|
+
|
69
|
+
expect(ContentfulMiddleman.instances.size).to eq(1)
|
70
|
+
end
|
71
|
+
|
72
|
+
describe 'webhook handler' do
|
73
|
+
it 'does not get called if rebuild_on_webhook is false' do
|
74
|
+
expect(ContentfulMiddleman::WebhookHandler).not_to receive(:start)
|
75
|
+
|
76
|
+
subject.after_configuration
|
77
|
+
end
|
78
|
+
|
79
|
+
it 'gets called if rebuild_on_webhook is true' do
|
80
|
+
options.rebuild_on_webhook = true
|
81
|
+
|
82
|
+
expect(ContentfulMiddleman::WebhookHandler).to receive(:start)
|
83
|
+
|
84
|
+
subject.after_configuration
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|