"Fossies" - the Fresh Open Source Software Archive

Member "redmine-4.1.1/app/controllers/issues_controller.rb" (6 Apr 2020, 22643 Bytes) of package /linux/www/redmine-4.1.1.tar.gz:


As a special service "Fossies" has tried to format the requested text file into HTML format (style: standard) with prefixed line numbers. Alternatively you can here view or download the uninterpreted source code file. See also the latest Fossies "Diffs" side-by-side code changes report for "issues_controller.rb": 4.1.0_vs_4.1.1.

    1 # frozen_string_literal: true
    2 
    3 # Redmine - project management software
    4 # Copyright (C) 2006-2019  Jean-Philippe Lang
    5 #
    6 # This program is free software; you can redistribute it and/or
    7 # modify it under the terms of the GNU General Public License
    8 # as published by the Free Software Foundation; either version 2
    9 # of the License, or (at your option) any later version.
   10 #
   11 # This program is distributed in the hope that it will be useful,
   12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
   13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   14 # GNU General Public License for more details.
   15 #
   16 # You should have received a copy of the GNU General Public License
   17 # along with this program; if not, write to the Free Software
   18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
   19 
   20 class IssuesController < ApplicationController
   21   default_search_scope :issues
   22 
   23   before_action :find_issue, :only => [:show, :edit, :update, :issue_tab]
   24   before_action :find_issues, :only => [:bulk_edit, :bulk_update, :destroy]
   25   before_action :authorize, :except => [:index, :new, :create]
   26   before_action :find_optional_project, :only => [:index, :new, :create]
   27   before_action :build_new_issue_from_params, :only => [:new, :create]
   28   accept_rss_auth :index, :show
   29   accept_api_auth :index, :show, :create, :update, :destroy
   30 
   31   rescue_from Query::StatementInvalid, :with => :query_statement_invalid
   32 
   33   helper :journals
   34   helper :projects
   35   helper :custom_fields
   36   helper :issue_relations
   37   helper :watchers
   38   helper :attachments
   39   helper :queries
   40   include QueriesHelper
   41   helper :repositories
   42   helper :timelog
   43 
   44   def index
   45     use_session = !request.format.csv?
   46     retrieve_query(IssueQuery, use_session)
   47 
   48     if @query.valid?
   49       respond_to do |format|
   50         format.html {
   51           @issue_count = @query.issue_count
   52           @issue_pages = Paginator.new @issue_count, per_page_option, params['page']
   53           @issues = @query.issues(:offset => @issue_pages.offset, :limit => @issue_pages.per_page)
   54           render :layout => !request.xhr?
   55         }
   56         format.api  {
   57           @offset, @limit = api_offset_and_limit
   58           @query.column_names = %w(author)
   59           @issue_count = @query.issue_count
   60           @issues = @query.issues(:offset => @offset, :limit => @limit)
   61           Issue.load_visible_relations(@issues) if include_in_api_response?('relations')
   62         }
   63         format.atom {
   64           @issues = @query.issues(:limit => Setting.feeds_limit.to_i)
   65           render_feed(@issues, :title => "#{@project || Setting.app_title}: #{l(:label_issue_plural)}")
   66         }
   67         format.csv  {
   68           @issues = @query.issues(:limit => Setting.issues_export_limit.to_i)
   69           send_data(query_to_csv(@issues, @query, params[:csv]), :type => 'text/csv; header=present', :filename => 'issues.csv')
   70         }
   71         format.pdf  {
   72           @issues = @query.issues(:limit => Setting.issues_export_limit.to_i)
   73           send_file_headers! :type => 'application/pdf', :filename => 'issues.pdf'
   74         }
   75       end
   76     else
   77       respond_to do |format|
   78         format.html { render :layout => !request.xhr? }
   79         format.any(:atom, :csv, :pdf) { head 422 }
   80         format.api { render_validation_errors(@query) }
   81       end
   82     end
   83   rescue ActiveRecord::RecordNotFound
   84     render_404
   85   end
   86 
   87   def show
   88     @journals = @issue.visible_journals_with_index
   89     @has_changesets = @issue.changesets.visible.preload(:repository, :user).exists?
   90     @relations = @issue.relations.select {|r| r.other_issue(@issue) && r.other_issue(@issue).visible? }
   91 
   92     @journals.reverse! if User.current.wants_comments_in_reverse_order?
   93 
   94     if User.current.allowed_to?(:view_time_entries, @project)
   95       Issue.load_visible_spent_hours([@issue])
   96       Issue.load_visible_total_spent_hours([@issue])
   97     end
   98 
   99     respond_to do |format|
  100       format.html {
  101         @allowed_statuses = @issue.new_statuses_allowed_to(User.current)
  102         @priorities = IssuePriority.active
  103         @time_entry = TimeEntry.new(:issue => @issue, :project => @issue.project)
  104         @time_entries = @issue.time_entries.visible.preload(:activity, :user)
  105         @relation = IssueRelation.new
  106         retrieve_previous_and_next_issue_ids
  107         render :template => 'issues/show'
  108       }
  109       format.api {
  110         @changesets = @issue.changesets.visible.preload(:repository, :user).to_a
  111         @changesets.reverse! if User.current.wants_comments_in_reverse_order?
  112       }
  113       format.atom { render :template => 'journals/index', :layout => false, :content_type => 'application/atom+xml' }
  114       format.pdf  {
  115         send_file_headers! :type => 'application/pdf', :filename => "#{@project.identifier}-#{@issue.id}.pdf"
  116       }
  117     end
  118   end
  119 
  120   def new
  121     respond_to do |format|
  122       format.html { render :action => 'new', :layout => !request.xhr? }
  123       format.js
  124     end
  125   end
  126 
  127   def create
  128     unless User.current.allowed_to?(:add_issues, @issue.project, :global => true)
  129       raise ::Unauthorized
  130     end
  131     call_hook(:controller_issues_new_before_save, { :params => params, :issue => @issue })
  132     @issue.save_attachments(params[:attachments] || (params[:issue] && params[:issue][:uploads]))
  133     if @issue.save
  134       call_hook(:controller_issues_new_after_save, { :params => params, :issue => @issue})
  135       respond_to do |format|
  136         format.html {
  137           render_attachment_warning_if_needed(@issue)
  138           flash[:notice] = l(:notice_issue_successful_create, :id => view_context.link_to("##{@issue.id}", issue_path(@issue), :title => @issue.subject))
  139           redirect_after_create
  140         }
  141         format.api  { render :action => 'show', :status => :created, :location => issue_url(@issue) }
  142       end
  143       return
  144     else
  145       respond_to do |format|
  146         format.html {
  147           if @issue.project.nil?
  148             render_error :status => 422
  149           else
  150             render :action => 'new'
  151           end
  152         }
  153         format.api  { render_validation_errors(@issue) }
  154       end
  155     end
  156   end
  157 
  158   def edit
  159     return unless update_issue_from_params
  160 
  161     respond_to do |format|
  162       format.html { }
  163       format.js
  164     end
  165   end
  166 
  167   def update
  168     return unless update_issue_from_params
  169     @issue.save_attachments(params[:attachments] || (params[:issue] && params[:issue][:uploads]))
  170     saved = false
  171     begin
  172       saved = save_issue_with_child_records
  173     rescue ActiveRecord::StaleObjectError
  174       @conflict = true
  175       if params[:last_journal_id]
  176         @conflict_journals = @issue.journals_after(params[:last_journal_id]).to_a
  177         @conflict_journals.reject!(&:private_notes?) unless User.current.allowed_to?(:view_private_notes, @issue.project)
  178       end
  179     end
  180 
  181     if saved
  182       render_attachment_warning_if_needed(@issue)
  183       flash[:notice] = l(:notice_successful_update) unless @issue.current_journal.new_record? || params[:no_flash]
  184 
  185       respond_to do |format|
  186         format.html { redirect_back_or_default issue_path(@issue, previous_and_next_issue_ids_params) }
  187         format.api  { render_api_ok }
  188       end
  189     else
  190       respond_to do |format|
  191         format.html { render :action => 'edit' }
  192         format.api  { render_validation_errors(@issue) }
  193       end
  194     end
  195   end
  196 
  197   def issue_tab
  198     return render_error :status => 422 unless request.xhr?
  199     tab = params[:name]
  200 
  201     case tab
  202     when 'time_entries'
  203       @time_entries = @issue.time_entries.visible.preload(:activity, :user).to_a
  204       render :partial => 'issues/tabs/time_entries', :locals => {:time_entries => @time_entries}
  205     when 'changesets'
  206       @changesets = @issue.changesets.visible.preload(:repository, :user).to_a
  207       @changesets.reverse! if User.current.wants_comments_in_reverse_order?
  208       render :partial => 'issues/tabs/changesets', :locals => {:changesets => @changesets}
  209     end
  210   end
  211 
  212   # Bulk edit/copy a set of issues
  213   def bulk_edit
  214     @issues.sort!
  215     @copy = params[:copy].present?
  216     @notes = params[:notes]
  217 
  218     if @copy
  219       unless User.current.allowed_to?(:copy_issues, @projects)
  220         raise ::Unauthorized
  221       end
  222     else
  223       unless @issues.all?(&:attributes_editable?)
  224         raise ::Unauthorized
  225       end
  226     end
  227 
  228     edited_issues = Issue.where(:id => @issues.map(&:id)).to_a
  229 
  230     @values_by_custom_field = {}
  231     edited_issues.each do |issue|
  232       issue.custom_field_values.each do |c|
  233         if c.value_present?
  234           @values_by_custom_field[c.custom_field] ||= []
  235           @values_by_custom_field[c.custom_field] << issue.id
  236         end
  237       end
  238     end
  239 
  240     @allowed_projects = Issue.allowed_target_projects
  241     if params[:issue]
  242       @target_project = @allowed_projects.detect {|p| p.id.to_s == params[:issue][:project_id].to_s}
  243       if @target_project
  244         target_projects = [@target_project]
  245         edited_issues.each {|issue| issue.project = @target_project}
  246       end
  247     end
  248     target_projects ||= @projects
  249 
  250     @trackers = target_projects.map {|p| Issue.allowed_target_trackers(p) }.reduce(:&)
  251     if params[:issue]
  252       @target_tracker = @trackers.detect {|t| t.id.to_s == params[:issue][:tracker_id].to_s}
  253       if @target_tracker
  254         edited_issues.each {|issue| issue.tracker = @target_tracker}
  255       end
  256     end
  257 
  258     if @copy
  259       # Copied issues will get their default statuses
  260       @available_statuses = []
  261     else
  262       @available_statuses = edited_issues.map(&:new_statuses_allowed_to).reduce(:&)
  263     end
  264     if params[:issue]
  265       @target_status = @available_statuses.detect {|t| t.id.to_s == params[:issue][:status_id].to_s}
  266       if @target_status
  267         edited_issues.each {|issue| issue.status = @target_status}
  268       end
  269     end
  270 
  271     edited_issues.each do |issue|
  272       issue.custom_field_values.each do |c|
  273         if c.value_present? && @values_by_custom_field[c.custom_field]
  274           @values_by_custom_field[c.custom_field].delete(issue.id)
  275         end
  276       end
  277     end
  278     @values_by_custom_field.delete_if {|k,v| v.blank?}
  279 
  280     @custom_fields = edited_issues.map{|i| i.editable_custom_fields}.reduce(:&).select {|field| field.format.bulk_edit_supported}
  281     @assignables = target_projects.map(&:assignable_users).reduce(:&)
  282     @versions = target_projects.map {|p| p.shared_versions.open}.reduce(:&)
  283     @categories = target_projects.map {|p| p.issue_categories}.reduce(:&)
  284     if @copy
  285       @attachments_present = @issues.detect {|i| i.attachments.any?}.present?
  286       @subtasks_present = @issues.detect {|i| !i.leaf?}.present?
  287       @watchers_present = User.current.allowed_to?(:add_issue_watchers, @projects) &&
  288                             Watcher.where(:watchable_type => 'Issue',
  289                                           :watchable_id => @issues.map(&:id)).exists?
  290     end
  291 
  292     @safe_attributes = edited_issues.map(&:safe_attribute_names).reduce(:&)
  293 
  294     @issue_params = params[:issue] || {}
  295     @issue_params[:custom_field_values] ||= {}
  296   end
  297 
  298   def bulk_update
  299     @issues.sort!
  300     @copy = params[:copy].present?
  301 
  302     attributes = parse_params_for_bulk_update(params[:issue])
  303     copy_subtasks = (params[:copy_subtasks] == '1')
  304     copy_attachments = (params[:copy_attachments] == '1')
  305     copy_watchers = (params[:copy_watchers] == '1')
  306 
  307     if @copy
  308       unless User.current.allowed_to?(:copy_issues, @projects)
  309         raise ::Unauthorized
  310       end
  311       target_projects = @projects
  312       if attributes['project_id'].present?
  313         target_projects = Project.where(:id => attributes['project_id']).to_a
  314       end
  315       unless User.current.allowed_to?(:add_issues, target_projects)
  316         raise ::Unauthorized
  317       end
  318       unless User.current.allowed_to?(:add_issue_watchers, @projects)
  319         copy_watchers = false
  320       end
  321     else
  322       unless @issues.all?(&:attributes_editable?)
  323         raise ::Unauthorized
  324       end
  325     end
  326 
  327     unsaved_issues = []
  328     saved_issues = []
  329 
  330     if @copy && copy_subtasks
  331       # Descendant issues will be copied with the parent task
  332       # Don't copy them twice
  333       @issues.reject! {|issue| @issues.detect {|other| issue.is_descendant_of?(other)}}
  334     end
  335 
  336     @issues.each do |orig_issue|
  337       orig_issue.reload
  338       if @copy
  339         issue = orig_issue.copy(
  340           {},
  341           :attachments => copy_attachments,
  342           :subtasks => copy_subtasks,
  343           :watchers => copy_watchers,
  344           :link => link_copy?(params[:link_copy])
  345         )
  346       else
  347         issue = orig_issue
  348       end
  349       journal = issue.init_journal(User.current, params[:notes])
  350       issue.safe_attributes = attributes
  351       call_hook(:controller_issues_bulk_edit_before_save, { :params => params, :issue => issue })
  352       if issue.save
  353         saved_issues << issue
  354       else
  355         unsaved_issues << orig_issue
  356       end
  357     end
  358 
  359     if unsaved_issues.empty?
  360       flash[:notice] = l(:notice_successful_update) unless saved_issues.empty?
  361       if params[:follow]
  362         if @issues.size == 1 && saved_issues.size == 1
  363           redirect_to issue_path(saved_issues.first)
  364         elsif saved_issues.map(&:project).uniq.size == 1
  365           redirect_to project_issues_path(saved_issues.map(&:project).first)
  366         end
  367       else
  368         redirect_back_or_default _project_issues_path(@project)
  369       end
  370     else
  371       @saved_issues = @issues
  372       @unsaved_issues = unsaved_issues
  373       @issues = Issue.visible.where(:id => @unsaved_issues.map(&:id)).to_a
  374       bulk_edit
  375       render :action => 'bulk_edit'
  376     end
  377   end
  378 
  379   def destroy
  380     raise Unauthorized unless @issues.all?(&:deletable?)
  381 
  382     # all issues and their descendants are about to be deleted
  383     issues_and_descendants_ids = Issue.self_and_descendants(@issues).pluck(:id)
  384     time_entries = TimeEntry.where(:issue_id => issues_and_descendants_ids)
  385     @hours = time_entries.sum(:hours).to_f
  386 
  387     if @hours > 0
  388       case params[:todo]
  389       when 'destroy'
  390         # nothing to do
  391       when 'nullify'
  392         if Setting.timelog_required_fields.include?('issue_id')
  393           flash.now[:error] = l(:field_issue) + " " + ::I18n.t('activerecord.errors.messages.blank')
  394           return
  395         else
  396         time_entries.update_all(:issue_id => nil)
  397         end
  398       when 'reassign'
  399         reassign_to = @project && @project.issues.find_by_id(params[:reassign_to_id])
  400         if reassign_to.nil?
  401           flash.now[:error] = l(:error_issue_not_found_in_project)
  402           return
  403         elsif issues_and_descendants_ids.include?(reassign_to.id)
  404           flash.now[:error] = l(:error_cannot_reassign_time_entries_to_an_issue_about_to_be_deleted)
  405           return
  406         else
  407           time_entries.update_all(:issue_id => reassign_to.id, :project_id => reassign_to.project_id)
  408         end
  409       else
  410         # display the destroy form if it's a user request
  411         return unless api_request?
  412       end
  413     end
  414     @issues.each do |issue|
  415       begin
  416         issue.reload.destroy
  417       rescue ::ActiveRecord::RecordNotFound # raised by #reload if issue no longer exists
  418         # nothing to do, issue was already deleted (eg. by a parent)
  419       end
  420     end
  421     respond_to do |format|
  422       format.html { redirect_back_or_default _project_issues_path(@project) }
  423       format.api  { render_api_ok }
  424     end
  425   end
  426 
  427   # Overrides Redmine::MenuManager::MenuController::ClassMethods for
  428   # when the "New issue" tab is enabled
  429   def current_menu_item
  430     if Setting.new_item_menu_tab == '1' && [:new, :create].include?(action_name.to_sym)
  431       :new_issue
  432     else
  433       super
  434     end
  435   end
  436 
  437   private
  438 
  439   def retrieve_previous_and_next_issue_ids
  440     if params[:prev_issue_id].present? || params[:next_issue_id].present?
  441       @prev_issue_id = params[:prev_issue_id].presence.try(:to_i)
  442       @next_issue_id = params[:next_issue_id].presence.try(:to_i)
  443       @issue_position = params[:issue_position].presence.try(:to_i)
  444       @issue_count = params[:issue_count].presence.try(:to_i)
  445     else
  446       retrieve_query_from_session
  447       if @query
  448         @per_page = per_page_option
  449         limit = 500
  450         issue_ids = @query.issue_ids(:limit => (limit + 1))
  451         if (idx = issue_ids.index(@issue.id)) && idx < limit
  452           if issue_ids.size < 500
  453             @issue_position = idx + 1
  454             @issue_count = issue_ids.size
  455           end
  456           @prev_issue_id = issue_ids[idx - 1] if idx > 0
  457           @next_issue_id = issue_ids[idx + 1] if idx < (issue_ids.size - 1)
  458         end
  459         query_params = @query.as_params
  460         if @issue_position
  461           query_params = query_params.merge(:page => (@issue_position / per_page_option) + 1, :per_page => per_page_option)
  462         end
  463         @query_path = _project_issues_path(@query.project, query_params)
  464       end
  465     end
  466   end
  467 
  468   def previous_and_next_issue_ids_params
  469     {
  470       :prev_issue_id => params[:prev_issue_id],
  471       :next_issue_id => params[:next_issue_id],
  472       :issue_position => params[:issue_position],
  473       :issue_count => params[:issue_count]
  474     }.reject {|k,v| k.blank?}
  475   end
  476 
  477   # Used by #edit and #update to set some common instance variables
  478   # from the params
  479   def update_issue_from_params
  480     @time_entry = TimeEntry.new(:issue => @issue, :project => @issue.project)
  481     if params[:time_entry]
  482       @time_entry.safe_attributes = params[:time_entry]
  483     end
  484 
  485     @issue.init_journal(User.current)
  486 
  487     issue_attributes = params[:issue]
  488     issue_attributes[:assigned_to_id] = User.current.id if issue_attributes && issue_attributes[:assigned_to_id] == 'me'
  489     if issue_attributes && params[:conflict_resolution]
  490       case params[:conflict_resolution]
  491       when 'overwrite'
  492         issue_attributes = issue_attributes.dup
  493         issue_attributes.delete(:lock_version)
  494       when 'add_notes'
  495         issue_attributes = issue_attributes.slice(:notes, :private_notes)
  496       when 'cancel'
  497         redirect_to issue_path(@issue)
  498         return false
  499       end
  500     end
  501     @issue.safe_attributes = issue_attributes
  502     @priorities = IssuePriority.active
  503     @allowed_statuses = @issue.new_statuses_allowed_to(User.current)
  504     true
  505   end
  506 
  507   # Used by #new and #create to build a new issue from the params
  508   # The new issue will be copied from an existing one if copy_from parameter is given
  509   def build_new_issue_from_params
  510     @issue = Issue.new
  511     if params[:copy_from]
  512       begin
  513         @issue.init_journal(User.current)
  514         @copy_from = Issue.visible.find(params[:copy_from])
  515         unless User.current.allowed_to?(:copy_issues, @copy_from.project)
  516           raise ::Unauthorized
  517         end
  518         @link_copy = link_copy?(params[:link_copy]) || request.get?
  519         @copy_attachments = params[:copy_attachments].present? || request.get?
  520         @copy_subtasks = params[:copy_subtasks].present? || request.get?
  521         @copy_watchers = User.current.allowed_to?(:add_issue_watchers, @project)
  522         @issue.copy_from(@copy_from, :attachments => @copy_attachments, :subtasks => @copy_subtasks, :watchers => @copy_watchers, :link => @link_copy)
  523         @issue.parent_issue_id = @copy_from.parent_id
  524       rescue ActiveRecord::RecordNotFound
  525         render_404
  526         return
  527       end
  528     end
  529     @issue.project = @project
  530     if request.get?
  531       @issue.project ||= @issue.allowed_target_projects.first
  532     end
  533     @issue.author ||= User.current
  534     @issue.start_date ||= User.current.today if Setting.default_issue_start_date_to_creation_date?
  535 
  536     attrs = (params[:issue] || {}).deep_dup
  537     if action_name == 'new' && params[:was_default_status] == attrs[:status_id]
  538       attrs.delete(:status_id)
  539     end
  540     if action_name == 'new' && params[:form_update_triggered_by] == 'issue_project_id'
  541       # Discard submitted version when changing the project on the issue form
  542       # so we can use the default version for the new project
  543       attrs.delete(:fixed_version_id)
  544     end
  545     attrs[:assigned_to_id] = User.current.id if attrs[:assigned_to_id] == 'me'
  546     @issue.safe_attributes = attrs
  547 
  548     if @issue.project
  549       @issue.tracker ||= @issue.allowed_target_trackers.first
  550       if @issue.tracker.nil?
  551         if @issue.project.trackers.any?
  552           # None of the project trackers is allowed to the user
  553           render_error :message => l(:error_no_tracker_allowed_for_new_issue_in_project), :status => 403
  554         else
  555           # Project has no trackers
  556           render_error l(:error_no_tracker_in_project)
  557         end
  558         return false
  559       end
  560       if @issue.status.nil?
  561         render_error l(:error_no_default_issue_status)
  562         return false
  563       end
  564     elsif request.get?
  565       render_error :message => l(:error_no_projects_with_tracker_allowed_for_new_issue), :status => 403
  566       return false
  567     end
  568 
  569     @priorities = IssuePriority.active
  570     @allowed_statuses = @issue.new_statuses_allowed_to(User.current)
  571   end
  572 
  573   # Saves @issue and a time_entry from the parameters
  574   def save_issue_with_child_records
  575     Issue.transaction do
  576       if params[:time_entry] && (params[:time_entry][:hours].present? || params[:time_entry][:comments].present?) && User.current.allowed_to?(:log_time, @issue.project)
  577         time_entry = @time_entry || TimeEntry.new
  578         time_entry.project = @issue.project
  579         time_entry.issue = @issue
  580         time_entry.author = User.current
  581         time_entry.user = User.current
  582         time_entry.spent_on = User.current.today
  583         time_entry.safe_attributes = params[:time_entry]
  584         @issue.time_entries << time_entry
  585       end
  586 
  587       call_hook(:controller_issues_edit_before_save, { :params => params, :issue => @issue, :time_entry => time_entry, :journal => @issue.current_journal})
  588       if @issue.save
  589         call_hook(:controller_issues_edit_after_save, { :params => params, :issue => @issue, :time_entry => time_entry, :journal => @issue.current_journal})
  590       else
  591         raise ActiveRecord::Rollback
  592       end
  593     end
  594   end
  595 
  596   # Returns true if the issue copy should be linked
  597   # to the original issue
  598   def link_copy?(param)
  599     case Setting.link_copied_issue
  600     when 'yes'
  601       true
  602     when 'no'
  603       false
  604     when 'ask'
  605       param == '1'
  606     end
  607   end
  608 
  609   # Redirects user after a successful issue creation
  610   def redirect_after_create
  611     if params[:continue]
  612       url_params = {}
  613       url_params[:issue] = {:tracker_id => @issue.tracker, :parent_issue_id => @issue.parent_issue_id}.reject {|k,v| v.nil?}
  614       url_params[:back_url] = params[:back_url].presence
  615 
  616       if params[:project_id]
  617         redirect_to new_project_issue_path(@issue.project, url_params)
  618       else
  619         url_params[:issue].merge! :project_id => @issue.project_id
  620         redirect_to new_issue_path(url_params)
  621       end
  622     else
  623       redirect_back_or_default issue_path(@issue)
  624     end
  625   end
  626 end