ec94868 by Johan Sørensen at 2009-04-22 1
# encoding: utf-8
8116ee4 by Tor Arne Vestbø at 2008-11-28 2
#--
ec94868 by Johan Sørensen at 2009-04-22 3
#   Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies)
4
#   Copyright (C) 2008 Johan Sørensen <johan@johansorensen.com>
8116ee4 by Tor Arne Vestbø at 2008-11-28 5
#   Copyright (C) 2008 David A. Cuadrado <krawek@gmail.com>
ec94868 by Johan Sørensen at 2009-04-22 6
#   Copyright (C) 2008 Tor Arne Vestbø <tavestbo@trolltech.com>
8116ee4 by Tor Arne Vestbø at 2008-11-28 7
#
8
#   This program is free software: you can redistribute it and/or modify
9
#   it under the terms of the GNU Affero General Public License as published by
10
#   the Free Software Foundation, either version 3 of the License, or
11
#   (at your option) any later version.
12
#
13
#   This program is distributed in the hope that it will be useful,
14
#   but WITHOUT ANY WARRANTY; without even the implied warranty of
15
#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
#   GNU Affero General Public License for more details.
17
#
18
#   You should have received a copy of the GNU Affero General Public License
19
#   along with this program.  If not, see <http://www.gnu.org/licenses/>.
20
#++
21
ab5a4d4 by Johan Sørensen at 2008-01-07 22
class Comment < ActiveRecord::Base
16d2ac1 by Marius Mathiesen at 2011-05-18 23
  include Gitorious::Search
24
  
ab5a4d4 by Johan Sørensen at 2008-01-07 25
  belongs_to :user
593bc96 by Johan Sørensen at 2009-04-22 26
  belongs_to :target, :polymorphic => true
d701253 by Johan Sørensen at 2008-01-26 27
  belongs_to :project
5c5947b by David A. Cuadrado at 2008-04-08 28
  has_many   :events, :as => :target, :dependent => :destroy
ae89ad8 by Johan Sørensen at 2009-05-19 29
  after_create :notify_target_if_supported
d4a271e by Marius Mathiesen at 2009-06-24 30
  after_create :update_state_in_target
31
  serialize :state_change, Array
aaca6d5 by Johan Sørensen at 2009-11-19 32
1551dfe by Marius Mathiesen at 2011-05-18 33
  is_indexed do |s|
34
    s.index :body
35
    s.index "user#login", :as => :commented_by
36
  end
aaca6d5 by Johan Sørensen at 2009-11-19 37
ab5a4d4 by Johan Sørensen at 2008-01-07 38
  attr_protected :user_id
aaca6d5 by Johan Sørensen at 2009-11-19 39
7aeaa92 by Marius Mathiesen at 2009-07-13 40
  validates_presence_of :user_id, :target, :project_id
41
  validates_presence_of :body, :if =>  Proc.new {|mr| mr.body_required?}
aaca6d5 by Johan Sørensen at 2009-11-19 42
43
  named_scope :with_shas, proc{|*shas|
ad229f6 by Johan Sørensen at 2009-04-22 44
    {:conditions => { :sha1 => shas.flatten }, :include => :user}
45
  }
aaca6d5 by Johan Sørensen at 2009-11-19 46
b38a38b by Johan Sørensen at 2009-11-04 47
  NOTIFICATION_TARGETS = [ MergeRequest, MergeRequestVersion ]
aaca6d5 by Johan Sørensen at 2009-11-19 48
ae89ad8 by Johan Sørensen at 2009-05-19 49
  def deliver_notification_to(another_user)
1853b0c by Marius Mathiesen at 2009-07-02 50
    message_body = "#{user.title} commented:\n\n#{body}"
aaca6d5 by Johan Sørensen at 2009-11-19 51
    if [MergeRequest, MergeRequestVersion].include?(target.class)
9de7735 by Johan Sørensen at 2009-11-04 52
      if state_change
aaca6d5 by Johan Sørensen at 2009-11-19 53
        message_body << "\n\nThe status of your merge request"
54
        message_body << " is now #{state_changed_to}"
9de7735 by Johan Sørensen at 2009-11-04 55
      end
56
      subject_class_name = "merge request"
57
    else
58
      subject_class_name = target.class.human_name.downcase
59
    end
ae89ad8 by Johan Sørensen at 2009-05-19 60
    message = Message.new({
61
      :sender => self.user,
62
      :recipient => another_user,
9de7735 by Johan Sørensen at 2009-11-04 63
      :subject => "#{user.title} commented on your #{subject_class_name}",
1853b0c by Marius Mathiesen at 2009-07-02 64
      :body => message_body,
ae89ad8 by Johan Sørensen at 2009-05-19 65
      :notifiable => self.target,
66
    })
67
    message.save
68
  end
aaca6d5 by Johan Sørensen at 2009-11-19 69
d3c7cf5 by Johan Sørensen at 2009-07-15 70
  def state=(new_state)
71
    return if new_state.blank?
d4a271e by Marius Mathiesen at 2009-06-24 72
    result = []
73
    if applies_to_merge_request?
cbf6823 by Johan Sørensen at 2009-08-24 74
      return if target.status_tag.to_s == new_state
75
      result << (target.status_tag.nil? ? nil : target.status_tag.name)
d4a271e by Marius Mathiesen at 2009-06-24 76
    end
d3c7cf5 by Johan Sørensen at 2009-07-15 77
    result << new_state
d4a271e by Marius Mathiesen at 2009-06-24 78
    self.state_change = result
79
  end
aaca6d5 by Johan Sørensen at 2009-11-19 80
d4a271e by Marius Mathiesen at 2009-06-24 81
  def state_changed_to
82
    state_change.to_a.last
83
  end
aaca6d5 by Johan Sørensen at 2009-11-19 84
d4a271e by Marius Mathiesen at 2009-06-24 85
  def state_changed_from
86
    state_change.to_a.size > 1 ? state_change.first : nil
87
  end
7aeaa92 by Marius Mathiesen at 2009-07-13 88
89
  def body_required?
90
    if applies_to_merge_request?
91
      return state_change.blank?
92
    else
93
      return true
94
    end
95
  end
a44bb2e by Marius Mathiesen at 2009-11-04 96
6af131b by Johan Sørensen at 2009-11-04 97
  # +lines_str+ is a representation of the first and last line-number
98
  # tuple (as generated by Diff::Unified::Generator) and the lines the
99
  # comment span, in the follow format:
100
  # first_tuple:last_tuple+line_span
101
  def lines=(lines_str)
102
    start, rest = lines_str.split(":")
103
    raise "invalid lines format" if rest.blank?
104
    last, amount = rest.split("+")
105
    if start.blank? || last.blank? || amount.blank?
106
      raise "invalid lines format"
b9d1de8 by Marius Mathiesen at 2009-11-04 107
    end
6af131b by Johan Sørensen at 2009-11-04 108
    self.first_line_number = start
109
    self.last_line_number = last
110
    self.number_of_lines = amount
a44bb2e by Marius Mathiesen at 2009-11-04 111
  end
112
89fc7af by Marius Mathiesen at 2009-11-04 113
  def lines
6af131b by Johan Sørensen at 2009-11-04 114
    "#{self.first_line_number}:#{self.last_line_number}+#{self.number_of_lines}"
89fc7af by Marius Mathiesen at 2009-11-04 115
  end
116
a44bb2e by Marius Mathiesen at 2009-11-04 117
  def sha_range
118
    first, last = sha1.split("-")
89fc7af by Marius Mathiesen at 2009-11-04 119
    first..(last||first)
a44bb2e by Marius Mathiesen at 2009-11-04 120
  end
6ce2d1d by Marius Mathiesen at 2009-11-04 121
122
  def applies_to_line_numbers?
495a1b7 by Marius Mathiesen at 2009-11-16 123
    return !first_line_number.blank?
6ce2d1d by Marius Mathiesen at 2009-11-04 124
  end
30ec1ad by Johan Sørensen at 2009-11-04 125
126
  def applies_to_merge_request?
127
    MergeRequest === target
128
  end
129
2f03401 by Marius Mathiesen at 2009-11-04 130
  def editable_by?(a_user)
5b61760 by Marius Mathiesen at 2009-11-04 131
    creator?(a_user) && recently_created?
132
  end
133
134
  def creator?(a_user)
135
    a_user == user
136
  end
137
138
  def recently_created?
139
    created_at > 10.minutes.ago
2f03401 by Marius Mathiesen at 2009-11-04 140
  end
141
ae89ad8 by Johan Sørensen at 2009-05-19 142
  protected
143
    def notify_target_if_supported
144
      if target && NOTIFICATION_TARGETS.include?(target.class)
b38a38b by Johan Sørensen at 2009-11-04 145
        if self.target === MergeRequestVersion
146
          target_user = target.merge_request.user
147
        else
148
          target_user = target.user
149
        end
150
        return if target_user == user
151
        deliver_notification_to(target_user)
ae89ad8 by Johan Sørensen at 2009-05-19 152
      end
153
    end
30ec1ad by Johan Sørensen at 2009-11-04 154
d4a271e by Marius Mathiesen at 2009-06-24 155
    def update_state_in_target
156
      if applies_to_merge_request? and state_change
4905d51 by Marius Mathiesen at 2009-07-02 157
        target.with_user(user) do
7149e3c by Marius Mathiesen at 2009-07-14 158
          if target.resolvable_by?(user)
159
            target.status_tag=(state_changed_to)
160
            target.create_status_change_event(body)
161
          end
4905d51 by Marius Mathiesen at 2009-07-02 162
        end
d4a271e by Marius Mathiesen at 2009-06-24 163
      end
164
    end
aaca6d5 by Johan Sørensen at 2009-11-19 165
ab5a4d4 by Johan Sørensen at 2008-01-07 166
end