editworkflow.cgi 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. #!/usr/bin/env perl -wT
  2. # -*- Mode: perl; indent-tabs-mode: nil -*-
  3. #
  4. # The contents of this file are subject to the Mozilla Public
  5. # License Version 1.1 (the "License"); you may not use this file
  6. # except in compliance with the License. You may obtain a copy of
  7. # the License at http://www.mozilla.org/MPL/
  8. #
  9. # Software distributed under the License is distributed on an "AS
  10. # IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
  11. # implied. See the License for the specific language governing
  12. # rights and limitations under the License.
  13. #
  14. # The Original Code is the Bugzilla Bug Tracking System.
  15. #
  16. # The Initial Developer of the Original Code is Frédéric Buclin.
  17. # Portions created by Frédéric Buclin are Copyright (C) 2007
  18. # Frédéric Buclin. All Rights Reserved.
  19. #
  20. # Contributor(s): Frédéric Buclin <LpSolit@gmail.com>
  21. use strict;
  22. use lib qw(. lib);
  23. use Bugzilla;
  24. use Bugzilla::Constants;
  25. use Bugzilla::Error;
  26. use Bugzilla::Token;
  27. use Bugzilla::Status;
  28. my $cgi = Bugzilla->cgi;
  29. my $dbh = Bugzilla->dbh;
  30. my $user = Bugzilla->login(LOGIN_REQUIRED);
  31. print $cgi->header();
  32. $user->in_group('admin')
  33. || ThrowUserError('auth_failure', {group => 'admin',
  34. action => 'modify',
  35. object => 'workflow'});
  36. my $action = $cgi->param('action') || 'edit';
  37. my $token = $cgi->param('token');
  38. sub get_workflow {
  39. my $dbh = Bugzilla->dbh;
  40. my $workflow = $dbh->selectall_arrayref('SELECT old_status, new_status, require_comment
  41. FROM status_workflow');
  42. my %workflow;
  43. foreach my $row (@$workflow) {
  44. my ($old, $new, $type) = @$row;
  45. $workflow{$old || 0}{$new} = $type;
  46. }
  47. return \%workflow;
  48. }
  49. sub load_template {
  50. my ($filename, $message) = @_;
  51. my $template = Bugzilla->template;
  52. my $vars = {};
  53. $vars->{'statuses'} = [Bugzilla::Status->get_all];
  54. $vars->{'workflow'} = get_workflow();
  55. $vars->{'token'} = issue_session_token("workflow_$filename");
  56. $vars->{'message'} = $message;
  57. $template->process("admin/workflow/$filename.html.tmpl", $vars)
  58. || ThrowTemplateError($template->error());
  59. exit;
  60. }
  61. if ($action eq 'edit') {
  62. load_template('edit');
  63. }
  64. elsif ($action eq 'update') {
  65. check_token_data($token, 'workflow_edit');
  66. my $statuses = [Bugzilla::Status->get_all];
  67. my $workflow = get_workflow();
  68. my $sth_insert = $dbh->prepare('INSERT INTO status_workflow (old_status, new_status)
  69. VALUES (?, ?)');
  70. my $sth_delete = $dbh->prepare('DELETE FROM status_workflow
  71. WHERE old_status = ? AND new_status = ?');
  72. my $sth_delnul = $dbh->prepare('DELETE FROM status_workflow
  73. WHERE old_status IS NULL AND new_status = ?');
  74. # Part 1: Initial bug statuses.
  75. foreach my $new (@$statuses) {
  76. if ($new->is_open && $cgi->param('w_0_' . $new->id)) {
  77. $sth_insert->execute(undef, $new->id)
  78. unless defined $workflow->{0}->{$new->id};
  79. }
  80. else {
  81. $sth_delnul->execute($new->id);
  82. }
  83. }
  84. # Part 2: Bug status changes.
  85. foreach my $old (@$statuses) {
  86. foreach my $new (@$statuses) {
  87. next if $old->id == $new->id;
  88. # All transitions to 'duplicate_or_move_bug_status' must be valid.
  89. if ($cgi->param('w_' . $old->id . '_' . $new->id)
  90. || ($new->name eq Bugzilla->params->{'duplicate_or_move_bug_status'}))
  91. {
  92. $sth_insert->execute($old->id, $new->id)
  93. unless defined $workflow->{$old->id}->{$new->id};
  94. }
  95. else {
  96. $sth_delete->execute($old->id, $new->id);
  97. }
  98. }
  99. }
  100. delete_token($token);
  101. load_template('edit', 'workflow_updated');
  102. }
  103. elsif ($action eq 'edit_comment') {
  104. load_template('comment');
  105. }
  106. elsif ($action eq 'update_comment') {
  107. check_token_data($token, 'workflow_comment');
  108. my $workflow = get_workflow();
  109. my $sth_update = $dbh->prepare('UPDATE status_workflow SET require_comment = ?
  110. WHERE old_status = ? AND new_status = ?');
  111. my $sth_updnul = $dbh->prepare('UPDATE status_workflow SET require_comment = ?
  112. WHERE old_status IS NULL AND new_status = ?');
  113. foreach my $old (keys %$workflow) {
  114. # Hashes cannot have undef as a key, so we use 0. But the DB
  115. # must store undef, for referential integrity.
  116. my $old_id_for_db = $old || undef;
  117. foreach my $new (keys %{$workflow->{$old}}) {
  118. my $comment_required = $cgi->param("c_${old}_$new") ? 1 : 0;
  119. next if ($workflow->{$old}->{$new} == $comment_required);
  120. if ($old_id_for_db) {
  121. $sth_update->execute($comment_required, $old_id_for_db, $new);
  122. }
  123. else {
  124. $sth_updnul->execute($comment_required, $new);
  125. }
  126. }
  127. }
  128. delete_token($token);
  129. load_template('comment', 'workflow_updated');
  130. }
  131. else {
  132. ThrowCodeError("action_unrecognized", {action => $action});
  133. }