comparison app/models/.svn/text-base/project.rb.svn-base @ 119:8661b858af72

* Update to Redmine trunk rev 4705
author Chris Cannam
date Thu, 13 Jan 2011 14:12:06 +0000
parents 94944d00e43c
children cbce1fd3b1b7
comparison
equal deleted inserted replaced
39:150ceac17a8d 119:8661b858af72
14 # You should have received a copy of the GNU General Public License 14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software 15 # along with this program; if not, write to the Free Software
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 17
18 class Project < ActiveRecord::Base 18 class Project < ActiveRecord::Base
19 include Redmine::SafeAttributes
20
19 # Project statuses 21 # Project statuses
20 STATUS_ACTIVE = 1 22 STATUS_ACTIVE = 1
21 STATUS_ARCHIVED = 9 23 STATUS_ARCHIVED = 9
22 24
23 # Maximum length for project identifiers 25 # Maximum length for project identifiers
62 acts_as_searchable :columns => ['name', 'identifier', 'description'], :project_key => 'id', :permission => nil 64 acts_as_searchable :columns => ['name', 'identifier', 'description'], :project_key => 'id', :permission => nil
63 acts_as_event :title => Proc.new {|o| "#{l(:label_project)}: #{o.name}"}, 65 acts_as_event :title => Proc.new {|o| "#{l(:label_project)}: #{o.name}"},
64 :url => Proc.new {|o| {:controller => 'projects', :action => 'show', :id => o}}, 66 :url => Proc.new {|o| {:controller => 'projects', :action => 'show', :id => o}},
65 :author => nil 67 :author => nil
66 68
67 attr_protected :status, :enabled_module_names 69 attr_protected :status
68 70
69 validates_presence_of :name, :identifier 71 validates_presence_of :name, :identifier
70 validates_uniqueness_of :identifier 72 validates_uniqueness_of :identifier
71 validates_associated :repository, :wiki 73 validates_associated :repository, :wiki
72 validates_length_of :name, :maximum => 255 74 validates_length_of :name, :maximum => 255
81 83
82 named_scope :has_module, lambda { |mod| { :conditions => ["#{Project.table_name}.id IN (SELECT em.project_id FROM #{EnabledModule.table_name} em WHERE em.name=?)", mod.to_s] } } 84 named_scope :has_module, lambda { |mod| { :conditions => ["#{Project.table_name}.id IN (SELECT em.project_id FROM #{EnabledModule.table_name} em WHERE em.name=?)", mod.to_s] } }
83 named_scope :active, { :conditions => "#{Project.table_name}.status = #{STATUS_ACTIVE}"} 85 named_scope :active, { :conditions => "#{Project.table_name}.status = #{STATUS_ACTIVE}"}
84 named_scope :all_public, { :conditions => { :is_public => true } } 86 named_scope :all_public, { :conditions => { :is_public => true } }
85 named_scope :visible, lambda { { :conditions => Project.visible_by(User.current) } } 87 named_scope :visible, lambda { { :conditions => Project.visible_by(User.current) } }
88
89 def initialize(attributes = nil)
90 super
91
92 initialized = (attributes || {}).stringify_keys
93 if !initialized.key?('identifier') && Setting.sequential_project_identifiers?
94 self.identifier = Project.next_identifier
95 end
96 if !initialized.key?('is_public')
97 self.is_public = Setting.default_projects_public?
98 end
99 if !initialized.key?('enabled_module_names')
100 self.enabled_module_names = Setting.default_projects_modules
101 end
102 if !initialized.key?('trackers') && !initialized.key?('tracker_ids')
103 self.trackers = Tracker.all
104 end
105 end
86 106
87 def identifier=(identifier) 107 def identifier=(identifier)
88 super unless identifier_frozen? 108 super unless identifier_frozen?
89 end 109 end
90 110
429 s 449 s
430 end 450 end
431 451
432 # The earliest start date of a project, based on it's issues and versions 452 # The earliest start date of a project, based on it's issues and versions
433 def start_date 453 def start_date
434 if module_enabled?(:issue_tracking) 454 [
435 [ 455 issues.minimum('start_date'),
436 issues.minimum('start_date'), 456 shared_versions.collect(&:effective_date),
437 shared_versions.collect(&:effective_date), 457 shared_versions.collect(&:start_date)
438 shared_versions.collect {|v| v.fixed_issues.minimum('start_date')} 458 ].flatten.compact.min
439 ].flatten.compact.min
440 end
441 end 459 end
442 460
443 # The latest due date of an issue or version 461 # The latest due date of an issue or version
444 def due_date 462 def due_date
445 if module_enabled?(:issue_tracking) 463 [
446 [ 464 issues.maximum('due_date'),
447 issues.maximum('due_date'), 465 shared_versions.collect(&:effective_date),
448 shared_versions.collect(&:effective_date), 466 shared_versions.collect {|v| v.fixed_issues.maximum('due_date')}
449 shared_versions.collect {|v| v.fixed_issues.maximum('due_date')} 467 ].flatten.compact.max
450 ].flatten.compact.max
451 end
452 end 468 end
453 469
454 def overdue? 470 def overdue?
455 active? && !due_date.nil? && (due_date < Date.today) 471 active? && !due_date.nil? && (due_date < Date.today)
456 end 472 end
490 enabled_modules.detect {|m| m.name == module_name} 506 enabled_modules.detect {|m| m.name == module_name}
491 end 507 end
492 508
493 def enabled_module_names=(module_names) 509 def enabled_module_names=(module_names)
494 if module_names && module_names.is_a?(Array) 510 if module_names && module_names.is_a?(Array)
495 module_names = module_names.collect(&:to_s) 511 module_names = module_names.collect(&:to_s).reject(&:blank?)
496 # remove disabled modules 512 # remove disabled modules
497 enabled_modules.each {|mod| mod.destroy unless module_names.include?(mod.name)} 513 enabled_modules.each {|mod| mod.destroy unless module_names.include?(mod.name)}
498 # add new modules 514 # add new modules
499 module_names.reject {|name| module_enabled?(name)}.each {|name| enabled_modules << EnabledModule.new(:name => name)} 515 module_names.reject {|name| module_enabled?(name)}.each {|name| enabled_modules << EnabledModule.new(:name => name)}
500 else 516 else
501 enabled_modules.clear 517 enabled_modules.clear
502 end 518 end
503 end 519 end
504 520
521 # Returns an array of the enabled modules names
522 def enabled_module_names
523 enabled_modules.collect(&:name)
524 end
525
526 safe_attributes 'name',
527 'description',
528 'homepage',
529 'is_public',
530 'identifier',
531 'custom_field_values',
532 'custom_fields',
533 'tracker_ids',
534 'issue_custom_field_ids'
535
536 safe_attributes 'enabled_module_names',
537 :if => lambda {|project, user| project.new_record? || user.allowed_to?(:select_project_modules, project) }
538
505 # Returns an array of projects that are in this project's hierarchy 539 # Returns an array of projects that are in this project's hierarchy
506 # 540 #
507 # Example: parents, children, siblings 541 # Example: parents, children, siblings
508 def hierarchy 542 def hierarchy
509 parents = project.self_and_ancestors || [] 543 parents = project.self_and_ancestors || []
667 new_issue.parent_issue_id = copied_parent.id 701 new_issue.parent_issue_id = copied_parent.id
668 end 702 end
669 end 703 end
670 704
671 self.issues << new_issue 705 self.issues << new_issue
672 issues_map[issue.id] = new_issue 706 if new_issue.new_record?
707 logger.info "Project#copy_issues: issue ##{issue.id} could not be copied: #{new_issue.errors.full_messages}" if logger && logger.info
708 else
709 issues_map[issue.id] = new_issue unless new_issue.new_record?
710 end
673 end 711 end
674 712
675 # Relations after in case issues related each other 713 # Relations after in case issues related each other
676 project.issues.each do |issue| 714 project.issues.each do |issue|
677 new_issue = issues_map[issue.id] 715 new_issue = issues_map[issue.id]
716 unless new_issue
717 # Issue was not copied
718 next
719 end
678 720
679 # Relations 721 # Relations
680 issue.relations_from.each do |source_relation| 722 issue.relations_from.each do |source_relation|
681 new_issue_relation = IssueRelation.new 723 new_issue_relation = IssueRelation.new
682 new_issue_relation.attributes = source_relation.attributes.dup.except("id", "issue_from_id", "issue_to_id") 724 new_issue_relation.attributes = source_relation.attributes.dup.except("id", "issue_from_id", "issue_to_id")
699 end 741 end
700 end 742 end
701 743
702 # Copies members from +project+ 744 # Copies members from +project+
703 def copy_members(project) 745 def copy_members(project)
704 project.memberships.each do |member| 746 # Copy users first, then groups to handle members with inherited and given roles
747 members_to_copy = []
748 members_to_copy += project.memberships.select {|m| m.principal.is_a?(User)}
749 members_to_copy += project.memberships.select {|m| !m.principal.is_a?(User)}
750
751 members_to_copy.each do |member|
705 new_member = Member.new 752 new_member = Member.new
706 new_member.attributes = member.attributes.dup.except("id", "project_id", "created_on") 753 new_member.attributes = member.attributes.dup.except("id", "project_id", "created_on")
707 # only copy non inherited roles 754 # only copy non inherited roles
708 # inherited roles will be added when copying the group membership 755 # inherited roles will be added when copying the group membership
709 role_ids = member.member_roles.reject(&:inherited?).collect(&:role_id) 756 role_ids = member.member_roles.reject(&:inherited?).collect(&:role_id)