class Block < ActiveRecord::Base
attr_accessible :title, :display, :limit, :box_id, :posts_per_page, :visualization_format, :language, :display_user, :box
# to be able to generate HTML
include ActionView::Helpers::UrlHelper
include ActionView::Helpers::TagHelper
# Block-specific stuff
include BlockHelper
delegate :environment, :to => :box, :allow_nil => true
acts_as_list :scope => :box
belongs_to :box
acts_as_having_settings
scope :enabled, :conditions => { :enabled => true }
def embedable?
false
end
def get_limit
[0,limit].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 display_to_user?(user)
display_user == 'all' || (user.nil? && display_user == 'not_logged') || (user && display_user == 'logged')
end
def display_always(context)
true
end
def display_home_page_only(context)
if context[:article]
return context[:article] == owner.home_page
else
return context[:request_path] == '/'
end
end
def display_except_home_page(context)
if context[:article]
return context[:article] != owner.home_page
else
return context[:request_path] != '/' + (owner.kind_of?(Profile) ? owner.identifier : '')
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'
# 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
# Returns the content to be used for this block.
#
# This method can return several types of objects:
#
# * String: if the string starts with http:// or https://, then it is assumed to be address of an IFRAME. Otherwise it's is used as regular HTML.
# * Hash: the hash is used to build an URL that is used as the address for a IFRAME.
# * Proc: the Proc is evaluated in the scope of BoxesHelper. The
# block can then use render, link_to, etc.
#
# The method can also return nil, which means "no content".
#
# See BoxesHelper#extract_block_content for implementation details.
def content(args={})
"This is block number %d" % self.id
end
# A footer to be appended to the end of the block. Returns nil.
#
# Override in your subclasses. You can return the same types supported by
# #content.
def footer
nil
end
# Is this block editable? (Default to false)
def editable?
true
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'),
}
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
end