##// END OF EJS Templates
Rails3: model: replace deprecated 'before_save' method at WikiPage model...
Toshi MARUYAMA -
r7318:e16d20f1b47f
parent child
Show More
@@ -1,224 +1,225
1 1 # Redmine - project management software
2 2 # Copyright (C) 2006-2011 Jean-Philippe Lang
3 3 #
4 4 # This program is free software; you can redistribute it and/or
5 5 # modify it under the terms of the GNU General Public License
6 6 # as published by the Free Software Foundation; either version 2
7 7 # of the License, or (at your option) any later version.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU General Public License
15 15 # along with this program; if not, write to the Free Software
16 16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 17
18 18 require 'diff'
19 19 require 'enumerator'
20 20
21 21 class WikiPage < ActiveRecord::Base
22 22 belongs_to :wiki
23 23 has_one :content, :class_name => 'WikiContent', :foreign_key => 'page_id', :dependent => :destroy
24 24 acts_as_attachable :delete_permission => :delete_wiki_pages_attachments
25 25 acts_as_tree :dependent => :nullify, :order => 'title'
26 26
27 27 acts_as_watchable
28 28 acts_as_event :title => Proc.new {|o| "#{l(:label_wiki)}: #{o.title}"},
29 29 :description => :text,
30 30 :datetime => :created_on,
31 31 :url => Proc.new {|o| {:controller => 'wiki', :action => 'show', :project_id => o.wiki.project, :id => o.title}}
32 32
33 33 acts_as_searchable :columns => ['title', 'text'],
34 34 :include => [{:wiki => :project}, :content],
35 35 :permission => :view_wiki_pages,
36 36 :project_key => "#{Wiki.table_name}.project_id"
37 37
38 38 attr_accessor :redirect_existing_links
39 39
40 40 validates_presence_of :title
41 41 validates_format_of :title, :with => /^[^,\.\/\?\;\|\s]*$/
42 42 validates_uniqueness_of :title, :scope => :wiki_id, :case_sensitive => false
43 43 validates_associated :content
44 44
45 45 validate :validate_parent_title
46 46 before_destroy :remove_redirects
47 before_save :handle_redirects
47 48
48 49 # eager load information about last updates, without loading text
49 50 named_scope :with_updated_on, {
50 51 :select => "#{WikiPage.table_name}.*, #{WikiContent.table_name}.updated_on",
51 52 :joins => "LEFT JOIN #{WikiContent.table_name} ON #{WikiContent.table_name}.page_id = #{WikiPage.table_name}.id"
52 53 }
53 54
54 55 # Wiki pages that are protected by default
55 56 DEFAULT_PROTECTED_PAGES = %w(sidebar)
56 57
57 58 def after_initialize
58 59 if new_record? && DEFAULT_PROTECTED_PAGES.include?(title.to_s.downcase)
59 60 self.protected = true
60 61 end
61 62 end
62 63
63 64 def visible?(user=User.current)
64 65 !user.nil? && user.allowed_to?(:view_wiki_pages, project)
65 66 end
66 67
67 68 def title=(value)
68 69 value = Wiki.titleize(value)
69 70 @previous_title = read_attribute(:title) if @previous_title.blank?
70 71 write_attribute(:title, value)
71 72 end
72 73
73 def before_save
74 def handle_redirects
74 75 self.title = Wiki.titleize(title)
75 76 # Manage redirects if the title has changed
76 77 if !@previous_title.blank? && (@previous_title != title) && !new_record?
77 78 # Update redirects that point to the old title
78 79 wiki.redirects.find_all_by_redirects_to(@previous_title).each do |r|
79 80 r.redirects_to = title
80 81 r.title == r.redirects_to ? r.destroy : r.save
81 82 end
82 83 # Remove redirects for the new title
83 84 wiki.redirects.find_all_by_title(title).each(&:destroy)
84 85 # Create a redirect to the new title
85 86 wiki.redirects << WikiRedirect.new(:title => @previous_title, :redirects_to => title) unless redirect_existing_links == "0"
86 87 @previous_title = nil
87 88 end
88 89 end
89 90
90 91 def remove_redirects
91 92 # Remove redirects to this page
92 93 wiki.redirects.find_all_by_redirects_to(title).each(&:destroy)
93 94 end
94 95
95 96 def pretty_title
96 97 WikiPage.pretty_title(title)
97 98 end
98 99
99 100 def content_for_version(version=nil)
100 101 result = content.versions.find_by_version(version.to_i) if version
101 102 result ||= content
102 103 result
103 104 end
104 105
105 106 def diff(version_to=nil, version_from=nil)
106 107 version_to = version_to ? version_to.to_i : self.content.version
107 108 version_from = version_from ? version_from.to_i : version_to - 1
108 109 version_to, version_from = version_from, version_to unless version_from < version_to
109 110
110 111 content_to = content.versions.find_by_version(version_to)
111 112 content_from = content.versions.find_by_version(version_from)
112 113
113 114 (content_to && content_from) ? WikiDiff.new(content_to, content_from) : nil
114 115 end
115 116
116 117 def annotate(version=nil)
117 118 version = version ? version.to_i : self.content.version
118 119 c = content.versions.find_by_version(version)
119 120 c ? WikiAnnotate.new(c) : nil
120 121 end
121 122
122 123 def self.pretty_title(str)
123 124 (str && str.is_a?(String)) ? str.tr('_', ' ') : str
124 125 end
125 126
126 127 def project
127 128 wiki.project
128 129 end
129 130
130 131 def text
131 132 content.text if content
132 133 end
133 134
134 135 def updated_on
135 136 unless @updated_on
136 137 if time = read_attribute(:updated_on)
137 138 # content updated_on was eager loaded with the page
138 139 @updated_on = Time.parse(time) rescue nil
139 140 else
140 141 @updated_on = content && content.updated_on
141 142 end
142 143 end
143 144 @updated_on
144 145 end
145 146
146 147 # Returns true if usr is allowed to edit the page, otherwise false
147 148 def editable_by?(usr)
148 149 !protected? || usr.allowed_to?(:protect_wiki_pages, wiki.project)
149 150 end
150 151
151 152 def attachments_deletable?(usr=User.current)
152 153 editable_by?(usr) && super(usr)
153 154 end
154 155
155 156 def parent_title
156 157 @parent_title || (self.parent && self.parent.pretty_title)
157 158 end
158 159
159 160 def parent_title=(t)
160 161 @parent_title = t
161 162 parent_page = t.blank? ? nil : self.wiki.find_page(t)
162 163 self.parent = parent_page
163 164 end
164 165
165 166 protected
166 167
167 168 def validate_parent_title
168 169 errors.add(:parent_title, :invalid) if !@parent_title.blank? && parent.nil?
169 170 errors.add(:parent_title, :circular_dependency) if parent && (parent == self || parent.ancestors.include?(self))
170 171 errors.add(:parent_title, :not_same_project) if parent && (parent.wiki_id != wiki_id)
171 172 end
172 173 end
173 174
174 175 class WikiDiff < Redmine::Helpers::Diff
175 176 attr_reader :content_to, :content_from
176 177
177 178 def initialize(content_to, content_from)
178 179 @content_to = content_to
179 180 @content_from = content_from
180 181 super(content_to.text, content_from.text)
181 182 end
182 183 end
183 184
184 185 class WikiAnnotate
185 186 attr_reader :lines, :content
186 187
187 188 def initialize(content)
188 189 @content = content
189 190 current = content
190 191 current_lines = current.text.split(/\r?\n/)
191 192 @lines = current_lines.collect {|t| [nil, nil, t]}
192 193 positions = []
193 194 current_lines.size.times {|i| positions << i}
194 195 while (current.previous)
195 196 d = current.previous.text.split(/\r?\n/).diff(current.text.split(/\r?\n/)).diffs.flatten
196 197 d.each_slice(3) do |s|
197 198 sign, line = s[0], s[1]
198 199 if sign == '+' && positions[line] && positions[line] != -1
199 200 if @lines[positions[line]][0].nil?
200 201 @lines[positions[line]][0] = current.version
201 202 @lines[positions[line]][1] = current.author
202 203 end
203 204 end
204 205 end
205 206 d.each_slice(3) do |s|
206 207 sign, line = s[0], s[1]
207 208 if sign == '-'
208 209 positions.insert(line, -1)
209 210 else
210 211 positions[line] = nil
211 212 end
212 213 end
213 214 positions.compact!
214 215 # Stop if every line is annotated
215 216 break unless @lines.detect { |line| line[0].nil? }
216 217 current = current.previous
217 218 end
218 219 @lines.each { |line|
219 220 line[0] ||= current.version
220 221 # if the last known version is > 1 (eg. history was cleared), we don't know the author
221 222 line[1] ||= current.author if current.version == 1
222 223 }
223 224 end
224 225 end
General Comments 0
You need to be logged in to leave comments. Login now