##// END OF EJS Templates
Fixed: wiki pages in search results are referenced by project number, not by project identifier (#4456)....
Jean-Philippe Lang -
r3117:5e1dc78d7539
parent child
Show More
@@ -1,193 +1,193
1 1 # Redmine - project management software
2 2 # Copyright (C) 2006-2009 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 :url => Proc.new {|o| {:controller => 'wiki', :id => o.wiki.project_id, :page => o.title}}
31 :url => Proc.new {|o| {:controller => 'wiki', :id => o.wiki.project, :page => o.title}}
32 32
33 33 acts_as_searchable :columns => ['title', 'text'],
34 34 :include => [{:wiki => :project}, :content],
35 35 :project_key => "#{Wiki.table_name}.project_id"
36 36
37 37 attr_accessor :redirect_existing_links
38 38
39 39 validates_presence_of :title
40 40 validates_format_of :title, :with => /^[^,\.\/\?\;\|\s]*$/
41 41 validates_uniqueness_of :title, :scope => :wiki_id, :case_sensitive => false
42 42 validates_associated :content
43 43
44 44 def visible?(user=User.current)
45 45 !user.nil? && user.allowed_to?(:view_wiki_pages, project)
46 46 end
47 47
48 48 def title=(value)
49 49 value = Wiki.titleize(value)
50 50 @previous_title = read_attribute(:title) if @previous_title.blank?
51 51 write_attribute(:title, value)
52 52 end
53 53
54 54 def before_save
55 55 self.title = Wiki.titleize(title)
56 56 # Manage redirects if the title has changed
57 57 if !@previous_title.blank? && (@previous_title != title) && !new_record?
58 58 # Update redirects that point to the old title
59 59 wiki.redirects.find_all_by_redirects_to(@previous_title).each do |r|
60 60 r.redirects_to = title
61 61 r.title == r.redirects_to ? r.destroy : r.save
62 62 end
63 63 # Remove redirects for the new title
64 64 wiki.redirects.find_all_by_title(title).each(&:destroy)
65 65 # Create a redirect to the new title
66 66 wiki.redirects << WikiRedirect.new(:title => @previous_title, :redirects_to => title) unless redirect_existing_links == "0"
67 67 @previous_title = nil
68 68 end
69 69 end
70 70
71 71 def before_destroy
72 72 # Remove redirects to this page
73 73 wiki.redirects.find_all_by_redirects_to(title).each(&:destroy)
74 74 end
75 75
76 76 def pretty_title
77 77 WikiPage.pretty_title(title)
78 78 end
79 79
80 80 def content_for_version(version=nil)
81 81 result = content.versions.find_by_version(version.to_i) if version
82 82 result ||= content
83 83 result
84 84 end
85 85
86 86 def diff(version_to=nil, version_from=nil)
87 87 version_to = version_to ? version_to.to_i : self.content.version
88 88 version_from = version_from ? version_from.to_i : version_to - 1
89 89 version_to, version_from = version_from, version_to unless version_from < version_to
90 90
91 91 content_to = content.versions.find_by_version(version_to)
92 92 content_from = content.versions.find_by_version(version_from)
93 93
94 94 (content_to && content_from) ? WikiDiff.new(content_to, content_from) : nil
95 95 end
96 96
97 97 def annotate(version=nil)
98 98 version = version ? version.to_i : self.content.version
99 99 c = content.versions.find_by_version(version)
100 100 c ? WikiAnnotate.new(c) : nil
101 101 end
102 102
103 103 def self.pretty_title(str)
104 104 (str && str.is_a?(String)) ? str.tr('_', ' ') : str
105 105 end
106 106
107 107 def project
108 108 wiki.project
109 109 end
110 110
111 111 def text
112 112 content.text if content
113 113 end
114 114
115 115 # Returns true if usr is allowed to edit the page, otherwise false
116 116 def editable_by?(usr)
117 117 !protected? || usr.allowed_to?(:protect_wiki_pages, wiki.project)
118 118 end
119 119
120 120 def attachments_deletable?(usr=User.current)
121 121 editable_by?(usr) && super(usr)
122 122 end
123 123
124 124 def parent_title
125 125 @parent_title || (self.parent && self.parent.pretty_title)
126 126 end
127 127
128 128 def parent_title=(t)
129 129 @parent_title = t
130 130 parent_page = t.blank? ? nil : self.wiki.find_page(t)
131 131 self.parent = parent_page
132 132 end
133 133
134 134 protected
135 135
136 136 def validate
137 137 errors.add(:parent_title, :invalid) if !@parent_title.blank? && parent.nil?
138 138 errors.add(:parent_title, :circular_dependency) if parent && (parent == self || parent.ancestors.include?(self))
139 139 errors.add(:parent_title, :not_same_project) if parent && (parent.wiki_id != wiki_id)
140 140 end
141 141 end
142 142
143 143 class WikiDiff
144 144 attr_reader :diff, :words, :content_to, :content_from
145 145
146 146 def initialize(content_to, content_from)
147 147 @content_to = content_to
148 148 @content_from = content_from
149 149 @words = content_to.text.split(/(\s+)/)
150 150 @words = @words.select {|word| word != ' '}
151 151 words_from = content_from.text.split(/(\s+)/)
152 152 words_from = words_from.select {|word| word != ' '}
153 153 @diff = words_from.diff @words
154 154 end
155 155 end
156 156
157 157 class WikiAnnotate
158 158 attr_reader :lines, :content
159 159
160 160 def initialize(content)
161 161 @content = content
162 162 current = content
163 163 current_lines = current.text.split(/\r?\n/)
164 164 @lines = current_lines.collect {|t| [nil, nil, t]}
165 165 positions = []
166 166 current_lines.size.times {|i| positions << i}
167 167 while (current.previous)
168 168 d = current.previous.text.split(/\r?\n/).diff(current.text.split(/\r?\n/)).diffs.flatten
169 169 d.each_slice(3) do |s|
170 170 sign, line = s[0], s[1]
171 171 if sign == '+' && positions[line] && positions[line] != -1
172 172 if @lines[positions[line]][0].nil?
173 173 @lines[positions[line]][0] = current.version
174 174 @lines[positions[line]][1] = current.author
175 175 end
176 176 end
177 177 end
178 178 d.each_slice(3) do |s|
179 179 sign, line = s[0], s[1]
180 180 if sign == '-'
181 181 positions.insert(line, -1)
182 182 else
183 183 positions[line] = nil
184 184 end
185 185 end
186 186 positions.compact!
187 187 # Stop if every line is annotated
188 188 break unless @lines.detect { |line| line[0].nil? }
189 189 current = current.previous
190 190 end
191 191 @lines.each { |line| line[0] ||= current.version }
192 192 end
193 193 end
General Comments 0
You need to be logged in to leave comments. Login now