Project

General

Profile

« Previous | Next » 

Revision 9528

Merged rails-3.2 branch.

View differences:

trunk/.gitignore
5 5
/config/database.yml
6 6
/config/email.yml
7 7
/config/initializers/session_store.rb
8
/config/initializers/secret_token.rb
8 9
/coverage
9 10
/db/*.db
10 11
/db/*.sqlite3
trunk/.hgignore
7 7
config/database.yml
8 8
config/email.yml
9 9
config/initializers/session_store.rb
10
config/initializers/secret_token.rb
10 11
coverage
11 12
db/*.db
12 13
db/*.sqlite3
trunk/Gemfile
1
source :rubygems
1
source 'http://rubygems.org'
2 2

  
3
gem "rails", "2.3.14"
4
gem "i18n", "~> 0.4.2"
3
gem 'rails', '3.2.3'
4
gem 'prototype-rails', '3.2.1'
5
gem "i18n", "~> 0.6.0"
5 6
gem "coderay", "~> 1.0.6"
6 7
gem "fastercsv", "~> 1.5.0", :platforms => [:mri_18, :mingw_18, :jruby]
7 8
gem "tzinfo", "~> 0.3.31"
9
gem "builder"
8 10

  
9 11
# Optional gem for LDAP authentication
10 12
group :ldap do
......
14 16
# Optional gem for OpenID authentication
15 17
group :openid do
16 18
  gem "ruby-openid", "~> 2.1.4", :require => "openid"
19
  gem "rack-openid"
17 20
end
18 21

  
19 22
# Optional gem for exporting the gantt to a PNG file, not supported with jruby
......
45 48

  
46 49
platforms :mri_19, :mingw_19 do
47 50
  group :mysql do
48
    gem "mysql2", "~> 0.2.7"
51
    gem "mysql2", "~> 0.3.11"
49 52
  end
50 53
end
51 54

  
......
69 72
  gem "rdoc", ">= 2.4.2"
70 73
end
71 74

  
75

  
72 76
group :test do
73
  gem "shoulda", "~> 2.10.3"
77
  gem "shoulda"
74 78
  gem "mocha"
75 79
end
76 80

  
trunk/Rakefile
1
#!/usr/bin/env rake
1 2
# Add your own tasks in files placed in lib/tasks ending in .rake,
2
# for example lib/tasks/switchtower.rake, and they will automatically be available to Rake.
3
# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
3 4

  
4
require(File.join(File.dirname(__FILE__), 'config', 'boot'))
5
require File.expand_path('../config/application', __FILE__)
5 6

  
6
require 'rake'
7
require 'rake/testtask'
8

  
9
begin
10
  require 'rdoc/task'
11
rescue LoadError
12
  # RDoc is not available
13
end
14

  
15
require 'tasks/rails'
7
RedmineApp::Application.load_tasks
trunk/app/controllers/application_controller.rb
22 22

  
23 23
class ApplicationController < ActionController::Base
24 24
  include Redmine::I18n
25
  
26
  class_attribute :accept_api_auth_actions
27
  class_attribute :accept_rss_auth_actions
28
  class_attribute :model_object
25 29

  
26 30
  layout 'base'
27
  exempt_from_layout 'builder', 'rsb'
28 31

  
29 32
  protect_from_forgery
30 33
  def handle_unverified_request
......
68 71
  end
69 72

  
70 73
  before_filter :user_setup, :check_if_login_required, :set_localization
71
  filter_parameter_logging :password
72 74

  
73 75
  rescue_from ActionController::InvalidAuthenticityToken, :with => :invalid_authenticity_token
74 76
  rescue_from ::Unauthorized, :with => :deny_access
......
77 79
  include Redmine::MenuManager::MenuController
78 80
  helper Redmine::MenuManager::MenuHelper
79 81

  
80
  Redmine::Scm::Base.all.each do |scm|
81
    require_dependency "repository/#{scm.underscore}"
82
  end
83

  
84 82
  def user_setup
85 83
    # Check the settings cache for each request
86 84
    Setting.check_cache
......
242 240
  end
243 241

  
244 242
  def find_model_object
245
    model = self.class.read_inheritable_attribute('model_object')
243
    model = self.class.model_object
246 244
    if model
247 245
      @object = model.find(params[:id])
248 246
      self.instance_variable_set('@' + controller_name.singularize, @object) if @object
......
252 250
  end
253 251

  
254 252
  def self.model_object(model)
255
    write_inheritable_attribute('model_object', model)
253
    self.model_object = model
256 254
  end
257 255

  
258 256
  # Filter for bulk issue operations
......
388 386

  
389 387
  def self.accept_rss_auth(*actions)
390 388
    if actions.any?
391
      write_inheritable_attribute('accept_rss_auth_actions', actions)
389
      self.accept_rss_auth_actions = actions
392 390
    else
393
      read_inheritable_attribute('accept_rss_auth_actions') || []
391
      self.accept_rss_auth_actions || []
394 392
    end
395 393
  end
396 394

  
......
400 398

  
401 399
  def self.accept_api_auth(*actions)
402 400
    if actions.any?
403
      write_inheritable_attribute('accept_api_auth_actions', actions)
401
      self.accept_api_auth_actions = actions
404 402
    else
405
      read_inheritable_attribute('accept_api_auth_actions') || []
403
      self.accept_api_auth_actions || []
406 404
    end
407 405
  end
408 406

  
......
523 521
    else
524 522
      @error_messages = objects.errors.full_messages
525 523
    end
526
    render :template => 'common/error_messages.api', :status => :unprocessable_entity, :layout => false
524
    render :template => 'common/error_messages.api', :status => :unprocessable_entity, :layout => nil
527 525
  end
528 526

  
529
  # Overrides #default_template so that the api template
530
  # is used automatically if it exists
531
  def default_template(action_name = self.action_name)
532
    if api_request?
533
      begin
534
        return self.view_paths.find_template(default_template_name(action_name), 'api')
535
      rescue ::ActionView::MissingTemplate
536
        # the api template was not found
537
        # fallback to the default behaviour
538
      end
539
    end
540
    super
541
  end
542

  
543
  # Overrides #pick_layout so that #render with no arguments
527
  # Overrides #_include_layout? so that #render with no arguments
544 528
  # doesn't use the layout for api requests
545
  def pick_layout(*args)
546
    api_request? ? nil : super
529
  def _include_layout?(*args)
530
    api_request? ? false : super
547 531
  end
548 532
end
trunk/app/controllers/messages_controller.rb
95 95
  # Delete a messages
96 96
  def destroy
97 97
    (render_403; return false) unless @message.destroyable_by?(User.current)
98
    r = @message.to_param
98 99
    @message.destroy
99 100
    redirect_to @message.parent.nil? ?
100 101
      { :controller => 'boards', :action => 'show', :project_id => @project, :id => @board } :
101
      { :action => 'show', :id => @message.parent, :r => @message }
102
      { :action => 'show', :id => @message.parent, :r => r }
102 103
  end
103 104

  
104 105
  def quote
trunk/app/controllers/repositories_controller.rb
18 18
require 'SVG/Graph/Bar'
19 19
require 'SVG/Graph/BarHorizontal'
20 20
require 'digest/sha1'
21
require 'redmine/scm/adapters/abstract_adapter'
21 22

  
22 23
class ChangesetNotFound < Exception; end
23 24
class InvalidRevisionParam < Exception; end
......
307 308
      @repository = @project.repository
308 309
    end
309 310
    (render_404; return false) unless @repository
310
    @path = params[:path].join('/') unless params[:path].nil?
311
    @path ||= ''
311
    @path = params[:path].is_a?(Array) ? params[:path].join('/') : params[:path].to_s
312 312
    @rev = params[:rev].blank? ? @repository.default_branch : params[:rev].to_s.strip
313 313
    @rev_to = params[:rev_to]
314 314

  
......
343 343
    @date_to = Date.today
344 344
    @date_from = @date_to << 11
345 345
    @date_from = Date.civil(@date_from.year, @date_from.month, 1)
346
    commits_by_day = repository.changesets.count(
346
    commits_by_day = Changeset.count(
347 347
                          :all, :group => :commit_date,
348
                          :conditions => ["commit_date BETWEEN ? AND ?", @date_from, @date_to])
348
                          :conditions => ["repository_id = ? AND commit_date BETWEEN ? AND ?", repository.id, @date_from, @date_to])
349 349
    commits_by_month = [0] * 12
350 350
    commits_by_day.each {|c| commits_by_month[c.first.to_date.months_ago] += c.last }
351 351

  
352
    changes_by_day = repository.changes.count(
353
                          :all, :group => :commit_date,
354
                          :conditions => ["commit_date BETWEEN ? AND ?", @date_from, @date_to])
352
    changes_by_day = Change.count(
353
                          :all, :group => :commit_date, :include => :changeset,
354
                          :conditions => ["#{Changeset.table_name}.repository_id = ? AND #{Changeset.table_name}.commit_date BETWEEN ? AND ?", repository.id, @date_from, @date_to])
355 355
    changes_by_month = [0] * 12
356 356
    changes_by_day.each {|c| changes_by_month[c.first.to_date.months_ago] += c.last }
357 357

  
......
384 384
  end
385 385

  
386 386
  def graph_commits_per_author(repository)
387
    commits_by_author = repository.changesets.count(:all, :group => :committer)
387
    commits_by_author = Changeset.count(:all, :group => :committer, :conditions => ["repository_id = ?", repository.id])
388 388
    commits_by_author.to_a.sort! {|x, y| x.last <=> y.last}
389 389

  
390
    changes_by_author = repository.changes.count(:all, :group => :committer)
390
    changes_by_author = Change.count(:all, :group => :committer, :include => :changeset, :conditions => ["#{Changeset.table_name}.repository_id = ?", repository.id])
391 391
    h = changes_by_author.inject({}) {|o, i| o[i.first] = i.last; o}
392 392

  
393 393
    fields = commits_by_author.collect {|r| r.first}
trunk/app/controllers/watchers_controller.rb
109 109
      @watched = klass.find(params[:object_id])
110 110
      @project = @watched.project
111 111
    elsif params[:project_id]
112
      @project = Project.visible.find(params[:project_id])
112
      @project = Project.visible.find_by_param(params[:project_id])
113 113
    end
114 114
  rescue
115 115
    render_404
trunk/app/controllers/wiki_controller.rb
163 163
    # Optimistic locking exception
164 164
    flash.now[:error] = l(:notice_locking_conflict)
165 165
    render :action => 'edit'
166
  rescue ActiveRecord::RecordNotSaved
167
    render :action => 'edit'
166 168
  end
167 169

  
168 170
  # rename a page
trunk/app/helpers/application_helper.rb
930 930
  def labelled_form_for(*args, &proc)
931 931
    args << {} unless args.last.is_a?(Hash)
932 932
    options = args.last
933
    if args.first.is_a?(Symbol)
934
      options.merge!(:as => args.shift)
935
    end
933 936
    options.merge!({:builder => Redmine::Views::LabelledFormBuilder})
934 937
    form_for(*args, &proc)
935 938
  end
......
1060 1063
  # +user+ can be a User or a string that will be scanned for an email address (eg. 'joe <[email protected]>')
1061 1064
  def avatar(user, options = { })
1062 1065
    if Setting.gravatar_enabled?
1063
      options.merge!({:ssl => (defined?(request) && request.ssl?), :default => Setting.gravatar_default})
1066
      options.merge!({:ssl => (request && request.ssl?), :default => Setting.gravatar_default})
1064 1067
      email = nil
1065 1068
      if user.respond_to?(:mail)
1066 1069
        email = user.mail
......
1079 1082

  
1080 1083
  # Returns the javascript tags that are included in the html layout head
1081 1084
  def javascript_heads
1082
    tags = javascript_include_tag(:defaults)
1085
    tags = javascript_include_tag('prototype', 'effects', 'dragdrop', 'controls', 'rails', 'application')
1083 1086
    unless User.current.pref.warn_on_leaving_unsaved == '0'
1084 1087
      tags << "\n".html_safe + javascript_tag("Event.observe(window, 'load', function(){ new WarnLeavingUnsaved('#{escape_javascript( l(:text_warn_on_leaving_unsaved) )}'); });")
1085 1088
    end
trunk/app/helpers/wiki_helper.rb
21 21

  
22 22
  def wiki_page_options_for_select(pages, selected = nil, parent = nil, level = 0)
23 23
    pages = pages.group_by(&:parent) unless pages.is_a?(Hash)
24
    s = ''
24
    s = ''.html_safe
25 25
    if pages.has_key?(parent)
26 26
      pages[parent].each do |page|
27 27
        attrs = "value='#{page.id}'"
28 28
        attrs << " selected='selected'" if selected == page
29
        indent = (level > 0) ? ('&nbsp;' * level * 2 + '&#187; ') : nil
29
        indent = (level > 0) ? ('&nbsp;' * level * 2 + '&#187; ') : ''
30 30

  
31
        s << "<option #{attrs}>#{indent}#{h page.pretty_title}</option>\n" +
31
        s << content_tag('option', (indent + h(page.pretty_title)).html_safe, :value => page.id.to_s, :selected => selected == page) +
32 32
               wiki_page_options_for_select(pages, selected, page, level + 1)
33 33
      end
34 34
    end
trunk/app/models/custom_field.rb
80 80
    when 'bool'
81 81
      [[l(:general_text_Yes), '1'], [l(:general_text_No), '0']]
82 82
    else
83
      read_possible_values_utf8_encoded || []
83
      possible_values || []
84 84
    end
85 85
  end
86 86

  
......
91 91
    when 'bool'
92 92
      ['1', '0']
93 93
    else
94
      read_possible_values_utf8_encoded
94
      values = super()
95
      if values.is_a?(Array)
96
        values.each do |value|
97
          value.force_encoding('UTF-8') if value.respond_to?(:force_encoding)
98
        end
99
      end
100
      values
95 101
    end
96 102
  end
97 103

  
98 104
  # Makes possible_values accept a multiline string
99 105
  def possible_values=(arg)
100 106
    if arg.is_a?(Array)
101
      write_attribute(:possible_values, arg.compact.collect(&:strip).select {|v| !v.blank?})
107
      super(arg.compact.collect(&:strip).select {|v| !v.blank?})
102 108
    else
103 109
      self.possible_values = arg.to_s.split(/[\n\r]+/)
104 110
    end
......
218 224
    end
219 225
    errs
220 226
  end
221

  
222
  def read_possible_values_utf8_encoded
223
    values = read_attribute(:possible_values)
224
    if values.is_a?(Array)
225
      values.each do |value|
226
        value.force_encoding('UTF-8') if value.respond_to?(:force_encoding)
227
      end
228
    end
229
    values
230
  end
231 227
end
trunk/app/models/issue.rb
246 246
    write_attribute(:description, arg)
247 247
  end
248 248

  
249
  # Overrides attributes= so that project and tracker get assigned first
250
  def attributes_with_project_and_tracker_first=(new_attributes, *args)
249
  # Overrides assign_attributes so that project and tracker get assigned first
250
  def assign_attributes_with_project_and_tracker_first(new_attributes, *args)
251 251
    return if new_attributes.nil?
252 252
    attrs = new_attributes.dup
253 253
    attrs.stringify_keys!
......
257 257
        send "#{attr}=", attrs.delete(attr)
258 258
      end
259 259
    end
260
    send :attributes_without_project_and_tracker_first=, attrs, *args
260
    send :assign_attributes_without_project_and_tracker_first, attrs, *args
261 261
  end
262 262
  # Do not redefine alias chain on reload (see #4838)
263
  alias_method_chain(:attributes=, :project_and_tracker_first) unless method_defined?(:attributes_without_project_and_tracker_first=)
263
  alias_method_chain(:assign_attributes, :project_and_tracker_first) unless method_defined?(:assign_attributes_without_project_and_tracker_first)
264 264

  
265 265
  def estimated_hours=(h)
266 266
    write_attribute :estimated_hours, (h.is_a?(String) ? h.to_hours : h)
......
350 350
    end
351 351

  
352 352
    # mass-assignment security bypass
353
    self.send :attributes=, attrs, false
353
    assign_attributes attrs, :without_protection => true
354 354
  end
355 355

  
356 356
  def done_ratio
......
921 921
      p.estimated_hours = nil if p.estimated_hours == 0.0
922 922

  
923 923
      # ancestors will be recursively updated
924
      p.save(false)
924
      p.save(:validate => false)
925 925
    end
926 926
  end
927 927

  
trunk/app/models/mail_handler.rb
15 15
# along with this program; if not, write to the Free Software
16 16
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
17 17

  
18
class MailHandler < ActionMailer::Base
18
require 'vendor/tmail'
19

  
20
class MailHandler
19 21
  include ActionView::Helpers::SanitizeHelper
20 22
  include Redmine::I18n
21 23

  
......
39 41
    @@handler_options[:allow_override] << 'status' unless @@handler_options[:issue].has_key?(:status)
40 42

  
41 43
    @@handler_options[:no_permission_check] = (@@handler_options[:no_permission_check].to_s == '1' ? true : false)
42
    super email
44

  
45
    mail = TMail::Mail.parse(email)
46
    mail.base64_decode
47
    new.receive(mail)
43 48
  end
44 49

  
50
  def logger
51
    Rails.logger
52
  end
53

  
45 54
  cattr_accessor :ignored_emails_headers
46 55
  @@ignored_emails_headers = {
47 56
    'X-Auto-Response-Suppress' => 'OOF',
trunk/app/models/mailer.rb
21 21
  helper :issues
22 22
  helper :custom_fields
23 23

  
24
  include ActionController::UrlWriter
25 24
  include Redmine::I18n
26 25

  
27 26
  def self.default_url_options
28
    h = Setting.host_name
29
    h = h.to_s.gsub(%r{\/.*$}, '') unless Redmine::Utils.relative_url_root.blank?
30
    { :host => h, :protocol => Setting.protocol }
27
    { :host => Setting.host_name, :protocol => Setting.protocol }
31 28
  end
32 29

  
33 30
  # Builds a tmail object used to email recipients of the added issue.
......
42 39
    redmine_headers 'Issue-Assignee' => issue.assigned_to.login if issue.assigned_to
43 40
    message_id issue
44 41
    @author = issue.author
45
    recipients issue.recipients
46
    cc(issue.watcher_recipients - @recipients)
47
    subject "[#{issue.project.name} - #{issue.tracker.name} ##{issue.id}] (#{issue.status.name}) #{issue.subject}"
48
    body :issue => issue,
49
         :issue_url => url_for(:controller => 'issues', :action => 'show', :id => issue)
50
    render_multipart('issue_add', body)
42
    @issue = issue
43
    @issue_url = url_for(:controller => 'issues', :action => 'show', :id => issue)
44
    recipients = issue.recipients
45
    cc = issue.watcher_recipients - recipients
46
    mail :to => recipients,
47
      :cc => cc,
48
      :subject => "[#{issue.project.name} - #{issue.tracker.name} ##{issue.id}] (#{issue.status.name}) #{issue.subject}"
51 49
  end
52 50

  
53 51
  # Builds a tmail object used to email recipients of the edited issue.
......
64 62
    message_id journal
65 63
    references issue
66 64
    @author = journal.user
67
    recipients issue.recipients
65
    recipients = issue.recipients
68 66
    # Watchers in cc
69
    cc(issue.watcher_recipients - @recipients)
67
    cc = issue.watcher_recipients - recipients
70 68
    s = "[#{issue.project.name} - #{issue.tracker.name} ##{issue.id}] "
71 69
    s << "(#{issue.status.name}) " if journal.new_value_for('status_id')
72 70
    s << issue.subject
73
    subject s
74
    body :issue => issue,
75
         :journal => journal,
76
         :issue_url => url_for(:controller => 'issues', :action => 'show', :id => issue, :anchor => "change-#{journal.id}")
77

  
78
    render_multipart('issue_edit', body)
71
    @issue = issue
72
    @journal = journal
73
    @issue_url = url_for(:controller => 'issues', :action => 'show', :id => issue, :anchor => "change-#{journal.id}")
74
    mail :to => recipients,
75
      :cc => cc,
76
      :subject => s
79 77
  end
80 78

  
81 79
  def reminder(user, issues, days)
82 80
    set_language_if_valid user.language
83
    recipients user.mail
84
    subject l(:mail_subject_reminder, :count => issues.size, :days => days)
85
    body :issues => issues,
86
         :days => days,
87
         :issues_url => url_for(:controller => 'issues', :action => 'index',
81
    @issues = issues
82
    @days = days
83
    @issues_url = url_for(:controller => 'issues', :action => 'index',
88 84
                                :set_filter => 1, :assigned_to_id => user.id,
89 85
                                :sort => 'due_date:asc')
90
    render_multipart('reminder', body)
86
    mail :to => user.mail,
87
      :subject => l(:mail_subject_reminder, :count => issues.size, :days => days)
91 88
  end
92 89

  
93 90
  # Builds a tmail object used to email users belonging to the added document's project.
......
97 94
  #   Mailer.deliver_document_added(document) => sends an email to the document's project recipients
98 95
  def document_added(document)
99 96
    redmine_headers 'Project' => document.project.identifier
100
    recipients document.recipients
101 97
    @author = User.current
102
    subject "[#{document.project.name}] #{l(:label_document_new)}: #{document.title}"
103
    body :document => document,
104
         :document_url => url_for(:controller => 'documents', :action => 'show', :id => document)
105
    render_multipart('document_added', body)
98
    @document = document
99
    @document_url = url_for(:controller => 'documents', :action => 'show', :id => document)
100
    mail :to => document.recipients,
101
      :subject => "[#{document.project.name}] #{l(:label_document_new)}: #{document.title}"
106 102
  end
107 103

  
108 104
  # Builds a tmail object used to email recipients of a project when an attachements are added.
......
119 115
    when 'Project'
120 116
      added_to_url = url_for(:controller => 'files', :action => 'index', :project_id => container)
121 117
      added_to = "#{l(:label_project)}: #{container}"
122
      recipients container.project.notified_users.select {|user| user.allowed_to?(:view_files, container.project)}.collect  {|u| u.mail}
118
      recipients = container.project.notified_users.select {|user| user.allowed_to?(:view_files, container.project)}.collect  {|u| u.mail}
123 119
    when 'Version'
124 120
      added_to_url = url_for(:controller => 'files', :action => 'index', :project_id => container.project)
125 121
      added_to = "#{l(:label_version)}: #{container.name}"
126
      recipients container.project.notified_users.select {|user| user.allowed_to?(:view_files, container.project)}.collect  {|u| u.mail}
122
      recipients = container.project.notified_users.select {|user| user.allowed_to?(:view_files, container.project)}.collect  {|u| u.mail}
127 123
    when 'Document'
128 124
      added_to_url = url_for(:controller => 'documents', :action => 'show', :id => container.id)
129 125
      added_to = "#{l(:label_document)}: #{container.title}"
130
      recipients container.recipients
126
      recipients = container.recipients
131 127
    end
132 128
    redmine_headers 'Project' => container.project.identifier
133
    subject "[#{container.project.name}] #{l(:label_attachment_new)}"
134
    body :attachments => attachments,
135
         :added_to => added_to,
136
         :added_to_url => added_to_url
137
    render_multipart('attachments_added', body)
129
    @attachments = attachments
130
    @added_to = added_to
131
    @added_to_url = added_to_url
132
    mail :to => recipients,
133
      :subject => "[#{container.project.name}] #{l(:label_attachment_new)}"
138 134
  end
139 135

  
140 136
  # Builds a tmail object used to email recipients of a news' project when a news item is added.
......
146 142
    redmine_headers 'Project' => news.project.identifier
147 143
    @author = news.author
148 144
    message_id news
149
    recipients news.recipients
150
    subject "[#{news.project.name}] #{l(:label_news)}: #{news.title}"
151
    body :news => news,
152
         :news_url => url_for(:controller => 'news', :action => 'show', :id => news)
153
    render_multipart('news_added', body)
145
    @news = news
146
    @news_url = url_for(:controller => 'news', :action => 'show', :id => news)
147
    mail :to => news.recipients,
148
      :subject => "[#{news.project.name}] #{l(:label_news)}: #{news.title}"
154 149
  end
155 150

  
156 151
  # Builds a tmail object used to email recipients of a news' project when a news comment is added.
......
163 158
    redmine_headers 'Project' => news.project.identifier
164 159
    @author = comment.author
165 160
    message_id comment
166
    recipients news.recipients
167
    cc news.watcher_recipients
168
    subject "Re: [#{news.project.name}] #{l(:label_news)}: #{news.title}"
169
    body :news => news,
170
         :comment => comment,
171
         :news_url => url_for(:controller => 'news', :action => 'show', :id => news)
172
    render_multipart('news_comment_added', body)
161
    @news = news
162
    @comment = comment
163
    @news_url = url_for(:controller => 'news', :action => 'show', :id => news)
164
    mail :to => news.recipients,
165
     :cc => news.watcher_recipients,
166
     :subject => "Re: [#{news.project.name}] #{l(:label_news)}: #{news.title}"
173 167
  end
174 168

  
175 169
  # Builds a tmail object used to email the recipients of the specified message that was posted.
......
183 177
    @author = message.author
184 178
    message_id message
185 179
    references message.parent unless message.parent.nil?
186
    recipients(message.recipients)
187
    cc((message.root.watcher_recipients + message.board.watcher_recipients).uniq - @recipients)
188
    subject "[#{message.board.project.name} - #{message.board.name} - msg#{message.root.id}] #{message.subject}"
189
    body :message => message,
190
         :message_url => url_for(message.event_url)
191
    render_multipart('message_posted', body)
180
    recipients = message.recipients
181
    cc = ((message.root.watcher_recipients + message.board.watcher_recipients).uniq - recipients)
182
    @message = message
183
    @message_url = url_for(message.event_url)
184
    mail :to => recipients,
185
      :cc => cc,
186
      :subject => "[#{message.board.project.name} - #{message.board.name} - msg#{message.root.id}] #{message.subject}"
192 187
  end
193 188

  
194 189
  # Builds a tmail object used to email the recipients of a project of the specified wiki content was added.
......
201 196
                    'Wiki-Page-Id' => wiki_content.page.id
202 197
    @author = wiki_content.author
203 198
    message_id wiki_content
204
    recipients wiki_content.recipients
205
    cc(wiki_content.page.wiki.watcher_recipients - recipients)
206
    subject "[#{wiki_content.project.name}] #{l(:mail_subject_wiki_content_added, :id => wiki_content.page.pretty_title)}"
207
    body :wiki_content => wiki_content,
208
         :wiki_content_url => url_for(:controller => 'wiki', :action => 'show',
199
    recipients = wiki_content.recipients
200
    cc = wiki_content.page.wiki.watcher_recipients - recipients
201
    @wiki_content = wiki_content
202
    @wiki_content_url = url_for(:controller => 'wiki', :action => 'show',
209 203
                                      :project_id => wiki_content.project,
210 204
                                      :id => wiki_content.page.title)
211
    render_multipart('wiki_content_added', body)
205
    mail :to => recipients,
206
      :cc => cc,
207
      :subject => "[#{wiki_content.project.name}] #{l(:mail_subject_wiki_content_added, :id => wiki_content.page.pretty_title)}"
212 208
  end
213 209

  
214 210
  # Builds a tmail object used to email the recipients of a project of the specified wiki content was updated.
......
221 217
                    'Wiki-Page-Id' => wiki_content.page.id
222 218
    @author = wiki_content.author
223 219
    message_id wiki_content
224
    recipients wiki_content.recipients
225
    cc(wiki_content.page.wiki.watcher_recipients + wiki_content.page.watcher_recipients - recipients)
226
    subject "[#{wiki_content.project.name}] #{l(:mail_subject_wiki_content_updated, :id => wiki_content.page.pretty_title)}"
227
    body :wiki_content => wiki_content,
228
         :wiki_content_url => url_for(:controller => 'wiki', :action => 'show',
220
    recipients = wiki_content.recipients
221
    cc = wiki_content.page.wiki.watcher_recipients + wiki_content.page.watcher_recipients - recipients
222
    @wiki_content = wiki_content
223
    @wiki_content_url = url_for(:controller => 'wiki', :action => 'show',
229 224
                                      :project_id => wiki_content.project,
230
                                      :id => wiki_content.page.title),
231
         :wiki_diff_url => url_for(:controller => 'wiki', :action => 'diff',
225
                                      :id => wiki_content.page.title)
226
    @wiki_diff_url = url_for(:controller => 'wiki', :action => 'diff',
232 227
                                   :project_id => wiki_content.project, :id => wiki_content.page.title,
233 228
                                   :version => wiki_content.version)
234
    render_multipart('wiki_content_updated', body)
229
    mail :to => recipients,
230
      :cc => cc,
231
      :subject => "[#{wiki_content.project.name}] #{l(:mail_subject_wiki_content_updated, :id => wiki_content.page.pretty_title)}"
235 232
  end
236 233

  
237 234
  # Builds a tmail object used to email the specified user their account information.
......
241 238
  #   Mailer.deliver_account_information(user, password) => sends account information to the user
242 239
  def account_information(user, password)
243 240
    set_language_if_valid user.language
244
    recipients user.mail
245
    subject l(:mail_subject_register, Setting.app_title)
246
    body :user => user,
247
         :password => password,
248
         :login_url => url_for(:controller => 'account', :action => 'login')
249
    render_multipart('account_information', body)
241
    @user = user
242
    @password = password
243
    @login_url = url_for(:controller => 'account', :action => 'login')
244
    mail :to => user.mail,
245
      :subject => l(:mail_subject_register, Setting.app_title)
250 246
  end
251 247

  
252 248
  # Builds a tmail object used to email all active administrators of an account activation request.
......
256 252
  #   Mailer.deliver_account_activation_request(user)=> sends an email to all active administrators
257 253
  def account_activation_request(user)
258 254
    # Send the email to all active administrators
259
    recipients User.active.find(:all, :conditions => {:admin => true}).collect { |u| u.mail }.compact
260
    subject l(:mail_subject_account_activation_request, Setting.app_title)
261
    body :user => user,
262
         :url => url_for(:controller => 'users', :action => 'index',
255
    recipients = User.active.find(:all, :conditions => {:admin => true}).collect { |u| u.mail }.compact
256
    @user = user
257
    @url = url_for(:controller => 'users', :action => 'index',
263 258
                         :status => User::STATUS_REGISTERED,
264 259
                         :sort_key => 'created_on', :sort_order => 'desc')
265
    render_multipart('account_activation_request', body)
260
    mail :to => recipients,
261
      :subject => l(:mail_subject_account_activation_request, Setting.app_title)
266 262
  end
267 263

  
268 264
  # Builds a tmail object used to email the specified user that their account was activated by an administrator.
......
272 268
  #   Mailer.deliver_account_activated(user) => sends an email to the registered user
273 269
  def account_activated(user)
274 270
    set_language_if_valid user.language
275
    recipients user.mail
276
    subject l(:mail_subject_register, Setting.app_title)
277
    body :user => user,
278
         :login_url => url_for(:controller => 'account', :action => 'login')
279
    render_multipart('account_activated', body)
271
    @user = user
272
    @login_url = url_for(:controller => 'account', :action => 'login')
273
    mail :to => user.mail,
274
      :subject => l(:mail_subject_register, Setting.app_title)
280 275
  end
281 276

  
282 277
  def lost_password(token)
283 278
    set_language_if_valid(token.user.language)
284
    recipients token.user.mail
285
    subject l(:mail_subject_lost_password, Setting.app_title)
286
    body :token => token,
287
         :url => url_for(:controller => 'account', :action => 'lost_password', :token => token.value)
288
    render_multipart('lost_password', body)
279
    @token = token
280
    @url = url_for(:controller => 'account', :action => 'lost_password', :token => token.value)
281
    mail :to => token.user.mail,
282
      :subject => l(:mail_subject_lost_password, Setting.app_title)
289 283
  end
290 284

  
291 285
  def register(token)
292 286
    set_language_if_valid(token.user.language)
293
    recipients token.user.mail
294
    subject l(:mail_subject_register, Setting.app_title)
295
    body :token => token,
296
         :url => url_for(:controller => 'account', :action => 'activate', :token => token.value)
297
    render_multipart('register', body)
287
    @token = token
288
    @url = url_for(:controller => 'account', :action => 'activate', :token => token.value)
289
    mail :to => token.user.mail,
290
      :subject => l(:mail_subject_register, Setting.app_title)
298 291
  end
299 292

  
300 293
  def test_email(user)
301 294
    set_language_if_valid(user.language)
302
    recipients user.mail
303
    subject 'Redmine test'
304
    body :url => url_for(:controller => 'welcome')
305
    render_multipart('test_email', body)
295
    @url = url_for(:controller => 'welcome')
296
    mail :to => user.mail,
297
      :subject => 'Redmine test'
306 298
  end
307 299

  
308 300
  # Overrides default deliver! method to prevent from sending an email
......
313 305
                    (cc.nil? || cc.empty?) &&
314 306
                    (bcc.nil? || bcc.empty?)
315 307

  
316
    # Set Message-Id and References
317
    if @message_id_object
318
      mail.message_id = self.class.message_id_for(@message_id_object)
319
    end
320
    if @references_objects
321
      mail.references = @references_objects.collect {|o| self.class.message_id_for(o)}
322
    end
323 308

  
324 309
    # Log errors when raise_delivery_errors is set to false, Rails does not
325 310
    raise_errors = self.class.raise_delivery_errors
......
383 368
    ActionMailer::Base.delivery_method = saved_method
384 369
  end
385 370

  
386
  private
387
  def initialize_defaults(method_name)
388
    super
389
    @initial_language = current_language
390
    set_language_if_valid Setting.default_language
391
    from Setting.mail_from
392

  
393
    # Common headers
394
    headers 'X-Mailer' => 'Redmine',
371
  def mail(headers={})
372
    headers.merge! 'X-Mailer' => 'Redmine',
395 373
            'X-Redmine-Host' => Setting.host_name,
396 374
            'X-Redmine-Site' => Setting.app_title,
397 375
            'X-Auto-Response-Suppress' => 'OOF',
398
            'Auto-Submitted' => 'auto-generated'
399
  end
376
            'Auto-Submitted' => 'auto-generated',
377
            'From' => Setting.mail_from
400 378

  
401
  # Appends a Redmine header field (name is prepended with 'X-Redmine-')
402
  def redmine_headers(h)
403
    h.each { |k,v| headers["X-Redmine-#{k}"] = v.to_s }
404
  end
405

  
406
  # Overrides the create_mail method
407
  def create_mail
408 379
    # Removes the author from the recipients and cc
409 380
    # if he doesn't want to receive notifications about what he does
410 381
    if @author && @author.logged? && @author.pref[:no_self_notified]
411
      if recipients
412
        recipients((recipients.is_a?(Array) ? recipients : [recipients]) - [@author.mail])
413
      end
414
      if cc
415
        cc((cc.is_a?(Array) ? cc : [cc]) - [@author.mail])
416
      end
382
      headers[:to].delete(@author.mail) if headers[:to].is_a?(Array)
383
      headers[:cc].delete(@author.mail) if headers[:cc].is_a?(Array)
417 384
    end
418 385

  
419 386
    if @author && @author.logged?
420 387
      redmine_headers 'Sender' => @author.login
421 388
    end
422 389

  
423
    notified_users = [recipients, cc].flatten.compact.uniq
424
    # Rails would log recipients only, not cc and bcc
425
    mylogger.info "Sending email notification to: #{notified_users.join(', ')}" if mylogger
426

  
427 390
    # Blind carbon copy recipients
428 391
    if Setting.bcc_recipients?
429
      bcc(notified_users)
430
      recipients []
431
      cc []
392
      headers[:bcc] = [headers[:to], headers[:cc]].flatten.uniq.reject(&:blank?)
393
      headers[:to] = nil
394
      headers[:cc] = nil
432 395
    end
396

  
397
    if @message_id_object
398
      headers[:message_id] = "<#{self.class.message_id_for(@message_id_object)}>"
399
    end
400
    if @references_objects
401
      headers[:references] = @references_objects.collect {|o| "<#{self.class.message_id_for(o)}>"}.join(' ')
402
    end
403

  
404
    super headers do |format|
405
      format.text
406
      format.html unless Setting.plain_text_mail?
407
    end
408

  
409
    set_language_if_valid @initial_language
410
  end
411

  
412
  def initialize(*args)
413
    @initial_language = current_language
414
    set_language_if_valid Setting.default_language
433 415
    super
434 416
  end
417
  
418
  def self.deliver_mail(mail)
419
    return false if mail.to.blank? && mail.cc.blank? && mail.bcc.blank?
420
    super
421
  end
435 422

  
436
  # Rails 2.3 has problems rendering implicit multipart messages with
437
  # layouts so this method will wrap an multipart messages with
438
  # explicit parts.
439
  #
440
  # https://rails.lighthouseapp.com/projects/8994/tickets/2338-actionmailer-mailer-views-and-content-type
441
  # https://rails.lighthouseapp.com/projects/8994/tickets/1799-actionmailer-doesnt-set-template_format-when-rendering-layouts
442

  
443
  def render_multipart(method_name, body)
444
    if Setting.plain_text_mail?
445
      content_type "text/plain"
446
      body render(:file => "#{method_name}.text.erb",
447
                  :body => body,
448
                  :layout => 'mailer.text.erb')
423
  def self.method_missing(method, *args, &block)
424
    if m = method.to_s.match(%r{^deliver_(.+)$})
425
      send(m[1], *args).deliver
449 426
    else
450
      content_type "multipart/alternative"
451
      part :content_type => "text/plain",
452
           :body => render(:file => "#{method_name}.text.erb",
453
                           :body => body, :layout => 'mailer.text.erb')
454
      part :content_type => "text/html",
455
           :body => render_message("#{method_name}.html.erb", body)
427
      super
456 428
    end
457 429
  end
458 430

  
459
  # Makes partial rendering work with Rails 1.2 (retro-compatibility)
460
  def self.controller_path
461
    ''
462
  end unless respond_to?('controller_path')
431
  private
463 432

  
433
  # Appends a Redmine header field (name is prepended with 'X-Redmine-')
434
  def redmine_headers(h)
435
    h.each { |k,v| headers["X-Redmine-#{k}"] = v.to_s }
436
  end
437

  
464 438
  # Returns a predictable Message-Id for the given object
465 439
  def self.message_id_for(object)
466 440
    # id + timestamp should reduce the odds of a collision
......
469 443
    hash = "redmine.#{object.class.name.demodulize.underscore}-#{object.id}.#{timestamp.strftime("%Y%m%d%H%M%S")}"
470 444
    host = Setting.mail_from.to_s.gsub(%r{^.*@}, '')
471 445
    host = "#{::Socket.gethostname}.redmine" if host.empty?
472
    "<#{hash}@#{host}>"
446
    "#{hash}@#{host}"
473 447
  end
474 448

  
475
  private
476

  
477 449
  def message_id(object)
478 450
    @message_id_object = object
479 451
  end
......
487 459
    Rails.logger
488 460
  end
489 461
end
490

  
491
# Patch TMail so that message_id is not overwritten
492
module TMail
493
  class Mail
494
    def add_message_id( fqdn = nil )
495
      self.message_id ||= ::TMail::new_message_id(fqdn)
496
    end
497
  end
498
end
trunk/app/models/project.rb
272 272
    end
273 273
  end
274 274

  
275
  def self.find_by_param(*args)
276
    self.find(*args)
277
  end
278

  
275 279
  def reload(*args)
276 280
    @shared_versions = nil
277 281
    @rolled_up_versions = nil
trunk/app/models/repository.rb
57 57
  end
58 58

  
59 59
  alias :attributes_without_extra_info= :attributes=
60
  def attributes=(new_attributes, guard_protected_attributes = true)
60
  def attributes=(new_attributes)
61 61
    return if new_attributes.nil?
62 62
    attributes = new_attributes.dup
63 63
    attributes.stringify_keys!
......
72 72
      end
73 73
    end
74 74

  
75
    send :attributes_without_extra_info=, p, guard_protected_attributes
75
    send :attributes_without_extra_info=, p
76 76
    if p_extra.keys.any?
77 77
      merge_extra_info(p_extra)
78 78
    end
trunk/app/models/role.rb
36 36
  before_destroy :check_deletable
37 37
  has_many :workflows, :dependent => :delete_all do
38 38
    def copy(source_role)
39
      Workflow.copy(nil, source_role, nil, proxy_owner)
39
      Workflow.copy(nil, source_role, nil, proxy_association.owner)
40 40
    end
41 41
  end
42 42

  
trunk/app/models/tracker.rb
20 20
  has_many :issues
21 21
  has_many :workflows, :dependent => :delete_all do
22 22
    def copy(source_tracker)
23
      Workflow.copy(source_tracker, nil, proxy_owner, nil)
23
      Workflow.copy(source_tracker, nil, proxy_association.owner, nil)
24 24
    end
25 25
  end
26 26

  
trunk/app/views/account/login.html.erb
1 1
<%= call_hook :view_account_login_top %>
2 2
<div id="login-form">
3
<% form_tag({:action=> "login"}) do %>
3
<%= form_tag({:action=> "login"}) do %>
4 4
<%= back_url_hidden_field_tag %>
5 5
<table>
6 6
<tr>
trunk/app/views/account/lost_password.html.erb
1 1
<h2><%=l(:label_password_lost)%></h2>
2 2

  
3 3
<div class="box">
4
<% form_tag({:action=> "lost_password"}, :class => "tabular") do %>
4
<%= form_tag({:action=> "lost_password"}, :class => "tabular") do %>
5 5

  
6 6
<p><label for="mail"><%=l(:field_mail)%> <span class="required">*</span></label>
7 7
<%= text_field_tag 'mail', nil, :size => 40 %>
trunk/app/views/account/password_recovery.html.erb
2 2

  
3 3
<%= error_messages_for 'user' %>
4 4

  
5
<% form_tag({:token => @token.value}) do %>
5
<%= form_tag({:token => @token.value}) do %>
6 6
<div class="box tabular">
7 7
<p><label for="new_password"><%=l(:field_new_password)%> <span class="required">*</span></label>
8 8
<%= password_field_tag 'new_password', nil, :size => 25 %>
trunk/app/views/account/register.html.erb
1 1
<h2><%=l(:label_register)%> <%=link_to l(:label_login_with_open_id_option), signin_url if Setting.openid? %></h2>
2 2

  
3
<% labelled_form_for @user, :url => {:action => 'register'} do |f| %>
3
<%= labelled_form_for @user, :url => {:action => 'register'} do |f| %>
4 4
<%= error_messages_for 'user' %>
5 5

  
6 6
<div class="box tabular">
trunk/app/views/activities/index.html.erb
40 40
<% end %>
41 41

  
42 42
<% content_for :sidebar do %>
43
<% form_tag({}, :method => :get) do %>
43
<%= form_tag({}, :method => :get) do %>
44 44
<h3><%= l(:label_activity) %></h3>
45 45
<p><% @activity.event_types.each do |t| %>
46 46
<%= check_box_tag "show_#{t}", 1, @activity.scope.include?(t) %>
trunk/app/views/admin/_no_data.html.erb
1 1
<div class="nodata">
2
<% form_tag({:action => 'default_configuration'}) do %>
2
<%= form_tag({:action => 'default_configuration'}) do %>
3 3
    <%= simple_format(l(:text_no_configuration_data)) %>
4 4
    <p><%= l(:field_language) %>:
5 5
    <%= select_tag 'lang', options_for_select(lang_options_for_select(false), current_language.to_s) %>
trunk/app/views/admin/projects.html.erb
4 4

  
5 5
<h2><%=l(:label_project_plural)%></h2>
6 6

  
7
<% form_tag({}, :method => :get) do %>
7
<%= form_tag({}, :method => :get) do %>
8 8
<fieldset><legend><%= l(:label_filter_plural) %></legend>
9 9
<label for='status'><%= l(:field_status) %> :</label>
10 10
<%= select_tag 'status', project_status_options_for_select(@status), :class => "small", :onchange => "this.form.submit(); return false;"  %>
trunk/app/views/attachments/diff.html.erb
7 7
   <span class="size">(<%= number_to_human_size @attachment.filesize %>)</span></p>
8 8
</div>
9 9
<p>
10
<% form_tag({}, :method => 'get') do %>
10
<%= form_tag({}, :method => 'get') do %>
11 11
    <label><%= l(:label_view_diff) %></label>
12 12
    <%= select_tag 'type',
13 13
                    options_for_select(
trunk/app/views/auth_sources/edit.html.erb
1 1
<h2><%=l(:label_auth_source)%> (<%= h(@auth_source.auth_method_name) %>)</h2>
2 2

  
3
<% form_tag({:action => 'update', :id => @auth_source}, :method => :put, :class => "tabular") do %>
3
<%= form_tag({:action => 'update', :id => @auth_source}, :method => :put, :class => "tabular") do %>
4 4
  <%= render :partial => auth_source_partial_name(@auth_source) %>
5 5
  <%= submit_tag l(:button_save) %>
6 6
<% end %>
trunk/app/views/auth_sources/new.html.erb
1 1
<h2><%=l(:label_auth_source_new)%> (<%= h(@auth_source.auth_method_name) %>)</h2>
2 2

  
3
<% form_tag({:action => 'create'}, :class => "tabular") do %>
3
<%= form_tag({:action => 'create'}, :class => "tabular") do %>
4 4
  <%= hidden_field_tag 'type', @auth_source.type %>
5 5
  <%= render :partial => auth_source_partial_name(@auth_source) %>
6 6
  <%= submit_tag l(:button_create) %>
trunk/app/views/boards/edit.html.erb
1 1
<h2><%= l(:label_board) %></h2>
2 2

  
3
<% labelled_form_for @board, :url => project_board_path(@project, @board) do |f| %>
3
<%= labelled_form_for @board, :url => project_board_path(@project, @board) do |f| %>
4 4
  <%= render :partial => 'form', :locals => {:f => f} %>
5 5
  <%= submit_tag l(:button_save) %>
6 6
<% end %>
trunk/app/views/boards/new.html.erb
1 1
<h2><%= l(:label_board_new) %></h2>
2 2

  
3
<% labelled_form_for @board, :url => project_boards_path(@project) do |f| %>
3
<%= labelled_form_for @board, :url => project_boards_path(@project) do |f| %>
4 4
  <%= render :partial => 'form', :locals => {:f => f} %>
5 5
  <%= submit_tag l(:button_create) %>
6 6
<% end %>
trunk/app/views/boards/show.html.erb
11 11
<div id="add-message" style="display:none;">
12 12
<% if authorize_for('messages', 'new') %>
13 13
<h2><%= link_to h(@board.name), :controller => 'boards', :action => 'show', :project_id => @project, :id => @board %> &#187; <%= l(:label_message_new) %></h2>
14
<% form_for :message, @message, :url => {:controller => 'messages', :action => 'new', :board_id => @board}, :html => {:multipart => true, :id => 'message-form'} do |f| %>
14
<%= form_for @message, :url => {:controller => 'messages', :action => 'new', :board_id => @board}, :html => {:multipart => true, :id => 'message-form'} do |f| %>
15 15
  <%= render :partial => 'messages/form', :locals => {:f => f} %>
16 16
  <p><%= submit_tag l(:button_create) %>
17 17
  <%= link_to_remote l(:label_preview),
trunk/app/views/calendars/show.html.erb
1 1
<h2><%= @query.new_record? ? l(:label_calendar) : h(@query.name) %></h2>
2 2

  
3
<% form_tag({:controller => 'calendars', :action => 'show', :project_id => @project}, :method => :get, :id => 'query_form') do %>
3
<%= form_tag({:controller => 'calendars', :action => 'show', :project_id => @project},
4
             :method => :get, :id => 'query_form') do %>
4 5
<%= hidden_field_tag 'set_filter', '1' %>
5 6
<fieldset id="filters" class="collapsible <%= @query.new_record? ? "" : "collapsed" %>">
6 7
  <legend onclick="toggleFieldset(this);"><%= l(:label_filter_plural) %></legend>
trunk/app/views/common/feed.atom.builder
1 1
xml.instruct!
2 2
xml.feed "xmlns" => "http://www.w3.org/2005/Atom" do
3 3
  xml.title   truncate_single_line(@title, :length => 100)
4
  xml.link    "rel" => "self", "href" => url_for(params.merge(:only_path => false, :escape => false))
5
  xml.link    "rel" => "alternate", "href" => url_for(params.merge(:only_path => false, :format => nil, :key => nil, :escape => false))
4
  xml.link    "rel" => "self", "href" => url_for(params.merge(:only_path => false))
5
  xml.link    "rel" => "alternate", "href" => url_for(params.merge(:only_path => false, :format => nil, :key => nil))
6 6
  xml.id      url_for(:controller => 'welcome', :only_path => false)
7 7
  xml.updated((@items.first ? @items.first.event_datetime : Time.now).xmlschema)
8 8
  xml.author  { xml.name "#{Setting.app_title}" }
trunk/app/views/custom_fields/edit.html.erb
2 2
  &#187; <%= link_to l(@custom_field.type_name), :controller => 'custom_fields', :action => 'index', :tab => @custom_field.class.name %>
3 3
  &#187; <%=h @custom_field.name %></h2>
4 4

  
5
<% labelled_form_for :custom_field, @custom_field, :url => custom_field_path(@custom_field), :html => {:method => :put} do |f| %>
5
<%= labelled_form_for :custom_field, @custom_field, :url => custom_field_path(@custom_field), :html => {:method => :put} do |f| %>
6 6
<%= render :partial => 'form', :locals => { :f => f } %>
7 7
<%= submit_tag l(:button_save) %>
8 8
<% end %>
trunk/app/views/custom_fields/new.html.erb
2 2
  &#187; <%= link_to l(@custom_field.type_name), :controller => 'custom_fields', :action => 'index', :tab => @custom_field.class.name %>
3 3
  &#187; <%= l(:label_custom_field_new) %></h2>
4 4

  
5
<% labelled_form_for :custom_field, @custom_field, :url => custom_fields_path do |f| %>
5
<%= labelled_form_for :custom_field, @custom_field, :url => custom_fields_path do |f| %>
6 6
<%= render :partial => 'form', :locals => { :f => f } %>
7 7
<%= hidden_field_tag 'type', @custom_field.type %>
8 8
<%= submit_tag l(:button_save) %>
trunk/app/views/documents/edit.html.erb
1 1
<h2><%=l(:label_document)%></h2>
2 2

  
3
<% labelled_form_for @document do |f| %>
3
<%= labelled_form_for @document do |f| %>
4 4
  <%= render :partial => 'form', :locals => {:f => f} %>
5 5
  <p><%= submit_tag l(:button_save) %></p>
6 6
<% end %>
trunk/app/views/documents/index.html.erb
5 5

  
6 6
<div id="add-document" style="display:none;">
7 7
<h2><%=l(:label_document_new)%></h2>
8
<% labelled_form_for @document, :url => project_documents_path(@project), :html => {:multipart => true} do |f| %>
8
<%= labelled_form_for @document, :url => project_documents_path(@project), :html => {:multipart => true} do |f| %>
9 9
<%= render :partial => 'form', :locals => {:f => f} %>
10 10
<p>
11 11
	<%= submit_tag l(:button_create) %>
trunk/app/views/documents/new.html.erb
1 1
<h2><%=l(:label_document_new)%></h2>
2 2

  
3
<% labelled_form_for @document, :url => project_documents_path(@project), :html => {:multipart => true} do |f| %>
3
<%= labelled_form_for @document, :url => project_documents_path(@project), :html => {:multipart => true} do |f| %>
4 4
  <%= render :partial => 'form', :locals => {:f => f} %>
5 5
  <p><%= submit_tag l(:button_create) %></p>
6 6
<% end %>
trunk/app/views/documents/show.html.erb
19 19
<% if authorize_for('documents', 'add_attachment') %>
20 20
<p><%= link_to l(:label_attachment_new), {}, :onclick => "Element.show('add_attachment_form'); Element.hide(this); Element.scrollTo('add_attachment_form'); return false;",
21 21
                                             :id => 'attach_files_link' %></p>
22
  <% form_tag({ :controller => 'documents', :action => 'add_attachment', :id => @document }, :multipart => true, :id => "add_attachment_form", :style => "display:none;") do %>
22
  <%= form_tag({ :controller => 'documents', :action => 'add_attachment', :id => @document }, :multipart => true, :id => "add_attachment_form", :style => "display:none;") do %>
23 23
  <div class="box">
24 24
  <p><%= render :partial => 'attachments/form' %></p>
25 25
  </div>
trunk/app/views/enumerations/destroy.html.erb
1 1
<h2><%= l(@enumeration.option_name) %>: <%=h @enumeration %></h2>
2 2

  
3
<% form_tag({}, :method => :delete) do %>
3
<%= form_tag({}, :method => :delete) do %>
4 4
<div class="box">
5 5
<p><strong><%= l(:text_enumeration_destroy_question, @enumeration.objects_count) %></strong></p>
6 6
<p><label for='reassign_to_id'><%= l(:text_enumeration_category_reassign_to) %></label>
trunk/app/views/enumerations/edit.html.erb
1 1
<h2><%= link_to l(@enumeration.option_name), enumerations_path %> &#187; <%=h @enumeration %></h2>
2 2

  
3
<% labelled_form_for :enumeration, @enumeration, :url => enumeration_path(@enumeration), :html => {:method => :put} do |f| %>
3
<%= labelled_form_for :enumeration, @enumeration, :url => enumeration_path(@enumeration), :html => {:method => :put} do |f| %>
4 4
  <%= render :partial => 'form', :locals => {:f => f} %>
5 5
  <%= submit_tag l(:button_save) %>
6 6
<% end %>
trunk/app/views/enumerations/new.html.erb
1 1
<h2><%= link_to l(@enumeration.option_name), enumerations_path %> &#187; <%=l(:label_enumeration_new)%></h2>
2 2

  
3
<% labelled_form_for :enumeration, @enumeration, :url => enumerations_path do |f| %>
3
<%= labelled_form_for :enumeration, @enumeration, :url => enumerations_path do |f| %>
4 4
  <%= f.hidden_field :type  %>
5 5
  <%= render :partial => 'form', :locals => {:f => f} %>
6 6
  <%= submit_tag l(:button_create) %>
trunk/app/views/files/new.html.erb
1 1
<h2><%=l(:label_attachment_new)%></h2>
2 2

  
3 3
<%= error_messages_for 'attachment' %>
4
<% form_tag(project_files_path(@project), :multipart => true, :class => "tabular") do %>
4
<%= form_tag(project_files_path(@project), :multipart => true, :class => "tabular") do %>
5 5
<div class="box">
6 6

  
7 7
<% if @versions.any? %>
trunk/app/views/gantts/show.html.erb
1 1
<% @gantt.view = self %>
2 2
<h2><%= @query.new_record? ? l(:label_gantt) : h(@query.name) %></h2>
3 3

  
4
<% form_tag({:controller => 'gantts', :action => 'show', :project_id => @project, :month => params[:month], :year => params[:year], :months => params[:months]}, :method => :get, :id => 'query_form') do %>
4
<%= form_tag({:controller => 'gantts', :action => 'show',
5
             :project_id => @project, :month => params[:month],
6
             :year => params[:year], :months => params[:months]},
7
             :method => :get, :id => 'query_form') do %>
5 8
<%= hidden_field_tag 'set_filter', '1' %>
6 9
<fieldset id="filters" class="collapsible <%= @query.new_record? ? "" : "collapsed" %>">
7 10
  <legend onclick="toggleFieldset(this);"><%= l(:label_filter_plural) %></legend>
trunk/app/views/groups/_general.html.erb
1
<% labelled_form_for @group do |f| %>
1
<%= labelled_form_for @group do |f| %>
2 2
<%= render :partial => 'form', :locals => { :f => f } %>
3 3
<%= submit_tag l(:button_save) %>
4 4
<% end %>
trunk/app/views/groups/_memberships.html.erb
16 16
  <td class="project"><%=h membership.project %></td>
17 17
  <td class="roles">
18 18
    <span id="member-<%= membership.id %>-roles"><%=h membership.roles.sort.collect(&:to_s).join(', ') %></span>
19
    <% remote_form_for(:membership, :url => { :action => 'edit_membership', :id => @group, :membership_id => membership },
20
                                    :html => { :id => "member-#{membership.id}-roles-form", :style => 'display:none;'}) do %>
19
    <%= form_for(:membership, :remote => true,
20
                 :url => { :action => 'edit_membership', :id => @group, :membership_id => membership },
21
                 :html => { :id => "member-#{membership.id}-roles-form", :style => 'display:none;'}) do %>
21 22
        <p><% roles.each do |role| %>
22 23
        <label><%= check_box_tag 'membership[role_ids][]', role.id, membership.roles.include?(role) %> <%=h role %></label><br />
23 24
        <% end %></p>
......
55 56
<div class="splitcontentright">
56 57
<% if projects.any? %>
57 58
<fieldset><legend><%=l(:label_project_new)%></legend>
58
<% remote_form_for(:membership, :url => { :action => 'edit_membership', :id => @group }) do %>
59
<%= form_for(:membership, :remote => true, :url => { :action => 'edit_membership', :id => @group }) do %>
59 60
<%= label_tag "membership_project_id", l(:description_choose_project), :class => "hidden-for-sighted" %>
60 61
<%= select_tag 'membership[project_id]', options_for_membership_project_select(@group, projects) %>
61 62
<p><%= l(:label_role_plural) %>:
trunk/app/views/groups/_users.html.erb
29 29
<div class="splitcontentright">
30 30
<% users = User.active.not_in_group(@group).all(:limit => 100) %>
31 31
<% if users.any? %>
32
  <% remote_form_for(@group, :url => group_users_path(@group), :html => {:method => :post}) do |f| %>
32
  <%= form_for(@group, :remote => true, :url => group_users_path(@group),
33
               :html => {:method => :post}) do |f| %>
33 34
    <fieldset><legend><%=l(:label_user_new)%></legend>
34 35

  
35 36
    <p><%= label_tag "user_search", l(:label_user_search) %><%= text_field_tag 'user_search', nil %></p>
trunk/app/views/groups/new.html.erb
1 1
<h2><%= link_to l(:label_group_plural), groups_path %> &#187; <%= l(:label_group_new) %></h2>
2 2

  
3
<% labelled_form_for @group do |f| %>
3
<%= labelled_form_for @group do |f| %>
4 4
<%= render :partial => 'form', :locals => { :f => f } %>
5 5
<p>
6 6
  <%= f.submit l(:button_create) %>
trunk/app/views/issue_categories/destroy.html.erb
1 1
<h2><%=l(:label_issue_category)%>: <%=h @category.name %></h2>
2 2

  
3
<% form_tag(issue_category_path(@category), :method => :delete) do %>
3
<%= form_tag(issue_category_path(@category), :method => :delete) do %>
4 4
<div class="box">
5 5
<p><strong><%= l(:text_issue_category_destroy_question, @issue_count) %></strong></p>
6 6
<p><label><%= radio_button_tag 'todo', 'nullify', true %> <%= l(:text_issue_category_destroy_assignments) %></label><br />
trunk/app/views/issue_statuses/edit.html.erb
1 1
<h2><%= link_to l(:label_issue_status_plural), issue_statuses_path %> &#187; <%=h @issue_status %></h2>
2 2

  
3
<% labelled_form_for @issue_status do |f| %>
3
<%= labelled_form_for @issue_status do |f| %>
4 4
  <%= render :partial => 'form', :locals => {:f => f} %>
5 5
  <%= submit_tag l(:button_save) %>
6 6
<% end %>
trunk/app/views/issue_statuses/new.html.erb
1 1
<h2><%= link_to l(:label_issue_status_plural), issue_statuses_path %> &#187; <%=l(:label_issue_status_new)%></h2>
2 2

  
3
<% labelled_form_for @issue_status do |f| %>
3
<%= labelled_form_for @issue_status do |f| %>
4 4
  <%= render :partial => 'form', :locals => {:f => f} %>
5 5
  <%= submit_tag l(:button_create) %>
6 6
<% end %>
trunk/app/views/issues/_action_menu.html.erb
1 1
<div class="contextual">
2 2
<%= link_to_if_authorized(l(:button_update), {:controller => 'issues', :action => 'edit', :id => @issue }, :onclick => 'showAndScrollTo("update", "notes"); return false;', :class => 'icon icon-edit', :accesskey => accesskey(:edit)) %>
3
<%= link_to_if_authorized l(:button_log_time), {:controller => 'timelog', :action => 'new', :issue_id => @issue}, :class => 'icon icon-time-add' %>
3
<%= link_to l(:button_log_time), new_issue_time_entry_path(@issue), :class => 'icon icon-time-add' if User.current.allowed_to?(:log_time, @project) %>
4 4
<%= watcher_tag(@issue, User.current) %>
5 5
<%= link_to_if_authorized l(:button_copy), {:controller => 'issues', :action => 'new', :project_id => @project, :copy_from => @issue}, :class => 'icon icon-copy' %>
6 6
<%= link_to l(:button_delete), issue_path(@issue), :confirm => issues_destroy_confirmation_message(@issue), :method => :delete, :class => 'icon icon-del' if User.current.allowed_to?(:delete_issues, @project) %>
trunk/app/views/issues/_attributes.html.erb
1
<% labelled_fields_for :issue, @issue do |f| %>
1
<%= labelled_fields_for :issue, @issue do |f| %>
2 2

  
3 3
<div class="splitcontent">
4 4
<div class="splitcontentleft">
... This diff was truncated because it exceeds the maximum size that can be displayed.

Also available in: Unified diff