##// END OF EJS Templates
Backported r2429, r2430, r248 to r2491 and r2522 from trunk (request and controller objects added to the hooks by default.)....
Backported r2429, r2430, r248 to r2491 and r2522 from trunk (request and controller objects added to the hooks by default.). git-svn-id: svn+ssh://rubyforge.org/var/svn/redmine/branches/0.8-stable@2558 e93f8b46-1217-0410-a6f0-8f06a7374b81

File last commit:

r2228:49b6f9e4dd41
r2490:36b5d4f6af04
Show More
project.rb
276 lines | 10.6 KiB | text/x-ruby | RubyLexer
Jean-Philippe Lang
added svn:eol-style native property on /app files...
r330 # redMine - project management software
# Copyright (C) 2006 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 Project < ActiveRecord::Base
Jean-Philippe Lang
Added the ability to archive projects:...
r546 # Project statuses
STATUS_ACTIVE = 1
STATUS_ARCHIVED = 9
Jean-Philippe Lang
Merged Rails 2.0 compatibility changes....
r962 has_many :members, :include => :user, :conditions => "#{User.table_name}.status=#{User::STATUS_ACTIVE}"
Jean-Philippe Lang
added svn:eol-style native property on /app files...
r330 has_many :users, :through => :members
Jean-Philippe Lang
Added project module concept....
r714 has_many :enabled_modules, :dependent => :delete_all
Jean-Philippe Lang
Added per-project tracker selection. Trackers can be selected on project settings....
r907 has_and_belongs_to_many :trackers, :order => "#{Tracker.table_name}.position"
Jean-Philippe Lang
fixed #9308 table_name pre/suffix support...
r334 has_many :issues, :dependent => :destroy, :order => "#{Issue.table_name}.created_on DESC", :include => [:status, :tracker]
Jean-Philippe Lang
Activity view improvements:...
r640 has_many :issue_changes, :through => :issues, :source => :journals
Jean-Philippe Lang
Fixed an error when trying to delete a project (versions/issues dependency)...
r571 has_many :versions, :dependent => :destroy, :order => "#{Version.table_name}.effective_date DESC, #{Version.table_name}.name DESC"
Jean-Philippe Lang
Simple time tracking functionality added. Time can be logged at issue or project level....
r365 has_many :time_entries, :dependent => :delete_all
Jean-Philippe Lang
added svn:eol-style native property on /app files...
r330 has_many :queries, :dependent => :delete_all
has_many :documents, :dependent => :destroy
has_many :news, :dependent => :delete_all, :include => :author
Jean-Philippe Lang
fixed #9308 table_name pre/suffix support...
r334 has_many :issue_categories, :dependent => :delete_all, :order => "#{IssueCategory.table_name}.name"
Jean-Philippe Lang
Fixed: Boards are not deleted when project is deleted (closes #963)....
r1301 has_many :boards, :dependent => :destroy, :order => "position ASC"
Jean-Philippe Lang
added svn:eol-style native property on /app files...
r330 has_one :repository, :dependent => :destroy
Jean-Philippe Lang
Improved Redmine links:...
r703 has_many :changesets, :through => :repository
Jean-Philippe Lang
added svn:eol-style native property on /app files...
r330 has_one :wiki, :dependent => :destroy
Jean-Philippe Lang
Custom fields can now be reordered....
r888 # Custom field for the project issues
Jean-Philippe Lang
Custom fields refactoring: most of code moved from controllers to models (using new module ActsAsCustomizable)....
r1578 has_and_belongs_to_many :issue_custom_fields,
Jean-Philippe Lang
Custom fields can now be reordered....
r888 :class_name => 'IssueCustomField',
:order => "#{CustomField.table_name}.position",
:join_table => "#{table_name_prefix}custom_fields_projects#{table_name_suffix}",
:association_foreign_key => 'custom_field_id'
Jean-Philippe Lang
added svn:eol-style native property on /app files...
r330 acts_as_tree :order => "name", :counter_cache => true
Jean-Philippe Lang
Merged r2116, r2117 and r2187 from trunk....
r2215 acts_as_attachable :view_permission => :view_files,
:delete_permission => :manage_files
Jean-Philippe Lang
Search engines now supports pagination....
r755
Jean-Philippe Lang
Custom fields refactoring: most of code moved from controllers to models (using new module ActsAsCustomizable)....
r1578 acts_as_customizable
Jean-Philippe Lang
Ability to search all projects or the projects the user belongs to (#791)....
r1420 acts_as_searchable :columns => ['name', 'description'], :project_key => 'id', :permission => nil
Jean-Philippe Lang
Search engines now supports pagination....
r755 acts_as_event :title => Proc.new {|o| "#{l(:label_project)}: #{o.name}"},
Jean-Philippe Lang
Fixed: no :author method error on projects atom feed (#1623)....
r1639 :url => Proc.new {|o| {:controller => 'projects', :action => 'show', :id => o.id}},
:author => nil
Jean-Philippe Lang
Search engines now supports pagination....
r755
Jean-Philippe Lang
Added project module concept....
r714 attr_protected :status, :enabled_module_names
Jean-Philippe Lang
Added the ability to archive projects:...
r546
Jean-Philippe Lang
Unlimited and optional project description. The project list will show truncated descriptions only (the first fews lines)....
r1074 validates_presence_of :name, :identifier
Jean-Philippe Lang
Initial commit for svn repository management and access control:...
r393 validates_uniqueness_of :name, :identifier
Jean-Philippe Lang
added svn:eol-style native property on /app files...
r330 validates_associated :repository, :wiki
Jean-Philippe Lang
Added some attributes length validations....
r397 validates_length_of :name, :maximum => 30
Jean-Philippe Lang
Change projects homepage limit to 255 chars (#663, #1095)....
r1443 validates_length_of :homepage, :maximum => 255
Jean-Philippe Lang
Merged r2218 to r2225 from trunk....
r2228 validates_length_of :identifier, :in => 2..20
Jean-Philippe Lang
Initial commit for svn repository management and access control:...
r393 validates_format_of :identifier, :with => /^[a-z0-9\-]*$/
Jean-Philippe Lang
Merged Rails 2.0 compatibility changes....
r962 before_destroy :delete_all_members
Jean-Philippe Lang
Merged nbc branch @ r1812 (commit access permission and reposman improvements)....
r1812
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] } }
Jean-Philippe Lang
Merged Rails 2.0 compatibility changes....
r962
Jean-Philippe Lang
Initial commit for svn repository management and access control:...
r393 def identifier=(identifier)
super unless identifier_frozen?
end
def identifier_frozen?
errors[:identifier].nil? && !(new_record? || identifier.blank?)
end
Jean-Philippe Lang
Added the ability to include subprojects issues on calendar & gantt (options box)...
r395 def issues_with_subprojects(include_subprojects=false)
conditions = nil
Jean-Philippe Lang
Fixed: Calendar and Gantt show private subprojects even if current user is not a member of them (#1217)....
r1416 if include_subprojects
ids = [id] + child_ids
conditions = ["#{Project.table_name}.id IN (#{ids.join(',')}) AND #{Project.visible_by}"]
Jean-Philippe Lang
Added the ability to include subprojects issues on calendar & gantt (options box)...
r395 end
Jean-Philippe Lang
Include subprojects versions on calendar and gantt (#1116)....
r1349 conditions ||= ["#{Project.table_name}.id = ?", id]
Jean-Philippe Lang
Fixed: calendar and gantt broken with Rails 2.0...
r969 # Quick and dirty fix for Rails 2 compatibility
Issue.send(:with_scope, :find => { :conditions => conditions }) do
Jean-Philippe Lang
Include subprojects versions on calendar and gantt (#1116)....
r1349 Version.send(:with_scope, :find => { :conditions => conditions }) do
yield
end
Jean-Philippe Lang
Added the ability to include subprojects issues on calendar & gantt (options box)...
r395 end
end
Jean-Philippe Lang
Added issues status changes on the activity view (initial patch by Cyril Mougel)....
r879
Jean-Philippe Lang
added svn:eol-style native property on /app files...
r330 # returns latest created projects
# non public projects will be returned only if user is a member of those
def self.latest(user=nil, count=5)
Jean-Philippe Lang
fixed #9308 table_name pre/suffix support...
r334 find(:all, :limit => count, :conditions => visible_by(user), :order => "created_on DESC")
Jean-Philippe Lang
added svn:eol-style native property on /app files...
r330 end
def self.visible_by(user=nil)
Jean-Philippe Lang
Fixed: Calendar and Gantt show private subprojects even if current user is not a member of them (#1217)....
r1416 user ||= User.current
Jean-Philippe Lang
Projects menu item now shows the list of public projects and projects for which the user is a member (marked with a star)....
r457 if user && user.admin?
Jean-Philippe Lang
Added a cross-project issue list. It displays the issues of all the projects visible by the user....
r673 return "#{Project.table_name}.status=#{Project::STATUS_ACTIVE}"
Jean-Philippe Lang
Fixed an error on welcome screen for users with no membership...
r566 elsif user && user.memberships.any?
Jean-Philippe Lang
Added a cross-project issue list. It displays the issues of all the projects visible by the user....
r673 return "#{Project.table_name}.status=#{Project::STATUS_ACTIVE} AND (#{Project.table_name}.is_public = #{connection.quoted_true} or #{Project.table_name}.id IN (#{user.memberships.collect{|m| m.project_id}.join(',')}))"
Jean-Philippe Lang
added svn:eol-style native property on /app files...
r330 else
Jean-Philippe Lang
Added a cross-project issue list. It displays the issues of all the projects visible by the user....
r673 return "#{Project.table_name}.status=#{Project::STATUS_ACTIVE} AND #{Project.table_name}.is_public = #{connection.quoted_true}"
Jean-Philippe Lang
Added the ability to archive projects:...
r546 end
end
Jean-Philippe Lang
Activity enhancements:...
r1213 def self.allowed_to_condition(user, permission, options={})
Jean-Philippe Lang
Propagates time tracking to the parent project (closes #433). Time report enhancements....
r1162 statements = []
Jean-Philippe Lang
Activity enhancements:...
r1213 base_statement = "#{Project.table_name}.status=#{Project::STATUS_ACTIVE}"
Jean-Philippe Lang
Fixed: cross-project issue list should not show issues of projects for which the issue tracking module was disabled....
r1905 if perm = Redmine::AccessControl.permission(permission)
unless perm.project_module.nil?
# If the permission belongs to a project module, make sure the module is enabled
base_statement << " AND EXISTS (SELECT em.id FROM #{EnabledModule.table_name} em WHERE em.name='#{perm.project_module}' AND em.project_id=#{Project.table_name}.id)"
end
end
Jean-Philippe Lang
Activity enhancements:...
r1213 if options[:project]
project_statement = "#{Project.table_name}.id = #{options[:project].id}"
project_statement << " OR #{Project.table_name}.parent_id = #{options[:project].id}" if options[:with_subprojects]
base_statement = "(#{project_statement}) AND (#{base_statement})"
end
Jean-Philippe Lang
Propagates time tracking to the parent project (closes #433). Time report enhancements....
r1162 if user.admin?
# no restriction
else
Jean-Philippe Lang
Activity enhancements:...
r1213 statements << "1=0"
Jean-Philippe Lang
Fixed: search engine may reveal private projects (#1613)....
r1635 if user.logged?
statements << "#{Project.table_name}.is_public = #{connection.quoted_true}" if Role.non_member.allowed_to?(permission)
allowed_project_ids = user.memberships.select {|m| m.role.allowed_to?(permission)}.collect {|m| m.project_id}
statements << "#{Project.table_name}.id IN (#{allowed_project_ids.join(',')})" if allowed_project_ids.any?
elsif Role.anonymous.allowed_to?(permission)
# anonymous user allowed on public project
statements << "#{Project.table_name}.is_public = #{connection.quoted_true}"
else
# anonymous user is not authorized
end
Jean-Philippe Lang
Propagates time tracking to the parent project (closes #433). Time report enhancements....
r1162 end
Jean-Philippe Lang
Activity enhancements:...
r1213 statements.empty? ? base_statement : "((#{base_statement}) AND (#{statements.join(' OR ')}))"
Jean-Philippe Lang
Propagates time tracking to the parent project (closes #433). Time report enhancements....
r1162 end
Jean-Philippe Lang
If 'Display subprojects issues on main projects' is set to false:...
r1283 def project_condition(with_subprojects)
cond = "#{Project.table_name}.id = #{id}"
cond = "(#{cond} OR #{Project.table_name}.parent_id = #{id})" if with_subprojects
cond
end
Jean-Philippe Lang
Project identifier is now used in URLs (instead of project id)....
r994 def self.find(*args)
if args.first && args.first.is_a?(String) && !args.first.match(/^\d*$/)
project = find_by_identifier(*args)
raise ActiveRecord::RecordNotFound, "Couldn't find Project with identifier=#{args.first}" if project.nil?
project
else
super
end
end
def to_param
Jean-Philippe Lang
Fixed: can not access old projects created with a numeric identifier (#1322)....
r1459 # id is used for projects with a numeric identifier (compatibility)
@to_param ||= (identifier.to_s =~ %r{^\d*$} ? id : identifier)
Jean-Philippe Lang
Project identifier is now used in URLs (instead of project id)....
r994 end
Jean-Philippe Lang
Added the ability to archive projects:...
r546 def active?
self.status == STATUS_ACTIVE
end
def archive
# Archive subprojects if any
children.each do |subproject|
subproject.archive
Jean-Philippe Lang
added svn:eol-style native property on /app files...
r330 end
Jean-Philippe Lang
Added the ability to archive projects:...
r546 update_attribute :status, STATUS_ARCHIVED
end
def unarchive
return false if parent && !parent.active?
update_attribute :status, STATUS_ACTIVE
end
def active_children
children.select {|child| child.active?}
Jean-Philippe Lang
added svn:eol-style native property on /app files...
r330 end
Jean-Philippe Lang
On the calendar, the gantt and in the Tracker filter on the issue list, only active trackers of the project (and its sub projects) can be selected....
r1057 # Returns an array of the trackers used by the project and its sub projects
def rolled_up_trackers
@rolled_up_trackers ||=
Tracker.find(:all, :include => :projects,
:select => "DISTINCT #{Tracker.table_name}.*",
:conditions => ["#{Project.table_name}.id = ? OR #{Project.table_name}.parent_id = ?", id, id],
:order => "#{Tracker.table_name}.position")
end
Jean-Philippe Lang
Merged Rails 2.0 compatibility changes....
r962 # Deletes all project's members
def delete_all_members
Member.delete_all(['project_id = ?', id])
end
Jean-Philippe Lang
Added 'Bulk edit' functionality....
r806 # Users issues can be assigned to
def assignable_users
Jean-Philippe Lang
'Assigned to' drop down list is now sorted by user's lastname....
r926 members.select {|m| m.role.assignable?}.collect {|m| m.user}.sort
Jean-Philippe Lang
Added 'Bulk edit' functionality....
r806 end
Jean-Philippe Lang
More flexible mail notifications settings at user level. A user has now 3 options:...
r842 # Returns the mail adresses of users that should be always notified on project events
def recipients
members.select {|m| m.mail_notification? || m.user.mail_notification?}.collect {|m| m.user.mail}
end
Jean-Philippe Lang
added svn:eol-style native property on /app files...
r330 # Returns an array of all custom fields enabled for project issues
# (explictly associated custom fields and custom fields enabled for all projects)
Jean-Philippe Lang
Custom fields refactoring: most of code moved from controllers to models (using new module ActsAsCustomizable)....
r1578 def all_issue_custom_fields
Jean-Philippe Lang
Fixes custom fields display order at several places (#1768)....
r1730 @all_issue_custom_fields ||= (IssueCustomField.for_all + issue_custom_fields).uniq.sort
Jean-Philippe Lang
added svn:eol-style native property on /app files...
r330 end
Jean-Philippe Lang
Subprojects are now grouped by projects in the 'Projects' top navigation drop-down menu....
r692
Jean-Philippe Lang
Ability to search all projects or the projects the user belongs to (#791)....
r1420 def project
self
end
Jean-Philippe Lang
Subprojects are now grouped by projects in the 'Projects' top navigation drop-down menu....
r692 def <=>(project)
Jean-Philippe Lang
* Added time zone support: users can select their time zone on their account view....
r904 name.downcase <=> project.name.downcase
Jean-Philippe Lang
Subprojects are now grouped by projects in the 'Projects' top navigation drop-down menu....
r692 end
Jean-Philippe Lang
Added project module concept....
r714
Jean-Philippe Lang
Unlimited and optional project description. The project list will show truncated descriptions only (the first fews lines)....
r1074 def to_s
name
end
# Returns a short description of the projects (first lines)
def short_description(length = 255)
description.gsub(/^(.{#{length}}[^\n]*).*$/m, '\1').strip if description
end
Jean-Philippe Lang
Added project module concept....
r714 def allows_to?(action)
if action.is_a? Hash
allowed_actions.include? "#{action[:controller]}/#{action[:action]}"
else
allowed_permissions.include? action
end
end
def module_enabled?(module_name)
module_name = module_name.to_s
enabled_modules.detect {|m| m.name == module_name}
end
def enabled_module_names=(module_names)
enabled_modules.clear
module_names = [] unless module_names && module_names.is_a?(Array)
module_names.each do |name|
enabled_modules << EnabledModule.new(:name => name.to_s)
end
end
Jean-Philippe Lang
Adds an option to generate sequential project identifiers....
r1776
# Returns an auto-generated project identifier based on the last identifier used
def self.next_identifier
p = Project.find(:first, :order => 'created_on DESC')
p.nil? ? nil : p.identifier.to_s.succ
end
Jean-Philippe Lang
added svn:eol-style native property on /app files...
r330
protected
def validate
errors.add(parent_id, " must be a root project") if parent and parent.parent
errors.add_to_base("A project with subprojects can't be a subproject") if parent and children.size > 0
Jean-Philippe Lang
Do not authorize project identifier with numbers only (would be interpreted as the project id in urls)....
r1094 errors.add(:identifier, :activerecord_error_invalid) if !identifier.blank? && identifier.match(/^\d*$/)
Jean-Philippe Lang
v0.2.0...
r5 end
Jean-Philippe Lang
Added project module concept....
r714
private
def allowed_permissions
@allowed_permissions ||= begin
module_names = enabled_modules.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
Jean-Philippe Lang
Initial commit...
r2 end