##// END OF EJS Templates
Fixed: private subprojects are listed on the issues view (#1217)....
Fixed: private subprojects are listed on the issues view (#1217). git-svn-id: http://redmine.rubyforge.org/svn/trunk@1432 e93f8b46-1217-0410-a6f0-8f06a7374b81

File last commit:

r1416:7ee38a95a005
r1417:9e225cc63ff8
Show More
project.rb
257 lines | 9.7 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
has_many :custom_values, :dependent => :delete_all, :as => :customized
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
has_and_belongs_to_many :custom_fields,
: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
Search engines now supports pagination....
r755
acts_as_searchable :columns => ['name', 'description'], :project_key => 'id'
acts_as_event :title => Proc.new {|o| "#{l(:label_project)}: #{o.name}"},
:url => Proc.new {|o| {:controller => 'projects', :action => 'show', :id => o.id}}
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 :custom_values, :on => :update
validates_associated :repository, :wiki
Jean-Philippe Lang
Added some attributes length validations....
r397 validates_length_of :name, :maximum => 30
Jean-Philippe Lang
Fixed: project homepage length validation inconsistent with database field....
r734 validates_length_of :homepage, :maximum => 60
Jean-Philippe Lang
Project name format limitation removed (name can now contain any character)....
r936 validates_length_of :identifier, :in => 3..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
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}"
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
elsif 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}
Jean-Philippe Lang
Fixed #759: Can not view a project without View time entries permission (broken by r1176)....
r1170 statements << "#{Project.table_name}.id IN (#{allowed_project_ids.join(',')})" if allowed_project_ids.any?
Jean-Philippe Lang
Activity enhancements:...
r1213 elsif Role.anonymous.allowed_to?(permission)
# anonymous user allowed on public project
statements << "#{Project.table_name}.is_public = #{connection.quoted_true}"
Jean-Philippe Lang
Propagates time tracking to the parent project (closes #433). Time report enhancements....
r1162 else
Jean-Philippe Lang
Activity enhancements:...
r1213 # anonymous user is not authorized
statements << "1=0"
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
identifier
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)
def custom_fields_for_issues(tracker)
Jean-Philippe Lang
fixed #9308 table_name pre/suffix support...
r334 all_custom_fields.select {|c| tracker.custom_fields.include? c }
Jean-Philippe Lang
added svn:eol-style native property on /app files...
r330 end
def all_custom_fields
Jean-Philippe Lang
fixed #9308 table_name pre/suffix support...
r334 @all_custom_fields ||= (IssueCustomField.for_all + custom_fields).uniq
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
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
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