Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
42 changed files
with
20,071 additions
and
7,727 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
--require rails_helper | ||
--require spec_helper | ||
--format documentation | ||
--color | ||
--order rand |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
60 changes: 60 additions & 0 deletions
60
wcc-contentful-app/lib/wcc/contentful/app/configuration.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
# frozen_string_literal: true | ||
|
||
# This object contains all the configuration options for the `wcc-contentful` gem. | ||
class WCC::Contentful::App::Configuration | ||
# TODO: things to configure in the app? | ||
ATTRIBUTES = %i[ | ||
preview_password | ||
].freeze | ||
|
||
# Sets the password that will be checked when the query string contains `preview=`, | ||
# if it matches, then the Contentful entries are fetched via the preview API. | ||
attr_accessor :preview_password | ||
|
||
attr_reader :wcc_contentful_config | ||
|
||
delegate(*WCC::Contentful::Configuration::ATTRIBUTES, to: :wcc_contentful_config) | ||
delegate(*(WCC::Contentful::Configuration::ATTRIBUTES.map { |a| "#{a}=" }), | ||
to: :wcc_contentful_config) | ||
|
||
def initialize(wcc_contentful_config) | ||
@wcc_contentful_config = wcc_contentful_config | ||
@preview_password = ENV['CONTENTFUL_PREVIEW_PASSWORD'] | ||
end | ||
|
||
# Validates the configuration, raising ArgumentError if anything is wrong. This | ||
# is called by WCC::Contentful::App.init! | ||
def validate! | ||
wcc_contentful_config.validate! | ||
end | ||
|
||
def frozen? | ||
false | ||
end | ||
|
||
class FrozenConfiguration | ||
attr_reader(*ATTRIBUTES) | ||
|
||
attr_reader :wcc_contentful_config | ||
|
||
delegate(*WCC::Contentful::Configuration::ATTRIBUTES, to: :wcc_contentful_config) | ||
|
||
def initialize(configuration, frozen_wcc_contentful_config) | ||
unless frozen_wcc_contentful_config.frozen? | ||
raise ArgumentError, 'Please first freeze the wcc_contentful_config' | ||
end | ||
|
||
@wcc_contentful_config = frozen_wcc_contentful_config | ||
|
||
ATTRIBUTES.each do |att| | ||
val = configuration.public_send(att) | ||
val.freeze if val.respond_to?(:freeze) | ||
instance_variable_set("@#{att}", val) | ||
end | ||
end | ||
|
||
def frozen? | ||
true | ||
end | ||
end | ||
end |
118 changes: 118 additions & 0 deletions
118
wcc-contentful-app/lib/wcc/contentful/app/middleware/publish_at.rb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,118 @@ | ||
# frozen_string_literal: true | ||
|
||
module WCC::Contentful::App::Middleware | ||
class PublishAt | ||
include WCC::Contentful::Middleware::Store | ||
|
||
def self.call(store, content_delivery_params, config) | ||
# This does not apply in preview mode | ||
return if content_delivery_params&.find { |h| h.is_a?(Hash) && (h[:preview] == true) } | ||
|
||
super | ||
end | ||
|
||
def select?(entry) | ||
publish_at = entry.dig('fields', 'publishAt', 'en-US') | ||
unpublish_at = entry.dig('fields', 'unpublishAt', 'en-US') | ||
|
||
after(publish_at) && before(unpublish_at) | ||
end | ||
|
||
def index(entry) | ||
maybe_drop_job(entry) if entry.dig('sys', 'type') == 'Entry' | ||
|
||
store.index(entry) if store.index? | ||
end | ||
|
||
private | ||
|
||
def after(time) | ||
return true unless time | ||
|
||
Time.zone.now >= Time.zone.parse(time) | ||
end | ||
|
||
def before(time) | ||
return true unless time | ||
|
||
Time.zone.now <= Time.zone.parse(time) | ||
end | ||
|
||
if defined?(ActiveJob::Base) | ||
def maybe_drop_job(entry) | ||
publish_at = entry.dig('fields', 'publishAt', 'en-US') | ||
unpublish_at = entry.dig('fields', 'unpublishAt', 'en-US') | ||
|
||
drop_job_at(publish_at, entry) if publish_at.present? && before(publish_at) | ||
drop_job_at(unpublish_at, entry) if unpublish_at.present? && before(unpublish_at) | ||
end | ||
|
||
def drop_job_at(timestamp, entry) | ||
ts = Time.zone.parse(timestamp) | ||
Job.set(wait_until: ts + 1.second).perform_later(entry, store) | ||
end | ||
|
||
class Job < ActiveJob::Base | ||
include Wisper::Publisher | ||
|
||
self.queue_adapter = :async | ||
|
||
def self.cache | ||
@cache ||= Rails.cache | ||
end | ||
attr_writer :cache | ||
|
||
def initialize(*arguments) | ||
super | ||
|
||
subscribe(WCC::Contentful::Events.instance, with: :rebroadcast) | ||
end | ||
|
||
def perform(entry, store) | ||
return unless latest_entry_version?(entry, store) | ||
|
||
publish_at = entry.dig('fields', 'publishAt', 'en-US') | ||
unpublish_at = entry.dig('fields', 'unpublishAt', 'en-US') | ||
latest_event = | ||
[publish_at, unpublish_at] | ||
.select { |x| x.present? && Time.zone.now >= Time.zone.parse(x) } | ||
.max | ||
|
||
if latest_event == publish_at | ||
emit_entry(entry) | ||
else | ||
emit_deleted_entry(entry) | ||
end | ||
end | ||
|
||
def latest_entry_version?(entry, store) | ||
# If the entry isn't in the backing store, then something's changed. | ||
return false unless from_store = store.find(entry.dig('sys', 'id')) | ||
|
||
entry.dig('sys', 'revision') >= from_store.dig('sys', 'revision') | ||
end | ||
|
||
def emit_entry(entry) | ||
emit_event(entry) | ||
end | ||
|
||
def emit_deleted_entry(entry) | ||
emit_event({ | ||
'sys' => entry['sys'].merge({ 'type' => 'DeletedEntry' }) | ||
}) | ||
end | ||
|
||
def emit_event(entry) | ||
event = WCC::Contentful::Event.from_raw(entry, source: self) | ||
type = entry.dig('sys', 'type') | ||
raise ArgumentError, "Unknown event type #{event}" unless type.present? | ||
|
||
broadcast(type, event) | ||
end | ||
end | ||
else | ||
def maybe_drop_job(entry) | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.