##// END OF EJS Templates
Rails3: model: replace deprecated 'before_destroy' method at WikiPage model...
Toshi MARUYAMA -
r7317:ec1b9f38f3d2
parent child
Show More
@@ -1,223 +1,224
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 before_destroy :remove_redirects
46 47
47 48 # eager load information about last updates, without loading text
48 49 named_scope :with_updated_on, {
49 50 :select => "#{WikiPage.table_name}.*, #{WikiContent.table_name}.updated_on",
50 51 :joins => "LEFT JOIN #{WikiContent.table_name} ON #{WikiContent.table_name}.page_id = #{WikiPage.table_name}.id"
51 52 }
52 53
53 54 # Wiki pages that are protected by default
54 55 DEFAULT_PROTECTED_PAGES = %w(sidebar)
55 56
56 57 def after_initialize
57 58 if new_record? && DEFAULT_PROTECTED_PAGES.include?(title.to_s.downcase)
58 59 self.protected = true
59 60 end
60 61 end
61 62
62 63 def visible?(user=User.current)
63 64 !user.nil? && user.allowed_to?(:view_wiki_pages, project)
64 65 end
65 66
66 67 def title=(value)
67 68 value = Wiki.titleize(value)
68 69 @previous_title = read_attribute(:title) if @previous_title.blank?
69 70 write_attribute(:title, value)
70 71 end
71 72
72 73 def before_save
73 74 self.title = Wiki.titleize(title)
74 75 # Manage redirects if the title has changed
75 76 if !@previous_title.blank? && (@previous_title != title) && !new_record?
76 77 # Update redirects that point to the old title
77 78 wiki.redirects.find_all_by_redirects_to(@previous_title).each do |r|
78 79 r.redirects_to = title
79 80 r.title == r.redirects_to ? r.destroy : r.save
80 81 end
81 82 # Remove redirects for the new title
82 83 wiki.redirects.find_all_by_title(title).each(&:destroy)
83 84 # Create a redirect to the new title
84 85 wiki.redirects << WikiRedirect.new(:title => @previous_title, :redirects_to => title) unless redirect_existing_links == "0"
85 86 @previous_title = nil
86 87 end
87 88 end
88 89
89 def before_destroy
90 def remove_redirects
90 91 # Remove redirects to this page
91 92 wiki.redirects.find_all_by_redirects_to(title).each(&:destroy)
92 93 end
93 94
94 95 def pretty_title
95 96 WikiPage.pretty_title(title)
96 97 end
97 98
98 99 def content_for_version(version=nil)
99 100 result = content.versions.find_by_version(version.to_i) if version
100 101 result ||= content
101 102 result
102 103 end
103 104
104 105 def diff(version_to=nil, version_from=nil)
105 106 version_to = version_to ? version_to.to_i : self.content.version
106 107 version_from = version_from ? version_from.to_i : version_to - 1
107 108 version_to, version_from = version_from, version_to unless version_from < version_to
108 109
109 110 content_to = content.versions.find_by_version(version_to)
110 111 content_from = content.versions.find_by_version(version_from)
111 112
112 113 (content_to && content_from) ? WikiDiff.new(content_to, content_from) : nil
113 114 end
114 115
115 116 def annotate(version=nil)
116 117 version = version ? version.to_i : self.content.version
117 118 c = content.versions.find_by_version(version)
118 119 c ? WikiAnnotate.new(c) : nil
119 120 end
120 121
121 122 def self.pretty_title(str)
122 123 (str && str.is_a?(String)) ? str.tr('_', ' ') : str
123 124 end
124 125
125 126 def project
126 127 wiki.project
127 128 end
128 129
129 130 def text
130 131 content.text if content
131 132 end
132 133
133 134 def updated_on
134 135 unless @updated_on
135 136 if time = read_attribute(:updated_on)
136 137 # content updated_on was eager loaded with the page
137 138 @updated_on = Time.parse(time) rescue nil
138 139 else
139 140 @updated_on = content && content.updated_on
140 141 end
141 142 end
142 143 @updated_on
143 144 end
144 145
145 146 # Returns true if usr is allowed to edit the page, otherwise false
146 147 def editable_by?(usr)
147 148 !protected? || usr.allowed_to?(:protect_wiki_pages, wiki.project)
148 149 end
149 150
150 151 def attachments_deletable?(usr=User.current)
151 152 editable_by?(usr) && super(usr)
152 153 end
153 154
154 155 def parent_title
155 156 @parent_title || (self.parent && self.parent.pretty_title)
156 157 end
157 158
158 159 def parent_title=(t)
159 160 @parent_title = t
160 161 parent_page = t.blank? ? nil : self.wiki.find_page(t)
161 162 self.parent = parent_page
162 163 end
163 164
164 165 protected
165 166
166 167 def validate_parent_title
167 168 errors.add(:parent_title, :invalid) if !@parent_title.blank? && parent.nil?
168 169 errors.add(:parent_title, :circular_dependency) if parent && (parent == self || parent.ancestors.include?(self))
169 170 errors.add(:parent_title, :not_same_project) if parent && (parent.wiki_id != wiki_id)
170 171 end
171 172 end
172 173
173 174 class WikiDiff < Redmine::Helpers::Diff
174 175 attr_reader :content_to, :content_from
175 176
176 177 def initialize(content_to, content_from)
177 178 @content_to = content_to
178 179 @content_from = content_from
179 180 super(content_to.text, content_from.text)
180 181 end
181 182 end
182 183
183 184 class WikiAnnotate
184 185 attr_reader :lines, :content
185 186
186 187 def initialize(content)
187 188 @content = content
188 189 current = content
189 190 current_lines = current.text.split(/\r?\n/)
190 191 @lines = current_lines.collect {|t| [nil, nil, t]}
191 192 positions = []
192 193 current_lines.size.times {|i| positions << i}
193 194 while (current.previous)
194 195 d = current.previous.text.split(/\r?\n/).diff(current.text.split(/\r?\n/)).diffs.flatten
195 196 d.each_slice(3) do |s|
196 197 sign, line = s[0], s[1]
197 198 if sign == '+' && positions[line] && positions[line] != -1
198 199 if @lines[positions[line]][0].nil?
199 200 @lines[positions[line]][0] = current.version
200 201 @lines[positions[line]][1] = current.author
201 202 end
202 203 end
203 204 end
204 205 d.each_slice(3) do |s|
205 206 sign, line = s[0], s[1]
206 207 if sign == '-'
207 208 positions.insert(line, -1)
208 209 else
209 210 positions[line] = nil
210 211 end
211 212 end
212 213 positions.compact!
213 214 # Stop if every line is annotated
214 215 break unless @lines.detect { |line| line[0].nil? }
215 216 current = current.previous
216 217 end
217 218 @lines.each { |line|
218 219 line[0] ||= current.version
219 220 # if the last known version is > 1 (eg. history was cleared), we don't know the author
220 221 line[1] ||= current.author if current.version == 1
221 222 }
222 223 end
223 224 end
General Comments 0
You need to be logged in to leave comments. Login now