Class: Journal

Inherits:
ActiveRecord::Base
  • Object
show all
Includes:
Redmine::SafeAttributes
Defined in:
app/models/journal.rb

Overview

Redmine - project management software Copyright (C) 2006-2022 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.

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Redmine::SafeAttributes

#delete_unsafe_attributes, included, #safe_attribute?, #safe_attribute_names, #safe_attributes=

Constructor Details

#initialize(*args) ⇒ Journal

Returns a new instance of Journal.


88
89
90
91
92
93
94
95
96
97
# File 'app/models/journal.rb', line 88

def initialize(*args)
  super
  if journalized
    if journalized.new_record?
      self.notify = false
    else
      start
    end
  end
end

Instance Attribute Details

#indiceObject

Returns the value of attribute indice.


30
31
32
# File 'app/models/journal.rb', line 30

def indice
  @indice
end

Class Method Details

.preload_journals_details_custom_fields(journals) ⇒ Object

Sets @custom_field instance variable on journals details using a single query


190
191
192
193
194
195
196
197
198
199
200
201
202
203
# File 'app/models/journal.rb', line 190

def self.preload_journals_details_custom_fields(journals)
  field_ids = journals.map(&:details).flatten.select {|d| d.property == 'cf'}.map(&:prop_key).uniq
  if field_ids.any?
    fields_by_id = CustomField.where(:id => field_ids).inject({}) {|h, f| h[f.id] = f; h}
    journals.each do |journal|
      journal.details.each do |detail|
        if detail.property == 'cf'
          detail.instance_variable_set :@custom_field, fields_by_id[detail.prop_key.to_i]
        end
      end
    end
  end
  journals
end

.visible_notes_condition(user = User.current, options = {}) ⇒ Object

Returns a SQL condition to filter out journals with notes that are not visible to user


83
84
85
86
# File 'app/models/journal.rb', line 83

def self.visible_notes_condition(user=User.current, options={})
  private_notes_permission = Project.allowed_to_condition(user, :view_private_notes, options)
  sanitize_sql_for_conditions(["(#{table_name}.private_notes = ? OR #{table_name}.user_id = ? OR (#{private_notes_permission}))", false, user.id])
end

Instance Method Details

#attachmentsObject


142
143
144
# File 'app/models/journal.rb', line 142

def attachments
  details.select{ |d| d.property == 'attachment' }.map{ |d| Attachment.find_by(:id => d.prop_key) }.compact
end

#css_classesObject

Returns a string of css classes


147
148
149
150
151
152
153
# File 'app/models/journal.rb', line 147

def css_classes
  s = +'journal'
  s << ' has-notes' unless notes.blank?
  s << ' has-details' unless details.blank?
  s << ' private-notes' if private_notes?
  s
end

#detail_for_attribute(attribute) ⇒ Object

Returns the JournalDetail for the given attribute, or nil if the attribute was not updated


120
121
122
# File 'app/models/journal.rb', line 120

def detail_for_attribute(attribute)
  details.detect {|detail| detail.prop_key == attribute}
end

#editable_by?(usr) ⇒ Boolean

Returns:

  • (Boolean)

134
135
136
# File 'app/models/journal.rb', line 134

def editable_by?(usr)
  usr && usr.logged? && (usr.allowed_to?(:edit_issue_notes, project) || (self.user == usr && usr.allowed_to?(:edit_own_issue_notes, project)))
end

#journalize_attachment(attachment, added_or_removed) ⇒ Object

Adds a journal detail for an attachment that was added or removed


221
222
223
224
225
226
227
228
229
# File 'app/models/journal.rb', line 221

def journalize_attachment(attachment, added_or_removed)
  key = (added_or_removed == :removed ? :old_value : :value)
  details <<
    JournalDetail.new(
      :property => 'attachment',
      :prop_key => attachment.id,
      key => attachment.filename
    )
end

#journalize_relation(relation, added_or_removed) ⇒ Object

Adds a journal detail for an issue relation that was added or removed


232
233
234
235
236
237
238
239
240
# File 'app/models/journal.rb', line 232

def journalize_relation(relation, added_or_removed)
  key = (added_or_removed == :removed ? :old_value : :value)
  details <<
    JournalDetail.new(
      :property  => 'relation',
      :prop_key  => relation.relation_type_for(journalized),
      key => relation.other_issue(journalized).try(:id)
    )
end

#new_statusObject

Returns the new status if the journal contains a status change, otherwise nil


125
126
127
128
# File 'app/models/journal.rb', line 125

def new_status
  s = new_value_for('status_id')
  s ? IssueStatus.find_by_id(s.to_i) : nil
end

#new_value_for(prop) ⇒ Object


130
131
132
# File 'app/models/journal.rb', line 130

def new_value_for(prop)
  detail_for_attribute(prop).try(:value)
end

#notified_mentionsObject


180
181
182
183
# File 'app/models/journal.rb', line 180

def notified_mentions
  notified = super
  select_journal_visible_user(notified)
end

#notified_usersObject


163
164
165
166
167
168
169
# File 'app/models/journal.rb', line 163

def notified_users
  notified = journalized.notified_users
  if private_notes?
    notified = notified.select {|user| user.allowed_to?(:view_private_notes, journalized.project)}
  end
  notified
end

#notified_watchersObject


175
176
177
178
# File 'app/models/journal.rb', line 175

def notified_watchers
  notified = journalized.notified_watchers
  select_journal_visible_user(notified)
end

#notify=(arg) ⇒ Object


159
160
161
# File 'app/models/journal.rb', line 159

def notify=(arg)
  @notify = arg
end

#notify?Boolean

Returns:

  • (Boolean)

155
156
157
# File 'app/models/journal.rb', line 155

def notify?
  @notify != false
end

#projectObject


138
139
140
# File 'app/models/journal.rb', line 138

def project
  journalized.respond_to?(:project) ? journalized.project : nil
end

#recipientsObject


171
172
173
# File 'app/models/journal.rb', line 171

def recipients
  notified_users.map(&:mail)
end

#save(*args) ⇒ Object


99
100
101
102
103
# File 'app/models/journal.rb', line 99

def save(*args)
  journalize_changes
  # Do not save an empty journal
  (details.empty? && notes.blank?) ? false : super()
end

#startObject

Stores the values of the attributes and custom fields of the journalized object


206
207
208
209
210
211
212
213
214
215
216
217
218
# File 'app/models/journal.rb', line 206

def start
  if journalized
    @attributes_before_change = journalized.journalized_attribute_names.inject({}) do |h, attribute|
      h[attribute] = journalized.send(attribute)
      h
    end
    @custom_values_before_change = journalized.custom_field_values.inject({}) do |h, c|
      h[c.custom_field_id] = c.value
      h
    end
  end
  self
end

#visible_details(user = User.current) ⇒ Object

Returns journal details that are visible to user


106
107
108
109
110
111
112
113
114
115
116
# File 'app/models/journal.rb', line 106

def visible_details(user=User.current)
  details.select do |detail|
    if detail.property == 'cf'
      detail.custom_field && detail.custom_field.visible_by?(project, user)
    elsif detail.property == 'relation'
      Issue.find_by_id(detail.value || detail.old_value).try(:visible?, user)
    else
      true
    end
  end
end

#watcher_recipientsObject


185
186
187
# File 'app/models/journal.rb', line 185

def watcher_recipients
  notified_watchers.map(&:mail)
end