diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index a47126052..ffc71ce1f 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -612,33 +612,7 @@ class ProjectsController < ApplicationController render :template => "projects/gantt.rhtml" end end - - def search - @question = params[:q] || "" - @question.strip! - @all_words = params[:all_words] || (params[:submit] ? false : true) - @scope = params[:scope] || (params[:submit] ? [] : %w(issues changesets news documents wiki) ) - # tokens must be at least 3 character long - @tokens = @question.split.uniq.select {|w| w.length > 2 } - if !@tokens.empty? - # no more than 5 tokens to search for - @tokens.slice! 5..-1 if @tokens.size > 5 - # strings used in sql like statement - like_tokens = @tokens.collect {|w| "%#{w.downcase}%"} - operator = @all_words ? " AND " : " OR " - limit = 10 - @results = [] - @results += @project.issues.find(:all, :limit => limit, :include => :author, :conditions => [ (["(LOWER(subject) like ? OR LOWER(description) like ?)"] * like_tokens.size).join(operator), * (like_tokens * 2).sort] ) if @scope.include? 'issues' - @results += @project.news.find(:all, :limit => limit, :conditions => [ (["(LOWER(title) like ? OR LOWER(description) like ?)"] * like_tokens.size).join(operator), * (like_tokens * 2).sort], :include => :author ) if @scope.include? 'news' - @results += @project.documents.find(:all, :limit => limit, :conditions => [ (["(LOWER(title) like ? OR LOWER(description) like ?)"] * like_tokens.size).join(operator), * (like_tokens * 2).sort] ) if @scope.include? 'documents' - @results += @project.wiki.pages.find(:all, :limit => limit, :include => :content, :conditions => [ (["(LOWER(title) like ? OR LOWER(text) like ?)"] * like_tokens.size).join(operator), * (like_tokens * 2).sort] ) if @project.wiki && @scope.include?('wiki') - @results += @project.repository.changesets.find(:all, :limit => limit, :conditions => [ (["(LOWER(comments) like ?)"] * like_tokens.size).join(operator), * (like_tokens).sort] ) if @project.repository && @scope.include?('changesets') - @question = @tokens.join(" ") - else - @question = "" - end - end - + def feeds @queries = @project.queries.find :all, :conditions => ["is_public=? or user_id=?", true, (logged_in_user ? logged_in_user.id : 0)] @key = logged_in_user.get_or_create_rss_key.value if logged_in_user diff --git a/app/controllers/search_controller.rb b/app/controllers/search_controller.rb new file mode 100644 index 000000000..c463e4a35 --- /dev/null +++ b/app/controllers/search_controller.rb @@ -0,0 +1,75 @@ +# redMine - project management software +# Copyright (C) 2006 Jean-Philippe Lang +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +class SearchController < ApplicationController + layout 'base' + + def index + @question = params[:q] || "" + @question.strip! + @all_words = params[:all_words] || (params[:submit] ? false : true) + @scope = params[:scope] || (params[:submit] ? [] : %w(projects issues changesets news documents wiki) ) + + # quick jump to an issue + if @scope.include?('issues') && @question.match(/^#?(\d+)$/) && Issue.find_by_id($1, :include => :project, :conditions => Project.visible_by(logged_in_user)) + redirect_to :controller => "issues", :action => "show", :id => $1 + return + end + + if params[:id] + find_project + return unless check_project_privacy + end + + # tokens must be at least 3 character long + @tokens = @question.split.uniq.select {|w| w.length > 2 } + + if !@tokens.empty? + # no more than 5 tokens to search for + @tokens.slice! 5..-1 if @tokens.size > 5 + # strings used in sql like statement + like_tokens = @tokens.collect {|w| "%#{w.downcase}%"} + operator = @all_words ? " AND " : " OR " + limit = 10 + @results = [] + if @project + @results += @project.issues.find(:all, :limit => limit, :include => :author, :conditions => [ (["(LOWER(subject) like ? OR LOWER(description) like ?)"] * like_tokens.size).join(operator), * (like_tokens * 2).sort] ) if @scope.include? 'issues' + @results += @project.news.find(:all, :limit => limit, :conditions => [ (["(LOWER(title) like ? OR LOWER(description) like ?)"] * like_tokens.size).join(operator), * (like_tokens * 2).sort], :include => :author ) if @scope.include? 'news' + @results += @project.documents.find(:all, :limit => limit, :conditions => [ (["(LOWER(title) like ? OR LOWER(description) like ?)"] * like_tokens.size).join(operator), * (like_tokens * 2).sort] ) if @scope.include? 'documents' + @results += @project.wiki.pages.find(:all, :limit => limit, :include => :content, :conditions => [ (["(LOWER(title) like ? OR LOWER(text) like ?)"] * like_tokens.size).join(operator), * (like_tokens * 2).sort] ) if @project.wiki && @scope.include?('wiki') + @results += @project.repository.changesets.find(:all, :limit => limit, :conditions => [ (["(LOWER(comments) like ?)"] * like_tokens.size).join(operator), * (like_tokens).sort] ) if @project.repository && @scope.include?('changesets') + else + Project.with_scope(:find => {:conditions => Project.visible_by(logged_in_user)}) do + @results += Project.find(:all, :limit => limit, :conditions => [ (["(LOWER(name) like ? OR LOWER(description) like ?)"] * like_tokens.size).join(operator), * (like_tokens * 2).sort] ) if @scope.include? 'projects' + end + # if only one project is found, user is redirected to its overview + redirect_to :controller => 'projects', :action => 'show', :id => @results.first and return if @results.size == 1 + end + @question = @tokens.join(" ") + else + @question = "" + end + end + +private + def find_project + @project = Project.find(params[:id]) + @html_title = @project.name + rescue ActiveRecord::RecordNotFound + render_404 + end +end diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb index 43febd413..c7e80b0a0 100644 --- a/app/helpers/projects_helper.rb +++ b/app/helpers/projects_helper.rb @@ -16,14 +16,4 @@ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. module ProjectsHelper - - def highlight_tokens(text, tokens) - return text unless tokens && !tokens.empty? - regexp = Regexp.new "(#{tokens.join('|')})", Regexp::IGNORECASE - result = '' - text.split(regexp).each_with_index do |words, i| - result << (i.even? ? (words.length > 100 ? "#{words[0..44]} ... #{words[-45..-1]}" : words) : content_tag('span', words, :class => 'highlight')) - end - result - end end diff --git a/app/helpers/search_helper.rb b/app/helpers/search_helper.rb new file mode 100644 index 000000000..bc408a305 --- /dev/null +++ b/app/helpers/search_helper.rb @@ -0,0 +1,28 @@ +# redMine - project management software +# Copyright (C) 2006-2007 Jean-Philippe Lang +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +module SearchHelper + def highlight_tokens(text, tokens) + return text unless tokens && !tokens.empty? + regexp = Regexp.new "(#{tokens.join('|')})", Regexp::IGNORECASE + result = '' + text.split(regexp).each_with_index do |words, i| + result << (i.even? ? (words.length > 100 ? "#{words[0..44]} ... #{words[-45..-1]}" : words) : content_tag('span', words, :class => 'highlight')) + end + result + end +end diff --git a/app/views/layouts/base.rhtml b/app/views/layouts/base.rhtml index 3d6390b95..945803b0a 100644 --- a/app/views/layouts/base.rhtml +++ b/app/views/layouts/base.rhtml @@ -27,9 +27,13 @@
<%= text_field_tag 'q', @question, :size => 30 %>
-<%= check_box_tag 'scope[]', 'issues', (@scope.include? 'issues') %>
-<% if @project.repository %>
-<%= check_box_tag 'scope[]', 'changesets', (@scope.include? 'changesets') %>
-<% end %>
-<%= check_box_tag 'scope[]', 'news', (@scope.include? 'news') %>
-<%= check_box_tag 'scope[]', 'documents', (@scope.include? 'documents') %>
-<% if @project.wiki %>
-<%= check_box_tag 'scope[]', 'wiki', (@scope.include? 'wiki') %>
-<% end %>
-
-<%= check_box_tag 'all_words', 1, @all_words %> <%= l(:label_all_words) %>
- <% if e.is_a? Issue %>
- <%= link_to_issue e %>: <%= highlight_tokens(h(e.subject), @tokens) %>
- <%= highlight_tokens(e.description, @tokens) %>
- <%= e.author.name %>, <%= format_time(e.created_on) %>
- <% elsif e.is_a? News %>
- <%=l(:label_news)%>: <%= link_to highlight_tokens(h(e.title), @tokens), :controller => 'news', :action => 'show', :id => e %>
- <%= highlight_tokens(e.description, @tokens) %>
- <%= e.author.name %>, <%= format_time(e.created_on) %>
- <% elsif e.is_a? Document %>
- <%=l(:label_document)%>: <%= link_to highlight_tokens(h(e.title), @tokens), :controller => 'documents', :action => 'show', :id => e %>
- <%= highlight_tokens(e.description, @tokens) %>
- <%= format_time(e.created_on) %>
- <% elsif e.is_a? WikiPage %>
- <%=l(:label_wiki)%>: <%= link_to highlight_tokens(h(e.pretty_title), @tokens), :controller => 'wiki', :action => 'index', :id => @project, :page => e.title %>
- <%= highlight_tokens(e.content.text, @tokens) %>
- <%= e.content.author ? e.content.author.name : "Anonymous" %>, <%= format_time(e.content.updated_on) %>
- <% elsif e.is_a? Changeset %>
- <%=l(:label_revision)%> <%= link_to h(e.revision), :controller => 'repositories', :action => 'revision', :id => @project, :rev => e.revision %>
- <%= highlight_tokens(e.comments, @tokens) %>
- <%= e.committer.blank? ? e.committer : "Anonymous" %>, <%= format_time(e.committed_on) %>
- <% end %>
-
<%= text_field_tag 'q', @question, :size => 30 %>
+
+<% if @project %>
+ <%= check_box_tag 'scope[]', 'issues', (@scope.include? 'issues') %>
+ <% if @project.repository %>
+ <%= check_box_tag 'scope[]', 'changesets', (@scope.include? 'changesets') %>
+ <% end %>
+ <%= check_box_tag 'scope[]', 'news', (@scope.include? 'news') %>
+ <%= check_box_tag 'scope[]', 'documents', (@scope.include? 'documents') %>
+ <% if @project.wiki %>
+ <%= check_box_tag 'scope[]', 'wiki', (@scope.include? 'wiki') %>
+ <% end %>
+<% else %>
+ <%= check_box_tag 'scope[]', 'projects', (@scope.include? 'projects') %>
+<% end %>
+
+<%= check_box_tag 'all_words', 1, @all_words %> <%= l(:label_all_words) %>
+ <% if e.is_a? Project %>
+ <%= link_to highlight_tokens(h(e.name), @tokens), :controller => 'projects', :action => 'show', :id => e %>
+ <%= highlight_tokens(e.description, @tokens) %>
+ <% elsif e.is_a? Issue %>
+ <%= link_to_issue e %>: <%= highlight_tokens(h(e.subject), @tokens) %>
+ <%= highlight_tokens(e.description, @tokens) %>
+ <%= e.author.name %>, <%= format_time(e.created_on) %>
+ <% elsif e.is_a? News %>
+ <%=l(:label_news)%>: <%= link_to highlight_tokens(h(e.title), @tokens), :controller => 'news', :action => 'show', :id => e %>
+ <%= highlight_tokens(e.description, @tokens) %>
+ <%= e.author.name %>, <%= format_time(e.created_on) %>
+ <% elsif e.is_a? Document %>
+ <%=l(:label_document)%>: <%= link_to highlight_tokens(h(e.title), @tokens), :controller => 'documents', :action => 'show', :id => e %>
+ <%= highlight_tokens(e.description, @tokens) %>
+ <%= format_time(e.created_on) %>
+ <% elsif e.is_a? WikiPage %>
+ <%=l(:label_wiki)%>: <%= link_to highlight_tokens(h(e.pretty_title), @tokens), :controller => 'wiki', :action => 'index', :id => @project, :page => e.title %>
+ <%= highlight_tokens(e.content.text, @tokens) %>
+ <%= e.content.author ? e.content.author.name : "Anonymous" %>, <%= format_time(e.content.updated_on) %>
+ <% elsif e.is_a? Changeset %>
+ <%=l(:label_revision)%> <%= link_to h(e.revision), :controller => 'repositories', :action => 'revision', :id => @project, :rev => e.revision %>
+ <%= highlight_tokens(e.comments, @tokens) %>
+ <%= e.committer.blank? ? e.committer : "Anonymous" %>, <%= format_time(e.committed_on) %>
+ <% end %>
+