223 lines
7.4 KiB
Ruby
223 lines
7.4 KiB
Ruby
class Course < ActiveRecord::Base
|
||
include Redmine::SafeAttributes
|
||
|
||
STATUS_ACTIVE = 1
|
||
STATUS_CLOSED = 5
|
||
STATUS_ARCHIVED = 9
|
||
|
||
attr_accessible :code, :extra, :name, :state, :tea_id, :time , :location, :state, :term, :password
|
||
belongs_to :project, :class_name => 'Course', :foreign_key => :extra, primary_key: :identifier
|
||
belongs_to :teacher, :class_name => 'User', :foreign_key => :tea_id # 定义一个方法teacher,该方法通过tea_id来调用User表
|
||
belongs_to :school, :class_name => 'School', :foreign_key => :school_id #定义一个方法school,该方法通过school_id来调用School表
|
||
has_many :bid
|
||
|
||
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})"
|
||
has_many :principals, :through => :member_principals, :source => :principal
|
||
has_many :users, :through => :members
|
||
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
|
||
has_many :student, :through => :students_for_courses, :source => :user
|
||
has_many :course_infos, :class_name => 'CourseInfos',:dependent => :destroy
|
||
has_many :enabled_modules, :dependent => :delete_all
|
||
has_many :boards, :dependent => :destroy, :order => "position ASC"
|
||
|
||
acts_as_taggable
|
||
#acts_as_nested_set :order => 'name', :dependent => :destroy
|
||
acts_as_attachable :view_permission => :view_files,
|
||
:delete_permission => :manage_files
|
||
|
||
validates_presence_of :password, :term
|
||
validates_format_of :class_period, :message => "class period can only digital!", :with =>/^[1-9]\d*$/
|
||
|
||
after_save :create_board_sync
|
||
before_destroy :delete_all_members
|
||
|
||
safe_attributes 'extra',
|
||
'time',
|
||
'name',
|
||
'extra',
|
||
'code',
|
||
'location',
|
||
'tea_id',
|
||
'password',
|
||
'term',
|
||
'password',
|
||
'description'
|
||
|
||
acts_as_customizable
|
||
|
||
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))
|
||
}
|
||
|
||
def visible?(user=User.current)
|
||
user.allowed_to?(:view_course, self)
|
||
end
|
||
|
||
def extra_frozen?
|
||
errors[:extra].blank? && !(new_record? || extra.blank?)
|
||
end
|
||
|
||
def archived?
|
||
self.status == STATUS_ARCHIVED
|
||
end
|
||
|
||
def self.visible_condition(user, options={})
|
||
allowed_to_condition(user, :view_course, options)
|
||
end
|
||
|
||
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
|
||
|
||
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
|
||
|
||
def allowed_actions
|
||
@actions_allowed ||= allowed_permissions.inject([]) { |actions, permission| actions += Redmine::AccessControl.allowed_actions(permission) }.flatten
|
||
end
|
||
|
||
# 返回用户组可以访问的课程
|
||
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
|
||
|
||
#自定义验证
|
||
def validate
|
||
if !class_period.match([0-9])
|
||
errors.add_to_base("class period can only digital")
|
||
end
|
||
end
|
||
|
||
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
|
||
|
||
def delete_all_members
|
||
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
|
||
|
||
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
|
||
|
||
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
|
||
|
||
def self.allowed_to_condition(user, permission, options={})
|
||
perm = Redmine::AccessControl.permission(permission)
|
||
base_statement = (perm && perm.read? ? "#{Course.table_name}.status <> #{Course::STATUS_ARCHIVED}" : "#{Course.table_name}.status = #{Course::STATUS_ACTIVE}")
|
||
if perm && perm.course_module
|
||
base_statement << " AND #{Course.table_name}.id IN (SELECT em.course_id FROM #{EnabledModule.table_name} em WHERE em.name='#{perm.course_module}')"
|
||
end
|
||
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
|
||
|
||
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?
|
||
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(',')})"
|
||
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
|
||
|
||
end
|