diff --git a/app/models/locomotive/extensions/page/redirect.rb b/app/models/locomotive/extensions/page/redirect.rb index 3ca00b08..b2672d02 100644 --- a/app/models/locomotive/extensions/page/redirect.rb +++ b/app/models/locomotive/extensions/page/redirect.rb @@ -7,12 +7,12 @@ module Locomotive included do + ## fields ## field :redirect, :type => Boolean, :default => false - field :redirect_url, :type => String + ## validations ## validates_presence_of :redirect_url, :if => :redirect - validates_format_of :redirect_url, :with => Locomotive::Regexps::URL, :allow_blank => true end diff --git a/app/models/locomotive/extensions/page/templatized.rb b/app/models/locomotive/extensions/page/templatized.rb index cdf25a87..8cd1622f 100644 --- a/app/models/locomotive/extensions/page/templatized.rb +++ b/app/models/locomotive/extensions/page/templatized.rb @@ -17,12 +17,38 @@ module Locomotive ## callbacks ## before_validation :set_slug_if_templatized before_validation :ensure_target_klass_name_security + + ## scopes ## + scope :templatized, :where => { :templatized => true } end + # Returns the class specified by the target_klass_name property + # + # @example + # + # page.target_klass_name = 'Locomotive::Entry12345' + # page.target_klass = Locomotive::Entry12345 + # + # @return [ Class ] The target class + # def target_klass target_klass_name.constantize end + # Gives the name which can be used in a liquid template in order + # to reference an entry. It uses the slug property if the target klass + # is a Locomotive content type or the class name itself for the other classes. + # + # @example + # + # page.target_klass_name = 'Locomotive::Entry12345' # related to the content type Articles + # page.target_entry_name = 'article' + # + # page.target_klass_name = 'OurProduct' + # page.target_entry_name = 'our_product' + # + # @return [ String ] The name in lowercase and underscored + # def target_entry_name if self.target_klass_name =~ /^Locomotive::Entry([a-z0-9]+)$/ @content_type ||= self.site.content_types.find($1) @@ -32,6 +58,12 @@ module Locomotive end end + # Finds the entry both specified by the target klass and identified by the permalink + # + # @param [ String ] permalink The permalink of the entry + # + # @return [ Object ] The document + # def fetch_target_entry(permalink) target_klass.find_by_permalink(permalink) end diff --git a/app/models/locomotive/page.rb b/app/models/locomotive/page.rb index 02f86c3d..337df736 100644 --- a/app/models/locomotive/page.rb +++ b/app/models/locomotive/page.rb @@ -17,6 +17,7 @@ module Locomotive field :title, :localize => true field :slug, :localize => true field :fullpath, :localize => true + field :handle field :raw_template, :localize => true field :locales, :type => Array field :published, :type => Boolean, :default => false @@ -40,6 +41,7 @@ module Locomotive ## validations ## validates_presence_of :site, :title, :slug validates_uniqueness_of :slug, :scope => [:site_id, :parent_id] + validates_uniqueness_of :handle, :allow_blank => true validates_exclusion_of :slug, :in => Locomotive.config.reserved_slugs, :if => Proc.new { |p| p.depth == 0 } ## named scopes ## @@ -48,6 +50,7 @@ module Locomotive scope :not_found, :where => { :slug => '404', :depth => 0 } scope :published, :where => { :published => true } scope :fullpath, lambda { |fullpath| { :where => { :fullpath => fullpath } } } + scope :handle, lambda { |handle| { :where => { :handle => handle } } } scope :minimal_attributes, :only => %w(title slug fullpath position depth published templatized redirect listed parent_id created_at updated_at) ## methods ## diff --git a/app/presenters/locomotive/page_presenter.rb b/app/presenters/locomotive/page_presenter.rb index 72eddd9c..b865f97e 100644 --- a/app/presenters/locomotive/page_presenter.rb +++ b/app/presenters/locomotive/page_presenter.rb @@ -1,7 +1,7 @@ module Locomotive class PagePresenter < BasePresenter - delegate :title, :slug, :fullpath, :raw_template, :published, :listed, :templatized, :redirect, :redirect_url, :template_changed, :cache_strategy, :to => :source + delegate :title, :slug, :fullpath, :handle, :raw_template, :published, :listed, :templatized, :redirect, :redirect_url, :template_changed, :cache_strategy, :to => :source def escaped_raw_template h(self.source.raw_template) @@ -12,7 +12,7 @@ module Locomotive end def included_methods - super + %w(title slug fullpath raw_template published listed templatized redirect redirect_url cache_strategy template_changed editable_elements localized_fullpaths) + super + %w(title slug fullpath handle raw_template published listed templatized redirect redirect_url cache_strategy template_changed editable_elements localized_fullpaths) end def localized_fullpaths diff --git a/app/views/locomotive/pages/_form.html.haml b/app/views/locomotive/pages/_form.html.haml index 5e070387..dda9c99e 100644 --- a/app/views/locomotive/pages/_form.html.haml +++ b/app/views/locomotive/pages/_form.html.haml @@ -30,6 +30,8 @@ = f.inputs :name => :advanced_options, :id => 'advanced-options', :class => "inputs foldable #{'folded' if inputs_folded?(@page)}" do + = f.input :handle + = f.input :templatized, :as => :'Locomotive::Toggle', :style => "#{'display: none' if @page.redirect?}" = f.input :target_klass_name, :as => :select, :collection => options_for_target_klass_name, :include_blank => false, :wrapper_html => { :style => "#{'display: none' unless @page.templatized?}" } diff --git a/config/locales/formtastic.en.yml b/config/locales/formtastic.en.yml index 01b19ac0..61023757 100644 --- a/config/locales/formtastic.en.yml +++ b/config/locales/formtastic.en.yml @@ -60,6 +60,7 @@ en: hints: page: + handle: "Unique identifier to retrieve this page within an external controller instance" published: "Only authenticated accounts can view unpublished pages." cache_strategy: "Cache the page for better performance. The 'Simple' choice is a good compromise." templatized: "Use the page as a template for a model you defined." diff --git a/lib/locomotive/carrierwave/asset.rb b/lib/locomotive/carrierwave/asset.rb index d3f597c6..624b651c 100644 --- a/lib/locomotive/carrierwave/asset.rb +++ b/lib/locomotive/carrierwave/asset.rb @@ -28,40 +28,36 @@ module Locomotive end - module InstanceMethods + def set_content_type(*args) + value = :other - def set_content_type(*args) - value = :other + content_type = file.content_type == 'application/octet-stream' ? File.mime_type?(original_filename) : file.content_type - content_type = file.content_type == 'application/octet-stream' ? File.mime_type?(original_filename) : file.content_type - - self.class.content_types.each_pair do |type, rules| - rules.each do |rule| - case rule - when String then value = type if content_type == rule - when Regexp then value = type if (content_type =~ rule) == 0 - end + self.class.content_types.each_pair do |type, rules| + rules.each do |rule| + case rule + when String then value = type if content_type == rule + when Regexp then value = type if (content_type =~ rule) == 0 end end - - model.content_type = value end - def set_size(*args) - model.size = file.size - end + model.content_type = value + end - def set_width_and_height - if model.image? - magick = ::Magick::Image.read(current_path).first - model.width, model.height = magick.columns, magick.rows - end - end + def set_size(*args) + model.size = file.size + end - def image?(file) - model.image? + def set_width_and_height + if model.image? + magick = ::Magick::Image.read(current_path).first + model.width, model.height = magick.columns, magick.rows end + end + def image?(file) + model.image? end end diff --git a/lib/locomotive/render.rb b/lib/locomotive/render.rb index cbcf33bb..68f54658 100644 --- a/lib/locomotive/render.rb +++ b/lib/locomotive/render.rb @@ -26,17 +26,7 @@ module Locomotive end def locomotive_page - path = (params[:path] || params[:page_path] || request.fullpath).clone # TODO: params[:path] is more consistent - path = path.split('?').first # take everything before the query string or the lookup fails - path.gsub!(/\.[a-zA-Z][a-zA-Z0-9]{2,}$/, '') # remove the page extension - path.gsub!(/^\//, '') # remove the leading slash - - path = 'index' if path.blank? || path == '_edit' - - if path != 'index' - dirname = File.dirname(path).gsub(/^\.$/, '') # also look for templatized page path - path = [path, File.join(dirname, 'content_type_template').gsub(/^\//, '')] - end + path = self.locomotive_page_path if page = current_site.pages.any_in(:fullpath => [*path]).first if not page.published? and current_locomotive_account.nil? @@ -55,6 +45,22 @@ module Locomotive page || not_found_page end + def locomotive_page_path + path = (params[:path] || params[:page_path] || request.fullpath).clone # TODO: params[:path] is more consistent + path = path.split('?').first # take everything before the query string or the lookup fails + path.gsub!(/\.[a-zA-Z][a-zA-Z0-9]{2,}$/, '') # remove the page extension + path.gsub!(/^\//, '') # remove the leading slash + + path = 'index' if path.blank? || path == '_edit' + + if path != 'index' + dirname = File.dirname(path).gsub(/^\.$/, '') # also look for templatized page path + path = [path, File.join(dirname, 'content_type_template').gsub(/^\//, '')] + end + + path + end + def locomotive_context assigns = { 'site' => current_site,