2013-09-06 16:40:07 +08:00
class Course < ActiveRecord :: Base
include Redmine :: SafeAttributes
2014-05-29 16:35:34 +08:00
STATUS_ACTIVE = 1
STATUS_CLOSED = 5
STATUS_ARCHIVED = 9
2013-09-06 16:40:07 +08:00
2014-06-09 14:23:31 +08:00
attr_accessible :code , :extra , :name , :state , :tea_id , :time , :location , :state , :term , :password , :is_public , :description , :class_period
2014-05-29 16:35:34 +08:00
belongs_to :project , :class_name = > 'Course' , :foreign_key = > :extra , primary_key : :identifier
2013-09-14 17:25:57 +08:00
belongs_to :teacher , :class_name = > 'User' , :foreign_key = > :tea_id # 定义一个方法teacher, 该方法通过tea_id来调用User表
2014-03-20 16:19:16 +08:00
belongs_to :school , :class_name = > 'School' , :foreign_key = > :school_id #定义一个方法school, 该方法通过school_id来调用School表
2013-09-06 16:40:07 +08:00
has_many :bid
2014-06-04 16:45:20 +08:00
has_many :members , :include = > [ :principal , :roles ] , :conditions = > " #{ Principal . table_name } .type='User' AND #{ Principal . table_name } .status= #{ Principal :: STATUS_ACTIVE } "
has_many :memberships , :class_name = > 'Member'
has_many :member_principals , :class_name = > 'Member' ,
:include = > :principal ,
:conditions = > " #{ Principal . table_name } .type='Group' OR ( #{ Principal . table_name } .type='User' AND #{ Principal . table_name } .status= #{ Principal :: STATUS_ACTIVE } ) "
2014-06-09 10:26:45 +08:00
has_many :principals , :through = > :member_principals , :source = > :principal
2014-06-04 16:45:20 +08:00
has_many :users , :through = > :members
2014-06-04 16:58:26 +08:00
has_many :homeworks , :through = > :homework_for_courses , :source = > :bid , :dependent = > :destroy
has_many :journals_for_messages , :as = > :jour , :dependent = > :destroy
has_many :homework_for_courses , :dependent = > :destroy
2014-07-18 09:55:10 +08:00
has_many :student , :class_name = > 'StudentsForCourse' , :source = > :user
2014-06-05 16:41:05 +08:00
has_many :course_infos , :class_name = > 'CourseInfos' , :dependent = > :destroy
2014-06-06 13:56:48 +08:00
has_many :enabled_modules , :dependent = > :delete_all
2014-06-09 10:26:45 +08:00
has_many :boards , :dependent = > :destroy , :order = > " position ASC "
2014-06-12 11:34:47 +08:00
#has_many :course_journals_for_messages, :class_name => 'CourseJournalsForMessage', :as => :jour, :dependent => :destroy
2014-06-11 16:46:13 +08:00
has_many :news , :dependent = > :destroy , :include = > :author
2014-07-03 10:12:30 +08:00
has_one :course_status , :class_name = > " CourseStatus " , :dependent = > :destroy
2014-06-05 11:55:46 +08:00
2014-06-05 15:20:09 +08:00
acts_as_taggable
2014-06-10 17:03:02 +08:00
acts_as_nested_set :order = > 'name' , :dependent = > :destroy
2014-06-05 15:20:09 +08:00
acts_as_attachable :view_permission = > :view_files ,
:delete_permission = > :manage_files
2014-06-04 16:45:20 +08:00
2014-07-19 15:58:11 +08:00
validates_presence_of :password , :term , :name , :class_period
2014-07-18 17:10:01 +08:00
validates_format_of :class_period , :with = > / ^ \ d*$ /
2014-07-18 11:49:47 +08:00
#validates_format_of :name,:with =>/^[a-zA-Z0-9_\u4e00-\u9fa5]+$/
2014-06-09 10:26:45 +08:00
2014-07-04 11:11:27 +08:00
before_save :self_validate
2014-07-18 09:20:16 +08:00
after_create :create_board_sync
2014-06-09 10:26:45 +08:00
before_destroy :delete_all_members
2013-09-06 16:40:07 +08:00
safe_attributes 'extra' ,
'time' ,
'name' ,
'extra' ,
2013-09-12 10:41:15 +08:00
'code' ,
2013-09-12 17:25:40 +08:00
'location' ,
'tea_id' ,
2013-09-28 23:08:24 +08:00
'password' ,
2013-09-29 19:46:59 +08:00
'term' ,
2014-06-09 14:23:31 +08:00
'is_public' ,
'description' ,
'class_period'
2014-05-09 17:13:23 +08:00
2014-06-04 15:47:09 +08:00
acts_as_customizable
2014-06-12 16:55:56 +08:00
scope :all_course
2014-05-29 16:35:34 +08:00
scope :active , lambda { where ( :status = > STATUS_ACTIVE ) }
scope :status , lambda { | arg | where ( arg . blank? ? nil : { :status = > arg . to_i } ) }
scope :all_public , lambda { where ( :is_public = > true ) }
scope :visible , lambda { | * args | where ( Course . visible_condition ( args . shift || User . current , * args ) ) }
scope :allowed_to , lambda { | * args |
user = User . current
permission = nil
if args . first . is_a? ( Symbol )
permission = args . shift
else
user = args . shift
permission = args . shift
end
where ( Course . allowed_to_condition ( user , permission , * args ) )
}
2014-06-12 16:55:56 +08:00
scope :like , lambda { | arg |
if arg . blank?
where ( nil )
else
pattern = " % #{ arg . to_s . strip . downcase } % "
2014-07-04 11:11:27 +08:00
where ( " LOWER(name) LIKE :p " , :p = > pattern )
2014-06-12 16:55:56 +08:00
end
}
2014-05-29 16:35:34 +08:00
2014-06-03 11:16:06 +08:00
def visible? ( user = User . current )
user . allowed_to? ( :view_course , self )
end
2014-06-11 11:04:38 +08:00
def parent_id_changed?
false
end
2014-07-11 09:07:09 +08:00
# Returns the mail adresses of users that should be always notified on project events
def recipients
notified_users . collect { | user | user . mail }
end
# Returns the users that should be notified on project events
def notified_users
# TODO: User part should be extracted to User#notify_about?
members . select { | m | m . principal . present? && ( m . mail_notification? || m . principal . mail_notification == 'all' ) } . collect { | m | m . principal }
end
2014-06-10 17:03:02 +08:00
# 课程的短描述信息
def short_description ( length = 255 )
2014-07-10 16:48:13 +08:00
description . gsub ( / < \/ ?.*?> / , " " ) . html_safe if description
2014-07-10 16:35:53 +08:00
#description.gsub(/^(.{#{length}}[^\n\r]*).*$/m, '\1...').strip if description
2014-06-10 17:03:02 +08:00
end
2014-07-16 09:45:39 +08:00
# 课程的短名称信息
def short_name ( length = 8 )
name . gsub ( / < \/ ?.*?> / , " " ) . html_safe if name
end
2014-07-10 16:48:13 +08:00
def strip_html ( html )
return html if html . empty? || ! html . include? ( '<' )
output = " "
tokenizer = HTML :: Tokenizer . new ( html )
while token = tokenizer . next
node = HTML :: Node . parse ( nil , 0 , 0 , token , false )
output += token unless ( node . kind_of? HTML :: Tag ) or ( token =~ / ^<! / )
end
return output
end
2014-06-04 15:47:09 +08:00
def extra_frozen?
errors [ :extra ] . blank? && ! ( new_record? || extra . blank? )
end
2014-06-04 16:45:20 +08:00
def archived?
self . status == STATUS_ARCHIVED
end
2014-06-04 15:47:09 +08:00
2014-06-06 13:56:48 +08:00
def self . visible_condition ( user , options = { } )
2014-06-03 11:16:06 +08:00
allowed_to_condition ( user , :view_course , options )
end
2014-06-12 09:20:39 +08:00
# 获取课程的资源类型列表
2014-06-09 14:23:31 +08:00
def attachmenttypes
@attachmenttypes = Attachmentstype . find ( :all , :conditions = > [ " #{ Attachmentstype . table_name } .typeId= ? " , self . attachmenttype ] )
end
2014-07-11 09:07:09 +08:00
2014-06-09 14:23:31 +08:00
# 获取资源后缀名列表
def contenttypes
attachmenttypes
if @attachmenttypes . length > 0
@attachmenttypes . last ( ) . suffixArr
end
end
2014-06-06 13:56:48 +08:00
def active?
self . status == STATUS_ACTIVE
end
#课程权限判断
def allows_to? ( action )
if archived?
# No action allowed on archived projects
return false
end
unless active? || Redmine :: AccessControl . read_action? ( action )
# No write action allowed on closed projects
return false
end
# No action allowed on disabled modules
if action . is_a? Hash
allowed_actions . include? " #{ action [ :controller ] } / #{ action [ :action ] } "
else
allowed_permissions . include? action
end
end
2014-06-12 09:20:39 +08:00
# 课程允许的权限集合
2014-06-06 13:56:48 +08:00
def allowed_permissions
@allowed_permissions || = begin
module_names = enabled_modules . all ( :select = > :name ) . collect { | m | m . name }
Redmine :: AccessControl . modules_permissions ( module_names ) . collect { | p | p . name }
end
end
2014-06-12 09:20:39 +08:00
# 课程允许的动作集合
2014-06-06 13:56:48 +08:00
def allowed_actions
@actions_allowed || = allowed_permissions . inject ( [ ] ) { | actions , permission | actions += Redmine :: AccessControl . allowed_actions ( permission ) } . flatten
end
# 返回用户组可以访问的课程
2014-06-05 11:01:46 +08:00
def users_by_role
members . includes ( :user , :roles ) . all . inject ( { } ) do | h , m |
m . roles . each do | r |
h [ r ] || = [ ]
h [ r ] << m . user
end
h
end
end
2014-05-29 16:35:34 +08:00
#自定义验证
2014-07-04 11:11:27 +08:00
def self_validate
2014-05-09 17:13:23 +08:00
end
2014-06-12 11:34:47 +08:00
# 创建课程讨论区
2014-06-09 10:26:45 +08:00
def create_board_sync
@board = self . boards . build
self . name = " #{ l ( :label_borad_course ) } "
@board . name = self . name
@board . description = self . name . to_s
@board . project_id = - 1
if @board . save
logger . debug " [Course Model] ===> #{ @board . to_json } "
else
logger . error " [Course Model] ===> Auto create board when course saved, because #{ @board . full_messages } "
end
end
2014-06-12 11:34:47 +08:00
# 新增课程留言
# add by nwb
def self . add_new_jour ( user , notes , id , options = { } )
course = Course . find ( id )
if options . count == 0
pjfm = course . journals_for_messages . build ( :user_id = > user . id , :notes = > notes , :reply_id = > 0 )
else
pjfm = course . journals_for_messages . build ( options )
end
pjfm . save
pjfm
end
2014-06-12 09:20:39 +08:00
# 删除课程所有成员
2014-06-09 10:26:45 +08:00
def delete_all_members
2014-06-26 09:15:56 +08:00
if self . members && self . members . count > 0
me , mr = Member . table_name , MemberRole . table_name
connection . delete ( " DELETE FROM #{ mr } WHERE #{ mr } .member_id IN (SELECT #{ me } .id FROM #{ me } WHERE #{ me } .course_id = #{ id } ) " )
Member . delete_all ( [ 'course_id = ?' , id ] )
end
2014-06-09 10:26:45 +08:00
end
2014-02-15 16:34:09 +08:00
def get_endup_time
begin
end_time = Time . parse ( self . endup_time )
rescue Exception = > e
end_time = Time . parse ( " 3000-01-01 " )
Rails . logger . error " [Error] course endup_time error. ===> #{ e } "
ensure
return end_time
end
end
2013-09-06 16:40:07 +08:00
2014-02-22 09:44:14 +08:00
def get_time
begin
time = Date . new ( self . time ) . to_time
rescue Exception = > e
time = Time . parse ( " 3000-01-01 " )
Rails . logger . error " [Error] course time error. ===> #{ e } "
ensure
return time
end
end
2014-05-29 16:35:34 +08:00
def self . allowed_to_condition ( user , permission , options = { } )
2014-06-03 16:21:00 +08:00
perm = Redmine :: AccessControl . permission ( permission )
2014-05-29 16:35:34 +08:00
base_statement = ( perm && perm . read? ? " #{ Course . table_name } .status <> #{ Course :: STATUS_ARCHIVED } " : " #{ Course . table_name } .status = #{ Course :: STATUS_ACTIVE } " )
2014-06-03 16:21:00 +08:00
if perm && perm . course_module
2014-06-04 09:19:01 +08:00
base_statement << " AND #{ Course . table_name } .id IN (SELECT em.course_id FROM #{ EnabledModule . table_name } em WHERE em.name=' #{ perm . course_module } ') "
2014-05-29 16:35:34 +08:00
end
2014-06-09 14:23:31 +08:00
if options [ :course ]
course_statement = " #{ Course . table_name } .id = #{ options [ :course ] . id } "
course_statement << " OR ( #{ Course . table_name } .lft > #{ options [ :course ] . lft } AND #{ Course . table_name } .rgt < #{ options [ :course ] . rgt } ) " if options [ :with_subcourses ]
base_statement = " ( #{ course_statement } ) AND ( #{ base_statement } ) "
end
2014-05-29 16:35:34 +08:00
if user . admin?
base_statement
else
statement_by_role = { }
unless options [ :member ]
role = user . logged? ? Role . non_member : Role . anonymous
if role . allowed_to? ( permission )
statement_by_role [ role ] = " #{ Course . table_name } .is_public = #{ connection . quoted_true } "
end
end
if user . logged?
2014-06-03 16:21:00 +08:00
user . courses_by_role . each do | role , courses |
if role . allowed_to? ( permission ) && courses . any?
statement_by_role [ role ] = " #{ Course . table_name } .id IN ( #{ courses . collect ( & :id ) . join ( ',' ) } ) "
2014-05-29 16:35:34 +08:00
end
end
end
if statement_by_role . empty?
" 1=0 "
else
if block_given?
statement_by_role . each do | role , statement |
if s = yield ( role , user )
statement_by_role [ role ] = " ( #{ statement } AND ( #{ s } )) "
end
end
end
" (( #{ base_statement } ) AND ( #{ statement_by_role . values . join ( ' OR ' ) } )) "
end
end
end
2014-07-04 11:51:26 +08:00
#项目与课程分离后,很多课程的名称等信息为空,这些数据信息存储在项目表中!!就是数据兼容的问题
2014-07-15 09:53:03 +08:00
#def name
# read_attribute('name') || Project.find_by_identifier(self.extra).try(:name)
#end
2013-09-06 16:40:07 +08:00
end