From 2b22706b8b911c753dcc64c93512c4b8c3b15844 Mon Sep 17 00:00:00 2001 From: ishikawa999 Date: Thu, 30 Sep 2021 04:26:52 +0000 Subject: [PATCH 2/8] Split multiple classes and modules that existed in the same file --- app/models/anonymous_user.rb | 69 ++++++++++++++++++ app/models/user.rb | 51 ------------- app/models/wiki_annotate.rb | 61 ++++++++++++++++ app/models/wiki_diff.rb | 28 ++++++++ app/models/wiki_page.rb | 53 -------------- lib/redmine.rb | 1 + lib/redmine/wiki_formatting.rb | 83 --------------------- lib/redmine/wiki_formatting/links_helper.rb | 107 ++++++++++++++++++++++++++++ 8 files changed, 266 insertions(+), 187 deletions(-) create mode 100644 app/models/anonymous_user.rb create mode 100644 app/models/wiki_annotate.rb create mode 100644 app/models/wiki_diff.rb create mode 100644 lib/redmine/wiki_formatting/links_helper.rb diff --git a/app/models/anonymous_user.rb b/app/models/anonymous_user.rb new file mode 100644 index 0000000000..d1b215b8e5 --- /dev/null +++ b/app/models/anonymous_user.rb @@ -0,0 +1,69 @@ +# frozen_string_literal: true + +# Redmine - project management software +# Copyright (C) 2006-2021 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 AnonymousUser < User + validate :validate_anonymous_uniqueness, :on => :create + + self.valid_statuses = [STATUS_ANONYMOUS] + + def validate_anonymous_uniqueness + # There should be only one AnonymousUser in the database + errors.add :base, 'An anonymous user already exists.' if AnonymousUser.unscoped.exists? + end + + def available_custom_fields + [] + end + + # Overrides a few properties + def logged?; false end + def admin; false end + def name(*args); I18n.t(:label_user_anonymous) end + def mail=(*args); nil end + def mail; nil end + def time_zone; nil end + def rss_key; nil end + + def pref + UserPreference.new(:user => self) + end + + # Returns the user's bult-in role + def builtin_role + @builtin_role ||= Role.anonymous + end + + def membership(*args) + nil + end + + def member_of?(*args) + false + end + + # Anonymous user can not be destroyed + def destroy + false + end + + protected + + def instantiate_email_address + end +end diff --git a/app/models/user.rb b/app/models/user.rb index cb0ad9e3a6..681829265d 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -999,54 +999,3 @@ class User < Principal end end end - -class AnonymousUser < User - validate :validate_anonymous_uniqueness, :on => :create - - self.valid_statuses = [STATUS_ANONYMOUS] - - def validate_anonymous_uniqueness - # There should be only one AnonymousUser in the database - errors.add :base, 'An anonymous user already exists.' if AnonymousUser.unscoped.exists? - end - - def available_custom_fields - [] - end - - # Overrides a few properties - def logged?; false end - def admin; false end - def name(*args); I18n.t(:label_user_anonymous) end - def mail=(*args); nil end - def mail; nil end - def time_zone; nil end - def rss_key; nil end - - def pref - UserPreference.new(:user => self) - end - - # Returns the user's bult-in role - def builtin_role - @builtin_role ||= Role.anonymous - end - - def membership(*args) - nil - end - - def member_of?(*args) - false - end - - # Anonymous user can not be destroyed - def destroy - false - end - - protected - - def instantiate_email_address - end -end diff --git a/app/models/wiki_annotate.rb b/app/models/wiki_annotate.rb new file mode 100644 index 0000000000..3be95ca0e6 --- /dev/null +++ b/app/models/wiki_annotate.rb @@ -0,0 +1,61 @@ +# frozen_string_literal: true + +# Redmine - project management software +# Copyright (C) 2006-2021 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 WikiAnnotate + attr_reader :lines, :content + + def initialize(content) + @content = content + current = content + current_lines = current.text.split(/\r?\n/) + @lines = current_lines.collect {|t| [nil, nil, t]} + positions = [] + current_lines.size.times {|i| positions << i} + while current.previous + d = current.previous.text.split(/\r?\n/).diff(current.text.split(/\r?\n/)).diffs.flatten + d.each_slice(3) do |s| + sign, line = s[0], s[1] + if sign == '+' && positions[line] && positions[line] != -1 + if @lines[positions[line]][0].nil? + @lines[positions[line]][0] = current.version + @lines[positions[line]][1] = current.author + end + end + end + d.each_slice(3) do |s| + sign, line = s[0], s[1] + if sign == '-' + positions.insert(line, -1) + else + positions[line] = nil + end + end + positions.compact! + # Stop if every line is annotated + break unless @lines.detect {|line| line[0].nil?} + + current = current.previous + end + @lines.each do |line| + line[0] ||= current.version + # if the last known version is > 1 (eg. history was cleared), we don't know the author + line[1] ||= current.author if current.version == 1 + end + end +end diff --git a/app/models/wiki_diff.rb b/app/models/wiki_diff.rb new file mode 100644 index 0000000000..00d35bb0b8 --- /dev/null +++ b/app/models/wiki_diff.rb @@ -0,0 +1,28 @@ +# frozen_string_literal: true + +# Redmine - project management software +# Copyright (C) 2006-2021 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 WikiDiff < Redmine::Helpers::Diff + attr_reader :content_to, :content_from + + def initialize(content_to, content_from) + @content_to = content_to + @content_from = content_from + super(content_to.text, content_from.text) + end +end diff --git a/app/models/wiki_page.rb b/app/models/wiki_page.rb index c3d09fd220..2e76e076ee 100644 --- a/app/models/wiki_page.rb +++ b/app/models/wiki_page.rb @@ -290,56 +290,3 @@ class WikiPage < ActiveRecord::Base (association(:content).loaded? ? content : content_without_text).try(name) end end - -class WikiDiff < Redmine::Helpers::Diff - attr_reader :content_to, :content_from - - def initialize(content_to, content_from) - @content_to = content_to - @content_from = content_from - super(content_to.text, content_from.text) - end -end - -class WikiAnnotate - attr_reader :lines, :content - - def initialize(content) - @content = content - current = content - current_lines = current.text.split(/\r?\n/) - @lines = current_lines.collect {|t| [nil, nil, t]} - positions = [] - current_lines.size.times {|i| positions << i} - while current.previous - d = current.previous.text.split(/\r?\n/).diff(current.text.split(/\r?\n/)).diffs.flatten - d.each_slice(3) do |s| - sign, line = s[0], s[1] - if sign == '+' && positions[line] && positions[line] != -1 - if @lines[positions[line]][0].nil? - @lines[positions[line]][0] = current.version - @lines[positions[line]][1] = current.author - end - end - end - d.each_slice(3) do |s| - sign, line = s[0], s[1] - if sign == '-' - positions.insert(line, -1) - else - positions[line] = nil - end - end - positions.compact! - # Stop if every line is annotated - break unless @lines.detect {|line| line[0].nil?} - - current = current.previous - end - @lines.each do |line| - line[0] ||= current.version - # if the last known version is > 1 (eg. history was cleared), we don't know the author - line[1] ||= current.author if current.version == 1 - end - end -end diff --git a/lib/redmine.rb b/lib/redmine.rb index d62521c4ef..05d2d293d1 100644 --- a/lib/redmine.rb +++ b/lib/redmine.rb @@ -44,6 +44,7 @@ require 'redmine/utils' require 'issue_relation' require 'redmine/configuration' require 'redmine/scm/adapters/command_failed' +require 'redmine/wiki_formatting/links_helper' require 'redmine/wiki_formatting' require 'redmine/wiki_formatting/macros' require 'redmine/wiki_formatting/html_parser' diff --git a/lib/redmine/wiki_formatting.rb b/lib/redmine/wiki_formatting.rb index 99058462be..471082edce 100644 --- a/lib/redmine/wiki_formatting.rb +++ b/lib/redmine/wiki_formatting.rb @@ -115,89 +115,6 @@ module Redmine end end - module LinksHelper - AUTO_LINK_RE = %r{ - ( # leading text - <\w+[^>]*?>| # leading HTML tag, or - [\s\(\[,;]| # leading punctuation, or - ^ # beginning of line - ) - ( - (?:https?://)| # protocol spec, or - (?:s?ftps?://)| - (?:www\.) # www.* - ) - ( - ([^<]\S*?) # url - (\/)? # slash - ) - ((?:>)?|[^[:alnum:]_\=\/;\(\)\-]*?) # post - (?=<|\s|$) - }x unless const_defined?(:AUTO_LINK_RE) - - # Destructively replaces urls into clickable links - def auto_link!(text) - text.gsub!(AUTO_LINK_RE) do - all, leading, proto, url, post = $&, $1, $2, $3, $6 - if /=]?/.match?(leading) - # don't replace URLs that are already linked - # and URLs prefixed with ! !> !< != (textile images) - all - else - # Idea below : an URL with unbalanced parenthesis and - # ending by ')' is put into external parenthesis - if url[-1] == ")" and ((url.count("(") - url.count(")")) < 0) - url = url[0..-2] # discard closing parenthesis from url - post = ")" + post # add closing parenthesis to post - end - content = proto + url - href = "#{proto=="www."?"http://www.":proto}#{url}" - %(#{leading}#{ERB::Util.html_escape content}#{post}).html_safe - end - end - end - - # Destructively replaces email addresses into clickable links - def auto_mailto!(text) - text.gsub!(/([\w\.!#\$%\-+.\/]+@[A-Za-z0-9\-]+(\.[A-Za-z0-9\-]+)+)/) do - mail = $1 - if /]*>(.*)(#{Regexp.escape(mail)})(.*)<\/a>/.match?(text) - mail - else - %().html_safe - end - end - end - - def restore_redmine_links(html) - # restore wiki links eg. [[Foo]] - html.gsub!(%r{\[(.*?)\]}) do - "[[#{$2}]]" - end - # restore Redmine links with double-quotes, eg. version:"1.0" - html.gsub!(/(\w):"(.+?)"/) do - "#{$1}:\"#{$2}\"" - end - # restore user links with @ in login name eg. [@jsmith@somenet.foo] - html.gsub!(%r{[@\A](.*?)}) do - "@#{$2}" - end - # restore user links with @ in login name eg. [user:jsmith@somenet.foo] - html.gsub!(%r{\buser:(.*?)<\/a>}) do - "user:#{$2}" - end - # restore attachments links with @ in file name eg. [attachment:image@2x.png] - html.gsub!(%r{\battachment:(.*?)}) do - "attachment:#{$2}" - end - # restore hires images which are misrecognized as email address eg. [printscreen@2x.png] - html.gsub!(%r{(.*?)}) do - "#{$3}" - end - html - end - end - # Default formatter module module NullFormatter class Formatter diff --git a/lib/redmine/wiki_formatting/links_helper.rb b/lib/redmine/wiki_formatting/links_helper.rb new file mode 100644 index 0000000000..2e057df3ed --- /dev/null +++ b/lib/redmine/wiki_formatting/links_helper.rb @@ -0,0 +1,107 @@ +# frozen_string_literal: true + +# Redmine - project management software +# Copyright (C) 2006-2021 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. + +require 'loofah/helpers' + +module Redmine + module WikiFormatting + module LinksHelper + AUTO_LINK_RE = %r{ + ( # leading text + <\w+[^>]*?>| # leading HTML tag, or + [\s\(\[,;]| # leading punctuation, or + ^ # beginning of line + ) + ( + (?:https?://)| # protocol spec, or + (?:s?ftps?://)| + (?:www\.) # www.* + ) + ( + ([^<]\S*?) # url + (\/)? # slash + ) + ((?:>)?|[^[:alnum:]_\=\/;\(\)\-]*?) # post + (?=<|\s|$) + }x unless const_defined?(:AUTO_LINK_RE) + + # Destructively replaces urls into clickable links + def auto_link!(text) + text.gsub!(AUTO_LINK_RE) do + all, leading, proto, url, post = $&, $1, $2, $3, $6 + if /=]?/.match?(leading) + # don't replace URLs that are already linked + # and URLs prefixed with ! !> !< != (textile images) + all + else + # Idea below : an URL with unbalanced parenthesis and + # ending by ')' is put into external parenthesis + if url[-1] == ")" and ((url.count("(") - url.count(")")) < 0) + url = url[0..-2] # discard closing parenthesis from url + post = ")" + post # add closing parenthesis to post + end + content = proto + url + href = "#{proto=="www."?"http://www.":proto}#{url}" + %(#{leading}#{ERB::Util.html_escape content}#{post}).html_safe + end + end + end + + # Destructively replaces email addresses into clickable links + def auto_mailto!(text) + text.gsub!(/([\w\.!#\$%\-+.\/]+@[A-Za-z0-9\-]+(\.[A-Za-z0-9\-]+)+)/) do + mail = $1 + if /]*>(.*)(#{Regexp.escape(mail)})(.*)<\/a>/.match?(text) + mail + else + %().html_safe + end + end + end + + def restore_redmine_links(html) + # restore wiki links eg. [[Foo]] + html.gsub!(%r{\[(.*?)\]}) do + "[[#{$2}]]" + end + # restore Redmine links with double-quotes, eg. version:"1.0" + html.gsub!(/(\w):"(.+?)"/) do + "#{$1}:\"#{$2}\"" + end + # restore user links with @ in login name eg. [@jsmith@somenet.foo] + html.gsub!(%r{[@\A](.*?)}) do + "@#{$2}" + end + # restore user links with @ in login name eg. [user:jsmith@somenet.foo] + html.gsub!(%r{\buser:(.*?)<\/a>}) do + "user:#{$2}" + end + # restore attachments links with @ in file name eg. [attachment:image@2x.png] + html.gsub!(%r{\battachment:(.*?)}) do + "attachment:#{$2}" + end + # restore hires images which are misrecognized as email address eg. [printscreen@2x.png] + html.gsub!(%r{(.*?)}) do + "#{$3}" + end + html + end + end + end +end -- 2.11.0