Skip to content

Commit

Permalink
Support Redmine 2.4 or higher with refactoring
Browse files Browse the repository at this point in the history
  • Loading branch information
hidakatsuya committed Oct 28, 2014
1 parent 3e62a1c commit 2a9fb47
Show file tree
Hide file tree
Showing 8 changed files with 160 additions and 113 deletions.
5 changes: 5 additions & 0 deletions app/hooks/application_hooks.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
module IssueWikiJournal
class ApplicationHooks < Redmine::Hook::ViewListener
render_on :view_layouts_base_body_bottom, partial: 'layouts/body_bottom'
end
end
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
module IssueWikiJournal
class WikiUpdatesHookListener < Redmine::Hook::ViewListener
class WikiControllerHooks < Redmine::Hook::ViewListener
def controller_wiki_edit_after_save(args = {})
page, params = args.values_at(:page, :params)
page, params = args.values_at :page, :params

if page_content_changed?(page, params[:content][:version])
changeset = WikiChangeset.new(page)
Expand Down
File renamed without changes.
6 changes: 4 additions & 2 deletions init.rb
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
require 'redmine'
require_dependency 'issue_wiki_journal'

Redmine::Plugin.register :redmine_issue_wiki_journal do
name 'Redmine Issue Wiki Journal Plugin'
author 'Katsuya Hidaka'
description 'This plugin will provides the feature which associate Wiki updates to the Issue'
version '0.0.1'
version '1.0.0'
url 'https://github.com/hidakatsuya/redmine_issue_wiki_journal'
author_url 'https://github.com/hidakatsuya'
# Requires Redmine 2.3.x or higher
requires_redmine '2.3'
end

require 'issue_wiki_journal'
19 changes: 16 additions & 3 deletions lib/issue_wiki_journal.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,17 @@
require 'issue_wiki_journal/wiki_changeset'
require 'issue_wiki_journal/wiki_updates_hook_listener'
require 'issue_wiki_journal/common_view_hooks'
require 'pathname'

module IssueWikiJournal
def self.root
@root ||= Pathname.new(File.expand_path('../../', __FILE__))
end

def self.version
Redmine::Plugin.find(:roots).version
end
end

# Load libraries
require_relative 'issue_wiki_journal/wiki_changeset'

# Load hooks
Dir[IssueWikiJournal.root.join('app/hooks/**/*_hooks.rb')].each {|f| require f }
5 changes: 0 additions & 5 deletions lib/issue_wiki_journal/common_view_hooks.rb

This file was deleted.

55 changes: 34 additions & 21 deletions lib/issue_wiki_journal/wiki_changeset.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
# coding: utf-8

module IssueWikiJournal
class WikiChangeset
include Redmine::I18n
Expand All @@ -22,27 +20,31 @@ def apply_to_related_issues!

attr_reader :comments, :user, :project

def fix_keywords
@fix_keywords ||= if ::Redmine::VERSION.to_s < '2.4'
Setting.commit_fix_keywords.downcase.split(",").collect(&:strip)
else
Setting.commit_update_keywords_array.map {|r| r['keywords']}.flatten.compact
end
end

# same as Changeset#scan_comment_for_issue_ids
def scan_comment_for_issue_ids
return if comments.blank?

ref_keywords = Setting.commit_ref_keywords.downcase.split(",").collect(&:strip)
ref_keywords_any = ref_keywords.delete('*')
fix_keywords = Setting.commit_fix_keywords.downcase.split(",").collect(&:strip)

kw_regexp = (ref_keywords + fix_keywords).collect{|kw| Regexp.escape(kw)}.join("|")

referenced_issues = []

comments.scan(/([\s\(\[,-]|^)((#{kw_regexp})[\s:]+)?(#\d+(\s+@#{TIMELOG_RE})?([\s,;&]+#\d+(\s+@#{TIMELOG_RE})?)*)(?=[[:punct:]]|\s|<|$)/i) do |match|
action, refs = match[2], match[3]
next unless action.present? || ref_keywords_any

refs.scan(/#(\d+)(\s+@#{TIMELOG_RE})?/).each do |m|
issue, hours = find_referenced_issue_by_id(m[0].to_i), m[2]
if issue
referenced_issues << issue
relate_to_issue(issue, fix_keywords.include?(action.to_s.downcase))
fix_issue(issue, action)
log_time(issue, hours) if hours && Setting.commit_logtime_enabled?
end
end
Expand All @@ -66,25 +68,36 @@ def find_referenced_issue_by_id(id)
issue
end

# based on Changeset#fix_issue, and
def relate_to_issue(issue, fix = false)
if fix
status = IssueStatus.find_by_id(Setting.commit_fix_status_id.to_i)
if status.nil?
logger.warn("No status matches commit_fix_status_id setting (#{Setting.commit_fix_status_id})") if logger
return issue
end

# the issue may have been updated by the closure of another one (eg. duplicate)
def fix_issue(issue, action)
if fix_keywords.include?(action)
issue.reload
issue.status = status unless issue.status.is_closed?

unless Setting.commit_fix_done_ratio.blank?
issue.done_ratio = Setting.commit_fix_done_ratio.to_i
# less than 2.4
if Redmine::VERSION.to_s < '2.4'
status = IssueStatus.find_by_id(Setting.commit_fix_status_id.to_i)
if status.nil?
logger.warn("No status matches commit_fix_status_id setting (#{Setting.commit_fix_status_id})") if logger
return issue
end

issue.status = status unless issue.status.is_closed?

unless Setting.commit_fix_done_ratio.blank?
issue.done_ratio = Setting.commit_fix_done_ratio.to_i
end
# greater than 2.4 or equal
else
rule = Setting.commit_update_keywords_array.detect do |rule|
rule['keywords'].include?(action) &&
(rule['if_tracker_id'].blank? || rule['if_tracker_id'] == issue.tracker_id.to_s)
end
if rule
issue.assign_attributes rule.slice(*Issue.attribute_names)
end
end
end

issue.init_journal(user || User.anonymous, message(fix))
issue.init_journal(user || User.anonymous, message)

unless issue.save
logger.warn("Issue ##{issue.id} could not be saved by changeset: #{issue.errors.full_messages}") if logger
Expand Down
179 changes: 99 additions & 80 deletions test/functional/wiki_controller_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -31,120 +31,139 @@ class IssueWikiJournal::WikiControllerTest < ActionController::TestCase
:wiki_contents,
:wiki_content_versions

def setup
setup do
@controller = ::WikiController.new
@request.session[:user_id] = 2
@project = Project.find(1)

# Set to 1 status to be applied by the fixing keywords
Setting.commit_fix_status_id = 5
# Allow issues of all the other projects to be referenced and fixed
Setting.commit_cross_project_ref = 1
end


test 'Journal message' do
journals = Issue.find(1).journals

[:en, :ja].each_with_index do |locale, i|
::I18n.locale = locale
update_wiki_page with: 'refs #1 message', as_version: i
assert_equal journals.last.notes,
changeset_message('New_Page', 'refs #1 message', version: i + 1),
"Journal message test with #{locale} locale"
context 'Referencing issues:' do
should 'add journal to Issue#1' do
assert_difference 'Journal.count' do
create_wiki_page with: 'refs #1 message'
end
end
end

test 'Journalizing: with comment "refs #1 message"' do
assert_difference 'Journal.count' do
create_wiki_page with: 'refs #1 message'
end
end

test 'Journalizing: with comment "refs #1 #2 message"' do
assert_difference 'Journal.count', +2 do
create_wiki_page with: 'refs #1 #2 message'
should 'add journal to Issue#1 and Issue#2' do
assert_difference 'Journal.count', +2 do
create_wiki_page with: 'refs #1 #2 message'
end
end
end

test 'Journalizing: with comment "fixes #1 message"' do
assert_difference 'Journal.count' do
create_wiki_page with: 'fixes #1 message'
end
end
should 'not add journal when no wiki updates' do
create_wiki_page

test 'Journalizing: without fix_status_id setting' do
Setting.commit_fix_status_id = 0
assert_difference 'Journal.count' do
create_wiki_page with: 'refs #1 message'
assert_no_difference 'Journal.count' do
# No content changes
update_wiki_page with: 'refs #1 message'
end
end
end

test 'Journalizing: no content updates' do
create_wiki_page
assert_no_difference 'Journal.count' do
# No content changes
update_wiki_page with: 'refs #1 message'
should 'translate message of journal' do
journals = Issue.find(1).journals

[:en, :ja].each_with_index do |locale, i|
::I18n.locale = locale
update_wiki_page with: 'refs #1 message', as_version: i
assert_equal journals.last.notes,
changeset_message('New_Page', 'refs #1 message', version: i + 1),
"Journal message test with #{locale} locale"
end
end
end

test 'Journalizing: when commit_cross_project_ref setting is OFF' do
Setting.commit_cross_project_ref = 0
context 'when commit_cross_project_ref setting is enabled' do
setup do
Setting.commit_cross_project_ref = 1
end

assert_no_difference 'Journal.count' do
create_wiki_page with: 'refs #1 message', in_project: Project.find(2)
should 'add journal to issue of other project' do
assert_difference 'Journal.count' do
create_wiki_page with: 'refs #1 message', in_project: Project.find(2)
end
end
end
end

test 'Journalizing: when commit_cross_project_ref setting is ON' do
Setting.commit_cross_project_ref = 1
context 'when commit_cross_project_ref setting is disabled' do
setup do
Setting.commit_cross_project_ref = 0
end

assert_difference 'Journal.count' do
create_wiki_page with: 'refs #1 message', in_project: Project.find(2)
should 'not add journal to issue of other project' do
assert_no_difference 'Journal.count' do
create_wiki_page with: 'refs #1 message', in_project: Project.find(2)
end
end
end
end

test 'Status changes: with comment "fixes #1 message"' do
create_wiki_page with: 'fixes #1 message'
assert Issue.find(1).closed?
end
context 'Fixing issues:' do
context 'when fix_status_id setting is set' do
setup do
set_fix_status_id_setting_to 5
end

test 'Status changes: with comment "fixes #1 #2 message"' do
create_wiki_page with: 'fixes #1 #2 message'
assert Issue.where(id: [1, 2]).all?(&:closed?)
end
should 'add journals to issue' do
assert_difference 'Journal.count', +2 do
create_wiki_page with: 'fixes #1 #2 message'
end
end

test 'Status changes: without fix_status_id setting' do
Setting.commit_fix_status_id = 0
assert_no_difference 'Journal.count' do
create_wiki_page with: 'fixes #1 message'
should 'update status of issue' do
create_wiki_page with: 'fixes #1 message'
assert Issue.find(1).closed?
end
end
refute Issue.find(1).closed?
end

test 'Status changes: no content updates' do
create_wiki_page
# No content changes
update_wiki_page with: 'fixes #1 message'
refute Issue.find(1).closed?
context 'when fix_status_id setting is not set' do
setup do
set_fix_status_id_setting_to 0
end

should 'not associate to issue' do
assert_no_difference 'Journal.count' do
create_wiki_page with: 'fixes #1 message'
end
# No status updates
assert_equal Issue.find(1).status_id, 1
end
end
end

test 'Composite comment: such as "fixes #1, refs #2 message"' do
assert_difference 'Journal.count', +2 do
create_wiki_page with: 'fixes #1, refs #2 message'
context 'Combination:' do
setup do
set_fix_status_id_setting_to 5
@comment = 'fixes #1, refs #2 message'
end

assert_equal Issue.find(1).journals.last.notes,
changeset_message('New_Page', 'fixes #1, refs #2 message')
assert Issue.find(1).closed?
should 'add journals' do
assert_difference 'Journal.count', +2 do
create_wiki_page with: @comment
end

assert_equal Issue.find(2).journals.last.notes,
changeset_message('New_Page', 'fixes #1, refs #2 message')
refute Issue.find(2).closed?
assert_equal Issue.find(1).journals.last.notes,
changeset_message('New_Page', 'fixes #1, refs #2 message')
assert_equal Issue.find(2).journals.last.notes,
changeset_message('New_Page', 'fixes #1, refs #2 message')
end

should 'update status' do
create_wiki_page with: @comment
assert Issue.find(1).closed?
end
end

private

def set_fix_status_id_setting_to(status_id)
if Redmine::VERSION.to_s < '2.4'
Setting.commit_fix_status_id = status_id
# Redmine 2.4 or higher
else
keywords = status_id.zero? ? [] : [{ 'keywords' => 'fixes', 'status_id' => status_id.to_s }]
Setting.commit_update_keywords = keywords
end
end

def update_wiki_page(args = {})
comment, version, project = args.values_at(:with, :as_version, :in_project)

Expand Down

0 comments on commit 2a9fb47

Please sign in to comment.