Mercurial > hg > soundsoftware-site
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) |