Created
January 28, 2015 22:03
-
-
Save ulitiy/b2757646ae6102faa130 to your computer and use it in GitHub Desktop.
next/previous locomotive drop
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
module Locomotive | |
module Liquid | |
module Drops | |
class ContentEntry < Base | |
delegate :_slug, :_permalink, :_translated, :seo_title, :meta_keywords, :meta_description, to: :@_source | |
def _id | |
@_source._id.to_s | |
end | |
def _label | |
@_label ||= @_source._label | |
end | |
# Returns the next content for the parent content type. | |
# If no content is found, nil is returned. | |
# | |
# Usage: | |
# | |
# {% if article.next %} | |
# <a href="/articles/{{ article.next._permalink }}">Read next article</a> | |
# {% endif %} | |
# | |
def next | |
next_or_previous :gt | |
end | |
# Returns the previous content for the parent content type. | |
# If no content is found, nil is returned. | |
# | |
# Usage: | |
# | |
# {% if article.previous %} | |
# <a href="/articles/{{ article.previous._permalink }}">Read previous article</a> | |
# {% endif %} | |
# | |
def previous | |
next_or_previous :lt | |
end | |
def next_or_previous matcher | |
self.modify_with_scope | |
matcher = matcher == :gt ? :lt : :gt if @_source.content_type.order_direction != 'asc' | |
attribute = @_source.content_type.order_by_attribute | |
direction = matcher == :gt ? 'asc' : 'desc' | |
criterion = attribute.to_sym.send(matcher) | |
value = @_source.send(attribute.to_sym) | |
order_by = [attribute, direction] | |
# throw @context['with_scope'] | |
# @_source.class.where({ _visible: true }.merge(@context['with_scope']).merge({ criterion => value })).limit(1).order_by(order_by).first.to_liquid | |
@_source.class.where({ _visible: true }.merge({ criterion => value })).limit(1).order_by(order_by).where(@context['with_scope']).first.to_liquid | |
# ContentTypeProxyCollection.new(@_source.content_type).all.where({ criterion => value }).limit(1).first.to_liquid # no context inside | |
end | |
def errors | |
@_source.errors.messages.to_hash.stringify_keys | |
end | |
def before_method(meth) | |
return '' if @_source.nil? | |
if not @@forbidden_attributes.include?(meth.to_s) | |
value = @_source.send(meth) | |
if value.respond_to?(:all) # check for an association | |
filter_and_order_list(value) | |
else | |
value | |
end | |
else | |
nil | |
end | |
end | |
protected | |
def filter_and_order_list(list) | |
conditions, order_by = HashWithIndifferentAccess.new(_visible: true), nil | |
if @context['with_scope'] | |
conditions.merge!(@context['with_scope']) | |
order_by = conditions.delete(:order_by).try(:split) | |
end | |
list.filtered(conditions, order_by) | |
end | |
########### COPIED FROM ContentTypeProxyCollection ######### | |
# Modify the attributes of the with_scope tag so that | |
# they can be resolved by MongoDB. | |
# | |
def modify_with_scope | |
@context['with_scope'].dup.each do |key, value| | |
field = @_source.content_type.find_entries_custom_field(key.to_s) | |
next if field.nil? | |
case field.type.to_sym | |
when :belongs_to | |
self.modify_with_scope_key(key, "#{key.to_s}_id", self.object_to_id(field, value)) | |
when :many_to_many | |
self.modify_with_scope_key(key, "#{key.to_s.singularize}_ids", self.object_to_id(field, value)) | |
when :select | |
option = field.select_options.detect { |option| [option.name, option._id.to_s].include?(value) } | |
self.modify_with_scope_key(key, "#{key.to_s}_id", option.try(:_id)) | |
end | |
end | |
end | |
# Change the value of a key of the with_scope depending of its type. | |
# If the key is a Origin::Key, we only change the name. | |
# If the key is a String, we replace it. | |
# | |
# @param [ Object ] key Either a String or a Origin::Key | |
# @param [ String ] name The new name of the key | |
# @param [ String ] value The new value associated to the key | |
# | |
def modify_with_scope_key(key, name, value) | |
if key.respond_to?(:operator) | |
key.instance_variable_set :@name, name | |
@context['with_scope'][key] = value | |
else | |
@context['with_scope'].delete(key) | |
@context['with_scope'][name] = value | |
end | |
end | |
# Get the _id attribute of a object or a list of objects which | |
# can include String (needed to retrieve a model | |
# based on its permalink or its label field) or ContentEntry instances. | |
# | |
# @param [ Object ] field The custom field | |
# @param [ Object ] value An object (content entry or label) or a list of objects | |
# | |
def object_to_id(field, value) | |
if value.respond_to?(:map) | |
value.map { |el| self.object_to_id(field, el) } | |
elsif value.respond_to?(:_id) | |
value._id | |
else | |
model = Locomotive::ContentType.class_name_to_content_type(field.class_name, @content_type.site) | |
model.entries.or({ _slug: value }, { model.label_field_name => value }).first.try(:_id) | |
end | |
end | |
######### | |
end | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment