class Block < ApplicationRecord
attr_accessible :title, :subtitle, :display, :limit, :box_id, :posts_per_page,
:visualization_format, :language, :display_user,
:box, :edit_modes, :move_modes, :mirror
include ActionView::Helpers::TagHelper
# Block-specific stuff
include BlockHelper
delegate :environment, :to => :box, :allow_nil => true
acts_as_list scope: -> block { where box_id: block.box_id }
belongs_to :box
belongs_to :mirror_block, :class_name => "Block"
has_many :observers, :class_name => "Block", :foreign_key => "mirror_block_id"
extend ActsAsHavingSettings::ClassMethods
acts_as_having_settings
scope :enabled, -> { where :enabled => true }
after_save do |block|
if block.owner.kind_of?(Profile) && block.owner.is_template? && block.mirror?
block.observers.each do |observer|
observer.copy_from(block)
observer.title = block.title
observer.save
end
end
end
def embedable?
false
end
def get_limit
[0,limit.to_i].max
end
def embed_code
me = self
proc do
content_tag('iframe', '',
:src => url_for(:controller => 'embed', :action => 'block', :id => me.id, :only_path => false),
:frameborder => 0,
:width => 1024,
:height => 768,
:class => "embed block #{me.class.name.to_css_class}"
)
end
end
# Determines whether a given block must be visible. Optionally a
# context must be specified. context must be a hash, and
# may contain the following keys:
#
# * :article: the article being viewed currently
# * :language: in which language the block will be displayed
# * :user: the logged user
def visible?(context = nil)
return false if display == 'never'
if context
return false if language != 'all' && language != context[:locale]
return false unless display_to_user?(context[:user])
begin
return self.send("display_#{display}", context)
rescue NoMethodError => exception
raise "Display '#{display}' is not a valid value."
end
end
true
end
def visible_to_user?(user)
visible = self.display_to_user?(user)
if self.owner.kind_of?(Profile)
visible &= self.owner.display_info_to?(user)
visible &= (self.visible? || user && user.has_permission?(:edit_profile_design, self.owner))
elsif self.owner.kind_of?(Environment)
visible &= (self.visible? || user && user.has_permission?(:edit_environment_design, self.owner))
end
visible
end
def display_to_user?(user)
display_user == 'all' || (user.nil? && display_user == 'not_logged') || (user && display_user == 'logged') || (user && display_user == 'followers' && owner.in_social_circle?(user))
end
def display_always(context)
true
end
def display_home_page_only(context)
if context[:article]
return context[:article] == owner.home_page
else
return home_page_path?(context[:request_path])
end
end
def display_except_home_page(context)
if context[:article]
return context[:article] != owner.home_page
else
return !home_page_path?(context[:request_path])
end
end
# The condition for displaying a block. It can assume the following values:
#
# * 'always': the block is always displayed
# * 'never': the block is hidden (it does not appear for visitors)
# * 'home_page_only' the block is displayed only when viewing the
# homepage of its owner.
# * 'except_home_page' the block is displayed only when viewing
# the homepage of its owner.
settings_items :display, :type => :string, :default => 'always'
# The condition for displaying a block to users. It can assume the following values:
#
# * 'all': the block is always displayed
# * 'logged': the block is displayed to logged users only
# * 'not_logged': the block is displayed only to not logged users
settings_items :display_user, :type => :string, :default => 'all'
# The block can be configured to be displayed in all languages or in just one language. It can assume any locale of the environment:
#
# * 'all': the block is always displayed
settings_items :language, :type => :string, :default => 'all'
# The block can be configured to define the edition modes options. Only can be edited by environment admins
# It can assume the following values:
#
# * 'all': the block owner has all edit options for this block
# * 'none': the block owner can't do anything with the block
settings_items :edit_modes, :type => :string, :default => 'all'
settings_items :move_modes, :type => :string, :default => 'all'
# returns the description of the block, used when the user sees a list of
# blocks to choose one to include in the design.
#
# Must be redefined in subclasses to match the description of each block
# type.
def self.description
'(dummy)'
end
def self.short_description
self.pretty_name
end
def self.icon
"/images/icon_block.png"
end
def self.icon_path
basename = self.name.split('::').last.underscore
File.join('images', 'blocks', basename, 'icon.png')
end
def self.pretty_name
self.name.split('::').last.gsub('Block','')
end
def self.default_icon_path
'/images/icon_block.png'
end
def self.preview_path
base_name = self.name.split('::').last.underscore
File.join('blocks', base_name,'previews')
end
def self.default_preview_path
"/images/block_preview.png"
end
# Is this block editable? (Default to true)
def editable?(user=nil)
self.edit_modes == "all"
end
def movable?
self.move_modes == "all"
end
# must always return false, except on MainBlock clas.
def main?
false
end
def owner
box ? box.owner : nil
end
def default_title
''
end
def title
if self[:title].blank?
self.default_title
else
self[:title]
end
end
def view_title
title
end
def cacheable?
true
end
alias :active_record_cache_key :cache_key
def cache_key(language='en', user=nil)
active_record_cache_key + '-' + language
end
def timeout
4.hours
end
def has_macro?
false
end
# Override in your subclasses.
# Define which events and context should cause the block cache to expire
# Possible events are: :article, :profile, :friendship, :category, :role_assignment
# Possible contexts are: :profile, :environment
def self.expire_on
{
:profile => [],
:environment => []
}
end
DISPLAY_OPTIONS = {
'always' => _('In all pages'),
'home_page_only' => _('Only in the homepage'),
'except_home_page' => _('In all pages, except in the homepage'),
'never' => _('Don\'t display'),
}
def display_options_available
DISPLAY_OPTIONS.keys
end
def display_options
DISPLAY_OPTIONS.slice(*display_options_available)
end
def display_user_options
@display_user_options ||= {
'all' => _('All users'),
'logged' => _('Logged'),
'not_logged' => _('Not logged'),
'followers' => owner.class != Environment && owner.organization? ? _('Members') : _('Friends')
}
end
def edit_block_options
@edit_options ||= {
'all' => _('Can be modified'),
'none' => _('Cannot be modified')
}
end
def move_block_options
@move_options ||= {
'all' => _('Can be moved'),
'none' => _('Cannot be moved')
}
end
def duplicate
duplicated_block = self.dup
duplicated_block.display = 'never'
duplicated_block.created_at = nil
duplicated_block.updated_at = nil
duplicated_block.save!
duplicated_block.insert_at(self.position + 1)
duplicated_block
end
def copy_from(block)
self.settings = block.settings
self.position = block.position
end
def add_observer(block)
self.observers << block
end
def api_content
nil
end
def display_api_content_by_default?
false
end
def allow_edit?(person)
return false if person.nil? || (!person.is_admin? && !editable?(person))
if self.owner.kind_of?(Profile)
return person.has_permission?(:edit_profile_design, owner)
elsif self.owner.kind_of?(Environment)
return person.has_permission?(:edit_environment_design, owner)
end
false
end
attr_accessor :api_content_params
private
def home_page_path
home_page_url = Noosfero.root('/')
if owner.kind_of?(Profile)
home_page_url += "profile/" if owner.home_page.nil?
home_page_url += owner.identifier
end
return home_page_url
end
def home_page_path? path
return path == home_page_path || path == (home_page_path + '/')
end
end