Class: Journal

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

Overview

Redmine - project management software Copyright © 2006-2023 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.



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

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.



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

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



197
198
199
200
201
202
203
204
205
206
207
208
209
210
# File 'app/models/journal.rb', line 197

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



85
86
87
88
# File 'app/models/journal.rb', line 85

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



144
145
146
147
# File 'app/models/journal.rb', line 144

def attachments
  ids = details.select {|d| d.property == 'attachment' && d.value.present?}.map(&:prop_key)
  Attachment.where(id: ids).sort_by {|a| ids.index(a.id.to_s)}
end

#css_classesObject

Returns a string of css classes



154
155
156
157
158
159
160
# File 'app/models/journal.rb', line 154

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



122
123
124
# File 'app/models/journal.rb', line 122

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

#editable_by?(usr) ⇒ Boolean

Returns:

  • (Boolean)


136
137
138
# File 'app/models/journal.rb', line 136

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



228
229
230
231
232
233
234
235
236
# File 'app/models/journal.rb', line 228

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



239
240
241
242
243
244
245
246
247
# File 'app/models/journal.rb', line 239

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



127
128
129
130
# File 'app/models/journal.rb', line 127

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

#new_value_for(prop) ⇒ Object



132
133
134
# File 'app/models/journal.rb', line 132

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

#notified_mentionsObject



187
188
189
190
# File 'app/models/journal.rb', line 187

def notified_mentions
  notified = super
  select_journal_visible_user(notified)
end

#notified_usersObject



170
171
172
173
174
175
176
# File 'app/models/journal.rb', line 170

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



182
183
184
185
# File 'app/models/journal.rb', line 182

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

#notify=(arg) ⇒ Object



166
167
168
# File 'app/models/journal.rb', line 166

def notify=(arg)
  @notify = arg
end

#notify?Boolean

Returns:

  • (Boolean)


162
163
164
# File 'app/models/journal.rb', line 162

def notify?
  @notify != false
end

#projectObject



140
141
142
# File 'app/models/journal.rb', line 140

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

#recipientsObject



178
179
180
# File 'app/models/journal.rb', line 178

def recipients
  notified_users.map(&:mail)
end

#save(*args) ⇒ Object



101
102
103
104
105
# File 'app/models/journal.rb', line 101

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



213
214
215
216
217
218
219
220
221
222
223
224
225
# File 'app/models/journal.rb', line 213

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?(*args) ⇒ Boolean

Returns:

  • (Boolean)


149
150
151
# File 'app/models/journal.rb', line 149

def visible?(*args)
  journalized.visible?(*args)
end

#visible_details(user = User.current) ⇒ Object

Returns journal details that are visible to user



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

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



192
193
194
# File 'app/models/journal.rb', line 192

def watcher_recipients
  notified_watchers.map(&:mail)
end