diff --git a/Bugzilla/BugMail.pm b/Bugzilla/BugMail.pm index 14f4e9b19..ac85a7335 100644 --- a/Bugzilla/BugMail.pm +++ b/Bugzilla/BugMail.pm @@ -341,11 +341,10 @@ sub Send { @diff_tmp = (); } $lastbug = $depbug; - my $urlbase = Bugzilla->params->{"urlbase"}; $thisdiff = "\nBug $id depends on bug $depbug, which changed state.\n\n" . "Bug $depbug Summary: $summary\n" . - "${urlbase}show_bug.cgi?id=$depbug\n\n"; + correct_urlbase() . "show_bug.cgi?id=$depbug\n\n"; $thisdiff .= three_columns("What ", "Old Value", "New Value"); $thisdiff .= ('-' x 76) . "\n"; $interestingchange = 0; @@ -381,7 +380,7 @@ sub Send { if ($deptext) { - push @diffparts, { text => "\n" . trim("\n\n" . $deptext) }; + push @diffparts, { text => "\n" . trim($deptext) }; } } @@ -616,12 +615,14 @@ sub sendMail } } - if (!$difftext && !$newcomments && !@$newcomments && !$isnew) { + if ($difftext eq "" && !scalar(@$newcomments) && !$isnew) { # Whoops, no differences! return 0; } my $diffs = $difftext; + # Remove extra newlines. + $diffs =~ s/^\n+//s; $diffs =~ s/\n+$//s; my @showfieldvalues = (); # for HTML emails if ($isnew) { my $head = ""; @@ -724,9 +725,15 @@ sub get_comments_by_bug { my $raw = 0; # Do not format comments which are not of type CMT_NORMAL. my $comments = Bugzilla::Bug::GetComments($id, "oldest_to_newest", $start, $end, $raw); + my $attach_base = correct_urlbase() . 'attachment.cgi?id='; foreach my $comment (@$comments) { $comment->{count} = $count++; + # If an attachment was created, then add an URL. (Note: the 'g'lobal + # replace should work with comments with multiple attachments.) + if ($comment->{body} =~ /Created an attachment \(/) { + $comment->{body} =~ s/(Created an attachment \(id=([0-9]+)\))/$1\n --> \($attach_base$2\)/g; + } } if (Bugzilla->params->{'insidergroup'}) { diff --git a/Bugzilla/Chart.pm b/Bugzilla/Chart.pm index 1f232f310..58089d29e 100644 --- a/Bugzilla/Chart.pm +++ b/Bugzilla/Chart.pm @@ -396,10 +396,10 @@ sub getVisibleSeries { "LEFT JOIN category_group_map AS cgm " . " ON series.category = cgm.category_id " . " AND cgm.group_id NOT IN($grouplist) " . - "WHERE creator = " . Bugzilla->user->id . " OR " . - " cgm.category_id IS NULL " . + "WHERE creator = ? OR (is_public = 1 AND cgm.category_id IS NULL) " . $dbh->sql_group_by('series.series_id', 'cc1.name, cc2.name, ' . - 'series.name')); + 'series.name'), + undef, Bugzilla->user->id); foreach my $series (@$serieses) { my ($cat, $subcat, $name, $series_id) = @$series; $cats{$cat}{$subcat}{$name} = $series_id; diff --git a/Bugzilla/Constants.pm b/Bugzilla/Constants.pm index a84893e10..44b3905d6 100644 --- a/Bugzilla/Constants.pm +++ b/Bugzilla/Constants.pm @@ -169,7 +169,7 @@ use File::Basename; # CONSTANTS # # Bugzilla version -use constant BUGZILLA_VERSION => "3.4.1"; +use constant BUGZILLA_VERSION => "3.4.2"; # These are unique values that are unlikely to match a string or a number, # to be used in criteria for match() functions and other things. They start diff --git a/Bugzilla/DB.pm b/Bugzilla/DB.pm index 5b42ea6e6..2c5b0a7f8 100644 --- a/Bugzilla/DB.pm +++ b/Bugzilla/DB.pm @@ -747,6 +747,28 @@ sub bz_drop_fk { } +sub bz_drop_related_fks { + my ($self, $table, $column) = @_; + my @tables = $self->_bz_real_schema->get_table_list(); + my @dropped; + foreach my $check_table (@tables) { + my @columns = $self->bz_table_columns($check_table); + foreach my $check_column (@columns) { + my $def = $self->bz_column_info($check_table, $check_column); + my $fk = $def->{REFERENCES}; + if ($fk + and (($fk->{TABLE} eq $table and $fk->{COLUMN} eq $column) + or ($check_column eq $column and $check_table eq $table))) + { + $self->bz_drop_fk($check_table, $check_column); + push(@dropped, [$check_table, $check_column, $fk]); + } + } # foreach $column + } # foreach $table + + return \@dropped; +} + sub bz_drop_index { my ($self, $table, $name) = @_; diff --git a/Bugzilla/DB/Mysql.pm b/Bugzilla/DB/Mysql.pm index 9d444e44c..20f0035ee 100644 --- a/Bugzilla/DB/Mysql.pm +++ b/Bugzilla/DB/Mysql.pm @@ -325,7 +325,7 @@ EOT my @isam_tables; foreach my $row (@$table_status) { my ($name, $type) = @$row; - push(@isam_tables, $name) if $type eq "ISAM"; + push(@isam_tables, $name) if (defined($type) && $type eq "ISAM"); } if(scalar(@isam_tables)) { @@ -370,7 +370,7 @@ EOT my @myisam_tables; foreach my $row (@$table_status) { my ($name, $type) = @$row; - if ($type =~ /^MYISAM$/i + if (defined ($type) && $type =~ /^MYISAM$/i && !grep($_ eq $name, Bugzilla::DB::Schema::Mysql::MYISAM_TABLES)) { push(@myisam_tables, $name) ; @@ -674,7 +674,7 @@ EOT my $utf_table_status = $self->selectall_arrayref("SHOW TABLE STATUS", {Slice=>{}}); $self->_after_table_status([map($_->{Name}, @$utf_table_status)]); - my @non_utf8_tables = grep($_->{Collation} !~ /^utf8/, @$utf_table_status); + my @non_utf8_tables = grep(defined($_->{Collation}) && $_->{Collation} !~ /^utf8/, @$utf_table_status); if (Bugzilla->params->{'utf8'} && scalar @non_utf8_tables) { print <bz_table_list_real) { my $info_sth = $self->prepare("SHOW FULL COLUMNS FROM $table"); $info_sth->execute(); @@ -749,13 +750,15 @@ EOT $self->bz_drop_index('test_runs', 'test_runs_summary_idx'); } + my $dropped = $self->bz_drop_related_fks($table, $name); + push(@dropped_fks, @$dropped); + print "Converting $table.$name to be stored as UTF-8...\n"; my $col_info = $self->bz_column_info_real($table, $name); # CHANGE COLUMN doesn't take PRIMARY KEY delete $col_info->{PRIMARYKEY}; - my $sql_def = $self->_bz_schema->get_type_ddl($col_info); # We don't want MySQL to actually try to *convert* # from our current charset to UTF-8, we just want to @@ -782,7 +785,12 @@ EOT } $self->do("ALTER TABLE $table DEFAULT CHARACTER SET utf8"); + } # foreach my $table (@tables) + + foreach my $fk_args (@dropped_fks) { + $self->bz_add_fk(@$fk_args); + } } # Sometimes you can have a situation where all the tables are utf8, diff --git a/Bugzilla/Hook.pm b/Bugzilla/Hook.pm index 5bc2e7716..de35f93b5 100644 --- a/Bugzilla/Hook.pm +++ b/Bugzilla/Hook.pm @@ -478,6 +478,33 @@ Params: =back +=head2 page-before_template + +This is a simple way to add your own pages to Bugzilla. This hooks C, +which loads templates from F