Project

General

Profile

Feature #36162 » 0001-WIP.patch

Marius BĂLTEANU, 2024-03-19 23:59

View differences:

app/models/mailer.rb
103 103
  # Example:
104 104
  #   Mailer.deliver_issue_add(issue)
105 105
  def self.deliver_issue_add(issue)
106
    users = issue.notified_users | issue.notified_watchers | issue.notified_mentions
107
    users.each do |user|
108
      issue_add(user, issue).deliver_later
106
    # users = issue.notified_users | issue.notified_watchers | issue.notified_mentions
107
    recipients = NotificationRecipients::BuildService::issue_add(issue)
108

  
109
    recipients.each do |r|
110
      issue_add(r.user, issue).deliver_later
109 111
    end
110 112
  end
111 113

  
......
139 141
  # Example:
140 142
  #   Mailer.deliver_issue_edit(journal)
141 143
  def self.deliver_issue_edit(journal)
142
    users  = journal.notified_users | journal.notified_watchers | journal.notified_mentions | journal.journalized.notified_mentions
143
    users.select! do |user|
144
      journal.notes? || journal.visible_details(user).any?
145
    end
146
    users.each do |user|
147
      issue_edit(user, journal).deliver_later
144
    recipients = NotificationRecipients::BuildService::issue_edit(journal)
145

  
146
    recipients.each do |r|
147
      issue_edit(r.user, journal).deliver_later
148 148
    end
149 149
  end
150 150

  
app/models/user_notification_recipient.rb
1
# frozen_string_literal: true
2

  
3
# Redmine - project management software
4
# Copyright (C) 2006-2023  Jean-Philippe Lang
5
#
6
# This program is free software; you can redistribute it and/or
7
# modify it under the terms of the GNU General Public License
8
# as published by the Free Software Foundation; either version 2
9
# of the License, or (at your option) any later version.
10
#
11
# This program is distributed in the hope that it will be useful,
12
# but WITHOUT ANY WARRANTY; without even the implied warranty of
13
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
# GNU General Public License for more details.
15
#
16
# You should have received a copy of the GNU General Public License
17
# along with this program; if not, write to the Free Software
18
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
19

  
20
class UserNotificationRecipient
21
  INVOLVED = 'involved'
22
  MENTIONED = 'mentioned'
23
  WATCHER = 'watcher'
24
  SUBSCRIBED = 'subscribed'
25
  ADMIN = 'admin'
26

  
27
  REASON_PRIORITY = [
28
    INVOLVED,
29
    MENTIONED,
30
    WATCHER,
31
    SUBSCRIBED,
32
    ADMIN
33
  ].freeze
34

  
35
  attr_reader :user, :reason
36

  
37
  def initialize(user, reason)
38
    @user = user
39
    @reason = reason
40
  end
41

  
42
  def self.reorder_by_priority(users)
43
    users = users.sort_by { |r| priority(r.notification_reason) }
44
    users.uniq!
45
    users
46
  end
47

  
48
  def self.priority(reason)
49
    REASON_PRIORITY.index(reason) || REASON_PRIORITY.length + 1
50
  end
51
end
app/services/notification_recipients/build_service.rb
1
# frozen_string_literal: true
2

  
3
# Redmine - project management software
4
# Copyright (C) 2006-  Jean-Philippe Lang
5
#
6
# This program is free software; you can redistribute it and/or
7
# modify it under the terms of the GNU General Public License
8
# as published by the Free Software Foundation; either version 2
9
# of the License, or (at your option) any later version.
10
#
11
# This program is distributed in the hope that it will be useful,
12
# but WITHOUT ANY WARRANTY; without even the implied warranty of
13
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
# GNU General Public License for more details.
15
#
16
# You should have received a copy of the GNU General Public License
17
# along with this program; if not, write to the Free Software
18
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
19

  
20
module NotificationRecipients
21
  module BuildService
22
    def self.issue_add(issue)
23
      ::NotificationRecipients::Builder::Issue.new(issue).notified_recipients
24
    end
25

  
26
    def self.issue_edit(journal)
27
      ::NotificationRecipients::Builder::Journal.new(journal).notified_recipients
28
    end
29
  end
30
end
app/services/notification_recipients/builder/base.rb
1
module NotificationRecipients
2
  module Builder
3
    class Base
4
      attr_reader :target
5

  
6
      def initialize(target)
7
        @target = target
8
      end
9

  
10
      def notified_recipients
11
        build_notified_recipients
12
        filter!
13
        reorder!
14

  
15
        self.recipients.freeze
16
      end
17

  
18
      def notified_users
19
        build_notified_users
20
        filter!
21
        reorder!
22

  
23
        self.recipients.freeze
24
      end
25

  
26
      def notified_mentions
27
        build_notified_mentions
28
        filter!
29

  
30
        self.recipients.freeze
31
      end
32

  
33
      def notified_watchers
34
        add_watchers(target)
35

  
36
        self.recipients.freeze
37
      end
38

  
39
      protected
40

  
41
      def recipients
42
        @recipients ||= []
43
      end
44

  
45
      def build_notified_watchers
46
        add_watchers(target)
47
      end
48

  
49
      def build_notified_mentions
50
        add_mentions(target)
51
      end
52

  
53
      def add_mentions(target)
54
        users = target.notified_mentions
55

  
56
        users.each do |user|
57
          add_recipient(user, UserNotificationRecipient::MENTIONED)
58
        end
59
      end
60

  
61
      def add_watchers(target)
62
        users = target.notified_watchers
63

  
64
        users.each do |user|
65
          add_recipient(user, UserNotificationRecipient::WATCHER)
66
        end
67
      end
68

  
69
      def add_recipient(user, reason)
70
        recipients.push(UserNotificationRecipient.new(user, reason))
71
      end
72

  
73
      def filter!
74
      end
75

  
76
      def reorder!
77
        self.recipients.sort_by! { |r| UserNotificationRecipient::priority(r.reason) }
78
        self.recipients.uniq!(&:user)
79
      end
80
    end
81
  end
82
end
app/services/notification_recipients/builder/issue.rb
1
module NotificationRecipients
2
  module Builder
3
    class Issue < Base
4

  
5
      protected
6

  
7
      def build_notified_recipients
8
        build_notified_users
9
        build_notified_mentions
10
        build_notified_watchers
11
      end
12

  
13
      def build_notified_users
14
        add_involved_users
15
        add_subscribed_users
16
        add_high_priority_users
17
      end
18

  
19
      def add_involved_users
20
        notified = [target.author, target.assigned_to, target.previous_assignee].compact.uniq
21
        notified = notified.map {|n| n.is_a?(Group) ? n.users : n}.flatten
22
        notified.uniq!
23
        notified = notified.select {|u| u.active? && u.notify_about?(target)}
24

  
25
        # Remove users that can not view the issue
26
        notified.reject! {|user| !target.visible?(user)}
27

  
28
        notified.each do |user|
29
          add_recipient(user, UserNotificationRecipient::INVOLVED)
30
        end
31
      end
32

  
33
      def add_subscribed_users
34
        notified = target.project.notified_users.to_a
35

  
36
        # Remove users that can not view the issue
37
        notified.reject! {|user| !target.visible?(user)}
38

  
39
        notified.each do |user|
40
          add_recipient(user, UserNotificationRecipient::SUBSCRIBED)
41
        end
42
      end
43

  
44
      def add_high_priority_users
45
        if target.priority.high?
46
          project.users.preload(:preference).select(&:notify_about_high_priority_issues?).each do |user|
47
            next unless target.visible?(user)
48

  
49
            add_recipient(user, UserNotificationRecipient::HIGH_PRIORITY)
50
          end
51
        end
52
      end
53
    end
54
  end
55
end
app/services/notification_recipients/builder/journal.rb
1
module NotificationRecipients
2
  module Builder
3
    class Journal < Base
4
      protected
5

  
6
      def build_notified_users
7
        recipients.concat(::NotificationRecipients::Builder::Issue.new(target.journalized).notified_users)
8
      end
9

  
10
      def build_notified_recipients
11
        build_notified_users
12
        build_notified_watchers
13
        build_notified_mentions
14
      end
15

  
16
      def build_notified_watchers
17
        add_watchers(target.journalized)
18
      end
19

  
20
      def build_notified_mentions
21
        add_mentions(target)
22
        add_mentions(target.journalized)
23
      end
24

  
25
      def filter!
26
        if target.private_notes?
27
          self.recipients.select! {|r | r.user.allowed_to?(:view_private_notes, target.journalized.project)}
28
          self.recipients.select! {|r | target.notes? || target.visible_details(r.user).any? }
29
        end
30
      end
31
    end
32
  end
33
end
(5-5/6)