Blob of app/models/project.rb (raw blob data)

1 class Project < ActiveRecord::Base
2
3 belongs_to :user
4 belongs_to :wiki
5 has_many :comments, :dependent => :destroy
6 has_many :tickets
7 has_many :repositories, :order => "repositories.mainline desc, repositories.created_at asc", :dependent => :destroy
8 has_many :repository_clones, :conditions => ["mainline = ?", false], :class_name => "Repository"
9 has_many :members, :dependent => :destroy
10 has_many :users, :through => :members
11 has_many :articles
12 has_one :mainline_repository, :conditions => ["mainline = ?", true], :class_name => "Repository"
13 has_one :milestone
14
15 URL_FORMAT_RE = /^(http|https|nntp):\/\//.freeze
16 validates_presence_of :title, :user_id, :slug
17 validates_uniqueness_of :slug, :case_sensitive => false
18 validates_format_of :slug, :with => /^[a-z0-9_\-]+$/i,
19 :message => "must match something in the range of [a-z0-9_\-]+"
20 # validates_format_of :home_url, :with => URL_FORMAT_RE,
21 # :if => proc{|record| !record.home_url.blank? },
22 # :message => "Must begin with http(s)"
23
24 before_validation :downcase_slug
25 after_create :create_mainline_repository
26
27 LICENSES = [
28 'Academic Free License v3.0',
29 'MIT License',
30 'BSD License',
31 'Ruby License',
32 'GNU General Public License version 2(GPLv2)',
33 'GNU General Public License version 3 (GPLv3)',
34 'GNU Library Public License (LGPL)',
35 'GNU Affero General Public License (AGPLv3)',
36 'Mozilla Public License 1.0 (MPL)',
37 'Mozilla Public License 1.1 (MPL 1.1)',
38 'Qt Public License (QPL)',
39 'Python License',
40 'zlib/libpng License',
41 'Apache Software License',
42 'Apple Public Source License',
43 'Perl Artistic License',
44 'Microsoft Permissive License (Ms-PL)',
45 'ISC License',
46 'Lisp Lesser License',
47 'Public Domain',
48 'Other Open Source Initiative Approved License',
49 'Other/Proprietary License',
50 'None',
51 ]
52
53 def self.find_by_slug!(slug)
54 find_by_slug(slug) || raise(ActiveRecord::RecordNotFound)
55 end
56
57 def self.find_by_slug(slug, curruser)
58 projects_allowed = Project.list_for_user(curruser.id)
59 find(:first, :conditions => ["status = '#{:active}' AND projects.slug = '#{slug}' AND ( audience = '#{:public}' OR projects.id IN (#{projects_allowed}) )"])
60 end
61
62 def self.per_page() 20 end
63
64 def self.top_tags(limit = 10)
65 tag_counts(:limit => limit, :order => "count desc")
66 end
67
68 def to_param
69 slug
70 end
71
72 def admin?(candidate)
73 candidate == user
74 end
75
76 def can_be_deleted_by?(candidate)
77 (candidate == user) && (repositories.size == 1)
78 end
79
80 # def tag_list=(tag_list)
81 # tag_list.gsub!(",", "")
82 #
83 # super
84 # end
85
86 def home_url=(url)
87 self[:home_url] = clean_url(url)
88 end
89
90 # def mailinglist_url=(url)
91 # self[:mailinglist_url] = clean_url(url)
92 # end
93
94 # def bugtracker_url=(url)
95 # self[:bugtracker_url] = clean_url(url)
96 # end
97
98 def stripped_description
99 description.gsub(/<\/?[^>]*>/, "")
100 # sanitizer = HTML::WhiteListSanitizer.new
101 # sanitizer.sanitize(description, :tags => %w(str), :attributes => %w(class))
102 end
103
104 def to_xml(opts = {})
105 info = Proc.new { |options|
106 builder = options[:builder]
107 builder.owner user.login
108
109 builder.repositories :type => "array" do
110 repositories.each { |repo|
111 builder.repository do
112 builder.id repo.id
113 builder.name repo.name
114 builder.owner repo.user.login
115 end
116 }
117 end
118 }
119 super({:procs => [info]}.merge(opts))
120 end
121
122 protected
123 def create_mainline_repository
124 self.repositories.create!(:user => self.user, :name => "mainline")
125 end
126
127 def downcase_slug
128 slug.downcase! if slug
129 end
130
131 # Try our best to guess the url
132 def clean_url(url)
133 return if url.blank?
134 begin
135 url = "http://#{url}" if URI.parse(url).class == URI::Generic
136 rescue
137 end
138 url
139 end
140
141 def self.public_count (user, curruser)
142 visible_projects = find_by_user(user, curruser)
143 return visible_projects.size
144 end
145
146 #
147 def self.allowed_access (project_id, curruser)
148 projects_allowed = Project.list_for_user(curruser.id)
149 find(:first, :conditions => ["status = '#{:active}' AND projects.id = '" << project_id.to_s << "' AND ( audience = '#{:public}' OR projects.id IN (" << projects_allowed << ") )"])
150 end
151
152 #
153 #FIXME this should maybe show inactive too
154 def self.find_by_user(user, curruser)
155 projects_allowed = Project.list_for_user(curruser.id)
156 projects_available = Project.list_for_user(user)
157 find(:all, :conditions => ["status = '#{:active}' AND projects.id IN (" << projects_available << ") AND ( audience = '#{:public}' OR projects.id IN (" << projects_allowed << ") )"])
158 end
159
160 # returns all allowed projects
161 def self.find_all_projects (curruser)
162 projects_allowed = Project.list_for_user(curruser.id)
163 find(:all, :conditions => ["status = '#{:active}' AND ( audience = '#{:public}' OR id IN (" << projects_allowed << ") )"])
164 end
165
166 def self.find_popular_projects (curruser)
167 projects_allowed = Project.list_for_user(curruser.id)
168 find(:all, :conditions => ["status = '#{:active}' AND ( audience = '#{:public}' OR id IN (" << projects_allowed << ") )"], :limit => 10, :order => "views DESC")
169 end
170
171 # returns all public projects (no private regardless of allowed)
172 def self.find_all_active_public_projects (curruser)
173 projects_allowed = Project.list_for_user(curruser.id)
174 find(:all, :conditions => ["status = '#{:active}' AND ( audience = '#{:public}' AND NOT id IN (" << projects_allowed << ") )"])
175 end
176
177 # returns only allowed, no public
178 def self.find_all_active_member_projects(curruser)
179 find(:all,
180 :joins => "INNER JOIN members ON projects.id = members.project_id AND members.user_id = '#{curruser.id}'",
181 :conditions => ["status = '#{:active}'"]
182 )
183 end
184
185 # takes a list of project_ids e.g. '1','2','3'
186 def self.find_by_list (list, curruser)
187 projects_allowed = Project.list_for_user(curruser.id)
188 find(:all, :conditions => ["status = '#{:active}' AND id IN (" << list << ") AND ( audience = '#{:public}' AND id IN (" << projects_allowed << ") )"])
189 end
190
191 #
192 # Get a list of project_ids of a user is a members of in the format '1','2','3'
193 #
194 def self.list_for_user(user_id)
195 if user_id
196 list = ""
197 projects = Member.find_by_user(user_id)
198 unless projects.empty?
199 start = true
200 for project in projects
201 !start ? list = list << "," : start = false
202 list = list << "'" << project.project_id.to_s << "'"
203 end
204 list
205 else
206 "'1'" # see below
207 end
208 else
209 "'1'" # Project.id 1 is no project (this is a bit of a frig really, without it 2 queries will be needed for all finds)
210 end
211 end
212
213 def self.tab_settings (tab, wiki_slug = "")
214 case tab
215 when PRJ_TAB_SUMMARY
216 title = "Summary"
217 url_suffix = "/"
218 when PRJ_TAB_GIT
219 title = "Git"
220 url_suffix = "/git/"
221 when PRJ_TAB_TEAM
222 title = "Team"
223 url_suffix = "/team/"
224 when PRJ_TAB_WIKI
225 title = "Wiki"
226 url_suffix = "/wikis/" + wiki_slug
227 when PRJ_TAB_TICKETS
228 title = "Tickets"
229 url_suffix = "/tickets/"
230 when PRJ_TAB_ARTICLES
231 title = "Articles"
232 url_suffix = "/articles/"
233 when PRJ_TAB_FORUM
234 title = "Forum"
235 url_suffix = "/forum/"
236 when PRJ_TAB_LOG
237 title = "Log"
238 url_suffix = "/log/"
239 when PRJ_TAB_CONFIG
240 title = "Config"
241 url_suffix = "/config/"
242 end
243 return title, url_suffix
244 end
245
246
247 end