@@ -754,144 +754,148 module ApplicationHelper | |||||
754 | # identifier:version:1.0.0 |
|
754 | # identifier:version:1.0.0 | |
755 | # identifier:source:some/file |
|
755 | # identifier:source:some/file | |
756 | def parse_redmine_links(text, default_project, obj, attr, only_path, options) |
|
756 | def parse_redmine_links(text, default_project, obj, attr, only_path, options) | |
757 | text.gsub!(%r{([\s\(,\-\[\>]|^)(!)?(([a-z0-9\-_]+):)?(attachment|document|version|forum|news|message|project|commit|source|export)?(((#)|((([a-z0-9\-_]+)\|)?(r)))((\d+)((#note)?-(\d+))?)|(:)([^"\s<>][^\s<>]*?|"[^"]+?"))(?=(?=[[:punct:]][^A-Za-z0-9_/])|,|\s|\]|<|$)}) do |m| |
|
757 | text.gsub!(%r{<a( [^>]+?)?>(.*?)</a>|([\s\(,\-\[\>]|^)(!)?(([a-z0-9\-_]+):)?(attachment|document|version|forum|news|message|project|commit|source|export)?(((#)|((([a-z0-9\-_]+)\|)?(r)))((\d+)((#note)?-(\d+))?)|(:)([^"\s<>][^\s<>]*?|"[^"]+?"))(?=(?=[[:punct:]][^A-Za-z0-9_/])|,|\s|\]|<|$)}) do |m| | |
758 |
leading, esc, project_prefix, project_identifier, prefix, repo_prefix, repo_identifier, sep, identifier, comment_suffix, comment_id = $1, |
|
758 | tag_content, leading, esc, project_prefix, project_identifier, prefix, repo_prefix, repo_identifier, sep, identifier, comment_suffix, comment_id = $1, $3, $4, $5, $6, $7, $12, $13, $10 || $14 || $20, $16 || $21, $17, $19 | |
759 | link = nil |
|
759 | if tag_content | |
760 | project = default_project |
|
760 | $& | |
761 | if project_identifier |
|
761 | else | |
762 | project = Project.visible.find_by_identifier(project_identifier) |
|
762 | link = nil | |
763 | end |
|
763 | project = default_project | |
764 | if esc.nil? |
|
764 | if project_identifier | |
765 | if prefix.nil? && sep == 'r' |
|
765 | project = Project.visible.find_by_identifier(project_identifier) | |
766 | if project |
|
766 | end | |
767 | repository = nil |
|
767 | if esc.nil? | |
768 | if repo_identifier |
|
768 | if prefix.nil? && sep == 'r' | |
769 | repository = project.repositories.detect {|repo| repo.identifier == repo_identifier} |
|
|||
770 | else |
|
|||
771 | repository = project.repository |
|
|||
772 | end |
|
|||
773 | # project.changesets.visible raises an SQL error because of a double join on repositories |
|
|||
774 | if repository && |
|
|||
775 | (changeset = Changeset.visible. |
|
|||
776 | find_by_repository_id_and_revision(repository.id, identifier)) |
|
|||
777 | link = link_to(h("#{project_prefix}#{repo_prefix}r#{identifier}"), |
|
|||
778 | {:only_path => only_path, :controller => 'repositories', |
|
|||
779 | :action => 'revision', :id => project, |
|
|||
780 | :repository_id => repository.identifier_param, |
|
|||
781 | :rev => changeset.revision}, |
|
|||
782 | :class => 'changeset', |
|
|||
783 | :title => truncate_single_line_raw(changeset.comments, 100)) |
|
|||
784 | end |
|
|||
785 | end |
|
|||
786 | elsif sep == '#' |
|
|||
787 | oid = identifier.to_i |
|
|||
788 | case prefix |
|
|||
789 | when nil |
|
|||
790 | if oid.to_s == identifier && |
|
|||
791 | issue = Issue.visible.includes(:status).find_by_id(oid) |
|
|||
792 | anchor = comment_id ? "note-#{comment_id}" : nil |
|
|||
793 | link = link_to(h("##{oid}#{comment_suffix}"), |
|
|||
794 | {:only_path => only_path, :controller => 'issues', |
|
|||
795 | :action => 'show', :id => oid, :anchor => anchor}, |
|
|||
796 | :class => issue.css_classes, |
|
|||
797 | :title => "#{issue.subject.truncate(100)} (#{issue.status.name})") |
|
|||
798 | end |
|
|||
799 | when 'document' |
|
|||
800 | if document = Document.visible.find_by_id(oid) |
|
|||
801 | link = link_to h(document.title), {:only_path => only_path, :controller => 'documents', :action => 'show', :id => document}, |
|
|||
802 | :class => 'document' |
|
|||
803 | end |
|
|||
804 | when 'version' |
|
|||
805 | if version = Version.visible.find_by_id(oid) |
|
|||
806 | link = link_to h(version.name), {:only_path => only_path, :controller => 'versions', :action => 'show', :id => version}, |
|
|||
807 | :class => 'version' |
|
|||
808 | end |
|
|||
809 | when 'message' |
|
|||
810 | if message = Message.visible.includes(:parent).find_by_id(oid) |
|
|||
811 | link = link_to_message(message, {:only_path => only_path}, :class => 'message') |
|
|||
812 | end |
|
|||
813 | when 'forum' |
|
|||
814 | if board = Board.visible.find_by_id(oid) |
|
|||
815 | link = link_to h(board.name), {:only_path => only_path, :controller => 'boards', :action => 'show', :id => board, :project_id => board.project}, |
|
|||
816 | :class => 'board' |
|
|||
817 | end |
|
|||
818 | when 'news' |
|
|||
819 | if news = News.visible.find_by_id(oid) |
|
|||
820 | link = link_to h(news.title), {:only_path => only_path, :controller => 'news', :action => 'show', :id => news}, |
|
|||
821 | :class => 'news' |
|
|||
822 | end |
|
|||
823 | when 'project' |
|
|||
824 | if p = Project.visible.find_by_id(oid) |
|
|||
825 | link = link_to_project(p, {:only_path => only_path}, :class => 'project') |
|
|||
826 | end |
|
|||
827 | end |
|
|||
828 | elsif sep == ':' |
|
|||
829 | # removes the double quotes if any |
|
|||
830 | name = identifier.gsub(%r{^"(.*)"$}, "\\1") |
|
|||
831 | name = CGI.unescapeHTML(name) |
|
|||
832 | case prefix |
|
|||
833 | when 'document' |
|
|||
834 | if project && document = project.documents.visible.find_by_title(name) |
|
|||
835 | link = link_to h(document.title), {:only_path => only_path, :controller => 'documents', :action => 'show', :id => document}, |
|
|||
836 | :class => 'document' |
|
|||
837 | end |
|
|||
838 | when 'version' |
|
|||
839 | if project && version = project.versions.visible.find_by_name(name) |
|
|||
840 | link = link_to h(version.name), {:only_path => only_path, :controller => 'versions', :action => 'show', :id => version}, |
|
|||
841 | :class => 'version' |
|
|||
842 | end |
|
|||
843 | when 'forum' |
|
|||
844 | if project && board = project.boards.visible.find_by_name(name) |
|
|||
845 | link = link_to h(board.name), {:only_path => only_path, :controller => 'boards', :action => 'show', :id => board, :project_id => board.project}, |
|
|||
846 | :class => 'board' |
|
|||
847 | end |
|
|||
848 | when 'news' |
|
|||
849 | if project && news = project.news.visible.find_by_title(name) |
|
|||
850 | link = link_to h(news.title), {:only_path => only_path, :controller => 'news', :action => 'show', :id => news}, |
|
|||
851 | :class => 'news' |
|
|||
852 | end |
|
|||
853 | when 'commit', 'source', 'export' |
|
|||
854 | if project |
|
769 | if project | |
855 | repository = nil |
|
770 | repository = nil | |
856 | if name =~ %r{^(([a-z0-9\-_]+)\|)(.+)$} |
|
771 | if repo_identifier | |
857 | repo_prefix, repo_identifier, name = $1, $2, $3 |
|
|||
858 | repository = project.repositories.detect {|repo| repo.identifier == repo_identifier} |
|
772 | repository = project.repositories.detect {|repo| repo.identifier == repo_identifier} | |
859 | else |
|
773 | else | |
860 | repository = project.repository |
|
774 | repository = project.repository | |
861 | end |
|
775 | end | |
862 | if prefix == 'commit' |
|
776 | # project.changesets.visible raises an SQL error because of a double join on repositories | |
863 | if repository && (changeset = Changeset.visible.where("repository_id = ? AND scmid LIKE ?", repository.id, "#{name}%").first) |
|
777 | if repository && | |
864 | link = link_to h("#{project_prefix}#{repo_prefix}#{name}"), {:only_path => only_path, :controller => 'repositories', :action => 'revision', :id => project, :repository_id => repository.identifier_param, :rev => changeset.identifier}, |
|
778 | (changeset = Changeset.visible. | |
865 | :class => 'changeset', |
|
779 | find_by_repository_id_and_revision(repository.id, identifier)) | |
866 | :title => truncate_single_line_raw(changeset.comments, 100) |
|
780 | link = link_to(h("#{project_prefix}#{repo_prefix}r#{identifier}"), | |
867 | end |
|
781 | {:only_path => only_path, :controller => 'repositories', | |
868 | else |
|
782 | :action => 'revision', :id => project, | |
869 | if repository && User.current.allowed_to?(:browse_repository, project) |
|
783 | :repository_id => repository.identifier_param, | |
870 | name =~ %r{^[/\\]*(.*?)(@([^/\\@]+?))?(#(L\d+))?$} |
|
784 | :rev => changeset.revision}, | |
871 | path, rev, anchor = $1, $3, $5 |
|
785 | :class => 'changeset', | |
872 | link = link_to h("#{project_prefix}#{prefix}:#{repo_prefix}#{name}"), {:only_path => only_path, :controller => 'repositories', :action => (prefix == 'export' ? 'raw' : 'entry'), :id => project, :repository_id => repository.identifier_param, |
|
786 | :title => truncate_single_line_raw(changeset.comments, 100)) | |
873 | :path => to_path_param(path), |
|
|||
874 | :rev => rev, |
|
|||
875 | :anchor => anchor}, |
|
|||
876 | :class => (prefix == 'export' ? 'source download' : 'source') |
|
|||
877 | end |
|
|||
878 | end |
|
787 | end | |
879 | repo_prefix = nil |
|
|||
880 | end |
|
788 | end | |
881 | when 'attachment' |
|
789 | elsif sep == '#' | |
882 | attachments = options[:attachments] || [] |
|
790 | oid = identifier.to_i | |
883 | attachments += obj.attachments if obj.respond_to?(:attachments) |
|
791 | case prefix | |
884 | if attachments && attachment = Attachment.latest_attach(attachments, name) |
|
792 | when nil | |
885 | link = link_to_attachment(attachment, :only_path => only_path, :download => true, :class => 'attachment') |
|
793 | if oid.to_s == identifier && | |
|
794 | issue = Issue.visible.includes(:status).find_by_id(oid) | |||
|
795 | anchor = comment_id ? "note-#{comment_id}" : nil | |||
|
796 | link = link_to(h("##{oid}#{comment_suffix}"), | |||
|
797 | {:only_path => only_path, :controller => 'issues', | |||
|
798 | :action => 'show', :id => oid, :anchor => anchor}, | |||
|
799 | :class => issue.css_classes, | |||
|
800 | :title => "#{issue.subject.truncate(100)} (#{issue.status.name})") | |||
|
801 | end | |||
|
802 | when 'document' | |||
|
803 | if document = Document.visible.find_by_id(oid) | |||
|
804 | link = link_to h(document.title), {:only_path => only_path, :controller => 'documents', :action => 'show', :id => document}, | |||
|
805 | :class => 'document' | |||
|
806 | end | |||
|
807 | when 'version' | |||
|
808 | if version = Version.visible.find_by_id(oid) | |||
|
809 | link = link_to h(version.name), {:only_path => only_path, :controller => 'versions', :action => 'show', :id => version}, | |||
|
810 | :class => 'version' | |||
|
811 | end | |||
|
812 | when 'message' | |||
|
813 | if message = Message.visible.includes(:parent).find_by_id(oid) | |||
|
814 | link = link_to_message(message, {:only_path => only_path}, :class => 'message') | |||
|
815 | end | |||
|
816 | when 'forum' | |||
|
817 | if board = Board.visible.find_by_id(oid) | |||
|
818 | link = link_to h(board.name), {:only_path => only_path, :controller => 'boards', :action => 'show', :id => board, :project_id => board.project}, | |||
|
819 | :class => 'board' | |||
|
820 | end | |||
|
821 | when 'news' | |||
|
822 | if news = News.visible.find_by_id(oid) | |||
|
823 | link = link_to h(news.title), {:only_path => only_path, :controller => 'news', :action => 'show', :id => news}, | |||
|
824 | :class => 'news' | |||
|
825 | end | |||
|
826 | when 'project' | |||
|
827 | if p = Project.visible.find_by_id(oid) | |||
|
828 | link = link_to_project(p, {:only_path => only_path}, :class => 'project') | |||
|
829 | end | |||
886 | end |
|
830 | end | |
887 | when 'project' |
|
831 | elsif sep == ':' | |
888 | if p = Project.visible.where("identifier = :s OR LOWER(name) = :s", :s => name.downcase).first |
|
832 | # removes the double quotes if any | |
889 | link = link_to_project(p, {:only_path => only_path}, :class => 'project') |
|
833 | name = identifier.gsub(%r{^"(.*)"$}, "\\1") | |
|
834 | name = CGI.unescapeHTML(name) | |||
|
835 | case prefix | |||
|
836 | when 'document' | |||
|
837 | if project && document = project.documents.visible.find_by_title(name) | |||
|
838 | link = link_to h(document.title), {:only_path => only_path, :controller => 'documents', :action => 'show', :id => document}, | |||
|
839 | :class => 'document' | |||
|
840 | end | |||
|
841 | when 'version' | |||
|
842 | if project && version = project.versions.visible.find_by_name(name) | |||
|
843 | link = link_to h(version.name), {:only_path => only_path, :controller => 'versions', :action => 'show', :id => version}, | |||
|
844 | :class => 'version' | |||
|
845 | end | |||
|
846 | when 'forum' | |||
|
847 | if project && board = project.boards.visible.find_by_name(name) | |||
|
848 | link = link_to h(board.name), {:only_path => only_path, :controller => 'boards', :action => 'show', :id => board, :project_id => board.project}, | |||
|
849 | :class => 'board' | |||
|
850 | end | |||
|
851 | when 'news' | |||
|
852 | if project && news = project.news.visible.find_by_title(name) | |||
|
853 | link = link_to h(news.title), {:only_path => only_path, :controller => 'news', :action => 'show', :id => news}, | |||
|
854 | :class => 'news' | |||
|
855 | end | |||
|
856 | when 'commit', 'source', 'export' | |||
|
857 | if project | |||
|
858 | repository = nil | |||
|
859 | if name =~ %r{^(([a-z0-9\-_]+)\|)(.+)$} | |||
|
860 | repo_prefix, repo_identifier, name = $1, $2, $3 | |||
|
861 | repository = project.repositories.detect {|repo| repo.identifier == repo_identifier} | |||
|
862 | else | |||
|
863 | repository = project.repository | |||
|
864 | end | |||
|
865 | if prefix == 'commit' | |||
|
866 | if repository && (changeset = Changeset.visible.where("repository_id = ? AND scmid LIKE ?", repository.id, "#{name}%").first) | |||
|
867 | link = link_to h("#{project_prefix}#{repo_prefix}#{name}"), {:only_path => only_path, :controller => 'repositories', :action => 'revision', :id => project, :repository_id => repository.identifier_param, :rev => changeset.identifier}, | |||
|
868 | :class => 'changeset', | |||
|
869 | :title => truncate_single_line_raw(changeset.comments, 100) | |||
|
870 | end | |||
|
871 | else | |||
|
872 | if repository && User.current.allowed_to?(:browse_repository, project) | |||
|
873 | name =~ %r{^[/\\]*(.*?)(@([^/\\@]+?))?(#(L\d+))?$} | |||
|
874 | path, rev, anchor = $1, $3, $5 | |||
|
875 | link = link_to h("#{project_prefix}#{prefix}:#{repo_prefix}#{name}"), {:only_path => only_path, :controller => 'repositories', :action => (prefix == 'export' ? 'raw' : 'entry'), :id => project, :repository_id => repository.identifier_param, | |||
|
876 | :path => to_path_param(path), | |||
|
877 | :rev => rev, | |||
|
878 | :anchor => anchor}, | |||
|
879 | :class => (prefix == 'export' ? 'source download' : 'source') | |||
|
880 | end | |||
|
881 | end | |||
|
882 | repo_prefix = nil | |||
|
883 | end | |||
|
884 | when 'attachment' | |||
|
885 | attachments = options[:attachments] || [] | |||
|
886 | attachments += obj.attachments if obj.respond_to?(:attachments) | |||
|
887 | if attachments && attachment = Attachment.latest_attach(attachments, name) | |||
|
888 | link = link_to_attachment(attachment, :only_path => only_path, :download => true, :class => 'attachment') | |||
|
889 | end | |||
|
890 | when 'project' | |||
|
891 | if p = Project.visible.where("identifier = :s OR LOWER(name) = :s", :s => name.downcase).first | |||
|
892 | link = link_to_project(p, {:only_path => only_path}, :class => 'project') | |||
|
893 | end | |||
890 | end |
|
894 | end | |
891 | end |
|
895 | end | |
892 | end |
|
896 | end | |
|
897 | (leading + (link || "#{project_prefix}#{prefix}#{repo_prefix}#{sep}#{identifier}#{comment_suffix}")) | |||
893 | end |
|
898 | end | |
894 | (leading + (link || "#{project_prefix}#{prefix}#{repo_prefix}#{sep}#{identifier}#{comment_suffix}")) |
|
|||
895 | end |
|
899 | end | |
896 | end |
|
900 | end | |
897 |
|
901 |
@@ -363,6 +363,12 RAW | |||||
363 | to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text), "#{text} failed" } |
|
363 | to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text), "#{text} failed" } | |
364 | end |
|
364 | end | |
365 |
|
365 | |||
|
366 | def test_should_not_parse_redmine_links_inside_link | |||
|
367 | raw = "r1 should not be parsed in http://example.com/url-r1/" | |||
|
368 | assert_match %r{<p><a class="changeset".*>r1</a> should not be parsed in <a class="external" href="http://example.com/url-r1/">http://example.com/url-r1/</a></p>}, | |||
|
369 | textilizable(raw, :project => Project.find(1)) | |||
|
370 | end | |||
|
371 | ||||
366 | def test_redmine_links_with_a_different_project_before_current_project |
|
372 | def test_redmine_links_with_a_different_project_before_current_project | |
367 | vp1 = Version.generate!(:project_id => 1, :name => '1.4.4') |
|
373 | vp1 = Version.generate!(:project_id => 1, :name => '1.4.4') | |
368 | vp3 = Version.generate!(:project_id => 3, :name => '1.4.4') |
|
374 | vp3 = Version.generate!(:project_id => 3, :name => '1.4.4') |
General Comments 0
You need to be logged in to leave comments.
Login now