contentful_middleman 1.1.1 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|
-
[](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
|