From b4410eb57d8e07de23de18b6375039c47e6cea35 Mon Sep 17 00:00:00 2001 From: Gervase Markham Date: Fri, 3 May 2013 10:13:53 -0400 Subject: Bug 866248 - backport new date custom field type from bug 801664 to bmo/4.2 r=glob --- Bugzilla/Bug.pm | 16 ++++++++++++++-- Bugzilla/Constants.pm | 8 +++++++- Bugzilla/DB/Schema/Mysql.pm | 2 +- Bugzilla/DB/Schema/Oracle.pm | 2 +- Bugzilla/DB/Schema/Pg.pm | 2 +- Bugzilla/DB/Schema/Sqlite.pm | 1 + Bugzilla/Field.pm | 10 ++++++---- Bugzilla/Migrate.pm | 7 +++++-- Bugzilla/Search.pm | 9 +++++++++ Bugzilla/WebService/Bug.pm | 4 +++- contrib/addcustomfield.pl | 1 + importxml.pl | 9 +++++++++ template/en/default/bug/field.html.tmpl | 5 +++-- template/en/default/global/field-descs.none.tmpl | 1 + template/en/default/search/field.html.tmpl | 2 +- 15 files changed, 63 insertions(+), 16 deletions(-) diff --git a/Bugzilla/Bug.pm b/Bugzilla/Bug.pm index a41da186b..383a865ef 100644 --- a/Bugzilla/Bug.pm +++ b/Bugzilla/Bug.pm @@ -166,6 +166,9 @@ sub VALIDATORS { elsif ($field->type == FIELD_TYPE_DATETIME) { $validator = \&_check_datetime_field; } + elsif ($field->type == FIELD_TYPE_DATE) { + $validator = \&_check_date_field; + } elsif ($field->type == FIELD_TYPE_FREETEXT) { $validator = \&_check_freetext_field; } @@ -248,7 +251,8 @@ use constant NUMERIC_COLUMNS => qw( ); sub DATE_COLUMNS { - my @fields = @{ Bugzilla->fields({ type => FIELD_TYPE_DATETIME }) }; + my @fields = (@{ Bugzilla->fields({ type => FIELD_TYPE_DATETIME }) }, + @{ Bugzilla->fields({ type => FIELD_TYPE_DATE }) }); return map { $_->name } @fields; } @@ -2057,8 +2061,12 @@ sub _check_field_is_mandatory { } } +sub _check_date_field { + my ($invocant, $date) = @_; + return $invocant->_check_datetime_field($date, undef, {date_only => 1}); +} sub _check_datetime_field { - my ($invocant, $date_time) = @_; + my ($invocant, $date_time, $field, $params) = @_; # Empty datetimes are empty strings or strings only containing # 0's, whitespace, and punctuation. @@ -2072,6 +2080,10 @@ sub _check_datetime_field { ThrowUserError('illegal_date', { date => $date, format => 'YYYY-MM-DD' }); } + if ($time && $params->{date_only}) { + ThrowUserError('illegal_date', { date => $date_time, + format => 'YYYY-MM-DD' }); + } if ($time && !validate_time($time)) { ThrowUserError('illegal_time', { 'time' => $time, format => 'HH:MM:SS' }); diff --git a/Bugzilla/Constants.pm b/Bugzilla/Constants.pm index c31565dd8..a30b987af 100644 --- a/Bugzilla/Constants.pm +++ b/Bugzilla/Constants.pm @@ -125,10 +125,12 @@ use Memoize; FIELD_TYPE_MULTI_SELECT FIELD_TYPE_TEXTAREA FIELD_TYPE_DATETIME + FIELD_TYPE_DATE FIELD_TYPE_BUG_ID FIELD_TYPE_BUG_URLS FIELD_TYPE_KEYWORDS - + FIELD_TYPE_HIGHEST_PLUS_ONE + EMPTY_DATETIME_REGEX ABNORMAL_SELECTS @@ -404,6 +406,10 @@ use constant FIELD_TYPE_DATETIME => 5; use constant FIELD_TYPE_BUG_ID => 6; use constant FIELD_TYPE_BUG_URLS => 7; use constant FIELD_TYPE_KEYWORDS => 8; +use constant FIELD_TYPE_DATE => 9; +# Add new field types above this line, and change the below value in the +# obvious fashion +use constant FIELD_TYPE_HIGHEST_PLUS_ONE => 10; use constant EMPTY_DATETIME_REGEX => qr/^[0\-:\sA-Za-z]+$/; diff --git a/Bugzilla/DB/Schema/Mysql.pm b/Bugzilla/DB/Schema/Mysql.pm index 8c9ea2dda..5fc50a986 100644 --- a/Bugzilla/DB/Schema/Mysql.pm +++ b/Bugzilla/DB/Schema/Mysql.pm @@ -120,7 +120,7 @@ sub _initialize { LONGBLOB => 'longblob', DATETIME => 'datetime', - + DATE => 'date', }; $self->_adjust_schema; diff --git a/Bugzilla/DB/Schema/Oracle.pm b/Bugzilla/DB/Schema/Oracle.pm index 9fafc4515..87f4e0115 100644 --- a/Bugzilla/DB/Schema/Oracle.pm +++ b/Bugzilla/DB/Schema/Oracle.pm @@ -70,7 +70,7 @@ sub _initialize { LONGBLOB => 'blob', DATETIME => 'date', - + DATE => 'date', }; $self->_adjust_schema; diff --git a/Bugzilla/DB/Schema/Pg.pm b/Bugzilla/DB/Schema/Pg.pm index d21f5099c..662120c03 100644 --- a/Bugzilla/DB/Schema/Pg.pm +++ b/Bugzilla/DB/Schema/Pg.pm @@ -80,7 +80,7 @@ sub _initialize { LONGBLOB => 'bytea', DATETIME => 'timestamp(0) without time zone', - + DATE => 'date', }; $self->_adjust_schema; diff --git a/Bugzilla/DB/Schema/Sqlite.pm b/Bugzilla/DB/Schema/Sqlite.pm index aad1f17bc..7ed9def3e 100644 --- a/Bugzilla/DB/Schema/Sqlite.pm +++ b/Bugzilla/DB/Schema/Sqlite.pm @@ -57,6 +57,7 @@ sub _initialize { LONGBLOB => 'blob', DATETIME => 'DATETIME', + DATE => 'DATETIME', }; $self->_adjust_schema; diff --git a/Bugzilla/Field.pm b/Bugzilla/Field.pm index 3d482b3c9..6b5b6ba94 100644 --- a/Bugzilla/Field.pm +++ b/Bugzilla/Field.pm @@ -161,6 +161,7 @@ use constant SQL_DEFINITIONS => { FIELD_TYPE_TEXTAREA, { TYPE => 'MEDIUMTEXT', NOTNULL => 1, DEFAULT => "''"}, FIELD_TYPE_DATETIME, { TYPE => 'DATETIME' }, + FIELD_TYPE_DATE, { TYPE => 'DATE' }, FIELD_TYPE_BUG_ID, { TYPE => 'INT3' }, }; @@ -349,9 +350,7 @@ sub _check_sortkey { sub _check_type { my ($invocant, $type, undef, $params) = @_; 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_KEYWORDS) + (detaint_natural($type) && $type < FIELD_TYPE_HIGHEST_PLUS_ONE) || ThrowCodeError('invalid_customfield_type', { type => $saved_type }); my $custom = blessed($invocant) ? $invocant->custom : $params->{custom}; @@ -943,7 +942,10 @@ sub remove_from_db { } else { $bugs_query = "SELECT COUNT(*) FROM bugs WHERE $name IS NOT NULL"; - if ($self->type != FIELD_TYPE_BUG_ID && $self->type != FIELD_TYPE_DATETIME) { + if ($self->type != FIELD_TYPE_BUG_ID + && $self->type != FIELD_TYPE_DATE + && $self->type != FIELD_TYPE_DATETIME) + { $bugs_query .= " AND $name != ''"; } # Ignore the default single select value diff --git a/Bugzilla/Migrate.pm b/Bugzilla/Migrate.pm index 2027af7d3..923fc36a4 100644 --- a/Bugzilla/Migrate.pm +++ b/Bugzilla/Migrate.pm @@ -459,8 +459,11 @@ sub translate_value { } my $field_obj = $self->bug_fields->{$field}; - if ($field eq 'creation_ts' or $field eq 'delta_ts' - or ($field_obj and $field_obj->type == FIELD_TYPE_DATETIME)) + if ($field eq 'creation_ts' + or $field eq 'delta_ts' + or ($field_obj and + ($field_obj->type == FIELD_TYPE_DATETIME + or $field_obj->type == FIELD_TYPE_DATE))) { $value = trim($value); return undef if !$value; diff --git a/Bugzilla/Search.pm b/Bugzilla/Search.pm index f0cb26357..747f1cd84 100644 --- a/Bugzilla/Search.pm +++ b/Bugzilla/Search.pm @@ -134,6 +134,7 @@ use Time::HiRes qw(gettimeofday tv_interval); # When doing searches, NULL datetimes are treated as this date. use constant EMPTY_DATETIME => '1970-01-01 00:00:00'; +use constant EMPTY_DATE => '1970-01-01'; # This is the regex for real numbers from Regexp::Common, modified to be # more readable. @@ -344,6 +345,7 @@ use constant OPERATOR_FIELD_OVERRIDE => { FIELD_TYPE_FREETEXT, { _non_changed => \&_nullable }, FIELD_TYPE_BUG_ID, { _non_changed => \&_nullable_int }, FIELD_TYPE_DATETIME, { _non_changed => \&_nullable_datetime }, + FIELD_TYPE_DATE, { _non_changed => \&_nullable_date }, FIELD_TYPE_TEXTAREA, { _non_changed => \&_nullable }, FIELD_TYPE_MULTI_SELECT, MULTI_SELECT_OVERRIDE, FIELD_TYPE_BUG_URLS, MULTI_SELECT_OVERRIDE, @@ -2645,6 +2647,13 @@ sub _nullable_datetime { $args->{full_field} = "COALESCE($field, $empty)"; } +sub _nullable_date { + my ($self, $args) = @_; + my $field = $args->{full_field}; + my $empty = Bugzilla->dbh->quote(EMPTY_DATE); + $args->{full_field} = "COALESCE($field, $empty)"; +} + sub _deadline { my ($self, $args) = @_; my $field = $args->{full_field}; diff --git a/Bugzilla/WebService/Bug.pm b/Bugzilla/WebService/Bug.pm index b6cfe897b..5c756b81a 100644 --- a/Bugzilla/WebService/Bug.pm +++ b/Bugzilla/WebService/Bug.pm @@ -963,7 +963,9 @@ sub _bug_to_hash { if ($field->type == FIELD_TYPE_BUG_ID) { $item{$name} = $self->type('int', $bug->$name); } - elsif ($field->type == FIELD_TYPE_DATETIME) { + elsif ($field->type == FIELD_TYPE_DATETIME + || $field->type == FIELD_TYPE_DATE) + { $item{$name} = $self->type('dateTime', $bug->$name); } elsif ($field->type == FIELD_TYPE_MULTI_SELECT) { diff --git a/contrib/addcustomfield.pl b/contrib/addcustomfield.pl index c7f93c297..4fa6589e4 100755 --- a/contrib/addcustomfield.pl +++ b/contrib/addcustomfield.pl @@ -31,6 +31,7 @@ my %types = ( 'multi_select' => FIELD_TYPE_MULTI_SELECT, 'textarea' => FIELD_TYPE_TEXTAREA, 'datetime' => FIELD_TYPE_DATETIME, + 'date' => FIELD_TYPE_DATE, 'bug_id' => FIELD_TYPE_BUG_ID, 'bug_urls' => FIELD_TYPE_BUG_URLS, 'keywords' => FIELD_TYPE_KEYWORDS, diff --git a/importxml.pl b/importxml.pl index 7ed4c9f21..e9b7c9ad7 100755 --- a/importxml.pl +++ b/importxml.pl @@ -1039,6 +1039,15 @@ sub process_bug { push(@query, $custom_field); push(@values, $value); } + } elsif ($field->type == FIELD_TYPE_DATE) { + eval { $value = Bugzilla::Bug->_check_date_field($value); }; + if ($@) { + $err .= "Skipping illegal value \"$value\" in $custom_field.\n" ; + } + else { + push(@query, $custom_field); + push(@values, $value); + } } else { $err .= "Type of custom field $custom_field is an unhandled FIELD_TYPE: " . $field->type . "\n"; diff --git a/template/en/default/bug/field.html.tmpl b/template/en/default/bug/field.html.tmpl index 78a449990..e157a80ed 100644 --- a/template/en/default/bug/field.html.tmpl +++ b/template/en/default/bug/field.html.tmpl @@ -57,8 +57,9 @@ value="[% value FILTER html %]" size="40" maxlength="[% constants.MAX_FREETEXT_LENGTH FILTER none %]" [% ' aria-required="true"' IF field.is_mandatory %]> - [% CASE constants.FIELD_TYPE_DATETIME %] - "Multiple-Selection Box", ${constants.FIELD_TYPE_TEXTAREA} => "Large Text Box", ${constants.FIELD_TYPE_DATETIME} => "Date/Time", + ${constants.FIELD_TYPE_DATE} => "Date", ${constants.FIELD_TYPE_BUG_ID} => "$terms.Bug ID", } %] diff --git a/template/en/default/search/field.html.tmpl b/template/en/default/search/field.html.tmpl index 19f199692..ae7ca1ad4 100644 --- a/template/en/default/search/field.html.tmpl +++ b/template/en/default/search/field.html.tmpl @@ -71,7 +71,7 @@ YAHOO.bugzilla.keywordAutocomplete.init('[% field.name FILTER js %]', 'keyword_autocomplete'); - [% CASE constants.FIELD_TYPE_DATETIME %] + [% CASE [constants.FIELD_TYPE_DATETIME, constants.FIELD_TYPE_DATE] %] [% INCLUDE "bug/field-label.html.tmpl" field = field tag_name = "span" -- cgit v1.2.3-24-g4f1b