module Locomotive class ContentEntry include Locomotive::Mongoid::Document ## extensions ## include ::CustomFields::Target include Extensions::Shared::Seo ## fields ## field :_slug field :_label_field_name field :_position, :type => Integer, :default => 0 field :_visible, :type => Boolean, :default => true ## validations ## validates :_slug, :presence => true, :uniqueness => { :scope => :content_type_id } ## associations ## belongs_to :site, :class_name => 'Locomotive::Site' belongs_to :content_type, :class_name => 'Locomotive::ContentType', :inverse_of => :entries ## callbacks ## before_validation :set_slug before_save :set_site before_save :set_visibility before_save :set_label_field_name before_create :add_to_list_bottom after_create :send_notifications ## named scopes ## scope :visible, :where => { :_visible => true } scope :latest_updated, :order_by => :updated_at.desc, :limit => Locomotive.config.ui[:latest_entries_nb] ## methods ## alias :visible? :_visible? alias :_permalink :_slug alias :_permalink= :_slug= def _label(type = nil) value = if self._label_field_name self.send(self._label_field_name.to_sym) else self.send((type || self.content_type).label_field_name.to_sym) end value.respond_to?(:to_label) ? value.to_label : value end def translated? if self.respond_to?(:"#{self._label_field_name}_translations") self.send(:"#{self._label_field_name}_translations").key?(::Mongoid::Fields::I18n.locale.to_s) #rescue false else true end end def next next_or_previous :gt end def previous next_or_previous :lt end def self.find_by_permalink(permalink) self.where(:_slug => permalink).first end def self.sort_entries!(ids) list = self.any_in(:_id => ids.map { |id| BSON::ObjectId.from_string(id.to_s) }).to_a ids.each_with_index do |id, position| if entry = list.detect { |e| e._id.to_s == id.to_s } entry.update_attributes :_position => position end end end def to_liquid Locomotive::Liquid::Drops::ContentEntry.new(self) end def to_presenter(options = {}) Locomotive::ContentEntryPresenter.new(self, options) end def as_json(options = {}) self.to_presenter.as_json end protected def next_or_previous(matcher = :gt) order_by = self.content_type.order_by_definition criterion = :_position.send(matcher) self.class.where(criterion => self._position).order_by([order_by]).limit(1).first end # Sets the slug of the instance by using the value of the highlighted field # (if available). If a sibling content instance has the same permalink then a # unique one will be generated def set_slug self._slug = self._label.dup if self._slug.blank? && self._label.present? if self._slug.present? self._slug.permalink! self._slug = self.next_unique_slug if self.slug_already_taken? end end # Return the next available unique slug as a string def next_unique_slug slug = self._slug.gsub(/-\d*$/, '') last_slug = self.class.where(:_id.ne => self._id, :_slug => /^#{slug}-?\d*?$/i).order_by(:_slug).last._slug next_number = last_slug.scan(/-(\d)$/).flatten.first.to_i + 1 [slug, next_number].join('-') end def slug_already_taken? self.class.where(:_id.ne => self._id, :_slug => self._slug).any? end def set_site self.site ||= self.content_type.site end def set_visibility if self.respond_to?(:visible) self.visible = true if self.visible.nil? self._visible = self.visible return end end def set_label_field_name self._label_field_name = self.content_type.label_field_name end def add_to_list_bottom self._position = self.class.max(:_position).to_i + 1 end def send_notifications return if !self.content_type.public_submission_enabled? || self.content_type.public_submission_accounts.blank? self.site.accounts.each do |account| next unless self.content_type.public_submission_accounts.include?(account._id) Locomotive::Notifications.new_content_entry(account, self).deliver end end end end