Class: Journal

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

Overview

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



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

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



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

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



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

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



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

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



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

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



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

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

#editable_by?(usr) ⇒ Boolean

Returns:

  • (Boolean)


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

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



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

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



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

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



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

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

#new_value_for(prop) ⇒ Object



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

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

#notified_mentionsObject



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

def notified_mentions
  notified = super
  select_journal_visible_user(notified)
end

#notified_usersObject



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

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



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

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

#notify=(arg) ⇒ Object



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

def notify=(arg)
  @notify = arg
end

#notify?Boolean

Returns:

  • (Boolean)


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

def notify?
  @notify != false
end

#projectObject



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

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

#recipientsObject



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

def recipients
  notified_users.map(&:mail)
end

#save(*args) ⇒ Object



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

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



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

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



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

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



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

def watcher_recipients
  notified_watchers.map(&:mail)
end