Changesets can be listed by changeset number.
The Git repository is here.
- Revision:
- 344
- Log:
Massive changeset which brings the old, ROOL customised Instiki
version up to date, but without any ROOL customisations in this
latest checked-in version (which is 0.19.1). This is deliberate,
so that it's easy to see the changes made for the ROOL version
in a subsequent changeset. The 'app/views/shared' directory is not
part of Instiki but is kept to maintain the change history with
updated ROOL customisations, some of which involve the same files
in that same directory.
- Author:
- rool
- Date:
- Sat Mar 19 19:52:13 +0000 2011
- Size:
- 5573 Bytes
1 | class Web < ActiveRecord::Base |
2 | ## Associations |
3 | |
4 | has_many :pages, :dependent => :destroy |
5 | has_many :wiki_files, :dependent => :destroy |
6 | |
7 | has_many :revisions, :through => :pages |
8 | |
9 | ## Hooks |
10 | |
11 | before_save :sanitize_markup |
12 | after_save :create_files_directory |
13 | |
14 | before_validation :validate_address |
15 | |
16 | ## Validations |
17 | |
18 | validates_uniqueness_of :address |
19 | |
20 | validates_length_of :color, :in => 3..6 |
21 | |
22 | ## Methods |
23 | |
24 | # @return [Wiki] a new Wiki instance |
25 | def wiki |
26 | Wiki.new |
27 | end |
28 | |
29 | def settings_changed?(markup, safe_mode, brackets_only) |
30 | self.markup != markup || |
31 | self.safe_mode != safe_mode || |
32 | self.brackets_only != brackets_only |
33 | end |
34 | |
35 | def add_page(name, content, time, author, renderer) |
36 | page = page(name) || pages.build(:name => name) |
37 | page.revise(content, name, time, author, renderer) |
38 | end |
39 | |
40 | # @return [Array<String>] a collection of all the names of the authors that |
41 | # have ever contributed to the pages for this Web |
42 | def authors |
43 | revisions.all( |
44 | :select => "DISTINCT revisions.author", |
45 | :order => "1" |
46 | ).collect(&:author) |
47 | end |
48 | |
49 | def categories |
50 | select.map { |page| page.categories }.flatten.uniq.sort |
51 | end |
52 | |
53 | # @param [String] name the name of some associated Page record to find |
54 | # @return [Page, nil] the associated Page record, or +nil+ if no record is |
55 | # found with the provided name |
56 | def page(name) |
57 | pages.find_by_name(name) |
58 | end |
59 | |
60 | # @return [Page] the last associated Page record |
61 | def last_page |
62 | pages.last |
63 | end |
64 | |
65 | # @param [String] name the name of some potential Page record |
66 | # @return [Boolean] whether or not a given Page record exists with a given |
67 | # name |
68 | def has_page?(name) |
69 | pages.exists?(:name => name) |
70 | end |
71 | |
72 | def has_redirect_for?(name) |
73 | WikiReference.page_that_redirects_for(self, name) |
74 | end |
75 | |
76 | def page_that_redirects_for(name) |
77 | page(WikiReference.page_that_redirects_for(self, name)) |
78 | end |
79 | |
80 | def has_file?(file_name) |
81 | wiki_files.exists?(:file_name => file_name) |
82 | end |
83 | |
84 | def file_list(sort_order="file_name") |
85 | wiki_files.all(:order => sort_order) |
86 | end |
87 | |
88 | def pages_that_link_to(page_name) |
89 | WikiReference.pages_that_link_to(self, page_name) |
90 | end |
91 | |
92 | def pages_that_link_to_file(file_name) |
93 | WikiReference.pages_that_link_to_file(self, file_name) |
94 | end |
95 | |
96 | # @param [String] file_name the name of some WikiFile of interest |
97 | # @return [String, nil] the description of some WikiFile of interest, nil if |
98 | # the WikiFile could not be found |
99 | def description(file_name) |
100 | wiki_files.find_by_file_name(file_name).try(:description) |
101 | end |
102 | |
103 | # @return [Symbol] the type of markup used by this Web |
104 | def markup |
105 | self[:markup].to_sym |
106 | end |
107 | |
108 | # @return [Hash] a Hash wherein the key is some author's name, and the |
109 | # values are an array of page names for that author. |
110 | def page_names_by_author |
111 | data = revisions.all( |
112 | :select => "DISTINCT revisions.author AS author, pages.name AS page_name", |
113 | :order => "pages.name" |
114 | ) |
115 | |
116 | data.inject({}) do |result, revision| |
117 | result[revision.author] ||= [] |
118 | result[revision.author] << revision.page_name |
119 | result |
120 | end |
121 | end |
122 | |
123 | # OPTIMIZE Use the +delete_all+ with conditions for extra efficiency |
124 | def remove_pages(pages_to_be_removed) |
125 | pages_to_be_removed.each { |p| p.destroy } |
126 | end |
127 | |
128 | def revised_at |
129 | select.most_recent_revision |
130 | end |
131 | |
132 | def select(&condition) |
133 | PageSet.new(self, pages, condition) |
134 | end |
135 | |
136 | def select_all |
137 | PageSet.new(self, pages, nil) |
138 | end |
139 | |
140 | # @return [String] uses the +address+ attribute for this record's parameter name |
141 | def to_param |
142 | address |
143 | end |
144 | |
145 | # Called by an +after_save+ hook. Creates the directory that houses this |
146 | # Web's associated files. |
147 | # |
148 | # TODO Move this into the WikiFile model |
149 | def create_files_directory |
150 | return unless allow_uploads == 1 |
151 | |
152 | dummy_file = wiki_files.build( |
153 | :file_name => "0", |
154 | :description => "0", |
155 | :content => "0" |
156 | ) |
157 | |
158 | File.umask(0002) |
159 | |
160 | begin |
161 | dummy_file.content_path.parent.mkpath |
162 | dummy_file.save |
163 | dummy_file.destroy |
164 | rescue => e |
165 | logger.error "Failed create files directory for #{address}: #{e}" |
166 | raise "Instiki could not create directory to store uploaded files. " + |
167 | "Please make sure that Instiki is allowed to create directory " + |
168 | "#{dummy_file.content_path.expand_path} and add files to it." |
169 | end |
170 | end |
171 | |
172 | # @return [Pathname] the path to the files for this record |
173 | def files_path |
174 | path = Rails.root.join("webs") |
175 | if default_web? |
176 | path.join("files") |
177 | else |
178 | path.join(address, "files") |
179 | end |
180 | end |
181 | |
182 | # @return [Pathname] the path to PNGs for this record |
183 | def blahtex_pngs_path |
184 | files_path.join("pngs") |
185 | end |
186 | |
187 | private |
188 | |
189 | # Returns an array of all the wiki words in any current revision |
190 | def wiki_words |
191 | pages.inject([]) { |wiki_words, page| wiki_words << page.wiki_words }.flatten.uniq |
192 | end |
193 | |
194 | # Returns an array of all the page names on this web |
195 | def page_names |
196 | pages.map { |p| p.name } |
197 | end |
198 | |
199 | protected |
200 | |
201 | def sanitize_markup |
202 | self.markup = markup.to_s |
203 | end |
204 | |
205 | def validate_address |
206 | unless address == CGI.escape(address) |
207 | self.errors.add(:address, 'should contain only valid URI characters') |
208 | raise Instiki::ValidationError.new("#{self.class.human_attribute_name('address')} #{errors.on(:address)}") |
209 | end |
210 | end |
211 | |
212 | # @return [Boolean] whether or not this record is considered the default Web |
213 | def default_web? |
214 | defined?(DEFAULT_WEB) && address == DEFAULT_WEB |
215 | end |
216 | end |