francois / mephisto forked from halorgium/mephisto

A refactored Mephisto that has multiple spam detection engines.

This URL has Read+Write access

francois (author)
Mon Mar 17 19:02:47 -0700 2008
commit  cf11753a6d59fbbfcbd0e063706395ff31600059
tree    99cad4a4e7cbdd79c3c9781008d0ee9d0cbc4451
parent  f1068ff008b7da9263fd9037d1a37b3813e70991
mephisto / app / models / theme.rb
100644 157 lines (138 sloc) 5.159 kb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
class Theme
  @@root_theme_files = %w(about.yml preview.png)
  @@theme_directories = %w(templates layouts javascripts stylesheets images)
  @@allowed_extensions = %w(.js .css .png .gif .jpg .swf .ico) | Site.extensions
  cattr_reader :root_theme_files, :theme_directories, :allowed_extensions
  attr_reader :path, :base_path, :extension
 
  def self.import(zip_file, options = {})
    dest = options[:to].is_a?(Pathname) ? options[:to] : Pathname.new(options[:to] || '.')
    basename = dest.basename.to_s
    if dest.exist? || basename == 'current'
      basename = basename =~ /(.*)_(\d+)$/ ? $1 : basename
      number = $2 ? $2.to_i + 1 : 2
      dirname = dest.dirname
      dest = dirname + "#{basename}_#{number}"
      while dest.exist?
        number += 1
        dest = dirname + "#{basename}_#{number}"
      end
    end
    FileUtils.mkdir_p dest.to_s unless dest.exist?
    Zip::ZipFile.open(zip_file) do |z|
      root_theme_files.each do |file|
        z.file.open(file) { |zf| File.open(dest + file, 'wb') { |f| f << zf.read } } if z.file.exist?(file)
      end
      theme_directories.each do |dir|
        dir_path = Pathname.new(dest + dir)
        FileUtils.mkdir_p dir_path unless dir_path.exist?
        z.dir.entries(dir).each do |entry|
          next unless entry =~ /(\.\w+)$/ && allowed_extensions.include?($1)
          z.file.open(File.join(dir, entry)) { |zf| File.open(dir_path + entry, 'wb') { |f| f << zf.read } }
        end
      end
    end
    dest.basename.to_s
  rescue
    dest.rmtree if dest.exist?
    raise ThemeError.new(dest, $!.message)
  end
 
  def initialize(base, site = nil)
    @site = site
    if base.is_a?(Pathname)
      @base_path = base.to_s
      @path = base
    else
      @base_path = base
      @path = Pathname.new(@base_path)
    end
    layout = (@path + "layouts").children(false).select {|v| v.to_s =~ /^layout/}[0] if (@path + "layouts").directory?
    @extension = layout.extname if layout
  end
 
  def current?
    @current ||= (@site && @site.current_theme_path == @path.basename.to_s) || :false
    @current != :false
  end
 
  def name
    class << self ; attr_reader :name ; end
    @name = @path.basename.to_s
  end
  
  alias to_param name
 
  def preview
    class << self; attr_reader :preview ; end
    @preview = @path + 'preview.png'
  end
 
  def properties
    class << self ; attr_reader :properties ; end
    about = path + 'about.yml'
    @properties = about.exist? ? YAML.load_file(about) : {}
  end
 
  [:summary, :author, :version, :homepage].each do |attr_name|
    eval <<-END
def #{attr_name}
class << self ; attr_reader :#{attr_name} ; end
@#{attr_name} = properties['#{attr_name}']
end
END
  end
 
  def title
    class << self ; attr_reader :title ; end
    @title = properties['title'] || name
  end
 
  def linked_author
    class << self ; attr_reader :linked_author ; end
    @linked_author = homepage.blank? ? author : %(<a href="#{CGI.escapeHTML homepage}">#{author}</a>)
  end
 
  def attachments
    class << self ; attr_reader :attachments ; end
    @attachments, @templates, @resources = Attachments.new, Templates.new, Resources.new
    [@attachments, @templates, @resources].each { |a| a.theme = self }
    Pathname.glob(File.join(base_path, '*/*')).each do |path|
      next unless path.file?
      @attachments << path
      ((path.extname == @extension) ? @templates : @resources) << path
    end
    @attachments
  end
 
  def resources
    class << self ; attr_reader :resources ; end
    attachments && instance_variable_get(:@resources)
  end
 
  def templates
    class << self ; attr_reader :templates ; end
    attachments && instance_variable_get(:@templates)
  end
 
  def export_as_zip(name, options = {})
    path = options[:to] || '.'
    Zip::ZipFile.open(File.join(path, "#{name}.zip"), Zip::ZipFile::CREATE) do |zip|
      theme_directories.each { |d| zip.dir.mkdir(d) }
      write_theme_files_with zip.file
    end
  end
 
  def export(name, options = {})
    path = File.join(options[:to] || '.', name)
    theme_directories.each { |d| FileUtils.mkdir_p File.join(path, d) }
    write_theme_files_with File, path
  end
 
  def eql?(comparison_object)
    self == (comparison_object)
  end
  
  def ==(comparison_object)
    base_path == (comparison_object.is_a?(Theme) ? comparison_object.base_path : comparison_object.to_s)
  end
 
  def similar_to?(theme)
    title == theme.title && version == theme.version
  end
 
  protected
    def write_theme_files_with(file_class, relative_path = '')
      # ZipFileSystem doesn't support wb
      write_mode = file_class.is_a?(Zip::ZipFileSystem::ZipFsFile) ? 'w' : 'wb'
      relative_path = Pathname.new(relative_path) unless relative_path.is_a?(Pathname)
      root_theme_files.each do |file|
        real_file = path + file
        file_class.open((relative_path + file).to_s, write_mode) { |f| f << real_file.read } if real_file.exist?
      end
      attachments.each do |full_path|
        file_class.open((relative_path + full_path.relative_path_from(path)).to_s, write_mode) { |f| f << full_path.read }
      end
    end
end