Changeset 1251

Show
Ignore:
Timestamp:
2008-11-12 21:05:07 (2 months ago)
Author:
gaspard
Message:

commit 6842d0e7e87fe09360327cc73d795ce083d02f51
Author: Gaspard Bucher <gaspard@teti.ch>

Simplified zena customization (adding new models). Just drop a plugin inside 'vendor/plugins'. All models defined in the 'models' folder will be loaded.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/app/helpers/application_helper.rb

    r1243 r1251  
    55module ApplicationHelper 
    66  include Zena::Acts::Secure 
     7  @@_asset_methods = {} 
     8   
     9  # define an asset method ('key' => method_name). 
     10  def self.asset_method(opts) 
     11    opts.each do |k,v| 
     12      @@_asset_methods[k] = v 
     13    end 
     14  end 
    715   
    816  def dom_id(node) 
     
    349357  # Parse the text in the given context (used by zazen) 
    350358  def make_asset(opts) 
    351     asset_type = opts[:asset_type] 
    352     content    = opts[:content] 
    353     node       = opts[:node] 
    354     case asset_type 
    355     when 'math' 
    356       if !(content =~ /^\s*\\begin\{(align|equation|itemize|equation)/) 
    357         pre = '\[' 
    358         post = '\]' 
    359       else 
    360         pre = post = '' 
    361       end 
    362        
    363       # FIXME: SECURITY LateX filtering: is this enough ? 
    364       if content =~ /\\input/ 
    365         return "<span class='math_preview'>#{content.gsub(/(\\input\w*)/, "<span style=\'color:red;\'>#{$1}</span> (not supported)")}</span>" 
    366       end 
    367        
    368       if opts[:output] == 'latex' 
    369         "#{pre}#{content}#{post}" 
    370       elsif ENABLE_MATH 
    371         # Create PNG image 
    372         # 1. get image path 
    373         math_id  = Digest::SHA1.hexdigest(content)[0..4] 
    374         filename = math_id + '.png' 
    375         filepath = node.asset_path(filename) 
    376         unless File.exist?(filepath) 
    377           if opts[:preview] 
    378             # do not render image during preview 
    379             tag = content =~ /\n/ ? 'pre' : 'span' 
    380             return "<#{tag} class='math_preview'>#{content}</#{tag}>" 
    381           else 
    382             # create image 
    383             FileUtils::mkpath(File.dirname(filepath)) unless File.exist?(File.dirname(filepath)) 
    384             begin 
    385               tempf = Tempfile.new(filename) # TODO: do we need to close this file ? 
    386               base = tempf.path 
    387 latex_template = %q{ 
    388 \documentclass[10pt]{article} 
    389 \usepackage[utf8]{inputenc} 
    390 \usepackage{amssymb} 
    391  
    392 \usepackage{amsmath} 
    393 \usepackage{amsfonts} 
    394 \usepackage{ulem}     % strikethrough (\sout{...}) 
    395 \usepackage{hyperref} % links 
    396  
    397  
    398 % shortcuts 
    399 \DeclareMathOperator*{\argmin}{arg\,min} 
    400 \newcommand{\ve}[1]{\boldsymbol{#1}} 
    401 \newcommand{\ma}[1]{\boldsymbol{#1}} 
    402 \newenvironment{m}{\begin{bmatrix}}{\end{bmatrix}} 
    403  
    404 \pagestyle{empty} 
    405 \begin{document} 
    406  
    407 
    408  
    409               File.open("#{base}.tex", 'wb') do |f| 
    410                 f.syswrite(latex_template) 
    411                 f.syswrite(pre) 
    412                 f.syswrite(content) 
    413                 f.syswrite(post) 
    414                 f.syswrite("\n\\end{document}\n") 
    415               end 
    416                
    417               system("cd #{File.dirname(tempf.path)}; latex -interaction=batchmode #{"#{base}.tex".inspect} &> '#{base}.err'") 
    418               if !File.exists?("#{base}.dvi") 
    419                 Node.logger.error(File.read("#{base}.err")) 
    420                 system("cp '#{RAILS_ROOT}/public/world.png' #{filepath.inspect}") 
    421               else 
    422                 system("dvips #{tempf.path}.dvi -E -o #{base}.ps &> '#{base}.err'") #||  Node.logger.error(File.read("#{base}.err")) 
    423                 system("convert -units PixelsPerInch -density 150 -matte -fuzz '10%' -transparent '#ffffff' #{base}.ps #{filepath.inspect} &> '#{base}.err'") #|| Node.logger.error(File.read("#{base}.err")) 
    424               end 
    425  
    426             ensure 
    427               system("rm -rf #{tempf.path.inspect} #{(tempf.path + '.*').inspect}") 
    428             end 
    429           end 
    430         end 
    431         "<span class='math'><img src='#{zen_path(node, :asset => math_id, :format => 'png')}'/></span>" 
    432       else 
    433         # Math not supported 
    434         "[#{asset_type}]#{content}[/#{asset_type}]" 
    435       end 
     359    asset_tag = opts[:asset_tag] 
     360    if asset_method = @@_asset_methods[asset_tag] 
     361      self.send(asset_method, opts) 
    436362    else 
    437363      # Unknown tag. Ignore 
    438       "[#{asset_type}]#{content}[/#{asset_type}]" 
     364      "[#{asset_tag}]#{opts[:content]}[/#{asset_tag}]" 
    439365    end 
    440366  end 
  • trunk/app/models/virtual_class.rb

    r1110 r1251  
    22  belongs_to    :create_group, :class_name => 'Group', :foreign_key => 'create_group_id' 
    33  validate      :valid_virtual_class 
    4   include Zena::Relations::AllRelationsFinder 
     4  include Zena::Relations::ClassMethods 
    55   
    66  def to_s 
  • trunk/config/environment.rb

    r1239 r1251  
    2828  end 
    2929   
    30  
     30  config.load_paths += Dir["#{RAILS_ROOT}/vendor/plugins/**/models"] 
     31   
     32   
    3133  # Force all environments to use the same logger level  
    3234  # (by default production uses :info, the others :debug) 
     
    9092 
    9193require File.join(lib_path, 'base_additions') 
     94require File.join(lib_path, 'use_find_helpers') 
     95require File.join(lib_path, 'use_zafu') 
    9296require File.join(lib_path, 'node_query') 
    9397require File.join(lib_path, 'comment_query') 
  • trunk/lib/base_additions.rb

    r1081 r1251  
    1 class ActiveRecord::Base 
    2   class << self 
    3      
    4     def fetch_ids(sql, id_attr='id') 
    5       unless sql =~ /SELECT/i 
    6         sql = "SELECT `#{id_attr}` FROM #{self.table_name} WHERE #{sql}" 
    7       end 
    8       connection.select_all(sql, "#{name} Load").map! do |record|  
    9         record[id_attr.to_s] 
    10       end 
    11     end 
    12      
    13     def fetch_list(sql, *attr_list) 
    14       unless sql =~ /SELECT/i 
    15         sql = "SELECT #{attr_list.map {|a| "`#{a}`"}.join(', ')} FROM #{self.table_name} WHERE #{sql}" 
    16       end 
    17       connection.select_all(sql, "#{name} Load").map! do |record|  
    18         Hash[*(attr_list.map {|attr| [attr, record[attr.to_s]] }.flatten)] 
    19       end 
    20     end 
    21      
    22     def next_zip(site_id) 
    23       res = connection.update "UPDATE zips SET zip=@zip:=zip+1 WHERE site_id = '#{site_id}'" 
    24       if res == 0 
    25         # error 
    26         raise Zena::BadConfiguration, "no zip entry for (#{site_id})" 
    27       end 
    28       rows = connection.execute "SELECT @zip" 
    29       rows.fetch_row[0].to_i 
    30     end 
    31      
    32     def fetch_attribute(attribute, sql) 
    33       unless sql =~ /SELECT/i 
    34         sql = "SELECT `#{attribute}` FROM #{table_name} WHERE #{sql}" 
    35       end 
    36       row = connection.execute(sql).fetch_row 
    37       row ? row[0] : nil 
    38     end 
    39   end   
    40 end 
    41  
    421module Zena 
    432  # This exception occurs when we have configuration problems. 
  • trunk/lib/core_ext/patcher.rb

    r1061 r1251  
    1 def load_patches_from_plugins 
    2   file_name = caller[0].split('/').last.split(':').first 
     1def foreach_plugin(&block) 
    32  plugins_folder = File.join(RAILS_ROOT, 'vendor', 'plugins') 
    43  Dir.foreach(plugins_folder) do |plugin| 
    54    next if plugin =~ /\A\./ 
    6     patch_file = File.join(plugins_folder, plugin, 'patch', file_name) 
     5    block.call(File.join(plugins_folder, plugin)) 
     6  end 
     7end 
     8 
     9def load_patches_from_plugins 
     10  file_name = caller[0].split('/').last.split(':').first 
     11  foreach_plugin do |plugin_path| 
     12    patch_file = File.join(plugin_path, 'patch', file_name) 
    713    if File.exist?(patch_file) 
    814      load patch_file 
     
    1016  end 
    1117end 
     18 
     19def load_models_from_plugins 
     20  foreach_plugin do |plugin_path| 
     21    Dir.foreach(File.join(plugins_path, 'models')) do |model_name| 
     22      load File.join(plugins_path, 'models', model_name) 
     23    end 
     24  end 
     25end 
  • trunk/lib/has_relations.rb

    r1250 r1251  
    44      # this is called when the module is included into the 'base' module 
    55      def self.included(base) 
    6         # add all methods from the module "AddActsAsMethod" to the 'base' module 
    7         base.extend Zena::Relations::ClassMethods 
     6        base.extend Zena::Relations::TriggerClassMethod 
     7      end 
     8    end 
     9 
     10    module TriggerClassMethod 
     11      def has_relations 
     12        validate      :relations_valid 
     13        after_save    :update_relations 
     14        after_destroy :destroy_links 
     15         
     16        class_eval <<-END 
     17          include Zena::Relations::InstanceMethods 
     18          class << self 
     19            include Zena::Relations::ClassMethods 
     20          end 
     21           
     22          def relation_base_class 
     23            #{self} 
     24          end 
     25        END 
    826      end 
    927    end 
    1028     
    11     module AllRelationsFinder 
     29    module ClassMethods 
    1230      # All relations related to the current class/virtual_class with its ancestors. 
    1331      def all_relations(start=nil) 
     
    2745        end 
    2846      end 
    29     end 
    30      
    31     module ClassMethods 
    32       def has_relations 
    33         validate      :relations_valid 
    34         after_save    :update_relations 
    35         after_destroy :destroy_links 
    36          
    37         class_eval <<-END 
    38         include Zena::Relations::InstanceMethods 
    39           def relation_base_class 
    40             #{self} 
    41           end 
    42         END 
    43       end 
    44       include Zena::Relations::AllRelationsFinder 
    4547    end 
    4648     
  • trunk/lib/parser/lib/rules/zazen.rb

    r1236 r1251  
    275275          eat $& 
    276276          # [math]....[/math] (we do not use <math> to avoid confusion with mathml) 
    277           store @helper.make_asset(:asset_type => $1, :content => $2, :node => @options[:node], :preview => @context[:preview], :output => @context[:output]) 
     277          store @helper.make_asset(:asset_tag => $1, :content => $2, :node => @options[:node], :preview => @context[:preview], :output => @context[:output]) 
    278278        end 
    279279      else 
  • trunk/lib/parser/lib/rules/zena.rb

    r1250 r1251  
    3939 
    4040require 'yaml' 
    41 begin 
    42   # FIXME: zafu_readable should belong to core_ext. 
    43   class ActiveRecord::Base 
    44     @@_zafu_readable  ||= {} # defined for each class 
    45     @@_safe_attribute ||= {} # defined for each class 
    46     @@_zafu_context   ||= {} # defined for each class (list of methods to change contexts) 
    47     @@_zafu_readable_attributes ||= {} # full list with inherited attributes 
    48     @@_safe_attribute_list      ||= {} # full list with inherited attributes 
    49     @@_zafu_known_contexts      ||= {} # full list with inherited attributes 
    50    
    51     def self.zafu_readable(*list) 
    52       @@_zafu_readable[self] ||= [] 
    53       @@_zafu_readable[self] = (@@_zafu_readable[self] + list.map{|l| l.to_s}).uniq 
    54     end 
    55      
    56     def self.safe_attribute(*list) 
    57       @@_safe_attribute[self] ||= [] 
    58       @@_safe_attribute[self] = (@@_safe_attribute[self] + list.map{|l| l.to_s}).uniq 
    59     end 
    60      
    61     def self.zafu_context(hash) 
    62       @@_zafu_context[self] ||= {} 
    63       @@_zafu_context[self].merge!(hash.stringify_keys) 
    64     end 
    65    
    66     def self.zafu_readable_attributes 
    67       @@_zafu_readable_attributes[self] ||= if superclass == ActiveRecord::Base 
    68         @@_zafu_readable[self] || [] 
    69       else 
    70         (superclass.zafu_readable_attributes + (@@_zafu_readable[self] || [])).uniq.sort 
    71       end 
    72     end 
    73      
    74     def self.safe_attribute_list 
    75       @@_safe_attribute_list[self] ||= if superclass == ActiveRecord::Base 
    76         @@_safe_attribute[self] || [] 
    77       else 
    78         (superclass.safe_attribute_list + (@@_safe_attribute[self] || [])).uniq.sort 
    79       end 
    80     end 
    81      
    82     def self.zafu_known_contexts 
    83       @@_zafu_known_contexts[self] ||= begin 
    84         res = {} 
    85         if superclass == ActiveRecord::Base 
    86           @@_zafu_context[self] || {} 
    87         else 
    88           superclass.zafu_known_contexts.merge(@@_zafu_context[self] || {}) 
    89         end.each do |k,v| 
    90           if v.kind_of?(Hash) 
    91             res[k] = v.merge(:node_class => parse_class(v[:node_class])) 
    92           else 
    93             res[k] = {:node_class => parse_class(v)} 
    94           end 
    95         end 
    96         res 
    97       end 
    98     end 
    99      
    100     def self.parse_class(klass) 
    101       if klass.kind_of?(Array) 
    102         if klass[0].kind_of?(String) 
    103           [Module::const_get(klass[0])] 
    104         else 
    105           klass 
    106         end 
    107       else 
    108         if klass.kind_of?(String) 
    109           Module::const_get(klass) 
    110         else 
    111           klass 
    112         end 
    113       end 
    114     end 
    115      
    116     def self.safe_attribute?(sym) 
    117       column_names.include?(sym) || zafu_readable?(sym) || safe_attribute_list.include?(sym.to_s) 
    118     end 
    119      
    120     def self.zafu_readable?(sym) 
    121       if sym.to_s =~ /(.*)_zips?$/ 
    122         return true if self.ancestors.include?(Node) && RelationProxy.find_by_role($1.singularize) 
    123       end 
    124       self.zafu_readable_attributes.include?(sym.to_s) 
    125     end 
    126    
    127     def zafu_read(sym) 
    128       return "'#{sym}' not readable" unless self.class.zafu_readable?(sym) 
    129       self.send(sym) 
    130     end 
    131   end 
    132 rescue NameError 
    133   puts "Testing out of Rails, ActiveRecord uninitialized." 
    134 end 
    13541 
    13642module Zena 
  • trunk/lib/parser/test/parser/zazen.yml

    r1248 r1251  
    209209make_asset: 
    210210  src: "my email: [email]bob@example.com[/email]." 
    211   res: "<p>my email: [make_asset asset_type:|email| content:|bob@example.com| output:|html|].</p>" 
     211  res: "<p>my email: [make_asset asset_tag:|email| content:|bob@example.com| output:|html|].</p>" 
  • trunk/test/helpers/testhelp.rb

    r1250 r1251  
    22require File.join(File.dirname(__FILE__), '..','..','lib','yaml_test') 
    33begin 
    4 #  require 'turn' 
    5 #  Test::Unit::UI::Console::TestRunner.use_progressbar = true 
     4  require 'turn' 
     5  Test::Unit::UI::Console::TestRunner.use_progressbar = true 
    66rescue MissingSourceFile 
    77  # ignore missing 'turn' testing gem 
  • trunk/vendor/plugins/zena_captcha/patch/application_helper.rb

    r1250 r1251  
    22module ApplicationHelper 
    33  include ReCaptcha::ViewHelper 
     4  asset_method 'email' => :email_asset 
    45   
    56  # FIXME: remove when rails 2.0. 
     
    2324  end 
    2425   
    25   def make_asset(opts) 
    26     asset_type = opts[:asset_type] 
    27     content    = opts[:content] 
    28     if asset_type == 'email' && current_site.d_mail_hide_priv && current_site.d_mail_hide_pub 
     26  def email_asset(opts) 
     27    content = opts[:content] 
     28    if current_site.d_mail_hide_priv && current_site.d_mail_hide_pub 
    2929      mail_hide(content, :mh_priv => current_site.d_mail_hide_priv, :mh_pub => current_site.d_mail_hide_pub) 
    3030    else 
    31       super 
     31      "<a href='mailto:#{content}'>#{content}</a>" 
    3232    end 
    3333  end