From 725f2fb7958c6a251efdb056d49063fc4f8da91a Mon Sep 17 00:00:00 2001 From: Gervase Markham Date: Wed, 2 Jan 2013 17:58:34 +0000 Subject: Bug 801664 - Add DATE type for custom fields. r=LpSolit. --- Bugzilla/Bug.pm | 18 ++++++++++++++++-- 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 +++- 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 +- 14 files changed, 64 insertions(+), 16 deletions(-) diff --git a/Bugzilla/Bug.pm b/Bugzilla/Bug.pm index c58fec460..6680ede55 100644 --- a/Bugzilla/Bug.pm +++ b/Bugzilla/Bug.pm @@ -146,6 +146,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; } @@ -233,7 +236,9 @@ use constant NUMERIC_COLUMNS => qw( ); sub DATE_COLUMNS { - my @fields = @{ Bugzilla->fields({ type => FIELD_TYPE_DATETIME }) }; + my @fields = (@{ Bugzilla->fields({ type => [FIELD_TYPE_DATETIME, + FIELD_TYPE_DATE] }) + }); return map { $_->name } @fields; } @@ -1983,8 +1988,13 @@ sub _check_field_is_mandatory { } } +sub _check_date_field { + my ($invocant, $date) = @_; + return _check_datetime_field($invocant, $date, 1); +} + sub _check_datetime_field { - my ($invocant, $date_time) = @_; + my ($invocant, $date_time, $date_only) = @_; # Empty datetimes are empty strings or strings only containing # 0's, whitespace, and punctuation. @@ -1998,6 +2008,10 @@ sub _check_datetime_field { ThrowUserError('illegal_date', { date => $date, format => 'YYYY-MM-DD' }); } + if ($time && $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 8410ae46a..212816a05 100644 --- a/Bugzilla/Constants.pm +++ b/Bugzilla/Constants.pm @@ -104,10 +104,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 @@ -385,6 +387,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 d44864791..9d634243f 100644 --- a/Bugzilla/DB/Schema/Mysql.pm +++ b/Bugzilla/DB/Schema/Mysql.pm @@ -106,7 +106,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 275027954..1bed5b5ca 100644 --- a/Bugzilla/DB/Schema/Oracle.pm +++ b/Bugzilla/DB/Schema/Oracle.pm @@ -56,7 +56,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 206a53def..fa784ef7d 100644 --- a/Bugzilla/DB/Schema/Pg.pm +++ b/Bugzilla/DB/Schema/Pg.pm @@ -66,7 +66,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 893e2387d..b29d7da22 100644 --- a/Bugzilla/DB/Schema/Sqlite.pm +++ b/Bugzilla/DB/Schema/Sqlite.pm @@ -46,6 +46,7 @@ sub _initialize { LONGBLOB => 'blob', DATETIME => 'DATETIME', + DATE => 'DATETIME', }; $self->_adjust_schema; diff --git a/Bugzilla/Field.pm b/Bugzilla/Field.pm index 14888287a..c85d43bb8 100644 --- a/Bugzilla/Field.pm +++ b/Bugzilla/Field.pm @@ -151,6 +151,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}; @@ -952,7 +951,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 6671ac375..6f3570fd3 100644 --- a/Bugzilla/Migrate.pm +++ b/Bugzilla/Migrate.pm @@ -447,8 +447,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 b9c37b4ed..71893a5fc 100644 --- a/Bugzilla/Search.pm +++ b/Bugzilla/Search.pm @@ -108,6 +108,7 @@ use Storable qw(dclone); # 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. @@ -310,6 +311,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, @@ -2511,6 +2513,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 709983389..fe102f70d 100644 --- a/Bugzilla/WebService/Bug.pm +++ b/Bugzilla/WebService/Bug.pm @@ -929,7 +929,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/importxml.pl b/importxml.pl index 92a85c6da..4e78f093f 100755 --- a/importxml.pl +++ b/importxml.pl @@ -1023,6 +1023,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 4255b1702..ef4d0e8b1 100644 --- a/template/en/default/bug/field.html.tmpl +++ b/template/en/default/bug/field.html.tmpl @@ -41,8 +41,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 ab7380857..dc1592e38 100644 --- a/template/en/default/search/field.html.tmpl +++ b/template/en/default/search/field.html.tmpl @@ -52,7 +52,7 @@ YAHOO.bugzilla.fieldAutocomplete.init('[% field.name FILTER js %]', '[% field.name FILTER js %]_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.1