Bug 117760 - Templatise showvotes.cgi and incorporate doeditvotes.cgi. Patch by gerv, r=myk, bbaetz.

This commit is contained in:
gerv%gerv.net 2002-04-05 07:13:55 +00:00
Родитель 4adce79fd2
Коммит 4276a12572
8 изменённых файлов: 602 добавлений и 15 удалений

Просмотреть файл

@ -1410,7 +1410,7 @@ Actions:
};
if ($loggedin) {
if ($::anyvotesallowed) {
$html .= " | <A HREF=\"showvotes.cgi\">My votes</A>\n";
$html .= " | <A HREF=\"votes.cgi?action=show_user\">My votes</A>\n";
}
}
if ($loggedin) {

Просмотреть файл

@ -287,9 +287,10 @@
</th>
<td>
[% bug.votes %]&nbsp;&nbsp;&nbsp;
<a href="showvotes.cgi?bug_id=[% bug.bug_id %]">Show votes for this
bug</a>&nbsp;&nbsp;&nbsp;
<a href="showvotes.cgi?voteon=[% bug.bug_id %]">Vote for this bug</a>
<a href="votes.cgi?action=show_bug&bug_id=[% bug.bug_id %]">Show
votes for this bug</a>&nbsp;&nbsp;&nbsp;
<a href="votes.cgi?action=show_user&bug_id=[% bug.bug_id %]">Vote
for this bug</a>
</td>
</tr>
</table>

Просмотреть файл

@ -97,7 +97,7 @@ function normal_keypress_handler( aEvent ) {
<text class="text-link" onclick="load_relative_url('[% mybugsurl FILTER html %]')" value="my bugs"/>
[% END %]
[% IF anyvotesallowed && username %]
<text class="text-link" onclick="load_relative_url('showvotes.cgi')" value="my votes"/>
<text class="text-link" onclick="load_relative_url('votes.cgi?action=show_user')" value="my votes"/>
[% END %]
[% FOREACH name = namedqueries %]

Просмотреть файл

@ -0,0 +1,46 @@
<!-- 1.0@bugzilla.org -->
[%# The contents of this file are subject to the Mozilla Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is the Bugzilla Bug Tracking System.
#
# The Initial Developer of the Original Code is Netscape Communications
# Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s): Gervase Markham <gerv@gerv.net>
#%]
[% INCLUDE global/header
title = "Remove your votes?"
%]
<p>
You are about to remove all of your bug votes. Are you sure you wish to
remove your vote from every bug you've voted on?
</p>
<form action="votes.cgi" method="post">
<input type="hidden" name="action" value="vote">
<p>
<input type="radio" name="delete_all_votes" value="1">
Yes, delete all my votes
</p>
<p>
<input type="radio" name="delete_all_votes" value="0" checked="checked">
No, go back and review my votes
</p>
<p>
<input type="submit" value="Submit">
</p>
</form>
[% INCLUDE global/footer %]

Просмотреть файл

@ -0,0 +1,49 @@
<!-- 1.0@bugzilla.org -->
[%# The contents of this file are subject to the Mozilla Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is the Bugzilla Bug Tracking System.
#
# The Initial Developer of the Original Code is Netscape Communications
# Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s): Gervase Markham <gerv@gerv.net>
#%]
[% INCLUDE global/header
title = "Show Votes"
h2 = "Bug <a href='show_bug.cgi?id=$bug_id'>$bug_id</a>"
%]
<table cellspacing="4">
<tr>
<th>Who</th>
<th>Number of votes</th>
</tr>
[% FOREACH user = users %]
<tr>
<td>
<a href="votes.cgi?action=show_user&user=[% user.name %]">
[% user.name %]
</a>
</td>
<td align="right">
[% user.count %]
</td>
</tr>
[% END %]
</table>
<p>Total votes: [% total %]</p>
[% INCLUDE global/footer %]

Просмотреть файл

@ -0,0 +1,130 @@
<!-- 1.0@bugzilla.org -->
[%# The contents of this file are subject to the Mozilla Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is the Bugzilla Bug Tracking System.
#
# The Initial Developer of the Original Code is Netscape Communications
# Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s): Gervase Markham <gerv@gerv.net>
#%]
[% INCLUDE global/header
title = "Show Votes"
h2 = user.name
%]
[% IF votes_recorded %]
<p>
<font color="red">
The changes to your votes have been saved.
</font>
</p>
[% ELSE %]
<br>
[% END %]
[% IF products.size %]
<form action="votes.cgi">
<input type="hidden" name="action" value="vote">
<table cellspacing="4">
<tr>
<td></td>
<th>Bug #</th>
<th>Summary</th>
<th>Votes</th>
</tr>
[% FOREACH product = products %]
<tr>
<th>[% product.name FILTER html %]</th>
<td></td>
[% IF product.maxperbug < product.maxvotes AND
product.maxperbug > 1 %]
<td>
<font size="-1">
(Note: only [% product.maxperbug %] vote
[% "s" IF product.maxperbug != 1 %] allowed per bug in
this product.)
</font>
</td>
[% END %]
</tr>
[% FOREACH bug = product.bugs %]
<tr>
<td></td>
<td>
[% "<strike>" IF NOT bug.opened %]
<a href="show_bug.cgi?id=[% bug.id %]">
[% bug.id %]</a>
[% "</strike>" IF NOT bug.opened %]
</td>
<td>
<a href="votes.cgi?action=show_bug&bug_id=[% bug.id %]">
[% bug.summary FILTER html %]
</a>
</td>
<td align="right">
[% IF user.canedit %]
[% IF product.onevoteonly %]
<input type="checkbox" name="[% bug.id %]" value="1"
[% " checked" IF bug.count %]>
[% ELSE %]
<input name="[% bug.id %]" value="[% bug.count %]"
size="2">
[% END %]
[% ELSE %]
[% bug.count %]
[% END %]
</td>
</tr>
[% END %]
<tr>
<td></td>
<td colspan="3">[% product.total %] vote
[% "s" IF product.total != 1 %] used out of [% product.maxvotes %]
allowed.
<br>
<br>
</td>
</tr>
[% END %]
</table>
[% IF user.canedit %]
<input type="submit" value="Change My Votes">
<br>
<br>
To change your votes, type in new numbers (using zero to
mean no votes) or change the checkbox, and then click
<b>Change My Votes</b>.
[% END %]
</form>
[% ELSE %]
<p>
[% IF user.canedit %]
You are
[% ELSE %]
This user is
[% END %]
currently not voting on any bugs.
</p>
[% END %]
<p>
<a href="votehelp.html">Help with voting</a>.
</p>
[% INCLUDE global/footer %]

Просмотреть файл

@ -1,4 +1,4 @@
<HTML>
<html>
<!--
The contents of this file are subject to the Mozilla Public
License Version 1.1 (the "License"); you may not use this file
@ -21,25 +21,29 @@
Contributor(s): Terry Weissman <terry@mozilla.org>
-->
<head>
<title>Bugzilla Voting</title>
</head>
<TITLE>Bugzilla Voting</TITLE>
<H1>Bugzilla Voting</H1>
<body>
<h1>Bugzilla Voting</h1>
<p>
Bugzilla has a "voting" feature. Each product allows users to have a
certain number of votes. (Some products may not allow any, which
means you can't vote on things in that product at all.) With your
vote, you indicate which bugs you think are the most important to be
fixed.
</p>
<p>
Depending on how the administrator has configured the relevant
product, you may be able to vote for the same bug more than one time.
But remember, you only have so many votes to use in total! So, you
can either vote a little for many bugs, or vote a lot for a few bugs.
</p>
<p>
To look at votes:
<ul>
@ -47,9 +51,9 @@ To look at votes:
"At least ___ votes" field. This will show you items that
match your query that have at least one vote.
</ul>
</p>
<p>
To vote for a bug:
<ul>
@ -64,9 +68,12 @@ To vote for a bug:
You will automatically get email notifying you of any changes that
occur on bugs you vote for.
</p>
<p>
You may review your votes at any time by clicking on the "My Votes" link in
the page footer (which appears on most pages), or by clicking <a
href="showvotes.cgi">here</a>.
You may review your votes at any time by clicking on the "<a
href="votes.cgi?action=show_user">My Votes</a>" link in
the page footer.
</p>
</body>
</html>

354
webtools/bugzilla/votes.cgi Executable file
Просмотреть файл

@ -0,0 +1,354 @@
#!/usr/bonsaitools/bin/perl -wT
# -*- Mode: perl; indent-tabs-mode: nil -*-
#
# The contents of this file are subject to the Mozilla Public
# License Version 1.1 (the "License"); you may not use this file
# except in compliance with the License. You may obtain a copy of
# the License at http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is the Bugzilla Bug Tracking System.
#
# The Initial Developer of the Original Code is Netscape Communications
# Corporation. Portions created by Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s): Terry Weissman <terry@mozilla.org>
# Stephan Niemz <st.n@gmx.net>
# Christopher Aillon <christopher@aillon.com>
# Gervase Markham <gerv@gerv.net>
use diagnostics;
use strict;
use lib ".";
require "CGI.pl";
use vars qw($usergroupset);
# Use global template variables
use vars qw($template $vars);
ConnectToDatabase();
# If the action is show_bug, you need a bug_id.
# If the action is show_user, you can supply a userid to show the votes for
# another user, otherwise you see your own.
# If the action is vote, your votes are set to those encoded in the URL as
# <bug_id>=<votes>.
#
# If no action is defined, we default to show_bug if a bug_id is given,
# otherwise to show_user.
my $action = $::FORM{'action'} ||
($::FORM{'bug_id'} ? "show_bug" : "show_user");
if ($action eq "show_bug" ||
($action eq "show_user" && defined($::FORM{'user'})))
{
quietly_check_login();
}
else {
confirm_login();
}
################################################################################
# Begin Data/Security Validation
################################################################################
# Make sure the bug ID is a positive integer representing an existing
# bug that the user is authorized to access.
if (defined $::FORM{'bug_id'}) {
ValidateBugID($::FORM{'bug_id'});
}
################################################################################
# End Data/Security Validation
################################################################################
if ($action eq "show_bug") {
show_bug();
}
elsif ($action eq "show_user") {
show_user();
}
elsif ($action eq "vote") {
record_votes();
show_user();
}
else {
DisplayError("Unknown action: " . html_quote($action));
}
exit;
# Display the names of all the people voting for this one bug.
sub show_bug {
my $bug_id = $::FORM{'bug_id'}
|| DisplayError("Please give a bug ID to show the votes for.")
&& exit;
my $total = 0;
my @users;
SendSQL("SELECT profiles.login_name, votes.who, votes.count
FROM votes, profiles
WHERE votes.bug_id = $bug_id
AND profiles.userid = votes.who");
while (MoreSQLData()) {
my ($name, $userid, $count) = (FetchSQLData());
push (@users, { name => $name, id => $userid, count => $count });
$total += $count;
}
$vars->{'bug_id'} = $bug_id;
$vars->{'users'} = \@users;
$vars->{'total'} = $total;
print "Content-type: text/html\n\n";
$template->process("voting/show-bug-votes.html.tmpl", $vars)
|| DisplayError("Template process failed: " . $template->error())
&& exit;
}
# Display all the votes for a particular user. If it's the user
# doing the viewing, give them the option to edit them too.
sub show_user {
GetVersionTable();
# If a bug_id is given, and we're editing, we'll add it to the votes list.
my $bug_id = $::FORM{'bug_id'} || "";
my $name = $::FORM{'user'} || $::COOKIE{'Bugzilla_login'};
my $who = DBname_to_id($name);
# After DBNameToIdAndCheck is templatised and prints a Content-Type,
# the above should revert to a call to that function, and this
# special error handling should go away.
if (!$who) {
DisplayError(html_quote($name) . " is not a valid username.\n");
exit;
}
my $canedit = 1 if ($name eq $::COOKIE{'Bugzilla_login'});
SendSQL("LOCK TABLES bugs READ, products READ, votes WRITE,
cc AS selectVisible_cc READ");
if ($canedit && $bug_id) {
# Make sure there is an entry for this bug
# in the vote table, just so that things display right.
SendSQL("SELECT votes.count FROM votes
WHERE votes.bug_id = $bug_id AND votes.who = $who");
if (!FetchOneColumn()) {
SendSQL("INSERT INTO votes (who, bug_id, count)
VALUES ($who, $bug_id, 0)");
}
}
# Calculate the max votes per bug for each product; doing it here means
# we can do it all in one query.
my %maxvotesperbug;
if($canedit) {
SendSQL("SELECT products.product, products.maxvotesperbug
FROM products");
while (MoreSQLData()) {
my ($prod, $max) = FetchSQLData();
$maxvotesperbug{$prod} = $max;
}
}
my @products;
# Read the votes data for this user for each product
foreach my $product (sort(keys(%::prodmaxvotes))) {
next if $::prodmaxvotes{$product} <= 0;
my @bugs;
my $total = 0;
my $onevoteonly = 0;
SendSQL("SELECT votes.bug_id, votes.count, bugs.short_desc,
bugs.bug_status
FROM votes, bugs
WHERE votes.who = $who
AND votes.bug_id = bugs.bug_id
AND bugs.product = " . SqlQuote($product) .
"ORDER BY votes.bug_id");
while (MoreSQLData()) {
my ($id, $count, $summary, $status) = FetchSQLData();
next if !defined($status);
$total += $count;
# Next if user can't see this bug. So, the totals will be correct
# and they can see there are votes 'missing', but not on what bug
# they are. This seems a reasonable compromise; the alternative is
# to lie in the totals.
next if !CanSeeBug($id, $who, $usergroupset);
push (@bugs, { id => $id,
summary => $summary,
count => $count,
opened => IsOpenedState($status) });
}
$onevoteonly = 1 if (min($::prodmaxvotes{$product},
$maxvotesperbug{$product}) == 1);
# Only add the product for display if there are any bugs in it.
if ($#bugs > -1) {
push (@products, { name => $product,
bugs => \@bugs,
onevoteonly => $onevoteonly,
total => $total,
maxvotes => $::prodmaxvotes{$product},
maxperbug => $maxvotesperbug{$product} });
}
}
SendSQL("DELETE FROM votes WHERE count <= 0");
SendSQL("UNLOCK TABLES");
$vars->{'user'} = { canedit => $canedit, name => $name, id => $who };
$vars->{'products'} = \@products;
print "Content-type: text/html\n\n";
$template->process("voting/show-user-votes.html.tmpl", $vars)
|| DisplayError("Template process failed: " . $template->error())
&& exit;
}
# Update the user's votes in the database.
sub record_votes {
############################################################################
# Begin Data/Security Validation
############################################################################
# Build a list of bug IDs for which votes have been submitted. Votes
# are submitted in form fields in which the field names are the bug
# IDs and the field values are the number of votes.
my @buglist = grep {/^[1-9][0-9]*$/} keys(%::FORM);
# If no bugs are in the buglist, let's make sure the user gets notified
# that their votes will get nuked if they continue.
if (scalar(@buglist) == 0) {
if (!defined($::FORM{'delete_all_votes'})) {
print "Content-type: text/html\n\n";
$template->process("voting/delete-all-votes.html.tmpl", $vars)
|| DisplayError("Template process failed: " . $template->error());
exit();
}
elsif ($::FORM{'delete_all_votes'} == 0) {
print "Location: votes.cgi\n\n";
exit();
}
}
# Call ValidateBugID on each bug ID to make sure it is a positive
# integer representing an existing bug that the user is authorized
# to access, and make sure the number of votes submitted is also
# a non-negative integer (a series of digits not preceded by a
# minus sign).
foreach my $id (@buglist) {
ValidateBugID($id);
detaint_natural($::FORM{$id})
|| DisplayError("Only use non-negative numbers for your bug votes.")
&& exit;
}
############################################################################
# End Data/Security Validation
############################################################################
GetVersionTable();
my $who = DBNameToIdAndCheck($::COOKIE{'Bugzilla_login'});
# If the user is voting for bugs, make sure they aren't overstuffing
# the ballot box.
if (scalar(@buglist)) {
SendSQL("SELECT bugs.bug_id, bugs.product, products.maxvotesperbug
FROM bugs, products
WHERE products.product = bugs.product
AND bugs.bug_id IN (" . join(", ", @buglist) . ")");
my %prodcount;
while (MoreSQLData()) {
my ($id, $prod, $max) = FetchSQLData();
$prodcount{$prod} ||= 0;
$prodcount{$prod} += $::FORM{$id};
# Make sure we haven't broken the votes-per-bug limit
if ($::FORM{$id} > $max) {
$prod = html_quote($prod);
my $votes = html_quote($::FORM{$id});
DisplayError("You may only use at most $max votes for a single
bug in the <tt>$prod</tt> product, but you are
trying to use $votes.", "Illegal vote");
exit();
}
}
# Make sure we haven't broken the votes-per-product limit
foreach my $prod (keys(%prodcount)) {
if ($prodcount{$prod} > $::prodmaxvotes{$prod}) {
$prod = html_quote($prod);
DisplayError("You may only use at most $::prodmaxvotes{$prod}
votes for bugs in the <tt>$prod</tt> product,
but you are trying to use $prodcount{$prod}.",
"Illegal vote");
exit();
}
}
}
# Update the user's votes in the database. If the user did not submit
# any votes, they may be using a form with checkboxes to remove all their
# votes (checkboxes are not submitted along with other form data when
# they are not checked, and Bugzilla uses them to represent single votes
# for products that only allow one vote per bug). In that case, we still
# need to clear the user's votes from the database.
my %affected;
SendSQL("LOCK TABLES bugs write, votes write, products read");
# Take note of, and delete the user's old votes from the database.
SendSQL("SELECT bug_id FROM votes WHERE who = $who");
while (MoreSQLData()) {
my $id = FetchOneColumn();
$affected{$id} = 1;
}
SendSQL("DELETE FROM votes WHERE who = $who");
# Insert the new values in their place
foreach my $id (@buglist) {
if ($::FORM{$id} > 0) {
SendSQL("INSERT INTO votes (who, bug_id, count)
VALUES ($who, $id, $::FORM{$id})");
}
$affected{$id} = 1;
}
# Update the cached values in the bugs table
foreach my $id (keys %affected) {
SendSQL("SELECT sum(count) FROM votes WHERE bug_id = $id");
my $v = FetchOneColumn();
$v ||= 0;
SendSQL("UPDATE bugs SET votes = $v, delta_ts=delta_ts
WHERE bug_id = $id");
CheckIfVotedConfirmed($id, $who);
}
SendSQL("UNLOCK TABLES");
$vars->{'votes_recorded'} = 1;
}