canvas-lms/app/models/conversation_message.rb

174 lines
5.7 KiB
Ruby

#
# Copyright (C) 2011 Instructure, Inc.
#
# This file is part of Canvas.
#
# Canvas is free software: you can redistribute it and/or modify it under
# the terms of the GNU Affero General Public License as published by the Free
# Software Foundation, version 3 of the License.
#
# Canvas 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 Affero General Public License for more
# details.
#
# You should have received a copy of the GNU Affero General Public License along
# with this program. If not, see <http://www.gnu.org/licenses/>.
#
class ConversationMessage < ActiveRecord::Base
include SendToStream
belongs_to :conversation
belongs_to :author, :class_name => 'User'
belongs_to :context, :polymorphic => true
has_many :conversation_message_participants
has_many :attachments, :as => :context, :order => 'created_at, id'
delegate :participants, :to => :conversation
delegate :subscribed_participants, :to => :conversation
attr_accessible
named_scope :human, :conditions => "NOT generated"
named_scope :with_media_comments, :conditions => "media_comment_id IS NOT NULL"
named_scope :latest_for_conversations, lambda{ |conversation_participants| {
:select => 'conversation_messages.*',
:joins => 'JOIN conversation_message_participants ON conversation_messages.id = conversation_message_id',
:conditions => [
"conversation_participant_id in (?) AND conversation_messages.created_at = (SELECT MAX(created_at) FROM conversation_messages cm2 WHERE cm2.conversation_id = conversation_messages.conversation_id)",
conversation_participants.map(&:id)
]
}}
validates_length_of :body, :maximum => maximum_text_length
has_a_broadcast_policy
set_broadcast_policy do |p|
p.dispatch :conversation_message
p.to { self.recipients }
p.whenever {|record| (record.just_created || @re_send_message) && !record.generated}
p.dispatch :added_to_conversation
p.to { self.new_recipients }
p.whenever {|record| (record.just_created || @re_send_message) && record.generated && record.event_data[:event_type] == :users_added}
end
on_create_send_to_streams do
self.recipients
end
before_save :infer_values
def infer_values
self.media_comment_id = nil if self.media_comment_id && self.media_comment_id.strip.empty?
if self.media_comment_id && self.media_comment_id_changed?
@media_comment = MediaObject.by_media_id(self.media_comment_id).first
self.media_comment_id = nil unless @media_comment
self.media_comment_type = @media_comment.media_type if @media_comment
end
self.media_comment_type = nil unless self.media_comment_id
end
def has_media_comment?
!self.media_comment_id.nil?
end
def media_comment
if !@media_comment && self.media_comment_id
@media_comment = MediaObject.by_media_id(self.media_comment_id).first
end
@media_comment
end
def media_comment=(media_comment)
self.media_comment_id = media_comment.media_id
self.media_comment_type = media_comment.media_type
@media_comment = media_comment
end
# TODO do this in SQL
def recipients
self.subscribed_participants - [self.author]
end
def new_recipients
return [] unless generated? and event_data[:event_type] == :users_added
recipients.select{ |u| event_data[:user_ids].include?(u.id) }
end
# for developer use on console only
def resend_message!
@re_send_message = true
self.save!
@re_send_message = false
end
def body
if generated?
format_event_message
else
read_attribute(:body)
end
end
def event_data
return {} unless generated?
@event_data ||= YAML.load(read_attribute(:body))
end
def format_event_message
case event_data[:event_type]
when :users_added
user_names = User.find_all_by_id(event_data[:user_ids], :order => "id").map(&:short_name)
EventFormatter.users_added(author.short_name, user_names)
end
end
def generate_user_note
return unless recipients.size == 1
recipient = recipients.first
return unless recipient.grants_right?(author, :create_user_notes) && recipient.associated_accounts.any?{|a| a.enable_user_notes }
self.extend TextHelper
title = t(:subject, "Private message, %{timestamp}", :timestamp => date_string(created_at))
note = format_message(body).first
recipient.user_notes.create(:creator => author, :title => title, :note => note)
end
def formatted_body(truncate=nil)
self.extend TextHelper
res = format_message(body).first
res = truncate_html(res, :max_length => truncate, :words => true) if truncate
res
end
def reply_from(opts)
conversation.reply_from(opts.merge(:context => self.context))
end
def forwarded_messages
@forwarded_messages ||= forwarded_message_ids && self.class.find_all_by_id(forwarded_message_ids.split(','), :order => 'created_at DESC') || []
end
def as_json(options = {})
super(:only => [:id, :created_at, :body, :generated, :author_id])['conversation_message'].merge({
'forwarded_messages' => forwarded_messages,
'attachments' => attachments,
'media_comment' => media_comment
})
end
class EventFormatter
def self.users_added(author_name, user_names)
I18n.t 'conversation_message.users_added', {
:one => "%{user} was added to the conversation by %{current_user}",
:other => "%{list_of_users} were added to the conversation by %{current_user}"
},
:count => user_names.size,
:user => user_names.first,
:list_of_users => user_names.all?(&:html_safe?) ? user_names.to_sentence.html_safe : user_names.to_sentence,
:current_user => author_name
end
end
end