socialforge/app/models/message.rb

416 lines
16 KiB
Ruby
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#encoding: utf-8
# Redmine - project management software
# Copyright (C) 2006-2013 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.
class Message < ActiveRecord::Base
require 'net/http'
require 'json'
include Redmine::SafeAttributes
include UserScoreHelper
include ApplicationHelper
has_many_kindeditor_assets :assets, :dependent => :destroy
belongs_to :board,:touch => true
belongs_to :author, :class_name => 'User', :foreign_key => 'author_id'
has_many :praise_tread, as: :praise_tread_object, dependent: :destroy
has_one :praise_tread_cache, as: :object, dependent: :destroy
# has_many :org_subfield_messages, :dependent => :destroy
# has_many :org_subfields, :through => :org_subfield_messages
acts_as_tree :counter_cache => :replies_count, :order => "#{Message.table_name}.created_on ASC"
acts_as_attachable
belongs_to :last_reply, :class_name => 'Message', :foreign_key => 'last_reply_id'
# added by fq
has_many :acts, :class_name => 'Activity', :as => :act, :dependent => :destroy
# 被ForgeActivity虚拟关联
has_many :forge_acts, :class_name => 'ForgeActivity',:as =>:forge_act ,:dependent => :destroy
# 课程动态
has_many :course_acts, :class_name => 'CourseActivity',:as =>:course_act ,:dependent => :destroy
# end
# 课程/项目 消息
has_many :course_messages, :class_name =>'CourseMessage', :as => :course_message, :dependent => :destroy
has_many :forge_messages, :class_name => 'ForgeMessage', :as => :forge_message, :dependent => :destroy
has_many :at_messages, as: :at_message, dependent: :destroy
has_many :ActivityNotifies,:as => :activity, :dependent => :destroy
#转发表
has_many :forwards, :as => :from, :dependent => :destroy
after_destroy :delete_org_activities
acts_as_searchable :columns => ['subject', 'content'],
:include => {:board => :project},
:project_key => "#{Board.table_name}.project_id",
:date_column => "#{table_name}.created_on"
acts_as_searchable :columns => ['subject', 'content'],
:include => {:board => :course},
:course_key => "#{Board.table_name}.course_id",
:date_column => "#{table_name}.created_at"
acts_as_event :title => Proc.new {|o| "#{o.board.name}: #{o.subject}"},
:description => :content,
:datetime => :updated_on,
# :datetime => "#{Message.table_name}.created_on",
:group => :parent,
:type => Proc.new {|o| o.parent_id.nil? ? 'message' : 'reply'},
:url => Proc.new {|o| {:controller => 'messages', :action => 'show', :board_id => o.board_id}.merge(o.parent_id.nil? ? {:id => o.id} :
{:id => o.parent_id, :r => o.id, :anchor => "message-#{o.id}"})}
acts_as_activity_provider :find_options => {:include => [{:board => :project}, :author]},
:author_key => :author_id
acts_as_activity_provider :find_options => {:include => [{:board => :course}, :author]},
:type => 'course_messages',
:author_key => :author_id
acts_as_watchable
validates_presence_of :board, :subject, :content
validates_length_of :subject, :maximum => 255
validate :cannot_reply_to_locked_topic, :on => :create
# after_create :add_author_as_watcher, :reset_counters!, :add_boards_count
after_update :update_messages_board, :update_activity
after_destroy :reset_counters!,:down_user_score,:delete_kindeditor_assets, :decrease_boards_count, :down_course_score
after_create :act_as_course_activity, :act_as_forge_activity, :act_as_student_score, act_as_at_message(:content, :author_id), :add_author_as_watcher, :reset_counters!, :add_boards_count, :act_as_system_message, :delay_message_send
#before_save :be_user_score
scope :visible, lambda {|*args|
includes(:board => :project).where(Project.allowed_to_condition(args.shift || User.current, :view_messages, *args))
}
scope :course_visible, lambda {|*args|
includes(:board => :course).where(Course.allowed_to_condition(args.shift || User.current, :view_course_messages, *args))
}
safe_attributes 'subject', 'content', 'reply_id'
safe_attributes 'board_id','locked', 'sticky',
:if => lambda {|message, user|
if message.project
user.allowed_to?(:edit_messages, message.project)
else
user.allowed_to?(:edit_messages, message.course)
end
}
def topic?
parent_id.nil?
end
def visible?(user=User.current)
if project
!user.nil? && user.allowed_to?(:view_messages, project)
elsif course
!user.nil? && user.allowed_to?(:view_messages, course)
end
end
def cannot_reply_to_locked_topic
# Can not reply to a locked topic
errors.add :base, 'Topic is locked' if root.locked? && self != root
end
def update_messages_board
if board_id_changed?
Message.update_all({:board_id => board_id}, ["id = ? OR parent_id = ?", root.id, root.id])
Board.reset_counters!(board_id_was)
Board.reset_counters!(board_id)
end
end
# 发帖精辟更新发帖总数
def add_boards_count
if self.project && !project.project_score.nil?
# 讨论区
if self.parent_id.nil?
count = self.project.project_score.board_num.to_i + 1
self.project.project_score.update_column(:board_num, count)
else # 回复
count = self.project.project_score.board_message_num.to_i + 1
self.project.project_score.update_column(:board_message_num, count)
end
end
end
# 删除帖子的时候更新帖子总数, 删除回复的时候总数不减少
def decrease_boards_count
if self.project && !project.project_score.nil?
# 讨论区
if self.parent_id.nil?
count = self.project.project_score.board_num - 1
self.project.project_score.update_attribute(:board_num, count < 0 ? 0 : count)
else # 回复
count = self.project.project_score.board_message_num - 1
self.project.project_score.update_attribute(:board_message_num, count < 0 ? 0 : count)
end
end
end
def reset_counters!
if parent && parent.id
Message.update_all({:last_reply_id => parent.children.maximum(:id)}, {:id => parent.id})
end
board.reset_counters!
end
def sticky=(arg)
write_attribute :sticky, (arg == true || arg.to_s == '1' ? 1 : 0)
end
def sticky?
sticky == 1
end
def project
board.project
end
def course
board.course
end
def course_editable_by?(usr)
usr && usr.logged? && (usr.allowed_to?(:edit_messages, course) || (self.author == usr && usr.allowed_to?(:edit_own_messages, course)))
end
def org_subfield_editable_by?(usr)
usr && usr.logged? && (usr.admin? || self.author == usr ||usr.admin_of_org?(self.board.org_subfield.organization))
end
def course_destroyable_by?(usr)
usr && usr.logged? && (usr.allowed_to?(:delete_messages, course) || (self.author == usr && usr.allowed_to?(:delete_own_messages, course)))
end
def editable_by?(usr)
usr && usr.logged? && (usr.allowed_to?(:edit_messages, project) || (self.author == usr && usr.allowed_to?(:edit_own_messages, project)))
end
def destroyable_by?(usr)
usr && usr.logged? && (usr.allowed_to?(:delete_messages, project) || (self.author == usr && usr.allowed_to?(:delete_own_messages, project)))
end
def set_notify_id(notify_id)
@notify_id= notify_id
end
def get_notify_id()
return @notify_id
end
def set_notify_is_read(notify_is_read)
@notify_is_read = notify_is_read
end
def get_notify_is_read()
return @notify_is_read
end
#动态的更新
def update_activity
update_course_activity(self.class, self.id)
update_user_activity(self.class, self.id)
update_forge_activity(self.class, self.id)
update_org_activity(self.class, self.id)
end
def creator_user
self.author
end
def created_time
self.created_on
end
def content_detail
self.content
end
private
def add_author_as_watcher
Watcher.create(:watchable => self.root, :user => author)
end
# fq
def act_as_activity
self.acts << Activity.new(:user_id => self.author_id)
end
# end
# Time 2015-02-27 14:32:25
# Author lizanle
# Description
def act_as_forge_activity
# 如果project为空那么就是课程相关的消息
if self.board.project_id != -1 && self.parent_id.nil?
self.forge_acts << ForgeActivity.new(:user_id => self.author_id, :project_id => self.board.project.id)
end
end
#课程动态公共表记录
def act_as_course_activity
if self.course && self.parent_id.nil?
self.course_acts << CourseActivity.new(:user_id => self.author_id,:course_id => self.board.course_id)
end
end
# 课程讨论区添加消息:
# 老师发帖所有人都能收到消息
# 学生发帖,有人回复则给该学生消息,没回复则不给其它人发送消息
# 帖子被回复的可以收到消息通知
# 项目讨论区添加消息:
# 主贴项目成员都能收到
# 回帖:帖子的发布人收到
def act_as_system_message
#ws = WechatService.new
if self.course
if self.parent_id.nil? # 主贴
self.course.members.includes(:user).each do |m|
if self.author.allowed_to?(:as_teacher, self.course) && m.user_id != self.author_id # 老师 自己的帖子不给自己发送消息
#self.course_messages << CourseMessage.new(:user_id => m.user_id, :course_id => self.board.course_id, :viewed => false)
# count = ShieldWechatMessage.where("container_type='User' and container_id=#{m.user_id} and shield_type='Course' and shield_id=#{self.course.id}").count
# if count == 0
# content = strip_html self.subject, 200
# ws.topic_publish_template m.user_id, "course_discussion", self.id, "#{l(:label_course_topic_template)}", content, self.author.try(:realname), format_time(self.created_on)
# end
end
end
else # 回帖
parent_author_id = Message.find(self.parent_id).author_id
if parent_author_id != self.author_id # 只针对主贴回复,回复自己的帖子不发消息
self.course_messages << CourseMessage.new(:user_id => parent_author_id, :course_id => self.board.course_id, :viewed => false)
# count = ShieldWechatMessage.where("container_type='User' and container_id=#{parent_author_id} and shield_type='Course' and shield_id=#{self.board.course_id}").count
# if count == 0
# content = strip_html self.content.html_safe, 200
# ws.comment_template parent_author_id, "course_discussion", self.parent_id, "#{l(:label_topic_comment_template)}", self.author.try(:realname), format_time(self.created_on), content
# end
end
end
elsif self.project # 项目相关
if self.parent_id.nil? # 主贴
self.project.members.includes(:user).each do |m|
if m.user_id != self.author_id
#self.forge_messages << ForgeMessage.new(:user_id => m.user_id, :project_id => self.board.project_id, :viewed => false)
# count = ShieldWechatMessage.where("container_type='User' and container_id=#{m.user_id} and shield_type='Project' and shield_id=#{self.project.id}").count
# if count == 0
# content = strip_html self.subject, 200
# ws.topic_publish_template m.user_id, "project_discussion", self.id, "#{l(:label_project_topic_template)}", content, self.author.try(:realname), format_time(self.created_on)
# end
end
end
else # 回帖
parent_author_id = Message.find(self.parent_id).author_id
if parent_author_id != self.author_id # 只针对主贴回复,回复自己的帖子不发消息
self.forge_messages << ForgeMessage.new(:user_id => parent_author_id, :project_id => self.board.project_id, :viewed => false)
# count = ShieldWechatMessage.where("container_type='User' and container_id=#{parent_author_id} and shield_type='Project' and shield_id=#{self.board.project_id}").count
# if count == 0
# content = strip_html self.content.html_safe, 200
# ws.comment_template parent_author_id, "project_discussion", self.parent_id, "#{l(:label_topic_comment_template)}", self.author.try(:realname), format_time(self.created_on), content
# end
end
end
end
end
def delay_message_send
if self.course
if self.parent_id.nil? # 发帖
self.delay.contain_messages_message
end
end
end
def contain_messages_message
self.course.members.includes(:user).each do |m|
if self.author.allowed_to?(:as_teacher, self.course) && m.user_id != self.author_id # 老师 自己的帖子不给自己发送消息
self.course_messages << CourseMessage.new(:user_id => m.user_id, :course_id => self.board.course_id, :viewed => false)
end
end
end
#更新用户分数 -by zjc
def be_user_score
#新建message且无parent的为发帖
if self.parent_id.nil? && !self.board.project.nil?
UserScore.joint(:post_message, self.author,nil,self, { message_id: self.id })
update_memo_number(self.author,1)
if self.board.project_id != -1
update_memo_number(self.author,2,self.board.project)
end
#新建message且有parent的为回帖
elsif !self.parent_id.nil? && !self.board.project.nil?
UserScore.joint(:reply_posting, self.author,self.parent.author,self, { message_id: self.id })
update_replay_for_memo(self.author,1)
if self.board.project_id != -1
update_replay_for_memo(self.author,2,self.board.project)
end
end
end
#减少用户分数
def down_user_score
if self.parent_id.nil? && !self.board.project.nil?
UserScore.joint(:delete_message, self.author,nil,self, { message_id: self.id })
update_memo_number(User.current,1)
if self.board.project_id != -1
update_memo_number(self.author,2,self.board.project)
end
elsif !self.parent_id.nil? && !self.board.project.nil?
UserScore.joint(:reply_deleting, self.author,self.parent.author,self, { message_id: self.id })
update_replay_for_memo(User.current,1)
if self.board.project_id != -1
update_replay_for_memo(self.author,2,self.board.project)
end
end
end
def send_mail
Mailer.run.message_posted(self) if Setting.notified_events.include?('message_posted')
end
# Time 2015-03-31 09:15:06
# Author lizanle
# Description 删除对应消息的图片资源
def delete_kindeditor_assets
delete_kindeditor_assets_from_disk self.id,OwnerTypeHelper::MESSAGE
end
# 课程成员得分(活跃度)
def act_as_student_score
if self.course
if self.parent_id.nil?
# 发帖
course_member_score(self.course.id, self.author_id, "Message")
else
# 回帖
course_member_score(self.course.id, self.author_id, "MessageReply")
end
end
end
# 删除帖子的时候更新课程帖子总数, 删除回复的时候减少总数
def down_course_score
if self.course
if self.parent_id.nil? # 发帖
down_course_score_num(self.course.id, self.author_id, "Message")
else
# 回帖
down_course_score_num(self.course.id, self.author_id, "MessageReply")
end
end
end
def delete_org_activities
OrgActivity.where("org_act_type='Message' and org_act_id =#{self.id} and container_type='OrgSubfield'").destroy_all
end
end