diff options
-rw-r--r-- | Bugzilla/DB.pm | 7 | ||||
-rw-r--r-- | Bugzilla/DB/Oracle.pm | 15 | ||||
-rw-r--r-- | Bugzilla/DB/Pg.pm | 12 | ||||
-rw-r--r-- | Bugzilla/DB/Sqlite.pm | 6 | ||||
-rw-r--r-- | Bugzilla/Search.pm | 36 | ||||
-rw-r--r-- | Bugzilla/WebService/Bug.pm | 7 | ||||
-rw-r--r-- | docs/en/xml/administration.xml | 15 | ||||
-rwxr-xr-x | email_in.pl | 19 | ||||
-rw-r--r-- | template/en/default/bug/edit.html.tmpl | 14 | ||||
-rw-r--r-- | template/en/default/bug/field-label.html.tmpl | 3 |
10 files changed, 73 insertions, 61 deletions
diff --git a/Bugzilla/DB.pm b/Bugzilla/DB.pm index a537d6131..083a1c208 100644 --- a/Bugzilla/DB.pm +++ b/Bugzilla/DB.pm @@ -397,8 +397,11 @@ sub sql_string_concat { sub sql_string_until { my ($self, $string, $substring) = @_; - return "SUBSTRING($string FROM 1 FOR " . - $self->sql_position($substring, $string) . " - 1)"; + + my $position = $self->sql_position($substring, $string); + return "CASE WHEN $position != 0" + . " THEN SUBSTR($string, 1, $position - 1)" + . " ELSE $string END"; } sub sql_in { diff --git a/Bugzilla/DB/Oracle.pm b/Bugzilla/DB/Oracle.pm index d91eb428e..711b84141 100644 --- a/Bugzilla/DB/Oracle.pm +++ b/Bugzilla/DB/Oracle.pm @@ -40,6 +40,8 @@ use base qw(Bugzilla::DB); use DBD::Oracle; use DBD::Oracle qw(:ora_types); +use List::Util qw(max); + use Bugzilla::Constants; use Bugzilla::Error; use Bugzilla::Util; @@ -50,6 +52,8 @@ use Bugzilla::Util; use constant EMPTY_STRING => '__BZ_EMPTY_STR__'; use constant ISOLATION_LEVEL => 'READ COMMITTED'; use constant BLOB_TYPE => { ora_type => ORA_BLOB }; +# The max size allowed for LOB fields, in kilobytes. +use constant MIN_LONG_READ_LEN => 32 * 1024; use constant FULLTEXT_OR => ' OR '; sub new { @@ -68,8 +72,8 @@ sub new { my $dsn = "dbi:Oracle:host=$host;sid=$dbname"; $dsn .= ";port=$port" if $port; my $attrs = { FetchHashKeyName => 'NAME_lc', - LongReadLen => ( Bugzilla->params->{'maxattachmentsize'} - || 1000 ) * 1024, + LongReadLen => max(Bugzilla->params->{'maxattachmentsize'}, + MIN_LONG_READ_LEN) * 1024, }; my $self = $class->db_new({ dsn => $dsn, user => $user, pass => $pass, attrs => $attrs }); @@ -156,13 +160,6 @@ sub sql_string_concat { return 'CONCAT(' . join(', ', @params) . ')'; } -sub sql_string_until { - my ($self, $string, $substring) = @_; - return "SUBSTR($string, 1, " - . $self->sql_position($substring, $string) - . " - 1)"; -} - sub sql_to_days { my ($self, $date) = @_; diff --git a/Bugzilla/DB/Pg.pm b/Bugzilla/DB/Pg.pm index 386a67709..e59a638a4 100644 --- a/Bugzilla/DB/Pg.pm +++ b/Bugzilla/DB/Pg.pm @@ -192,18 +192,6 @@ sub sql_string_concat { return '(CAST(' . join(' AS text) || CAST(', @params) . ' AS text))'; } -sub sql_string_until { - my ($self, $string, $substring) = @_; - - # PostgreSQL does not permit a negative substring length; therefore we - # use CASE to only perform the SUBSTRING operation when $substring can - # be found withing $string. - my $position = $self->sql_position($substring, $string); - return "CASE WHEN $position != 0" - . " THEN SUBSTRING($string FROM 1 FOR $position - 1)" - . " ELSE $string END"; -} - # Tell us whether or not a particular sequence exists in the DB. sub bz_sequence_exists { my ($self, $seq_name) = @_; diff --git a/Bugzilla/DB/Sqlite.pm b/Bugzilla/DB/Sqlite.pm index fb6aaba97..e13fd18e1 100644 --- a/Bugzilla/DB/Sqlite.pm +++ b/Bugzilla/DB/Sqlite.pm @@ -237,12 +237,6 @@ sub sql_date_math { return "DATETIME($date, '$operator' || $interval || ' $units')"; } -sub sql_string_until { - my ($self, $string, $substring) = @_; - my $position = $self->sql_position($substring, $string); - return "SUBSTR($string, 1, $position - 1)" -} - ############### # bz_ methods # ############### diff --git a/Bugzilla/Search.pm b/Bugzilla/Search.pm index fdc0e2991..0c9f84689 100644 --- a/Bugzilla/Search.pm +++ b/Bugzilla/Search.pm @@ -55,6 +55,7 @@ use Bugzilla::Keyword; use Data::Dumper; use Date::Format; use Date::Parse; +use Scalar::Util qw(blessed); use List::MoreUtils qw(all part uniq); use POSIX qw(INT_MAX); use Storable qw(dclone); @@ -509,9 +510,14 @@ use constant COLUMN_JOINS => { # and we don't want it to happen at compile time, so we have it as a # subroutine. sub COLUMNS { + my $invocant = shift; + my $user = blessed($invocant) ? $invocant->_user : Bugzilla->user; my $dbh = Bugzilla->dbh; my $cache = Bugzilla->request_cache; - return $cache->{search_columns} if defined $cache->{search_columns}; + + if (defined $cache->{search_columns}->{$user->id}) { + return $cache->{search_columns}->{$user->id}; + } # These are columns that don't exist in fielddefs, but are valid buglist # columns. (Also see near the bottom of this function for the definition @@ -567,10 +573,7 @@ sub COLUMNS { foreach my $col (@email_fields) { my $sql = "map_${col}.login_name"; - # XXX This needs to be generated inside an accessor instead, - # probably, because it should use $self->_user to determine - # this, not Bugzilla->user. - if (!Bugzilla->user->id) { + if (!$user->id) { $sql = $dbh->sql_string_until($sql, $dbh->quote('@')); } $special_sql{$col} = $sql; @@ -605,12 +608,15 @@ sub COLUMNS { Bugzilla::Hook::process('buglist_columns', { columns => \%columns }); - $cache->{search_columns} = \%columns; - return $cache->{search_columns}; + $cache->{search_columns}->{$user->id} = \%columns; + return $cache->{search_columns}->{$user->id}; } sub REPORT_COLUMNS { - my $columns = dclone(COLUMNS); + my $invocant = shift; + my $user = blessed($invocant) ? $invocant->_user : Bugzilla->user; + + my $columns = dclone(blessed($invocant) ? $invocant->COLUMNS : COLUMNS); # There's no reason to support reporting on unique fields. # Also, some other fields don't make very good reporting axises, # or simply don't work with the current reporting system. @@ -625,7 +631,7 @@ sub REPORT_COLUMNS { # If you're not a time-tracker, you can't use time-tracking # columns. - if (!Bugzilla->user->is_timetracker) { + if (!$user->is_timetracker) { push(@no_report_columns, TIMETRACKING_FIELDS); } @@ -841,7 +847,7 @@ sub _sql_select { my $alias = $column; # Aliases cannot contain dots in them. We convert them to underscores. $alias =~ s/\./_/g; - my $sql = COLUMNS->{$column}->{name} . " AS $alias"; + my $sql = $self->COLUMNS->{$column}->{name} . " AS $alias"; push(@sql_fields, $sql); } return @sql_fields; @@ -1190,7 +1196,7 @@ sub _sql_group_by { my @extra_group_by; foreach my $column ($self->_select_columns) { next if $self->_skip_group_by->{$column}; - my $sql = COLUMNS->{$column}->{name}; + my $sql = $self->COLUMNS->{$column}->{name}; push(@extra_group_by, $sql); } @@ -2299,11 +2305,11 @@ sub _content_matches { # # We build the relevance SQL by modifying the COLUMNS list directly, # which is kind of a hack but works. - my $current = COLUMNS->{'relevance'}->{name}; + my $current = $self->COLUMNS->{'relevance'}->{name}; $current = $current ? "$current + " : ''; # For NOT searches, we just add 0 to the relevance. my $select_term = $operator =~ /not/ ? 0 : "($current$rterm1 + $rterm2)"; - COLUMNS->{'relevance'}->{name} = $select_term; + $self->COLUMNS->{'relevance'}->{name} = $select_term; } sub _long_descs_count { @@ -2353,13 +2359,13 @@ sub _work_time_changedbefore_after { sub _work_time { my ($self, $args) = @_; $self->_add_extra_column('actual_time'); - $args->{full_field} = COLUMNS->{actual_time}->{name}; + $args->{full_field} = $self->COLUMNS->{actual_time}->{name}; } sub _percentage_complete { my ($self, $args) = @_; - $args->{full_field} = COLUMNS->{percentage_complete}->{name}; + $args->{full_field} = $self->COLUMNS->{percentage_complete}->{name}; # We need actual_time in _select_columns, otherwise we can't use # it in the expression for searching percentage_complete. diff --git a/Bugzilla/WebService/Bug.pm b/Bugzilla/WebService/Bug.pm index 8506c4b47..ca9ee1014 100644 --- a/Bugzilla/WebService/Bug.pm +++ b/Bugzilla/WebService/Bug.pm @@ -665,9 +665,12 @@ sub add_attachment { my @created; $dbh->bz_start_transaction(); + my $timestamp = $dbh->selectrow_array('SELECT LOCALTIMESTAMP(0)'); + foreach my $bug (@bugs) { my $attachment = Bugzilla::Attachment->create({ bug => $bug, + creation_ts => $timestamp, data => $params->{data}, description => $params->{summary}, filename => $params->{file_name}, @@ -682,7 +685,7 @@ sub add_attachment { extra_data => $attachment->id }); push(@created, $attachment); } - $_->bug->update($_->attached) foreach @created; + $_->bug->update($timestamp) foreach @created; $dbh->bz_commit_transaction(); $_->send_changes() foreach @bugs; @@ -2541,7 +2544,7 @@ This allows you to add a comment to a bug in Bugzilla. =over -=item C<id> (int) B<Required> - The id or alias of the bug to append a +=item C<id> (int or string) B<Required> - The id or alias of the bug to append a comment to. =item C<comment> (string) B<Required> - The comment to append to the bug. diff --git a/docs/en/xml/administration.xml b/docs/en/xml/administration.xml index 4b7189755..cabb772d2 100644 --- a/docs/en/xml/administration.xml +++ b/docs/en/xml/administration.xml @@ -2365,6 +2365,11 @@ ReadOnly: ENTRY, NA/NA, CANEDIT several types available: <simplelist> <member> + Bug ID: A field where you can enter the ID of another bug from + the same Bugzilla installation. To point to a bug in a remote + installation, use the See Also field instead. + </member> + <member> Large Text Box: A multiple line box for entering free text. </member> <member> @@ -2427,6 +2432,16 @@ ReadOnly: ENTRY, NA/NA, CANEDIT be displayed at all. Obsolete Custom Fields are hidden. </para> </listitem> + + <listitem> + <para> + <emphasis>Is mandatory:</emphasis> + Boolean that determines whether this field must be set. + For single and multi-select fields, this means that a (non-default) + value must be selected, and for text and date fields, some text + must be entered. + </para> + </listitem> </itemizedlist> </para> </section> diff --git a/email_in.pl b/email_in.pl index 55e7b119a..ed4cf9a04 100755 --- a/email_in.pl +++ b/email_in.pl @@ -158,22 +158,29 @@ sub parse_mail { return \%fields; } -sub post_bug { +sub check_email_fields { my ($fields) = @_; - debug_print('Posting a new bug...'); - - my $user = Bugzilla->user; my ($retval, $non_conclusive_fields) = Bugzilla::User::match_field({ 'assigned_to' => { 'type' => 'single' }, 'qa_contact' => { 'type' => 'single' }, - 'cc' => { 'type' => 'multi' } + 'cc' => { 'type' => 'multi' }, + 'newcc' => { 'type' => 'multi' } }, $fields, MATCH_SKIP_CONFIRM); if ($retval != USER_MATCH_SUCCESS) { ThrowUserError('user_match_too_many', {fields => $non_conclusive_fields}); } +} + +sub post_bug { + my ($fields) = @_; + debug_print('Posting a new bug...'); + + my $user = Bugzilla->user; + + check_email_fields($fields); my $bug = Bugzilla::Bug->create($fields); debug_print("Created bug " . $bug->id); @@ -214,6 +221,8 @@ sub process_bug { $fields{'removecc'} = 1; } + check_email_fields(\%fields); + my $cgi = Bugzilla->cgi; foreach my $field (keys %fields) { $cgi->param(-name => $field, -value => $fields{$field}); diff --git a/template/en/default/bug/edit.html.tmpl b/template/en/default/bug/edit.html.tmpl index 3a154b557..ccec86449 100644 --- a/template/en/default/bug/edit.html.tmpl +++ b/template/en/default/bug/edit.html.tmpl @@ -531,15 +531,11 @@ [%############################################################################%] [% BLOCK section_url_keyword_whiteboard %] <tr> - <td class="field_label"> - <label for="bug_file_loc" accesskey="u"><b> - [% IF is_safe_url(bug.bug_file_loc) %] - <a href="[% bug.bug_file_loc FILTER html %]"><u>U</u>RL</a> - [% ELSE %] - <u>U</u>RL - [% END %] - [%%]</b></label>: - </td> + [% INCLUDE "bug/field-label.html.tmpl" + field = bug_fields.bug_file_loc + editable = 1 + accesskey = "u" + %] <td> [% IF bug.check_can_change_field("bug_file_loc", 0, 1) %] <span id="bz_url_edit_container" class="bz_default_hidden"> diff --git a/template/en/default/bug/field-label.html.tmpl b/template/en/default/bug/field-label.html.tmpl index fe3bed75b..ecb49318e 100644 --- a/template/en/default/bug/field-label.html.tmpl +++ b/template/en/default/bug/field-label.html.tmpl @@ -24,6 +24,7 @@ # hidden: True if the field label should start hidden. # rowspan: a "rowspan" value for the label's <th>. # tag_name: the tag to use to surround the label + # accesskey: access key for the label #%] [% DEFAULT tag_name = "th" %] @@ -33,7 +34,7 @@ [% IF rowspan %] rowspan="[% rowspan FILTER html %]"[% END %]> [% IF editable %] - <label for="[% field.name FILTER html %]"> + <label for="[% field.name FILTER html %]"[% IF accesskey %] accesskey="[% accesskey FILTER html %]"[% END %]> [% END %] <a |