Login
[x]
Log in using an account from:
Fedora Account System
Red Hat Associate
Red Hat Customer
Or login using a Red Hat Bugzilla account
Forgot Password
Login:
Hide Forgot
Create an Account
Red Hat Bugzilla – Attachment 298010 Details for
Bug 406111
3.1: Issue Tracker Integration
[?]
New
Simple Search
Advanced Search
My Links
Browse
Requests
Reports
Current State
Search
Tabular reports
Graphical reports
Duplicates
Other Reports
User Changes
Plotly Reports
Bug Status
Bug Severity
Non-Defaults
|
Product Dashboard
Help
Page Help!
Bug Writing Guidelines
What's new
Browser Support Policy
5.0.4.rh83 Release notes
FAQ
Guides index
User guide
Web Services
Contact
Legal
This site requires JavaScript to be enabled to function correctly, please enable it.
[patch]
Issue tracker integration using custom fields (v2)
issuetracker.patch (text/plain), 51.40 KB, created by
David Lawrence
on 2008-03-14 03:33:08 UTC
(
hide
)
Description:
Issue tracker integration using custom fields (v2)
Filename:
MIME Type:
Creator:
David Lawrence
Created:
2008-03-14 03:33:08 UTC
Size:
51.40 KB
patch
obsolete
>? patches >Index: colchange.cgi >=================================================================== >RCS file: /cvs/qa/rh_bugzilla_3/colchange.cgi,v >retrieving revision 1.6 >diff -u -p -r1.6 colchange.cgi >--- colchange.cgi 5 Mar 2008 21:41:51 -0000 1.6 >+++ colchange.cgi 14 Mar 2008 03:22:39 -0000 >@@ -90,7 +90,8 @@ if (Bugzilla->params->{"useissuetracker" > > push(@masterlist, ("short_desc", "short_short_desc")); > >-my @custom_fields = grep { $_->type != FIELD_TYPE_MULTI_SELECT } >+my @custom_fields = grep { $_->type != FIELD_TYPE_MULTI_SELECT >+ && $_->type != FIELD_TYPE_FREETEXT_MULTI_INTEGER} > Bugzilla->active_custom_fields; > push(@masterlist, map { $_->name } @custom_fields); > >Index: config.cgi >=================================================================== >RCS file: /cvs/qa/rh_bugzilla_3/config.cgi,v >retrieving revision 1.2 >diff -u -p -r1.2 config.cgi >--- config.cgi 27 Feb 2008 20:50:20 -0000 1.2 >+++ config.cgi 14 Mar 2008 03:22:40 -0000 >@@ -56,7 +56,9 @@ $vars->{'keyword'} = [map($_->name, B > $vars->{'resolution'} = get_legal_field_values('resolution'); > $vars->{'status'} = get_legal_field_values('bug_status'); > $vars->{'custom_fields'} = >- [ grep {$_->type == FIELD_TYPE_SINGLE_SELECT || $_->type == FIELD_TYPE_MULTI_SELECT} >+ [ grep {$_->type == FIELD_TYPE_SINGLE_SELECT >+ || $_->type == FIELD_TYPE_MULTI_SELECT >+ || $_->type == FIELD_TYPE_FREETEXT_MULTI_INTEGER} > Bugzilla->active_custom_fields ]; > > # Include a list of product objects. >Index: post_bug.cgi >=================================================================== >RCS file: /cvs/qa/rh_bugzilla_3/post_bug.cgi,v >retrieving revision 1.8 >diff -u -p -r1.8 post_bug.cgi >--- post_bug.cgi 5 Mar 2008 21:41:51 -0000 1.8 >+++ post_bug.cgi 14 Mar 2008 03:22:40 -0000 >@@ -124,7 +124,9 @@ $template->process($format->{'template'} > || ThrowTemplateError($template->error()); > > # Include custom fields editable on bug creation. >-my @custom_bug_fields = grep {$_->type != FIELD_TYPE_MULTI_SELECT && $_->enter_bug} >+my @custom_bug_fields = grep {$_->type != FIELD_TYPE_MULTI_SELECT >+ && $_->type != FIELD_TYPE_FREETEXT_MULTI_INTEGER >+ && $_->enter_bug} > Bugzilla->active_custom_fields; > > # Undefined custom fields are ignored to ensure they will get their default >@@ -168,7 +170,9 @@ $bug_params{'cc'} = [$cgi->para > $bug_params{'groups'} = \@selected_groups; > $bug_params{'comment'} = $comment; > >-my @multi_selects = grep {$_->type == FIELD_TYPE_MULTI_SELECT && $_->enter_bug} >+my @multi_selects = grep {($_->type == FIELD_TYPE_MULTI_SELECT >+ || $_->type == FIELD_TYPE_FREETEXT_MULTI_INTEGER) >+ && $_->enter_bug} > Bugzilla->active_custom_fields; > > foreach my $field (@multi_selects) { >Index: Bugzilla/Bug.pm >=================================================================== >RCS file: /cvs/qa/rh_bugzilla_3/Bugzilla/Bug.pm,v >retrieving revision 1.28 >diff -u -p -r1.28 Bug.pm >--- Bugzilla/Bug.pm 10 Mar 2008 14:04:08 -0000 1.28 >+++ Bugzilla/Bug.pm 14 Mar 2008 03:22:43 -0000 >@@ -68,7 +68,8 @@ use constant LIST_ORDER => ID_FIELD; > # This is a sub because it needs to call other subroutines. > sub DB_COLUMNS { > my $dbh = Bugzilla->dbh; >- my @custom = grep {$_->type != FIELD_TYPE_MULTI_SELECT} >+ my @custom = grep {$_->type != FIELD_TYPE_MULTI_SELECT >+ && $_->type != FIELD_TYPE_FREETEXT_MULTI_INTEGER} > Bugzilla->active_custom_fields; > my @custom_names = map {$_->name} @custom; > return qw( >@@ -138,6 +139,9 @@ sub VALIDATORS { > elsif ($field->type == FIELD_TYPE_MULTI_SELECT) { > $validator = \&_check_multi_select_field; > } >+ elsif ($field->type == FIELD_TYPE_FREETEXT_MULTI_INTEGER) { >+ $validator = \&_check_freetext_multi_integer; >+ } > elsif ($field->type == FIELD_TYPE_DATETIME) { > $validator = \&_check_datetime_field; > } >@@ -166,7 +170,8 @@ use constant UPDATE_VALIDATORS => { > }; > > sub UPDATE_COLUMNS { >- my @custom = grep {$_->type != FIELD_TYPE_MULTI_SELECT} >+ my @custom = grep {$_->type != FIELD_TYPE_MULTI_SELECT >+ && $_->type != FIELD_TYPE_FREETEXT_MULTI_INTEGER} > Bugzilla->active_custom_fields; > my @custom_names = map {$_->name} @custom; > my @columns = qw( >@@ -711,7 +716,8 @@ sub update { > } > > # Insert the values into the multiselect value tables >- my @multi_selects = grep {$_->type == FIELD_TYPE_MULTI_SELECT} >+ my @multi_selects = grep {$_->type == FIELD_TYPE_MULTI_SELECT >+ || $_->type == FIELD_TYPE_FREETEXT_MULTI_INTEGER} > Bugzilla->active_custom_fields; > foreach my $field (@multi_selects) { > my $name = $field->name; >@@ -770,7 +776,8 @@ sub update { > sub _extract_multi_selects { > my ($invocant, $params) = @_; > >- my @multi_selects = grep {$_->type == FIELD_TYPE_MULTI_SELECT} >+ my @multi_selects = grep {$_->type == FIELD_TYPE_MULTI_SELECT >+ || $_->type == FIELD_TYPE_FREETEXT_MULTI_INTEGER} > Bugzilla->active_custom_fields; > my %ms_values; > foreach my $field (@multi_selects) { >@@ -1690,6 +1697,30 @@ sub _check_multi_select_field { > return $values; > } > >+sub _check_freetext_multi_integer { >+ my ($invocant, $value, $field) = @_; >+ my @value_list; >+ my %value_hash; >+ return [] if !$value; >+ foreach my $item (split(/[,\s]+/, $value)) { >+ $item = trim($item); >+ my $v = $item; >+ detaint_natural($item) >+ || ThrowUserError('field_invalid_value', >+ { value => $v, field => $field, type => 'integer' }); >+ $value_hash{$item} = 1; >+ } >+ >+ @value_list = sort keys %value_hash; >+ >+ # REDHAT EXTENSION START 406111 >+ Bugzilla::Hook::process('check_freetext_multi_integer', >+ { current => $invocant->$field, field => $field, values => \@value_list }); >+ # REDHAT EXTENSION END 406111 >+ >+ return \@value_list; >+} >+ > sub _check_select_field { > my ($invocant, $value, $field) = @_; > $value = trim($value); >@@ -3670,7 +3701,9 @@ sub AUTOLOAD { > > $self->{_multi_selects} ||= [Bugzilla->get_fields( > {custom => 1, type => FIELD_TYPE_MULTI_SELECT })]; >- if ( grep($_->name eq $attr, @{$self->{_multi_selects}}) ) { >+ $self->{_multi_freetext_integers} ||= [Bugzilla->get_fields( >+ {custom => 1, type => FIELD_TYPE_FREETEXT_MULTI_INTEGER })]; >+ if ( grep($_->name eq $attr, (@{$self->{_multi_selects}}, @{$self->{_multi_freetext_integers}})) ) { > $self->{$attr} ||= Bugzilla->dbh->selectcol_arrayref( > "SELECT value FROM bug_$attr WHERE bug_id = ? ORDER BY value", > undef, $self->id); >Index: Bugzilla/Constants.pm >=================================================================== >RCS file: /cvs/qa/rh_bugzilla_3/Bugzilla/Constants.pm,v >retrieving revision 1.7 >diff -u -p -r1.7 Constants.pm >--- Bugzilla/Constants.pm 4 Feb 2008 04:54:38 -0000 1.7 >+++ Bugzilla/Constants.pm 14 Mar 2008 03:22:43 -0000 >@@ -121,6 +121,7 @@ use File::Basename; > FIELD_TYPE_MULTI_SELECT > FIELD_TYPE_TEXTAREA > FIELD_TYPE_DATETIME >+ FIELD_TYPE_FREETEXT_MULTI_INTEGER > > USAGE_MODE_BROWSER > USAGE_MODE_CMDLINE >@@ -347,6 +348,7 @@ use constant FIELD_TYPE_SINGLE_SELECT => > use constant FIELD_TYPE_MULTI_SELECT => 3; > use constant FIELD_TYPE_TEXTAREA => 4; > use constant FIELD_TYPE_DATETIME => 5; >+use constant FIELD_TYPE_FREETEXT_MULTI_INTEGER => 6; > > # The maximum number of days a token will remain valid. > use constant MAX_TOKEN_AGE => 3; >Index: Bugzilla/DB.pm >=================================================================== >RCS file: /cvs/qa/rh_bugzilla_3/Bugzilla/DB.pm,v >retrieving revision 1.8 >diff -u -p -r1.8 DB.pm >--- Bugzilla/DB.pm 11 Feb 2008 03:19:45 -0000 1.8 >+++ Bugzilla/DB.pm 14 Mar 2008 03:22:45 -0000 >@@ -677,14 +677,19 @@ sub _bz_add_field_table { > > sub bz_add_field_tables { > my ($self, $field) = @_; >- >- $self->_bz_add_field_table($field->name, >- $self->_bz_schema->FIELD_TABLE_SCHEMA); >+ >+ if ( $field->type != FIELD_TYPE_FREETEXT_MULTI_INTEGER ) { >+ $self->_bz_add_field_table($field->name, >+ $self->_bz_schema->FIELD_TABLE_SCHEMA); >+ } > if ( $field->type == FIELD_TYPE_MULTI_SELECT ) { > $self->_bz_add_field_table('bug_' . $field->name, > $self->_bz_schema->MULTI_SELECT_VALUE_TABLE); > } >- >+ if ( $field->type == FIELD_TYPE_FREETEXT_MULTI_INTEGER ) { >+ $self->_bz_add_field_table('bug_' . $field->name, >+ $self->_bz_schema->MULTI_SELECT_INTEGER_TABLE); >+ } > } > > sub bz_drop_field_tables { >Index: Bugzilla/Field.pm >=================================================================== >RCS file: /cvs/qa/rh_bugzilla_3/Bugzilla/Field.pm,v >retrieving revision 1.7 >diff -u -p -r1.7 Field.pm >--- Bugzilla/Field.pm 5 Mar 2008 21:41:51 -0000 1.7 >+++ Bugzilla/Field.pm 14 Mar 2008 03:22:45 -0000 >@@ -250,7 +250,7 @@ sub _check_type { > my $saved_type = $type; > # The constant here should be updated every time a new, > # higher field type is added. >- (detaint_natural($type) && $type <= FIELD_TYPE_DATETIME) >+ (detaint_natural($type) && $type <= FIELD_TYPE_FREETEXT_MULTI_INTEGER) > || ThrowCodeError('invalid_customfield_type', { type => $saved_type }); > return $type; > } >@@ -449,7 +449,8 @@ sub remove_from_db { > # Check to see if bugs table has records (slow) > my $bugs_query = ""; > >- if ($self->type == FIELD_TYPE_MULTI_SELECT) { >+ if ($self->type == FIELD_TYPE_MULTI_SELECT >+ || $self->type == FIELD_TYPE_FREETEXT_MULTI_INTEGER) { > $bugs_query = "SELECT COUNT(*) FROM bug_$name"; > } > else { >@@ -476,12 +477,14 @@ sub remove_from_db { > my $type = $self->type; > > # the values for multi-select are stored in a seperate table >- if ($type != FIELD_TYPE_MULTI_SELECT) { >+ if ($type != FIELD_TYPE_MULTI_SELECT >+ && $type != FIELD_TYPE_FREETEXT_MULTI_INTEGER) { > $dbh->bz_drop_column('bugs', $name); > } > > if ($type == FIELD_TYPE_SINGLE_SELECT >- || $type == FIELD_TYPE_MULTI_SELECT) >+ || $type == FIELD_TYPE_MULTI_SELECT >+ || $type == FIELD_TYPE_FREETEXT_MULTI_INTEGER) > { > # Delete the table that holds the legal values for this field. > $dbh->bz_drop_field_tables($self); >@@ -539,7 +542,8 @@ sub create { > } > > if ($type == FIELD_TYPE_SINGLE_SELECT >- || $type == FIELD_TYPE_MULTI_SELECT) >+ || $type == FIELD_TYPE_MULTI_SELECT >+ || $type == FIELD_TYPE_FREETEXT_MULTI_INTEGER) > { > # Create the table that holds the legal values for this field. > $dbh->bz_add_field_tables($field); >Index: Bugzilla/Search.pm >=================================================================== >RCS file: /cvs/qa/rh_bugzilla_3/Bugzilla/Search.pm,v >retrieving revision 1.18 >diff -u -p -r1.18 Search.pm >--- Bugzilla/Search.pm 12 Mar 2008 17:18:40 -0000 1.18 >+++ Bugzilla/Search.pm 14 Mar 2008 03:22:47 -0000 >@@ -127,6 +127,10 @@ sub init { > > my @multi_select_fields = Bugzilla->get_fields({ type => FIELD_TYPE_MULTI_SELECT, > obsolete => 0 }); >+ >+ my @multi_freetext_integer_fields = Bugzilla->get_fields({ type => FIELD_TYPE_FREETEXT_MULTI_INTEGER, >+ obsolete => 0 }); >+ > foreach my $field (@select_fields) { > my $name = $field->name; > $special_order{"bugs.$name"} = [ "$name.sortkey", "$name.value" ], >@@ -233,6 +237,7 @@ sub init { > # Include custom select fields. > push(@legal_fields, map { $_->name } @select_fields); > push(@legal_fields, map { $_->name } @multi_select_fields); >+ push(@legal_fields, map { $_->name } @multi_freetext_integer_fields); > > foreach my $field ($params->param()) { > if (lsearch(\@legal_fields, $field) != -1) { >@@ -416,7 +421,7 @@ sub init { > push(@specialchart, ['content', 'matches', $params->param('content')]); > } > >- my $multi_fields = join('|', map($_->name, @multi_select_fields)); >+ my $multi_fields = join('|', map($_->name, (@multi_select_fields, @multi_freetext_integer_fields))); > > my $chartid; > my $sequence = 0; >Index: Bugzilla/Template.pm >=================================================================== >RCS file: /cvs/qa/rh_bugzilla_3/Bugzilla/Template.pm,v >retrieving revision 1.5 >diff -u -p -r1.5 Template.pm >--- Bugzilla/Template.pm 15 Feb 2008 05:24:14 -0000 1.5 >+++ Bugzilla/Template.pm 14 Mar 2008 03:22:48 -0000 >@@ -258,6 +258,11 @@ sub quoteUrls { > ~get_bug_link($1, $1) > ~egmx; > >+ # REDHAT EXTENSION START 406111 >+ Bugzilla::Hook::process('quote_urls', >+ { text => \$text, things => \@things, count => \$count }); >+ # REDHAT EXTENSION END 406111 >+ > # Now remove the encoding hacks > $text =~ s/\0\0(\d+)\0\0/$things[$1]/eg; > $text =~ s/$chr1\0/\0/g; >Index: Bugzilla/DB/Schema.pm >=================================================================== >RCS file: /cvs/qa/rh_bugzilla_3/Bugzilla/DB/Schema.pm,v >retrieving revision 1.12 >diff -u -p -r1.12 Schema.pm >--- Bugzilla/DB/Schema.pm 15 Feb 2008 16:26:13 -0000 1.12 >+++ Bugzilla/DB/Schema.pm 14 Mar 2008 03:22:50 -0000 >@@ -1453,6 +1453,18 @@ use constant MULTI_SELECT_VALUE_TABLE => > ], > }; > >+use constant MULTI_SELECT_INTEGER_TABLE => { >+ FIELDS => [ >+ bug_id => {TYPE => 'INT3', NOTNULL => 1, >+ REFERENCES => {TABLE => 'bugs', >+ COLUMN => 'bug_id'}}, >+ value => {TYPE => 'INT3', NOTNULL => 1}, >+ ], >+ INDEXES => [ >+ bug_id_idx => {FIELDS => [qw( bug_id value)], TYPE => 'UNIQUE'}, >+ ], >+}; >+ > > #-------------------------------------------------------------------------- > >Index: extensions/issuetracker/code/check_freetext_multi_integer.pl >=================================================================== >RCS file: extensions/issuetracker/code/check_freetext_multi_integer.pl >diff -N extensions/issuetracker/code/check_freetext_multi_integer.pl >--- /dev/null 1 Jan 1970 00:00:00 -0000 >+++ extensions/issuetracker/code/check_freetext_multi_integer.pl 14 Mar 2008 03:22:51 -0000 >@@ -0,0 +1,38 @@ >+# -*- 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 Everything Solved, Inc. >+# Portions created by Everything Solved, Inc. are Copyright (C) 2007 >+# Everything Solved, Inc. All Rights Reserved. >+# >+# Contributor(s): Dave Lawrence <dkl@redhat.com> >+ >+use strict; >+use warnings; >+use Bugzilla; >+use Bugzilla::Util; >+use extensions::issuetracker::lib::IssueTracker; >+ >+my $current = Bugzilla->hook_args->{'current'}; >+my $field = Bugzilla->hook_args->{'field'}; >+my $values = Bugzilla->hook_args->{'values'}; >+ >+if ( $field eq 'cf_issuetracker' ) { >+ my ($removed, $added) = diff_arrays($current, $values); >+ my $it = extensions::issuetracker::lib::IssueTracker->new(); >+ foreach my $item ( @$added ) { >+ $it->validateIssueID($item); >+ } >+} >+ >Index: extensions/issuetracker/code/filter_change.pl >=================================================================== >RCS file: extensions/issuetracker/code/filter_change.pl >diff -N extensions/issuetracker/code/filter_change.pl >--- /dev/null 1 Jan 1970 00:00:00 -0000 >+++ extensions/issuetracker/code/filter_change.pl 14 Mar 2008 03:22:51 -0000 >@@ -0,0 +1,35 @@ >+# -*- 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 Everything Solved, Inc. >+# Portions created by Everything Solved, Inc. are Copyright (C) 2007 >+# Everything Solved, Inc. All Rights Reserved. >+# >+# Contributor(s): Dave Lawrence <dkl@redhat.com> >+ >+use strict; >+use warnings; >+use Bugzilla; >+ >+my $field = Bugzilla->hook_args->{field}; >+my $visible = Bugzilla->hook_args->{visible}; >+ >+my %permission_map = ( >+ cf_issuetracker => 'issuetracker', >+); >+ >+if ( exists $permission_map{$field} >+ and not Bugzilla->user->in_group($permission_map{$field}) ) { >+ $$visible = 0; >+} >Index: extensions/issuetracker/code/filter_custom_fields.pl >=================================================================== >RCS file: extensions/issuetracker/code/filter_custom_fields.pl >diff -N extensions/issuetracker/code/filter_custom_fields.pl >--- /dev/null 1 Jan 1970 00:00:00 -0000 >+++ extensions/issuetracker/code/filter_custom_fields.pl 14 Mar 2008 03:22:51 -0000 >@@ -0,0 +1,41 @@ >+# -*- 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 Everything Solved, Inc. >+# Portions created by Everything Solved, Inc. are Copyright (C) 2007 >+# Everything Solved, Inc. All Rights Reserved. >+# >+# Contributor(s): Dave Lawrence <dkl@redhat.com> >+ >+use strict; >+use warnings; >+use Bugzilla; >+ >+my $custom_fields = Bugzilla->hook_args->{custom_fields}; >+ >+my @filtered_fields; >+ >+my %permission_map = ( >+ cf_issuetracker => 'issuetracker', >+); >+ >+foreach my $field ( @{$$custom_fields} ) { >+ if ( exists $permission_map{$field->name} ) { >+ push(@filtered_fields, $field) if Bugzilla->user->in_group($permission_map{$field->name}); >+ } else { >+ push(@filtered_fields, $field); >+ } >+} >+ >+$$custom_fields = \@filtered_fields; >Index: extensions/issuetracker/code/quote_urls.pl >=================================================================== >RCS file: extensions/issuetracker/code/quote_urls.pl >diff -N extensions/issuetracker/code/quote_urls.pl >--- /dev/null 1 Jan 1970 00:00:00 -0000 >+++ extensions/issuetracker/code/quote_urls.pl 14 Mar 2008 03:22:51 -0000 >@@ -0,0 +1,52 @@ >+# -*- 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 Everything Solved, Inc. >+# Portions created by Everything Solved, Inc. are Copyright (C) 2007 >+# Everything Solved, Inc. All Rights Reserved. >+# >+# Contributor(s): Dave Lawrence <dkl@redhat.com> >+ >+use strict; >+use warnings; >+use Bugzilla; >+ >+my $can_see_issuetracker = Bugzilla->params->{useissuetracker} and Bugzilla->user->in_group('issuetracker'); >+ >+my $text = Bugzilla->hook_args->{'text'}; >+my $things = Bugzilla->hook_args->{'things'}; >+my $count = Bugzilla->hook_args->{'count'}; >+ >+# This handles issue tracker links, must be "issue <id>" format. >+ >+$$text =~ s~\b(issue\s*\#?\s*(\d+)) >+ ~($$things[$$count++] = get_it_link($2, $1)) && >+ ("\0\0" . ($$count-1) . "\0\0") >+ ~egmxi; >+ >+$$text =~ s~\b(it_file\s*\#?\s*(\d+)) >+ ~($$things[$$count++] = get_it_file_link($2, $1)) && >+ ("\0\0" . ($$count-1) . "\0\0") >+ ~egmxi; >+ >+sub get_it_link { >+ my ($id, $link_text) = @_; >+ return "<a href=\"https://enterprise.redhat.com/issue-tracker/?module=issues&action=view&tid=$id\">$link_text</a>"; >+} >+ >+sub get_it_file_link { >+ my ($id, $link_text) = @_; >+ my $it_key = Bugzilla->user->in_group('devel') ? Bugzilla->params->{issuetracker_download_key} : ''; >+ return "<a href=\"https://enterprise\.redhat\.com/issue-tracker/\?module=download&fid=$id&key=$it_key\">$link_text</a>"; >+} >Index: extensions/issuetracker/code/webservice.pl >=================================================================== >RCS file: extensions/issuetracker/code/webservice.pl >diff -N extensions/issuetracker/code/webservice.pl >--- /dev/null 1 Jan 1970 00:00:00 -0000 >+++ extensions/issuetracker/code/webservice.pl 14 Mar 2008 03:22:51 -0000 >@@ -0,0 +1,156 @@ >+# -*- 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 Everything Solved, Inc. >+# Portions created by Everything Solved, Inc. are Copyright (C) 2007 >+# Everything Solved, Inc. All Rights Reserved. >+# >+# Contributor(s): Max Kanat-Alexander <mkanat@bugzilla.org> >+# Dave Lawrence <dkl@redhat.com> >+ >+use strict; >+use warnings; >+use Bugzilla; >+my $dispatch = Bugzilla->hook_args->{dispatch}; >+$dispatch->{bugzilla} = "bugzilla"; >+ >+package bugzilla; >+ >+## libraries and pragmas >+use base qw(Bugzilla::WebService); >+import SOAP::Data qw(type); >+ >+use Bugzilla::Constants; >+use Bugzilla::Error; >+use Bugzilla::Bug; >+use Bugzilla::BugMail; >+use Bugzilla::Constants; >+use Bugzilla::Field; >+use extensions::issuetracker::lib::IssueTracker; >+ >+# Create an IT to BZ mapping >+sub addIT { >+ my ( $self, $bug_id, $it_id, $score, $username, $password, $nomail ) = @_; >+ >+ if ( not Bugzilla->params->{useissuetracker} >+ or not Bugzilla->user->in_group('issuetracker') ) { >+ return {}; >+ } >+ >+ $it_id || ThrowCodeError( 'param_required', { param => 'issue' } ); >+ >+ # Validate new issue id >+ my $it = extensions::issuetracker::lib::IssueTracker->new(); >+ $it->validateIssueID($it_id); >+ >+ $bug_id || ThrowCodeError( 'param_required', { param => 'id' } ); >+ >+ ValidateBugID($bug_id); >+ my $bug = new Bugzilla::Bug($bug_id); >+ >+ # we have to check if the user can edit the bug the product >+ # is currently in, before we allow them to change anything. >+ Bugzilla->user->can_edit_product( $bug->product_id ) >+ || ThrowUserError( "product_edit_denied", >+ { product => $bug->product } ); >+ >+ # Add to the current list >+ my %current_issues = map { $_ => 1 } @{$bug->cf_issuetracker}; >+ $current_issues{$it_id} = 1; >+ >+ # Set the value with the new list >+ my $field = Bugzilla::Field->new({name => 'cf_issuetracker'}); >+ $bug->set_custom_field($field, join(" ", keys %current_issues)); >+ >+ # Check for tao@redhat.com (IT User) cc list member >+ $bug->add_cc('tao@redhat.com'); >+ >+ # Update the bug >+ $bug->update(); >+ >+ $nomail ||= 0; >+ >+ if ( not $nomail ) { >+ return Bugzilla::BugMail::Send( $bug_id, { changer => $username }); >+ } >+ >+ return {}; >+} >+ >+# Delete a IT to BZ mapping >+sub deleteIT { >+ my ( $self, $bug_id, $it_id, $username, $password, $nomail ) = @_; >+ >+ if ( not Bugzilla->params->{useissuetracker} >+ or not Bugzilla->user->in_group('issuetracker') ) { >+ return {}; >+ } >+ >+ $it_id || ThrowCodeError( 'param_required', { param => 'issue' } ); >+ $bug_id || ThrowCodeError( 'param_required', { param => 'id' } ); >+ >+ ValidateBugID($bug_id); >+ my $bug = new Bugzilla::Bug($bug_id); >+ >+ # we have to check if the user can edit the bug the product >+ # is currently in, before we allow them to change anything. >+ Bugzilla->user->can_edit_product( $bug->product_id ) >+ || ThrowUserError( "product_edit_denied", >+ { product => $bug->product } ); >+ >+ # Remove from current list >+ my %current_issues = map { $_ => 1 } @{$bug->cf_issuetracker}; >+ delete $current_issues{$it_id}; >+ >+ # Set the value with the new list >+ my $field = Bugzilla::Field->new({name => 'cf_issuetracker'}); >+ $bug->set_custom_field($field, join(" ", keys %current_issues)); >+ >+ # Update the bug >+ $bug->update(); >+ >+ $nomail ||= 0; >+ >+ if ( not $nomail ) { >+ return Bugzilla::BugMail::Send( $bug_id, { changer => $username }); >+ } >+ >+ return {}; >+} >+ >+sub issueExists { >+ my ( $self, $it_id ) = @_; >+ >+ if ( not Bugzilla->params->{useissuetracker} >+ or not Bugzilla->user->in_group('issuetracker') ) { >+ return []; >+ } >+ >+ $it_id || ThrowCodeError( 'param_required', { param => 'issue' } ); >+ >+ my $dbh = Bugzilla->dbh; >+ >+ # Gather list of bug ids that this issue tracker ticket belongs to >+ my $sth = $dbh->prepare("SELECT bug_id FROM bug_cf_issuetracker WHERE value = $it_id"); >+ $sth->execute(); >+ >+ my @buglist; >+ while ( my ($bug_id) = $sth->fetchrow_array() ) { >+ push(@buglist, $bug_id) if Bugzilla->user->can_see_bug($bug_id); >+ } >+ >+ return \@buglist; >+} >+ >+1; >Index: extensions/issuetracker/lib/IssueTracker.pm >=================================================================== >RCS file: extensions/issuetracker/lib/IssueTracker.pm >diff -N extensions/issuetracker/lib/IssueTracker.pm >--- /dev/null 1 Jan 1970 00:00:00 -0000 >+++ extensions/issuetracker/lib/IssueTracker.pm 14 Mar 2008 03:22:52 -0000 >@@ -0,0 +1,739 @@ >+# -*- 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): Mike MacKenzie <mmackenz@redhat.com> >+# Dave Lawrence <dkl@redhat.com> >+ >+=pod >+ >+=head1 NAME >+ >+Bugzilla::IssueTracker - Interface to the Issue Tracker system. >+ >+=head1 SYNOPSIS >+ >+ # Create basic IssueTracker object >+ my $it = IssueTracker->new() >+ >+ # Validate the IssueTracker IDs provided by the user >+ $it->validateIssueID($it_id); >+ >+=head1 DESCRIPTION >+ >+This module provides an interface for working with the >+Issue Tracker system. >+ >+=cut >+ >+############################################################################ >+# Module Initialization >+############################################################################ >+ >+use strict; >+ >+package extensions::issuetracker::lib::IssueTracker; >+ >+use Bugzilla; >+use Bugzilla::Error; >+use Bugzilla::Util; >+use XMLRPC::Lite; >+use Data::Dumper; >+ >+# constant for the max number of tries to connect to IT before >+# sending an error email >+use constant MAXTRIES => 3; >+ >+ >+############################################################################ >+# Functions/Methods >+############################################################################ >+ >+=pod >+ >+=head1 METHODS >+ >+=over 4 >+ >+=item C<new> >+ >+Creates a new IssueTracker object. >+ >+=cut >+ >+############################################################################# >+# Initialization >+############################################################################# >+ >+sub new { >+ my $invocant = shift; >+ my $class = ref($invocant) || $invocant; >+ my $object = $class->_init(@_); >+ bless($object, $class) if $object; >+ return $object; >+} >+ >+=item C<_init> >+ >+Initializes the object using any data that is passed. (PRIVATE) >+ >+=cut >+ >+sub _init { >+ my ($self, $params) = @_; >+ >+ return {} >+} >+ >+# documentation for the Issue Tracker's XML RPC call used below >+# >+# IT.addEvent($struct, $username, $password): Adds an event to an >+# Issue-Tracker ticket >+# >+# Parameters: >+# >+# $struct: Data structure containing the following keys >+# >+# * 'tid': >+# Issue-Tracker Ticket ID that you are sending this event to >+# [string] (REQUIRED) >+# * 'bugzilla_id': >+# The Bugzilla ID that is associated with this IT ticket >+# [string] (REQUIRED) >+# * 'comment' >+# Struct (OPTIONAL) >+# o text [string]: New comment on the bugzilla bug >+# o private [boolean]: Public/Private flag for the comment >+# (defaults to 't') >+# * 'private' >+# Flag ('t'/'f') to make this event private/public [string] >+# (OPTIONAL) (defaults to 't') >+# * 'summary' >+# Array[old string, new string] - Brief description of bug (OPTIONAL) >+# * 'status' >+# Array[old string, new string] - Status of the bug (OPTIONAL) >+# * 'resolution' >+# Array[old string, new string] - If bug is closed, list reason (OPTIONAL) >+# * 'assignedto' >+# Array[old string, new string] - The email address of the >+# person assigned to the bug (OPTIONAL) >+# * 'blocks' >+# Array[old Array, new Array] - List of bug ids that cannot be >+# closed until this bug is closed (OPTIONAL) >+# * 'dependson' >+# Array[old Array, new Array] - List of bug ids that must be >+# closed before this bug is closed (OPTIONAL) >+# * 'notify' >+# String - Comma-separated list of additional email addresses to >+# notify (OPTIONAL) >+# >+# $username Required username for Bugzilla [string] >+# $password Required password for Bugzilla [string] >+ >+=pod >+ >+=item C<sendChanges> >+ >+Z<> >+ >+ (\@sentids,\@skippedids) sendChanges(\@changelist, $start, $end) >+ >+Reports 'interesting' changes that have (presumably) just been applied >+to the bug in the caller to all of the caller's issues via XML-RPC. >+All changes, except new comments, are reported in C<@changelist>, an >+array of arrays. Only the items at indexes 0,2,3,4, and 6 are of interest >+to this method: >+ >+=over >+ >+=item 0 >+ >+The login name of the person making the change >+ >+=item 2 >+ >+The date and time the change was made. Must be in a common >+format, but the exact format is not defined. >+ >+=item 3 >+ >+The old value of the field >+ >+=item 4 >+ >+The new value of the field >+ >+=item 6 >+ >+The name of the field that was changed >+ >+=back >+ >+Only changes to certain fields are reported. The current list of >+'interesting' fields is short_desc, bug_status, resolution, >+assigned_to, blocked, and dependson. >+ >+New comments, that were added between C<start> and C<end> >+date/times, are also reported to the issue tracker, >+ >+C<changelist> is required. The other two arguments are optional. >+ >+The return value is false (undef in scalar context, () in array >+context) if no changes need to be reported -- if there are no issues >+associated with this bug, or none of the reported changes are >+'interesting'. Otherwise, an array of two array refs is returned, the >+first array lists the ids that were successfully notified of changes, >+the second lists ids that were not successfully notified. >+ >+Any fatal errors arising from the XML-RPC system are turned into >+warnings on STDERR. >+ >+All changes in C<changelist> should be within the range of dates >+C<start> and C<end>, so that comments regarding these changes are >+included. This restriction is not enforced by this method, however. >+ >+The peculiar argument structure and behaviors of this method reflect >+the fact that this needs to interact smoothly with >+BugMail::ProcessOneBug(). >+ >+=cut >+ >+my $username = Bugzilla->params->{issuetracker_rpc_user}; >+my $password = Bugzilla->params->{issuetracker_rpc_password}; >+ >+sub _RPCNOERROR; >+sub _RPC; >+ >+sub sendChanges { >+ my ( $self, $diffs, $start, $end, $nocomment ) = @_; >+ my ( %incl, %excl, %diffs, %events ); >+ >+ my $issues = $self->issues; >+ >+ #use Data::Dumper; warn Dumper $diffs; >+ # get the changes and comments we are interested in >+ my %fields = qw( short_desc summary >+ bug_status status >+ priority priority >+ bug_severity severity >+ resolution resolution >+ assigned_to assignedto >+ fixed_in fixedin >+ blocked blocked >+ dependson dependson >+ keywords keywords >+ issuetracker issuetracker >+ flagtypes.name flag); >+ my @diffs = grep $fields{ $_->[7] }, @$diffs; >+ >+ # Do not pass comment if we are only interested in attribute changes >+ my $comments = []; >+ if ( !$nocomment ) { >+ $comments >+ = Bugzilla::Bug::GetComments( $self->{bz_id}, 'oldest_to_newest', >+ $start, $end ); >+ } >+ >+ # Grab list of group ids to pass with event >+ my $bug = new Bugzilla::Bug( $self->{bz_id}, Bugzilla->user->id ); >+ >+ # If current user cannot see bug, load it as bugzilla user so >+ # the message will be transferred anyway >+ my $cant_see = 0; >+ if ( $bug->{error} && $bug->{error} =~ /NotPermitted/i ) { >+ $bug = new Bugzilla::Bug( >+ $self->{bz_id}, >+ Bugzilla->user->login_to_id( >+ Bugzilla->params->{issuetracker_user} >+ ) >+ ); >+ $cant_see = 1; >+ } >+ >+ # Return empty if we still can't see >+ if ( $bug->{error} ) { >+ warn "Error opening bug $self->{bz_id}: $bug->{error}\n"; >+ return ( [], [] ); >+ } >+ >+ my $groupsref = $bug->groups; >+ my $groups = []; >+ foreach my $ref ( @{$groupsref} ) { >+ push( @{$groups}, $ref->{'bit'} ) if $ref->{'ison'}; >+ } >+ >+ # make sure there are interesting changes to report >+ # and there are affected issues to report them to >+ return >+ unless @diffs || @$comments >+ and @$issues || grep $_->[6] eq 'issuetracker', @diffs; >+ >+ # Arrange changes into events based on the time at which changes occurred. >+ # All changes occurring at the same time are assumed to be one event. >+ # Note: performed_by assumes all changes made at the same time are >+ # made by the same person. As long as times include fractional seconds this >+ # should be true 99.9999999% of the time. >+ foreach my $diff (@diffs) { >+ $diffs{ $diff->[3] } = [] if not exists $diffs{ $diff->[3] }; >+ push( @{ $diffs{ $diff->[3] } }, $diff ); >+ } >+ >+ foreach my $time ( sort keys %diffs ) { >+ print STDERR "time: $time\n"; >+ $events{$time} = { >+ bugzilla_id => $self->{bz_id}, >+ performed_by => $diffs{$time}[0][0], >+ groups => $groups, >+ }; >+ foreach my $diff ( @{ $diffs{$time} } ) { >+ $events{$time}{ $fields{ $diff->[7] } } >+ = [ $diff->[4], $diff->[5] ]; >+ } >+ if ( $bug->{'resolution'} eq 'DUPLICATE' ) { >+ $events{$time}{'dup_id'} = $bug->dup_id; >+ } >+ $events{$time}{issuetracker} = $issues; # MUST be after the map above >+ } >+ >+ # add in comments >+ foreach my $comment (@$comments) { >+ my $time = $comment->{'time'}; >+ >+ # create event with basic information if not already created. >+ unless ( exists $events{$time} ) { >+ $events{$time} = { >+ bugzilla_id => $self->{bz_id}, >+ performed_by => $comment->{author}->login, >+ groups => $groups, >+ issuetracker => $issues, >+ }; >+ } >+ $events{$time}{comment} = { >+ text => $comment->{body}, >+ private => $comment->{isprivate} ? 0 : 1 >+ }; >+ } >+ >+ # get the xmlrpc client >+ my $rpc = _RPCNOERROR or return ( [], $issues ); >+ >+ foreach my $evt ( keys %events ) { >+ my $result = eval { callIT_HASHX( 'addEvent', $events{$evt} ) }; >+ >+ print STDERR Dumper($result); >+ >+ # record what happened >+ if ( my $e = $@ ) { >+ mailError( join( ', ', @{ $events{$evt}{'issuetracker'} } ), >+ $e, Dumper( $events{$evt} ) ); >+ $excl{"(Issuetrackers not updated for changes at $evt)"} = 1; >+ next; >+ } >+ foreach my $issue ( keys %{$result} ) { >+ $incl{$issue} = 1 if $result->{$issue}; >+ } >+ foreach my $issue ( @{$issues} ) { >+ $excl{$issue} = 1 if !$result->{$issue}; >+ } >+ } >+ >+ if ($cant_see) { >+ return ( [], [] ); >+ } >+ else { >+ return ( [ keys %incl ], [ keys %excl ] ); >+ } >+} >+ >+=pod >+ >+=item C<getScore> >+ >+Z<> >+ >+ int getScore($it_id) >+ >+Retrieves current score for IssueTracker ID from IssueTracker database. >+Otherwise defaults to -1 to denote not score yet. >+ >+kbaker: it should use undef to represent "no score yet" >+ >+=cut >+ >+sub getScore { >+ my ( $self, $it_id ) = @_; >+ >+ if ( !detaint_natural($it_id) ) { >+ return -1; >+ } >+ >+ my $result = eval { callIT_HASH( 'getScore', [$it_id] ) }; >+ >+ # record what happened but do not stop >+ if ( my $e = $@ ) { >+ mailError( $it_id, $e ); >+ >+ #ThrowCodeError('xmlrpc_error', >+ # { action=>'Getting score for issuetracker IDs', message=>"$eval_error" }); >+ return -1; >+ } >+ >+ if ( defined( $result->{$it_id} ) ) { >+ return $result->{$it_id}; >+ } >+ return -1; >+} >+ >+=pod C<mailError> >+ >+ void mailError($it_id, $error) >+ >+Mails Issue Tracker error message to bugzilla-maintainer >+ >+=cut >+ >+sub mailError { >+ my ( $it_id, $error, $extra ) = @_; >+ >+ my $host = eval { require Sys::Hostname; Sys::Hostname::hostname() } >+ || 'undefined'; >+ my $stack = eval { require Carp; Carp::longmess("stack backtrace") } >+ || 'undefined'; >+ my $user >+ = eval { require Bugzilla; Bugzilla->user->identity } || 'undefined'; >+ >+ warn "Error communicating with IssueTracker ID(s): $it_id: $error"; >+ >+ # Send email to bugzilla owner about the problem >+ my $err_msg = "To: " . Bugzilla->params->{maintainer} . "\n"; >+ $err_msg .= "From: bugzilla\@redhat.com\n"; >+ $err_msg >+ .= "Subject: Error communicating with IssueTracker ID(s): $it_id\n\n"; >+ $err_msg .= "Error communicating with IssueTracker ID(s): $it_id\n"; >+ $err_msg .= "Error \$\@: $error\n\n"; >+ $err_msg .= "Host: $host\n"; >+ $err_msg .= "Pid: $$\n"; >+ $err_msg .= "User: $user\n"; >+ $err_msg .= "Remote Address: $ENV{REMOTE_ADDR}\n"; >+ $err_msg .= "Stack Trace:\n$stack\n"; >+ $err_msg .= "Extra Data:\n$extra\n" if $extra; >+ >+ open( SENDMAIL, "|/usr/lib/sendmail -t -i" ) >+ || warn "Can't open sendmail"; >+ print SENDMAIL $err_msg; >+ close SENDMAIL || warn "Can't close sendmail"; >+} >+ >+=pod >+ >+=item C<validateIssueID> >+ >+Z<> >+ >+ void validateIssueID($it_id) >+ >+Validates that a given issue tracker ID (C<$it_id>) corresponds to a >+real issue in the issue tracker and also if it currently does not have >+a bug id associated with it. >+ >+Throws a user error if there is a problem with the input C<$it_id>. >+ >+=cut >+ >+sub validateIssueID { >+ >+ # Check to see actually a valid issue >+ $_[0]->issueIDIsValid( $_[1] ) >+ || ThrowUserError( "invalid_issue_id", { badissue => $_[1] } ); >+ >+ # Check to see if issue already has one or more bugs associated >+ $_[0]->issueHasBug( $_[1] ) >+ && ThrowUserError( "issue_has_bug", { badissue => $_[1] } ); >+} >+ >+=pod >+ >+=item C<issueIDIsValid> >+ >+Z<> >+ >+ $boolean issueIDIsValid($it_id) >+ >+Validates that a given issue tracker ID (C<$it_id>) corresponds to a >+real issue in the issue tracker and is allowed to be linked. >+ >+Returns a true value if the issue ID is valid, false otherwise. >+ >+=cut >+ >+sub issueIDIsValid { >+ my ( undef, $it_id ) = @_; >+ >+ if ( !detaint_natural($it_id) ) { >+ ThrowCodeError( >+ 'xmlrpc_error', >+ { action => "Validating issuetracker IDs", >+ message => >+ "Error: Issue Tracker ID $it_id is not a valid integer." >+ } >+ ); >+ } >+ >+ my $result = eval { callIT( 'issueExists', $it_id ) }; >+ >+ if ( my $e = $@ ) { >+ >+ ThrowCodeError( >+ 'xmlrpc_error', >+ { action => "Validating issuetracker IDs", >+ message => "Error: $e" >+ } >+ ); >+ } >+ >+ return $result; >+} >+ >+=pod >+ >+=item C<issueHasBug> >+ >+Z<> >+ >+ $boolean issueHasBug($it_id) >+ >+Validates that a given issue tracker ID (C<$it_id>) does not >+already have a bug id associated with it. >+ >+Returns a true value if the adding of the issue ID is valid, false otherwise. >+ >+=cut >+ >+sub issueHasBug { >+ my ( undef, $it_id ) = @_; >+ >+ if ( !detaint_natural($it_id) ) { >+ ThrowCodeError( >+ 'xmlrpc_error', >+ { action => "Validating issuetracker IDs", >+ message => >+ "Error: Issue Tracker ID $it_id is not a valid integer." >+ } >+ ); >+ } >+ >+ my $result = eval { callIT_HASH( 'getBugzillaIDs', [$it_id] ) }; >+ >+ if ( my $e = $@ ) { >+ ThrowCodeError( >+ 'xmlrpc_error', >+ { action => "Validating issuetracker IDs", >+ message => "Error: $e" >+ } >+ ); >+ } >+ >+ # If issue has one or more bugs assigned to it, we fail >+ if ( exists $result->{$it_id} and @{ $result->{$it_id} } > 0 ) { >+ return 1; >+ } >+ >+ return 0; >+} >+ >+=item callIT_HASH( $function, @function_params ) >+ >+returns result hash ref on success. >+ >+die's on error. >+ >+=cut >+ >+sub callIT_HASH { >+ my $func = shift; >+ my @func_params = @_; >+ >+ my $result = callIT( $func, @func_params ); >+ if ( not defined $result ) { >+ die "no result returned from $func call to Issue Tracker"; >+ } >+ if ( ref($result) ne 'HASH' ) { >+ die "expected HASH from $func call to Issue Tracker but got: " >+ . Data::Dumper::Dumper($result); >+ } >+ return $result; # success >+} >+ >+=item callIT_HASHX( $function, @function_params ) >+ >+returns result hash ref on success. Handles the case where IT returns >+an empty string sometimes and a HASH other times. The caller of callIT_HASHX >+will always get a hash back. >+ >+die's on error. >+ >+=cut >+ >+sub callIT_HASHX { >+ my $func = shift; >+ my @func_params = @_; >+ >+ my $result = callIT( $func, @func_params ); >+ if ( not defined $result ) { >+ die "no result returned from $func call to Issue Tracker"; >+ } >+ if ( not ref($result) and $result eq '' ) { >+ return {}; >+ } >+ if ( ref($result) ne 'HASH' ) { >+ die "expected HASH from $func call to Issue Tracker but got: " >+ . Data::Dumper::Dumper($result); >+ } >+ return $result; # success >+} >+ >+=item callIT( $function, @function_params ) >+ >+returns result success. >+ >+die's on error. >+ >+=cut >+ >+sub callIT { >+ my $func = shift; >+ my @func_params = @_; >+ >+ my $rpc = _RPC(); >+ >+TRY: >+ >+ for my $try ( 1 .. MAXTRIES ) { >+ my $result = eval { >+ my $call = $rpc->call( "IT.$func", @func_params, $username, >+ $password ); >+ if ( not $call ) { >+ die "IT.$func failure: no call object returned by rpc!!"; >+ } >+ if ( $call->faultstring ) { >+ die "IT.$func failure: " . $call->faultstring; >+ } >+ $call->result; >+ }; >+ >+ my $call_error = $@; >+ >+ if ( !$call_error ) { >+ return $result; >+ } >+ >+ if ( $try == MAXTRIES ) { >+ die $call_error; >+ } >+ else { >+ warn "IT.$func call failed attempt $try with: $call_error"; >+ } >+ >+ sleep 2; >+ } >+ >+ die "callIT failure: should never get here"; >+} >+ >+=pod >+ >+=back >+ >+=head2 Class Variables >+ >+Note: this/these are described as variables, but are implemented as >+functions that take no arguments and return the described value. >+Since they don't care about their arguments, they can be called as >+regular functions, class methods or instance methods. >+ >+=over 4 >+ >+=cut >+ >+=pod >+ >+=item C<XMLRPC::Lite _RPC> >+ >+A client for interacting with the Issue Tracker's XML-RPC server. The >+first time this is called it creates the client object. If the client >+can't be created it will throw a code error. Once created, this is >+the same object as C<_RPCNOERROR>. >+ >+=cut >+ >+my $rpc; >+ >+sub _RPC { >+ >+ # already created >+ return $rpc if $rpc; >+ >+ # create and return new >+ eval { >+ $rpc = new XMLRPC::Lite( >+ proxy => Bugzilla->params->{issuetracker_rpcserver} ); >+ }; >+ >+ ThrowCodeError( 'cannot_create_xmlrpc_client', { message => "$@" } ) >+ if $@; >+ return $rpc; >+} >+ >+=pod >+ >+=item C<XMLRPC::Lite _RPCNOERROR> >+ >+A client for interacting with the Issue Tracker's XML-RPC server. The >+first time this is called it creates the client object. If the client >+can't be created undef will be returned. Once created this is the >+same object as C<_RPC> >+ >+=cut >+ >+# if Bugzilla used real exceptions, this wouldn't be necessary. -mpm >+sub _RPCNOERROR { >+ >+ # already created >+ return $rpc if $rpc; >+ >+ # create and return new >+ eval { >+ $rpc = new XMLRPC::Lite( >+ proxy => Bugzilla->params->{issuetracker_rpcserver} ); >+ }; >+ >+ warn "Can't create XML-RPC client: $@" if $@; >+ return $rpc; >+} >+ >+=pod >+ >+=back >+ >+=head1 SEE ALSO >+ >+L<Bugzilla|Bugzilla> >+ >+=cut >+ >+1; >Index: extensions/issuetracker/template/en/bug/field-links.html.tmpl >=================================================================== >RCS file: extensions/issuetracker/template/en/bug/field-links.html.tmpl >diff -N extensions/issuetracker/template/en/bug/field-links.html.tmpl >--- /dev/null 1 Jan 1970 00:00:00 -0000 >+++ extensions/issuetracker/template/en/bug/field-links.html.tmpl 14 Mar 2008 03:22:52 -0000 >@@ -0,0 +1,4 @@ >+[% FOREACH issue = bug.cf_issuetracker %] >+ <a href="[% Param('issuetracker_urlbase') %][% issue FILTER url_quote %]">[% issue FILTER html %]</a>[% " " %] >+[% END %] >+ >Index: extensions/issuetracker/template/en/global/user-error-errors.html.tmpl >=================================================================== >RCS file: extensions/issuetracker/template/en/global/user-error-errors.html.tmpl >diff -N extensions/issuetracker/template/en/global/user-error-errors.html.tmpl >--- /dev/null 1 Jan 1970 00:00:00 -0000 >+++ extensions/issuetracker/template/en/global/user-error-errors.html.tmpl 14 Mar 2008 03:22:52 -0000 >@@ -0,0 +1,10 @@ >+[% IF error == "invalid_issue_id" %] >+ [% title = "Invalid Issue Tracker ID" %] >+ The issue tracker ID, '[% badissue FILTER html %]', is invalid. >+ It must be a positive integer and must be an existing ticket ID in the issue >+ tracker system. >+[% ELSIF error == "issue_has_bug" %] >+ [% title = "Invalid Issue Tracker ID" %] >+ The issue tracker ID, '[% badissue FILTER html %]', already has a >+ [% terms.bug %] associated with it. >+[% END %] >Index: template/en/default/bug/field.html.tmpl >=================================================================== >RCS file: /cvs/qa/rh_bugzilla_3/template/en/default/bug/field.html.tmpl,v >retrieving revision 1.3 >diff -u -p -r1.3 field.html.tmpl >--- template/en/default/bug/field.html.tmpl 14 Jan 2008 15:38:36 -0000 1.3 >+++ template/en/default/bug/field.html.tmpl 14 Mar 2008 03:22:52 -0000 >@@ -61,6 +61,12 @@ > <script type="text/javascript"> > createCalendar('[% field.name FILTER js %]') > </script> >+ [% CASE constants.FIELD_TYPE_FREETEXT_MULTI_INTEGER %] >+ <input id="[% field.name FILTER html %]" name="[% field.name FILTER html %]" >+ value="[% value.join(' ') FILTER html %]" size="60" >+ maxlength="[% constants.MAX_FREETEXT_LENGTH FILTER none %]"> >+ <br/> >+ [% Hook.process('links') %] > [% CASE [ constants.FIELD_TYPE_SINGLE_SELECT > constants.FIELD_TYPE_MULTI_SELECT ] %] > <select id="[% field.name FILTER html %]" >Index: template/en/default/global/field-descs.none.tmpl >=================================================================== >RCS file: /cvs/qa/rh_bugzilla_3/template/en/default/global/field-descs.none.tmpl,v >retrieving revision 1.4 >diff -u -p -r1.4 field-descs.none.tmpl >--- template/en/default/global/field-descs.none.tmpl 5 Mar 2008 21:41:51 -0000 1.4 >+++ template/en/default/global/field-descs.none.tmpl 14 Mar 2008 03:22:53 -0000 >@@ -78,12 +78,13 @@ > IF !field_descs.${bz_field.name}.defined %] > [% END %] > >-[% field_types = { ${constants.FIELD_TYPE_UNKNOWN} => "Unknown Type", >- ${constants.FIELD_TYPE_FREETEXT} => "Free Text", >- ${constants.FIELD_TYPE_SINGLE_SELECT} => "Drop Down", >- ${constants.FIELD_TYPE_MULTI_SELECT} => "Multiple-Selection Box", >- ${constants.FIELD_TYPE_TEXTAREA} => "Large Text Box", >- ${constants.FIELD_TYPE_DATETIME} => "Date/Time", >+[% field_types = { ${constants.FIELD_TYPE_UNKNOWN} => "Unknown Type", >+ ${constants.FIELD_TYPE_FREETEXT} => "Free Text", >+ ${constants.FIELD_TYPE_SINGLE_SELECT} => "Drop Down", >+ ${constants.FIELD_TYPE_MULTI_SELECT} => "Multiple-Selection Box", >+ ${constants.FIELD_TYPE_FREETEXT_MULTI_INTEGER} => "Multiple Value Text Box (Integer)", >+ ${constants.FIELD_TYPE_TEXTAREA} => "Large Text Box", >+ ${constants.FIELD_TYPE_DATETIME} => "Date/Time", > } %] > > [% status_descs = { "UNCONFIRMED" => "UNCONFIRMED", >Index: template/en/default/global/user-error.html.tmpl >=================================================================== >RCS file: /cvs/qa/rh_bugzilla_3/template/en/default/global/user-error.html.tmpl,v >retrieving revision 1.19 >diff -u -p -r1.19 user-error.html.tmpl >--- template/en/default/global/user-error.html.tmpl 11 Mar 2008 03:47:17 -0000 1.19 >+++ template/en/default/global/user-error.html.tmpl 14 Mar 2008 03:22:54 -0000 >@@ -406,6 +406,12 @@ > does not exist or you aren't authorized to > enter [% terms.abug %] into it. > >+ [% ELSIF error == "field_invalid_value" %] >+ [% title = "Invalid Field Value" %] >+ You entered an invalid value <em>[% value FILTER html %]</em> >+ for the [% field_descs.$field FILTER html %] field. Value must >+ be in form of [% type FILTER html %]. >+ > [% ELSIF error == "field_already_exists" %] > [% title = "Field Already Exists" %] > The field '[% field.name FILTER html %]'
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Flags:
dkl
: review? (
kbaker
)
Actions:
View
|
Diff
Attachments on
bug 406111
:
295481
|
295565
|
295587
|
295999
|
297255
|
298010
|
298220