diff options
author | lpsolit%gmail.com <> | 2006-02-21 22:08:18 +0100 |
---|---|---|
committer | lpsolit%gmail.com <> | 2006-02-21 22:08:18 +0100 |
commit | da9ac9431cc959eedef78a5118ac3b4c6fbf7d03 (patch) | |
tree | 840e490e59e6a28c083b31a7281877a74105b997 | |
parent | 7780ace7e977d39ef9c904697e355248becf192b (diff) | |
download | bugzilla-da9ac9431cc959eedef78a5118ac3b4c6fbf7d03.tar.gz bugzilla-da9ac9431cc959eedef78a5118ac3b4c6fbf7d03.tar.xz |
Bug 287325: Ability to add custom plain-text fields to a Bug - Patch by Myk Melez <myk@mozilla.org> r=mkanat a=justdave
-rw-r--r-- | Bugzilla.pm | 12 | ||||
-rwxr-xr-x | Bugzilla/Bug.pm | 116 | ||||
-rw-r--r-- | Bugzilla/Constants.pm | 13 | ||||
-rw-r--r-- | Bugzilla/DB/Schema.pm | 5 | ||||
-rw-r--r-- | Bugzilla/Field.pm | 342 | ||||
-rwxr-xr-x | checksetup.pl | 9 | ||||
-rwxr-xr-x | customfield.pl | 88 | ||||
-rwxr-xr-x | editcomponents.cgi | 1 | ||||
-rwxr-xr-x | editmilestones.cgi | 1 | ||||
-rwxr-xr-x | editproducts.cgi | 1 | ||||
-rwxr-xr-x | process_bug.cgi | 14 | ||||
-rwxr-xr-x | show_activity.cgi | 1 | ||||
-rwxr-xr-x | show_bug.cgi | 2 | ||||
-rwxr-xr-x | showdependencytree.cgi | 1 | ||||
-rwxr-xr-x | summarize_time.cgi | 1 | ||||
-rw-r--r-- | template/en/default/bug/edit.html.tmpl | 9 | ||||
-rw-r--r-- | template/en/default/bug/field.html.tmpl | 36 |
17 files changed, 565 insertions, 87 deletions
diff --git a/Bugzilla.pm b/Bugzilla.pm index 2a0a66014..eca0ebf63 100644 --- a/Bugzilla.pm +++ b/Bugzilla.pm @@ -35,6 +35,7 @@ use Bugzilla::Template; use Bugzilla::User; use Bugzilla::Error; use Bugzilla::Util; +use Bugzilla::Field; use File::Basename; @@ -276,6 +277,17 @@ sub switch_to_main_db { return $class->dbh; } +sub get_fields { + my $class = shift; + my $criteria = shift; + return Bugzilla::Field::match($criteria); +} + +sub custom_field_names { + # Get a list of custom fields and convert it into a list of their names. + return map($_->{name}, Bugzilla::Field::match({ custom=>1, obsolete=>0 })); +} + # Private methods # Per process cleanup diff --git a/Bugzilla/Bug.pm b/Bugzilla/Bug.pm index cab54d7da..22f62f186 100755 --- a/Bugzilla/Bug.pm +++ b/Bugzilla/Bug.pm @@ -69,41 +69,6 @@ use constant MAX_COMMENT_LENGTH => 65535; ##################################################################### -sub fields { - # Keep this ordering in sync with bugzilla.dtd - my @fields = qw(bug_id alias creation_ts short_desc delta_ts - reporter_accessible cclist_accessible - classification_id classification - product component version rep_platform op_sys - bug_status resolution - bug_file_loc status_whiteboard keywords - priority bug_severity target_milestone - dependson blocked votes everconfirmed - reporter assigned_to cc - ); - - if (Param('useqacontact')) { - push @fields, "qa_contact"; - } - - if (Param('timetrackinggroup')) { - push @fields, qw(estimated_time remaining_time actual_time deadline); - } - - return @fields; -} - -my %ok_field; -foreach my $key (qw(error groups - longdescs milestoneurl attachments - isopened isunconfirmed - flag_types num_attachment_flag_types - show_attachment_flags use_keywords any_flags_requesteeble - ), - fields()) { - $ok_field{$key}++; -} - # create a new empty bug # sub new { @@ -162,6 +127,11 @@ sub initBug { $self->{'who'} = new Bugzilla::User($user_id); + my $custom_fields = ""; + if (length(Bugzilla->custom_field_names) > 0) { + $custom_fields = ", " . join(", ", Bugzilla->custom_field_names); + } + my $query = " SELECT bugs.bug_id, alias, products.classification_id, classifications.name, @@ -175,7 +145,8 @@ sub initBug { delta_ts, COALESCE(SUM(votes.vote_count), 0), everconfirmed, reporter_accessible, cclist_accessible, estimated_time, remaining_time, " . - $dbh->sql_date_format('deadline', '%Y-%m-%d') . " + $dbh->sql_date_format('deadline', '%Y-%m-%d') . + $custom_fields . " FROM bugs LEFT JOIN votes ON bugs.bug_id = votes.bug_id @@ -212,7 +183,8 @@ sub initBug { "target_milestone", "qa_contact_id", "status_whiteboard", "creation_ts", "delta_ts", "votes", "everconfirmed", "reporter_accessible", "cclist_accessible", - "estimated_time", "remaining_time", "deadline") + "estimated_time", "remaining_time", "deadline", + Bugzilla->custom_field_names) { $fields{$field} = shift @row; if (defined $fields{$field}) { @@ -290,8 +262,41 @@ sub remove_from_db { return $self; } + ##################################################################### -# Accessors +# Class Accessors +##################################################################### + +sub fields { + my $class = shift; + + return ( + # Standard Fields + # Keep this ordering in sync with bugzilla.dtd. + qw(bug_id alias creation_ts short_desc delta_ts + reporter_accessible cclist_accessible + classification_id classification + product component version rep_platform op_sys + bug_status resolution + bug_file_loc status_whiteboard keywords + priority bug_severity target_milestone + dependson blocked votes + reporter assigned_to cc), + + # Conditional Fields + Param('useqacontact') ? "qa_contact" : (), + Param('timetrackinggroup') ? qw(estimated_time remaining_time + actual_time deadline) + : (), + + # Custom Fields + Bugzilla->custom_field_names + ); +} + + +##################################################################### +# Instance Accessors ##################################################################### # These subs are in alphabetical order, as much as possible. @@ -1299,13 +1304,46 @@ sub ValidateDependencies { return %deps; } + +##################################################################### +# Autoloaded Accessors +##################################################################### + +# Determines whether an attribute access trapped by the AUTOLOAD function +# is for a valid bug attribute. Bug attributes are properties and methods +# predefined by this module as well as bug fields for which an accessor +# can be defined by AUTOLOAD at runtime when the accessor is first accessed. +# +# XXX Strangely, some predefined attributes are on the list, but others aren't, +# and the original code didn't specify why that is. Presumably the only +# attributes that need to be on this list are those that aren't predefined; +# we should verify that and update the list accordingly. +# +sub _validate_attribute { + my ($attribute) = @_; + + my @valid_attributes = ( + # Miscellaneous properties and methods. + qw(error groups + longdescs milestoneurl attachments + isopened isunconfirmed + flag_types num_attachment_flag_types + show_attachment_flags use_keywords any_flags_requesteeble), + + # Bug fields. + Bugzilla::Bug->fields + ); + + return grep($attribute eq $_, @valid_attributes) ? 1 : 0; +} + sub AUTOLOAD { use vars qw($AUTOLOAD); my $attr = $AUTOLOAD; $attr =~ s/.*:://; return unless $attr=~ /[^A-Z]/; - confess ("invalid bug attribute $attr") unless $ok_field{$attr}; + confess("invalid bug attribute $attr") unless _validate_attribute($attr); no strict 'refs'; *$AUTOLOAD = sub { diff --git a/Bugzilla/Constants.pm b/Bugzilla/Constants.pm index c00518732..afb621f78 100644 --- a/Bugzilla/Constants.pm +++ b/Bugzilla/Constants.pm @@ -91,6 +91,9 @@ use base qw(Exporter); ADMIN_GROUP_NAME SENDMAIL_EXE + + FIELD_TYPE_UNKNOWN + FIELD_TYPE_FREETEXT ); @Bugzilla::Constants::EXPORT_OK = qw(contenttypes); @@ -243,4 +246,14 @@ use constant ADMIN_GROUP_NAME => 'admin'; # Path to sendmail.exe (Windows only) use constant SENDMAIL_EXE => '/usr/lib/sendmail.exe'; +# Field types. Match values in fielddefs.type column. These are purposely +# not named after database column types, since Bugzilla fields comprise not +# only storage but also logic. For example, we might add a "user" field type +# whose values are stored in an integer column in the database but for which +# we do more than we would do for a standard integer type (f.e. we might +# display a user picker). + +use constant FIELD_TYPE_UNKNOWN => 0; +use constant FIELD_TYPE_FREETEXT => 1; + 1; diff --git a/Bugzilla/DB/Schema.pm b/Bugzilla/DB/Schema.pm index 63b19578d..3caeba707 100644 --- a/Bugzilla/DB/Schema.pm +++ b/Bugzilla/DB/Schema.pm @@ -36,6 +36,7 @@ package Bugzilla::DB::Schema; use strict; use Bugzilla::Error; use Bugzilla::Util; +use Bugzilla::Constants; use Safe; # Historical, needed for SCHEMA_VERSION = '1.00' @@ -453,6 +454,10 @@ use constant ABSTRACT_SCHEMA => { fieldid => {TYPE => 'MEDIUMSERIAL', NOTNULL => 1, PRIMARYKEY => 1}, name => {TYPE => 'varchar(64)', NOTNULL => 1}, + type => {TYPE => 'INT2', NOTNULL => 1, + DEFAULT => FIELD_TYPE_UNKNOWN}, + custom => {TYPE => 'BOOLEAN', NOTNULL => 1, + DEFAULT => 'FALSE'}, description => {TYPE => 'MEDIUMTEXT', NOTNULL => 1}, mailhead => {TYPE => 'BOOLEAN', NOTNULL => 1, DEFAULT => 'FALSE'}, diff --git a/Bugzilla/Field.pm b/Bugzilla/Field.pm index 09c4731ac..8585ff760 100644 --- a/Bugzilla/Field.pm +++ b/Bugzilla/Field.pm @@ -14,6 +14,57 @@ # # Contributor(s): Dan Mosedale <dmose@mozilla.org> # Frédéric Buclin <LpSolit@gmail.com> +# Myk Melez <myk@mozilla.org> + +=head1 NAME + +Bugzilla::Field - a particular piece of information about bugs + and useful routines for form field manipulation + +=head1 SYNOPSIS + + use Bugzilla; + use Data::Dumper; + + # Display information about all fields. + print Dumper(Bugzilla->get_fields()); + + # Display information about non-obsolete custom fields. + print Dumper(Bugzilla->get_fields({ obsolete => 1, custom => 1 })); + + # Display a list of the names of non-obsolete custom fields. + print Bugzilla->custom_field_names; + + use Bugzilla::Field; + + # Display information about non-obsolete custom fields. + # Bugzilla->get_fields() is a wrapper around Bugzilla::Field::match(), + # so both methods take the same arguments. + print Dumper(Bugzilla::Field::match({ obsolete => 1, custom => 1 })); + + # Create a custom field. + my $field = Bugzilla::Field::create("hilarity", "Hilarity"); + print "$field->{description} is a custom field\n"; + + # Instantiate a Field object for an existing field. + my $field = new Bugzilla::Field('qacontact_accessible'); + if ($field->{obsolete}) { + print "$field->{description} is obsolete\n"; + } + + # Validation Routines + check_form_field($cgi, $fieldname, \@legal_values); + check_form_field_defined($cgi, $fieldname); + $fieldid = get_field_id($fieldname); + +=head1 DESCRIPTION + +Field.pm defines field objects, which represent the particular pieces +of information that Bugzilla stores about bugs. + +This package also provides functions for dealing with CGI form fields. + +=cut package Bugzilla::Field; @@ -24,73 +75,214 @@ use base qw(Exporter); get_field_id); use Bugzilla::Util; +use Bugzilla::Constants; use Bugzilla::Error; +use constant DB_COLUMNS => ( + 'fieldid AS id', + 'name', + 'description', + 'type', + 'custom', + 'obsolete' +); + +our $columns = join(", ", DB_COLUMNS); + +sub new { + my $invocant = shift; + my $name = shift; + my $self = shift || Bugzilla->dbh->selectrow_hashref( + "SELECT $columns FROM fielddefs WHERE name = ?", + undef, + $name + ); + bless($self, $invocant); + return $self; +} -sub check_form_field { - my ($cgi, $fieldname, $legalsRef) = @_; - my $dbh = Bugzilla->dbh; +=pod - if (!defined $cgi->param($fieldname) - || trim($cgi->param($fieldname)) eq "" - || (defined($legalsRef) - && lsearch($legalsRef, $cgi->param($fieldname)) < 0)) - { - trick_taint($fieldname); - my ($result) = $dbh->selectrow_array("SELECT description FROM fielddefs - WHERE name = ?", undef, $fieldname); - - my $field = $result || $fieldname; - ThrowCodeError("illegal_field", { field => $field }); - } -} +=head2 Instance Properties -sub check_form_field_defined { - my ($cgi, $fieldname) = @_; +=over - if (!defined $cgi->param($fieldname)) { - ThrowCodeError("undefined_field", { field => $fieldname }); - } -} +=item C<id> + +the unique identifier for the field; + +=back + +=cut + +sub id { return $_[0]->{id} } + +=over + +=item C<name> + +the name of the field in the database; begins with "cf_" if field +is a custom field, but test the value of the boolean "custom" property +to determine if a given field is a custom field; + +=back + +=cut + +sub name { return $_[0]->{name} } + +=over + +=item C<description> + +a short string describing the field; displayed to Bugzilla users +in several places within Bugzilla's UI, f.e. as the form field label +on the "show bug" page; + +=back + +=cut + +sub description { return $_[0]->{description} } + +=over + +=item C<type> + +an integer specifying the kind of field this is; values correspond to +the FIELD_TYPE_* constants in Constants.pm + +=back + +=cut + +sub type { return $_[0]->{type} } + +=over + +=item C<custom> + +a boolean specifying whether or not the field is a custom field; +if true, field name should start "cf_", but use this property to determine +which fields are custom fields; + +=back + +=cut + +sub custom { return $_[0]->{custom} } + +=over + +=item C<obsolete> + +a boolean specifying whether or not the field is obsolete; + +=back + +=cut + +sub obsolete { return $_[0]->{obsolete} } + + +=pod + +=head2 Class Methods + +=over + +=item C<create($name, $desc)> + +Description: creates a new custom field. + +Params: C<$name> - string - the name of the field; + C<$desc> - string - the field label to display in the UI. + +Returns: a field object. + +=back + +=cut + +sub create { + my ($name, $desc, $custom) = @_; + + # Convert the $custom argument into a DB-compatible value. + $custom = $custom ? 1 : 0; -sub get_field_id { - my ($name) = @_; my $dbh = Bugzilla->dbh; - trick_taint($name); - my $id = $dbh->selectrow_array('SELECT fieldid FROM fielddefs - WHERE name = ?', undef, $name); + # Some day we'll allow invocants to specify the sort key. + my ($sortkey) = + $dbh->selectrow_array("SELECT MAX(sortkey) + 1 FROM fielddefs"); - ThrowCodeError('invalid_field_name', {field => $name}) unless $id; - return $id + # Some day we'll require invocants to specify the field type. + my $type = FIELD_TYPE_FREETEXT; + + # Create the database column that stores the data for this field. + $dbh->bz_add_column("bugs", $name, { TYPE => 'varchar(255)' }); + + # Add the field to the list of fields at this Bugzilla installation. + my $sth = $dbh->prepare( + "INSERT INTO fielddefs (name, description, sortkey, type, + custom, mailhead) + VALUES (?, ?, ?, ?, ?, 1)" + ); + $sth->execute($name, $desc, $sortkey, $type, $custom); + + return new Bugzilla::Field($name); } -1; -__END__ +=pod -=head1 NAME +=over -Bugzilla::Field - Useful routines for fields manipulation +=item C<match($criteria)> -=head1 SYNOPSIS +Description: returns a list of fields that match the specified criteria. - use Bugzilla::Field; +Params: C<$criteria> - hash reference - the criteria to match against. + Hash keys represent field properties; hash values represent + their values. All criteria are optional. Valid criteria are + "custom" and "obsolete", and both take boolean values. - # Validation Routines - check_form_field($cgi, $fieldname, \@legal_values); - check_form_field_defined($cgi, $fieldname); - $fieldid = get_field_id($fieldname); + Note: Bugzilla->get_fields() and Bugzilla->custom_field_names + wrap this method for most callers. -=head1 DESCRIPTION +Returns: a list of field objects. -This package provides functions for dealing with CGI form fields. +=back -=head1 FUNCTIONS +=cut -This package provides several types of routines: +sub match { + my ($criteria) = @_; + + my @terms; + if (defined $criteria->{name}) { + push(@terms, "name=" . Bugzilla->dbh->quote($criteria->{name})); + } + if (defined $criteria->{custom}) { + push(@terms, "custom=" . ($criteria->{custom} ? "1" : "0")); + } + if (defined $criteria->{obsolete}) { + push(@terms, "obsolete=" . ($criteria->{obsolete} ? "1" : "0")); + } + my $where = (scalar(@terms) > 0) ? "WHERE " . join(" AND ", @terms) : ""; + + my $records = Bugzilla->dbh->selectall_arrayref( + "SELECT $columns FROM fielddefs $where ORDER BY sortkey", + { Slice => {}} + ); + # Generate a array of field objects from the array of field records. + my @fields = map( new Bugzilla::Field(undef, $_), @$records ); + return @fields; +} + +=pod -=head2 Validation +=head2 Data Validation =over @@ -108,6 +300,32 @@ Params: $cgi - a CGI object Returns: nothing +=back + +=cut + +sub check_form_field { + my ($cgi, $fieldname, $legalsRef) = @_; + my $dbh = Bugzilla->dbh; + + if (!defined $cgi->param($fieldname) + || trim($cgi->param($fieldname)) eq "" + || (defined($legalsRef) + && lsearch($legalsRef, $cgi->param($fieldname)) < 0)) + { + trick_taint($fieldname); + my ($result) = $dbh->selectrow_array("SELECT description FROM fielddefs + WHERE name = ?", undef, $fieldname); + + my $field = $result || $fieldname; + ThrowCodeError("illegal_field", { field => $field }); + } +} + +=pod + +=over + =item C<check_form_field_defined($cgi, $fieldname)> Description: Makes sure the field $fieldname is defined and its value @@ -118,14 +336,48 @@ Params: $cgi - a CGI object Returns: nothing +=back + +=cut + +sub check_form_field_defined { + my ($cgi, $fieldname) = @_; + + if (!defined $cgi->param($fieldname)) { + ThrowCodeError("undefined_field", { field => $fieldname }); + } +} + +=pod + +=over + =item C<get_field_id($fieldname)> Description: Returns the ID of the specified field name and throws an error if this field does not exist. -Params: $fieldname - a field name +Params: $name - a field name Returns: the corresponding field ID or an error if the field name does not exist. =back + +=cut + +sub get_field_id { + my ($name) = @_; + my $dbh = Bugzilla->dbh; + + trick_taint($name); + my $id = $dbh->selectrow_array('SELECT fieldid FROM fielddefs + WHERE name = ?', undef, $name); + + ThrowCodeError('invalid_field_name', {field => $name}) unless $id; + return $id +} + +1; + +__END__ diff --git a/checksetup.pl b/checksetup.pl index 4ec455efa..f88c8bb28 100755 --- a/checksetup.pl +++ b/checksetup.pl @@ -1305,7 +1305,7 @@ unless ($switch{'no_templates'}) { # These are the files which need to be marked executable my @executable_files = ('whineatnews.pl', 'collectstats.pl', 'checksetup.pl', 'importxml.pl', 'runtests.pl', 'testserver.pl', - 'whine.pl'); + 'whine.pl', 'customfield.pl'); # tell me if a file is executable. All CGI files and those in @executable_files # are executable @@ -4263,6 +4263,13 @@ if (scalar(@$controlchar_bugs)) print " done.\n" if $found; } +# 2005-08-10 Myk Melez <myk@mozilla.org> bug 287325 +# Record each field's type and whether or not it's a custom field in fielddefs. +$dbh->bz_add_column('fielddefs', 'type', + { TYPE => 'INT2', NOTNULL => 1, DEFAULT => 0 }); +$dbh->bz_add_column('fielddefs', 'custom', + { TYPE => 'BOOLEAN', NOTNULL => 1, DEFAULT => 'FALSE' }); + # If you had to change the --TABLE-- definition in any way, then add your # differential change code *** A B O V E *** this comment. # diff --git a/customfield.pl b/customfield.pl new file mode 100755 index 000000000..106c60582 --- /dev/null +++ b/customfield.pl @@ -0,0 +1,88 @@ +#!/usr/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): Myk Melez <myk@mozilla.org> + +################################################################################ +# Script Initialization +################################################################################ + +use strict; + +use lib "."; +require "globals.pl"; + +use Bugzilla::Field; +use Getopt::Long; + +my ($name, $desc); +my $result = GetOptions("name=s" => \$name, + "description|desc=s" => \$desc); + +if (!$name or !$desc) { + my $command = + $^O =~ /MSWin32/i ? "perl -T customfield.pl" : "./customfield.pl"; + print <<END; +Usage: + + Use this script to add a custom field to your Bugzilla installation + by invoking it with the --name and --desc command-line options: + + $command --name=<field_name> --desc="<field description>" + + <field_name> is the name of the custom field in the database. + The string "cf_" will be prepended to this name to distinguish + the field from standard fields. This name must conform to the + naming rules for the database server you use. + + <field description> is a short string describing the field. It will + be displayed to Bugzilla users in several parts of Bugzilla's UI, + for example as the label for the field on the "show bug" page. + +Warning: + + Custom fields can make Bugzilla less usable. See this URL + for alternatives to custom fields: + + http://www.gerv.net/hacking/custom-fields.html + + You should try to implement applicable alternatives before using + this script to add a custom field. +END + + exit; +} + +# Prepend cf_ to the custom field name to distinguish it from standard fields. +$name =~ /^cf_/ + or $name = "cf_" . $name; + +# Exit gracefully if there is already a field with the given name. +if (scalar(Bugzilla::Field::match({ name=>$name })) > 0) { + print "There is already a field named $name. Please choose " . + "a different name.\n"; + exit; +} + + +# Create the field. +print "Creating custom field $name ...\n"; +my $field = Bugzilla::Field::create($name, $desc, 1); +print "Custom field $name created.\n"; diff --git a/editcomponents.cgi b/editcomponents.cgi index c65fd3167..3cbd71a9c 100755 --- a/editcomponents.cgi +++ b/editcomponents.cgi @@ -31,6 +31,7 @@ use lib "."; require "globals.pl"; +use Bugzilla; use Bugzilla::Constants; use Bugzilla::Config qw(:DEFAULT $datadir); use Bugzilla::Series; diff --git a/editmilestones.cgi b/editmilestones.cgi index c87828526..bb80164ab 100755 --- a/editmilestones.cgi +++ b/editmilestones.cgi @@ -21,6 +21,7 @@ use lib "."; require "globals.pl"; +use Bugzilla; use Bugzilla::Constants; use Bugzilla::Config qw(:DEFAULT $datadir); use Bugzilla::Product; diff --git a/editproducts.cgi b/editproducts.cgi index 2b7c5dc5d..d9ebcedd9 100755 --- a/editproducts.cgi +++ b/editproducts.cgi @@ -33,6 +33,7 @@ use strict; use lib "."; +use Bugzilla; use Bugzilla::Constants; require "globals.pl"; use Bugzilla::Bug; diff --git a/process_bug.cgi b/process_bug.cgi index a8a0f5f0d..a489594f4 100755 --- a/process_bug.cgi +++ b/process_bug.cgi @@ -694,7 +694,7 @@ if ($action eq Param('move-button-text')) { $msg .= "From: Bugzilla <" . $from . ">\n"; $msg .= "Subject: Moving bug(s) " . join(', ', @idlist) . "\n\n"; - my @fieldlist = (Bugzilla::Bug::fields(), 'group', 'long_desc', + my @fieldlist = (Bugzilla::Bug->fields, 'group', 'long_desc', 'attachment', 'attachmentdata'); my %displayfields; foreach (@fieldlist) { @@ -867,6 +867,18 @@ foreach my $field ("rep_platform", "priority", "bug_severity", } } +# Add custom fields data to the query that will update the database. +foreach my $field (Bugzilla->custom_field_names) { + if (defined $cgi->param($field) + && (!$cgi->param('dontchange') + || $cgi->param($field) ne $cgi->param('dontchange'))) + { + DoComma(); + $::query .= "$field = " . SqlQuote(trim($cgi->param($field))); + } +} + + my $prod_id; my $prod_changed; my @newprod_ids; diff --git a/show_activity.cgi b/show_activity.cgi index 9b7273a4c..e44bc7054 100755 --- a/show_activity.cgi +++ b/show_activity.cgi @@ -28,6 +28,7 @@ use lib qw(.); require "globals.pl"; +use Bugzilla; use Bugzilla::Bug; my $cgi = Bugzilla->cgi; diff --git a/show_bug.cgi b/show_bug.cgi index 4d6819a36..19aa88573 100755 --- a/show_bug.cgi +++ b/show_bug.cgi @@ -108,7 +108,7 @@ $vars->{'bug_list'} = \@bug_list; # If no explicit list is defined, we show all fields. We then exclude any # on the exclusion list. This is so you can say e.g. "Everything except # attachments" without listing almost all the fields. -my @fieldlist = (Bugzilla::Bug::fields(), 'group', 'long_desc', +my @fieldlist = (Bugzilla::Bug->fields, 'group', 'long_desc', 'attachment', 'attachmentdata'); my %displayfields; diff --git a/showdependencytree.cgi b/showdependencytree.cgi index d9d71b0ab..03abb2729 100755 --- a/showdependencytree.cgi +++ b/showdependencytree.cgi @@ -27,6 +27,7 @@ use strict; use lib qw(.); require "globals.pl"; +use Bugzilla; use Bugzilla::User; use Bugzilla::Bug; diff --git a/summarize_time.cgi b/summarize_time.cgi index 44c4f8d50..0827077e8 100755 --- a/summarize_time.cgi +++ b/summarize_time.cgi @@ -23,6 +23,7 @@ use lib qw(.); use Date::Parse; # strptime use Date::Format; # strftime +use Bugzilla; use Bugzilla::Bug; # EmitDependList use Bugzilla::Util; # trim use Bugzilla::Constants; # LOGIN_* diff --git a/template/en/default/bug/edit.html.tmpl b/template/en/default/bug/edit.html.tmpl index c1f00025e..349b05049 100644 --- a/template/en/default/bug/edit.html.tmpl +++ b/template/en/default/bug/edit.html.tmpl @@ -497,6 +497,15 @@ </table> [% END %] +[%# *** Custom Fields *** %] + +[% USE Bugzilla %] +<table> + [% FOREACH field = Bugzilla.get_fields({ obsolete => 0, custom => 1 }) %] + [% PROCESS bug/field.html.tmpl value=bug.${field.name} %] + [% END %] +</table> + [%# *** Attachments *** %] [% PROCESS attachment/list.html.tmpl diff --git a/template/en/default/bug/field.html.tmpl b/template/en/default/bug/field.html.tmpl new file mode 100644 index 000000000..cbde9cf27 --- /dev/null +++ b/template/en/default/bug/field.html.tmpl @@ -0,0 +1,36 @@ +[%# 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): Myk Melez <myk@mozilla.org> + #%] + +<tr> + [% SWITCH field.type %] + [% CASE constants.FIELD_TYPE_FREETEXT %] + <th align="right"> + <label for="[% field.name FILTER html %]"> + [% field.description FILTER html %]: + </label> + </th> + <td> + <input name="[% field.name FILTER html %]" + value="[% value FILTER html %]" + size="60"> + </td> + [% END %] +</tr> |