Changeset 463

Show
Ignore:
Timestamp:
2007-04-30 21:49:51 (2 years ago)
Author:
gaspard
Message:

[zafu] fixed tests, updated the way find_template_text works.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/TODO

    r455 r463  
    11 
    22== Todo 
     3* What if a Note/Contact contains pages and one of these pages has 'custom_base' set ? 
    34* Replace Trans... with Gettext 
    45* BUG: flash not working in UsersController when updating preferences. 
  • trunk/app/controllers/application.rb

    r459 r463  
    129129    # there, they are searched in the database and compiled into 'app/views/templates/compiled'. 
    130130    def template_url(opts={}) 
    131       skin_name = opts[:skin]   || (@node ? @node[:skin] : nil) || 'default' 
    132       skin_name = skin_name.gsub(/[^a-zA-Z]/,'') # security 
     131      @skin_name = opts[:skin]   || (@node ? @node[:skin] : nil) || 'default' 
     132      @skin_name = @skin_name.gsub(/[^a-zA-Z]/,'') # security 
    133133      mode      = opts[:mode]   || params[:mode] 
    134134      format    = opts[:format] || params[:format] || 'html' 
    135135      klass     = @node.class 
    136       # FIXME: rescue_template = opts[:rescue_template] || '/templates/fixed/default/any' 
    137       # FIXME: @skin_obj   = nil 
    138       # classes : 
     136       
     137      # possible classes for the master template : 
    139138      klasses = [] 
    140139      klass.kpath.split(//).each_index { |i| klasses << klass.kpath[0..i] } 
    141      
    142       best_match = {  
    143         :conditions => ["tkpath IN (?) AND format = ? AND mode #{mode ? '=' : 'IS'} ?", klasses, format, mode], 
    144         :select     => "*, (template_contents.skin_name = '#{skin_name}') AS skin_ok", 
     140       
     141      template = secure(Template) { Template.find(:first,  
     142        :conditions => ["tkpath IN (?) AND format = ? AND mode #{mode ? '=' : 'IS'} ? AND template_contents.node_id = nodes.id", klasses, format, mode], 
     143        :from       => "nodes, template_contents", 
     144        :select     => "nodes.*, template_contents.*, (template_contents.skin_name = #{@skin_name}) AS skin_ok", 
    145145        :order      => "length(tkpath) DESC, skin_ok DESC" 
    146       } 
    147      
    148       if skin_name == 'default' 
    149         template = TemplateContent.find(:first, best_match) 
    150         skin_root = "#{SITES_ROOT}/shared" 
    151       else 
    152         best_match[:conditions][0] += " AND template_contents.node_id = nodes.id" 
    153         best_match[:from]   = "nodes, template_contents" 
    154         best_match[:select] = "nodes.*, template_contents.*, (template_contents.skin_name = #{skin_name}) AS skin_ok", 
    155         template = secure(Template) { Template.find(:first, best_match) } 
    156          
    157         skin_root = "#{SITES_ROOT}/#{visitor.site.host}" 
    158       end 
    159        
     146      )} 
     147       
     148      # FIXME use a default fixed template. 
    160149      raise ActiveRecord::RecordNotFound unless template 
    161150       
    162151      mode = "_#{mode}" if mode 
     152      # FIXME use fullpath instead of 'skin_name' 
     153      skin_root = "#{SITES_ROOT}/#{visitor.site.host}" 
    163154      skin_path = "/#{template[:skin_name]}/#{template[:klass]}#{mode}.#{format}" 
    164155      main_path = "/#{visitor.lang}/main.erb" 
     
    166157       
    167158      if File.exists?(url) 
    168         if skin_name == 'default' && (File.stat(url).mtime < File.stat("#{skin_root}/zafu#{skin_path}").mtime || RAILS_ENV == 'development') 
     159        # FIXME: use CachedPage to store the compiled template instead of this File.stat test 
     160        if File.stat(url).mtime < template.v_updated_at 
     161          # template changed, render 
    169162          FileUtils.rmtree("#{skin_root}/zafu.compiled#{skin_path}") 
    170         elsif skin_name != 'default' && (File.stat(url).mtime < template.v_updated_at || RAILS_ENV == 'development') 
    171           FileUtils.rmtree("#{skin_root}/zafu.compiled#{skin_path}") 
    172         else 
    173           # we can use the cached version 
    174           return url 
    175         end 
    176       end 
    177      
    178       # render zafu 
    179       response.template.instance_variable_set(:@session, session) 
    180       skin_helper = response.template 
    181       res = ZafuParser.new_with_url(skin_path, :helper => skin_helper).render 
    182       FileUtils::mkpath(File.dirname(url)) unless File.exists?(File.dirname(url)) 
    183       File.open(url, "wb") { |f| f.syswrite(res) }     
     163          response.template.instance_variable_set(:@session, session) 
     164          skin_helper = response.template 
     165          res = ZafuParser.new_with_url(skin_path, :helper => skin_helper).render 
     166          FileUtils::mkpath(File.dirname(url)) unless File.exists?(File.dirname(url)) 
     167          File.open(url, "wb") { |f| f.syswrite(res) } 
     168        end 
     169      end 
    184170     
    185171      return url 
    186172    end 
    187173   
     174    # Return a template's content from an url. If the url does not start with a '/', we try by replacing the 
     175    # first element with the current skin_name and if it does not work, we try with the full url. If the url 
     176    # start with a '/' we use the full url directly. 
    188177    # tested in MainControllerTest 
    189178    def template_text_for_url(url) 
    190        
    191       url = url[1..-1] # strip leading '/' 
    192       url = url.split('/') 
    193       skin_name = url.shift 
    194       if skin_name == 'default' 
    195         path = File.join(SITES_ROOT, 'shared', 'zafu', 'default', *url) 
    196         if File.exists?(path) 
    197           File.read(path) 
    198         else 
    199           nil 
    200         end 
    201       else 
    202         if @skin_obj && @skin_obj[:name] == skin_name 
    203           skin = @skin_obj 
    204         end 
    205         skin ||= secure(Skin) { Skin.find_by_name(skin_name) } 
     179      @skin ||= {} 
     180      if url =~ /^\// 
     181        url = url[1..-1].split('/') 
     182        skin_names = [url.shift] 
     183      else 
     184        url = url.split('/') 
     185        skin_names = [@skin_name, url.shift] 
     186      end 
     187       
     188      partial = nil 
     189      skin_names.each do |skin_name| 
     190        skin = @skin[skin_name] ||= secure(Skin) { Skin.find_by_name(skin_name) } 
    206191        path = (skin.fullpath.split('/') + url).join('/') 
    207         partial = secure(TextDocument) { TextDocument.find_by_path(path) } 
    208         partial.version.text 
    209       end 
    210     rescue ActiveRecord::RecordNotFound 
    211       return nil 
     192        break if partial = secure(TextDocument) { TextDocument.find_by_path(path) } 
     193      end 
     194      partial ? partial.version.text : nil 
    212195    end 
    213196 
  • trunk/app/models/node.rb

    r455 r463  
    146146      node = find(:first, :conditions=>"zip = #{zip.to_i}") 
    147147      raise ActiveRecord::RecordNotFound unless node 
    148       node 
    149     end 
    150      
    151     # Find an node by it's full path. Cache 'fullpath' if found. 
    152     def find_by_path(path) 
    153       return nil unless scope = scoped_methods[0] 
    154       return nil unless scope[:create] 
    155       visitor = scoped_methods[0][:create][:visitor] # use secure scope to get visitor 
    156       node = self.find_by_fullpath(path) 
    157       if node.nil? 
    158         path = path.split('/') 
    159         last = path.pop 
    160         Node.with_exclusive_scope do 
    161           node = Node.find(visitor.site[:root_id]) 
    162           path.each do |p| 
    163             raise ActiveRecord::RecordNotFound unless node = Node.find_by_name_and_parent_id(p, node[:id]) 
    164           end 
    165         end 
    166         raise ActiveRecord::RecordNotFound unless node = self.find_by_name_and_parent_id(last, node[:id]) 
    167         path << last 
    168         node.fullpath = path.join('/') 
    169         # bypass callbacks here 
    170         Node.connection.execute "UPDATE #{Node.table_name} SET fullpath='#{path.join('/').gsub("'",'"')}' WHERE id='#{node[:id]}'" 
    171       end 
    172148      node 
    173149    end 
  • trunk/app/models/page.rb

    r455 r463  
    1515      Page 
    1616    end 
    17    
     17     
     18    # Find an node by it's full path. Cache 'fullpath' if found. 
     19    def find_by_path(path) 
     20      return nil unless scope = scoped_methods[0] 
     21      return nil unless scope[:create] 
     22      visitor = scoped_methods[0][:create][:visitor] # use secure scope to get visitor 
     23      node = self.find_by_fullpath(path) 
     24      if node.nil? 
     25        path = path.split('/') 
     26        last = path.pop 
     27        Node.with_exclusive_scope do 
     28          node = Node.find(visitor.site[:root_id]) 
     29          path.each do |p| 
     30            raise ActiveRecord::RecordNotFound unless node = Node.find_by_name_and_parent_id(p, node[:id]) 
     31          end 
     32        end 
     33        raise ActiveRecord::RecordNotFound unless node = self.find_by_name_and_parent_id(last, node[:id]) 
     34        path << last 
     35        node.fullpath = path.join('/') 
     36        # bypass callbacks here 
     37        Node.connection.execute "UPDATE #{Node.table_name} SET fullpath='#{path.join('/').gsub("'",'"')}' WHERE id='#{node[:id]}'" 
     38      end 
     39      node 
     40    end 
     41     
    1842    def select_classes 
    1943      list = subclasses.inject([]) do |list, k| 
  • trunk/lib/parser/lib/parser.rb

    r455 r463  
    1010 
    1111    def template_text_for_url(url) 
    12       url = url[1..-1] # strip leading '/' 
    13       url = url.gsub('/','_') 
    14       if test = @strings[url
     12      url = url[1..-1] if url[0..0] == '/' # just ignore the 'relative' or 'absolute' tricks. 
     13       
     14      if test = @strings[url.gsub('/','_')
    1515        test['src'] 
    1616      else 
     
    5656      helper = opts[:helper] || ParserModule::DummyHelper.new 
    5757      text, absolute_url = self.find_template_text(url,helper) 
    58       current_folder = absolute_url ? absolute_url.split('/')[0..-2].join('/') : '/' 
     58      current_folder     = absolute_url ? absolute_url.split('/')[1..-2].join('/') : nil 
    5959      self.new(text, :helper=>helper, :current_folder=>current_folder, :included_history=>[absolute_url]) 
    6060    end 
     
    6363    # This method is used when 'including' text 
    6464    def find_template_text(url, helper, current_folder=nil) 
    65       current_folder ||= '/' 
    66       # remove trailing '/' 
    67       if current_folder[-1..-1] == '/' 
    68         current_folder = current_folder[0..-2] 
    69       end 
    7065       
    71       if url[0..0] == '/' 
    72         # absolute url 
    73         urls = [url,"#{url}/_#{url.split('/').last}"] 
    74       else 
    75         # relative path 
    76         urls = ["#{current_folder}/#{url}", "#{current_folder}/#{url}/_#{url.split('/').last}", 
    77         "/default/#{url}", "/default/#{url}/_#{url.split('/').last}"] 
     66      if (url[0..0] != '/') && current_folder 
     67        url = "#{current_folder}/#{url}" 
    7868      end 
    7969       
    80       text = absolute_url = nil 
    81       urls.each do |template_url| 
    82         if text = helper.send(:template_text_for_url,template_url) 
    83           absolute_url = template_url 
    84           break 
    85         end 
    86       end 
    87       text ||= "<span class='parser_error'>template '#{url}' not found</span>" 
    88       return [text, absolute_url] 
     70      text = helper.send(:template_text_for_url, url) || "<span class='parser_error'>template '#{url}' not found</span>" 
     71      url = "/#{url}" unless url[0..0] == '/' # has to be an absolute path 
     72      return [text, url] 
    8973    end 
    9074     
     
    119103  end 
    120104   
     105  def replace_with(obj)   
     106    @blocks   = obj.blocks 
     107    @params   = obj.params 
     108  end 
     109   
    121110  def render(context={}) 
    122111    return '' if context["no_#{@method}".to_sym] 
     
    132121      end 
    133122      if replacer = (@context[:parts] || {})[@context[:name]] 
    134         @blocks   = replacer.blocks 
    135         @params   = replacer.params 
     123        replace_with(replacer) 
    136124      end 
    137125    end 
     
    177165  def r_include 
    178166    expand_with(:preflight=>true) 
    179     @blocks = @included_blocks || @blocks 
    180167    if @parts != {} 
    181       expand_with(:parts => (@context[:parts] || {}).merge(@parts)
    182     else 
    183       expand_with 
     168      expand_with(:parts => (@context[:parts] || {}).merge(@parts), :blocks => @included_blocks
     169    else 
     170      expand_with(:blocks => @included_blocks) 
    184171    end 
    185172  end 
     
    221208    text = @text 
    222209    @options[:included_history] ||= [] 
    223     @options[:current_folder]   ||= '/' 
     210     
    224211    @text, absolute_url = self.class.find_template_text(@params[:template], @options[:helper], @options[:current_folder]) 
     212     
    225213    if absolute_url 
    226214      if @options[:included_history].include?(absolute_url) 
     
    228216      else 
    229217        @options[:included_history] += [absolute_url] 
    230         @options[:current_folder] = absolute_url.split('/')[0..-2].join('/') 
    231       end 
    232     end 
     218        @options[:current_folder]    = absolute_url.split('/')[1..-2].join('/') 
     219      end 
     220    end 
     221     
    233222    @text = before_parse(@text) 
    234223    enter(:void) # scan fetched text 
     
    254243  end 
    255244   
     245  # Build blocks 
    256246  def store(obj) 
    257247    if obj.kind_of?(String) && @blocks.last.kind_of?(String) 
     
    262252  end 
    263253   
     254  # Set output during render 
    264255  def out(obj) 
    265256    @result << obj 
     
    398389   
    399390  def expand_with(acontext={}) 
     391    blocks = acontext.delete(:blocks) || @blocks 
    400392    res = "" 
    401393    @pass  = {} # current object sees some information from it's direct descendants 
    402394    @parts = {} 
    403395    new_context = @context.merge(acontext) 
    404     @blocks.each do |b| 
     396    blocks.each do |b| 
    405397      if b.kind_of?(String) 
    406398        res << b 
  • trunk/lib/parser/lib/rules/zafu.rb

    r455 r463  
    33module Zafu 
    44  module Tags 
     5    attr_accessor :html_tag, :html_tag_params 
     6     
     7    def replace_with(obj) 
     8      super 
     9      @html_tag          = obj.html_tag        || @html_tag 
     10      @html_tag_params   = obj.html_tag_params || @html_tag_params 
     11    end 
    512     
    613    def render(context={}) 
     
    241248      elsif @text =~ /\A[^>]*?>/ 
    242249        # html tag 
     250        store opts[:space_before] 
    243251        flush $& 
    244252      else 
  • trunk/lib/parser/test/parser_test.rb

    r370 r463  
    3333  testfile :zafu, :zafu_asset, :zafu_insight, :zazen 
    3434  def test_single 
    35     do_test('zafu', 'tada') 
     35    do_test('zafu', 'complex_example') 
    3636  end 
    3737  def test_zazen_image_no_image 
  • trunk/lib/parser/test/zafu.yml

    r315 r463  
    110110  res: "<span class='parser_error'>[include error: /infinite/bar --&gt; /infinite/foo --&gt; /infinite/bar ]</span>" 
    111111   
    112 other_context: 
     112default_context: 
    113113  src: "from other: <z:include template='menu'/> and <z:include template='/include/menu'/>" 
    114114  res: "from other: the [test]menu[/test] is nice and include_menu: the [test]menu[/test] is nice" 
     
    125125  src: | 
    126126    Some people say <z:hello/> 
    127     Some say <z:include template='menu'/> 
     127    Some say <z:include template='/default/menu'/> 
    128128      <ul class='list' do='set_context' life='ok'> 
    129129        <li>truc</li> 
     
    138138        <li>truc</li> 
    139139        <li>machin</li> 
    140         [test {> :life=>'ok'}]<li>sunny day</li>[/test] 
    141       </ul> 
     140    [test {> :life=>'ok'}]    <li>sunny day</li> 
     141    [/test]  </ul> 
    142142    the [test {> :var=>'complex'}]menu[/test] is nice 
    143143 
     
    163163        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> 
    164164    <title do='test'>node title</title> 
     165    end 
    165166  res: | 
    166167    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" 
    167168        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> 
    168     [test]<title>node title</title>[/test] 
    169    
     169    [test]<title>node title</title> 
     170    [/test]end 
    170171no_tag: 
    171172  src: "<z:set_context no_test='true'>this is a <z:test>test</z:test>dog</z:set_context>" 
     
    201202 
    202203name: 
    203   src: "super: <z:void name='super'>hey <z:text text='ho' name='man'/></z:void>" 
     204  src: "super: <z:void name='super'>hey <z:void name='man' do='text' text='ho'/></z:void>" 
    204205  res: "super: hey ho" 
    205206 
     
    213214 
    214215name_title: 
    215   src: "title: <h1 do='text' text='dummy' name='title'>blah</h1>" 
     216  src: "title: <h1 do='void' name='title' do='text' text='dummy'>blah</h1>" 
    216217  res: "title: <h1>dummy</h1>" 
    217218 
     
    226227     
    227228  res: | 
    228     [test]<p>blah</p>[/test] 
    229     [test]<p>blah</p>[/test] 
    230     ok 
     229    [test]<p>blah</p> 
     230    [/test][test]<p>blah</p> 
     231    [/test]ok 
    231232 
    232233names: 
  • trunk/lib/parser/test/zafu_insight.yml

    r311 r463  
    1313include: 
    1414  src: "<z:include template='/menu'><z:with part='a'>do <z:inspect/></z:with></z:include>" 
    15   res: "var a: do [inspect {> :menu=>'true', :name=>'a', :parts=>''}/]" 
     15  res: "var a: do [inspect {> :menu=>'true', :name=>'a', :parts=>'ado [inspect {> :preflight=>'true'}/]'}/]"