Commit 725f2fb7 authored by Gervase Markham's avatar Gervase Markham Committed by Gervase Markham

Bug 801664 - Add DATE type for custom fields. r=LpSolit.

parent 21b50cba
...@@ -146,6 +146,9 @@ sub VALIDATORS { ...@@ -146,6 +146,9 @@ sub VALIDATORS {
elsif ($field->type == FIELD_TYPE_DATETIME) { elsif ($field->type == FIELD_TYPE_DATETIME) {
$validator = \&_check_datetime_field; $validator = \&_check_datetime_field;
} }
elsif ($field->type == FIELD_TYPE_DATE) {
$validator = \&_check_date_field;
}
elsif ($field->type == FIELD_TYPE_FREETEXT) { elsif ($field->type == FIELD_TYPE_FREETEXT) {
$validator = \&_check_freetext_field; $validator = \&_check_freetext_field;
} }
...@@ -233,7 +236,9 @@ use constant NUMERIC_COLUMNS => qw( ...@@ -233,7 +236,9 @@ use constant NUMERIC_COLUMNS => qw(
); );
sub DATE_COLUMNS { 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; return map { $_->name } @fields;
} }
...@@ -1983,8 +1988,13 @@ sub _check_field_is_mandatory { ...@@ -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 { sub _check_datetime_field {
my ($invocant, $date_time) = @_; my ($invocant, $date_time, $date_only) = @_;
# Empty datetimes are empty strings or strings only containing # Empty datetimes are empty strings or strings only containing
# 0's, whitespace, and punctuation. # 0's, whitespace, and punctuation.
...@@ -1998,6 +2008,10 @@ sub _check_datetime_field { ...@@ -1998,6 +2008,10 @@ sub _check_datetime_field {
ThrowUserError('illegal_date', { date => $date, ThrowUserError('illegal_date', { date => $date,
format => 'YYYY-MM-DD' }); format => 'YYYY-MM-DD' });
} }
if ($time && $date_only) {
ThrowUserError('illegal_date', { date => $date_time,
format => 'YYYY-MM-DD' });
}
if ($time && !validate_time($time)) { if ($time && !validate_time($time)) {
ThrowUserError('illegal_time', { 'time' => $time, ThrowUserError('illegal_time', { 'time' => $time,
format => 'HH:MM:SS' }); format => 'HH:MM:SS' });
......
...@@ -104,10 +104,12 @@ use Memoize; ...@@ -104,10 +104,12 @@ use Memoize;
FIELD_TYPE_MULTI_SELECT FIELD_TYPE_MULTI_SELECT
FIELD_TYPE_TEXTAREA FIELD_TYPE_TEXTAREA
FIELD_TYPE_DATETIME FIELD_TYPE_DATETIME
FIELD_TYPE_DATE
FIELD_TYPE_BUG_ID FIELD_TYPE_BUG_ID
FIELD_TYPE_BUG_URLS FIELD_TYPE_BUG_URLS
FIELD_TYPE_KEYWORDS FIELD_TYPE_KEYWORDS
FIELD_TYPE_HIGHEST_PLUS_ONE
EMPTY_DATETIME_REGEX EMPTY_DATETIME_REGEX
ABNORMAL_SELECTS ABNORMAL_SELECTS
...@@ -385,6 +387,10 @@ use constant FIELD_TYPE_DATETIME => 5; ...@@ -385,6 +387,10 @@ use constant FIELD_TYPE_DATETIME => 5;
use constant FIELD_TYPE_BUG_ID => 6; use constant FIELD_TYPE_BUG_ID => 6;
use constant FIELD_TYPE_BUG_URLS => 7; use constant FIELD_TYPE_BUG_URLS => 7;
use constant FIELD_TYPE_KEYWORDS => 8; 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]+$/; use constant EMPTY_DATETIME_REGEX => qr/^[0\-:\sA-Za-z]+$/;
......
...@@ -106,7 +106,7 @@ sub _initialize { ...@@ -106,7 +106,7 @@ sub _initialize {
LONGBLOB => 'longblob', LONGBLOB => 'longblob',
DATETIME => 'datetime', DATETIME => 'datetime',
DATE => 'date',
}; };
$self->_adjust_schema; $self->_adjust_schema;
......
...@@ -56,7 +56,7 @@ sub _initialize { ...@@ -56,7 +56,7 @@ sub _initialize {
LONGBLOB => 'blob', LONGBLOB => 'blob',
DATETIME => 'date', DATETIME => 'date',
DATE => 'date',
}; };
$self->_adjust_schema; $self->_adjust_schema;
......
...@@ -66,7 +66,7 @@ sub _initialize { ...@@ -66,7 +66,7 @@ sub _initialize {
LONGBLOB => 'bytea', LONGBLOB => 'bytea',
DATETIME => 'timestamp(0) without time zone', DATETIME => 'timestamp(0) without time zone',
DATE => 'date',
}; };
$self->_adjust_schema; $self->_adjust_schema;
......
...@@ -46,6 +46,7 @@ sub _initialize { ...@@ -46,6 +46,7 @@ sub _initialize {
LONGBLOB => 'blob', LONGBLOB => 'blob',
DATETIME => 'DATETIME', DATETIME => 'DATETIME',
DATE => 'DATETIME',
}; };
$self->_adjust_schema; $self->_adjust_schema;
......
...@@ -151,6 +151,7 @@ use constant SQL_DEFINITIONS => { ...@@ -151,6 +151,7 @@ use constant SQL_DEFINITIONS => {
FIELD_TYPE_TEXTAREA, { TYPE => 'MEDIUMTEXT', FIELD_TYPE_TEXTAREA, { TYPE => 'MEDIUMTEXT',
NOTNULL => 1, DEFAULT => "''"}, NOTNULL => 1, DEFAULT => "''"},
FIELD_TYPE_DATETIME, { TYPE => 'DATETIME' }, FIELD_TYPE_DATETIME, { TYPE => 'DATETIME' },
FIELD_TYPE_DATE, { TYPE => 'DATE' },
FIELD_TYPE_BUG_ID, { TYPE => 'INT3' }, FIELD_TYPE_BUG_ID, { TYPE => 'INT3' },
}; };
...@@ -349,9 +350,7 @@ sub _check_sortkey { ...@@ -349,9 +350,7 @@ sub _check_sortkey {
sub _check_type { sub _check_type {
my ($invocant, $type, undef, $params) = @_; my ($invocant, $type, undef, $params) = @_;
my $saved_type = $type; my $saved_type = $type;
# The constant here should be updated every time a new, (detaint_natural($type) && $type < FIELD_TYPE_HIGHEST_PLUS_ONE)
# higher field type is added.
(detaint_natural($type) && $type <= FIELD_TYPE_KEYWORDS)
|| ThrowCodeError('invalid_customfield_type', { type => $saved_type }); || ThrowCodeError('invalid_customfield_type', { type => $saved_type });
my $custom = blessed($invocant) ? $invocant->custom : $params->{custom}; my $custom = blessed($invocant) ? $invocant->custom : $params->{custom};
...@@ -952,7 +951,10 @@ sub remove_from_db { ...@@ -952,7 +951,10 @@ sub remove_from_db {
} }
else { else {
$bugs_query = "SELECT COUNT(*) FROM bugs WHERE $name IS NOT NULL"; $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 != ''"; $bugs_query .= " AND $name != ''";
} }
# Ignore the default single select value # Ignore the default single select value
......
...@@ -447,8 +447,11 @@ sub translate_value { ...@@ -447,8 +447,11 @@ sub translate_value {
} }
my $field_obj = $self->bug_fields->{$field}; my $field_obj = $self->bug_fields->{$field};
if ($field eq 'creation_ts' or $field eq 'delta_ts' if ($field eq 'creation_ts'
or ($field_obj and $field_obj->type == FIELD_TYPE_DATETIME)) 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); $value = trim($value);
return undef if !$value; return undef if !$value;
......
...@@ -108,6 +108,7 @@ use Storable qw(dclone); ...@@ -108,6 +108,7 @@ use Storable qw(dclone);
# When doing searches, NULL datetimes are treated as this date. # When doing searches, NULL datetimes are treated as this date.
use constant EMPTY_DATETIME => '1970-01-01 00:00:00'; 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 # This is the regex for real numbers from Regexp::Common, modified to be
# more readable. # more readable.
...@@ -310,6 +311,7 @@ use constant OPERATOR_FIELD_OVERRIDE => { ...@@ -310,6 +311,7 @@ use constant OPERATOR_FIELD_OVERRIDE => {
FIELD_TYPE_FREETEXT, { _non_changed => \&_nullable }, FIELD_TYPE_FREETEXT, { _non_changed => \&_nullable },
FIELD_TYPE_BUG_ID, { _non_changed => \&_nullable_int }, FIELD_TYPE_BUG_ID, { _non_changed => \&_nullable_int },
FIELD_TYPE_DATETIME, { _non_changed => \&_nullable_datetime }, FIELD_TYPE_DATETIME, { _non_changed => \&_nullable_datetime },
FIELD_TYPE_DATE, { _non_changed => \&_nullable_date },
FIELD_TYPE_TEXTAREA, { _non_changed => \&_nullable }, FIELD_TYPE_TEXTAREA, { _non_changed => \&_nullable },
FIELD_TYPE_MULTI_SELECT, MULTI_SELECT_OVERRIDE, FIELD_TYPE_MULTI_SELECT, MULTI_SELECT_OVERRIDE,
FIELD_TYPE_BUG_URLS, MULTI_SELECT_OVERRIDE, FIELD_TYPE_BUG_URLS, MULTI_SELECT_OVERRIDE,
...@@ -2511,6 +2513,13 @@ sub _nullable_datetime { ...@@ -2511,6 +2513,13 @@ sub _nullable_datetime {
$args->{full_field} = "COALESCE($field, $empty)"; $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 { sub _deadline {
my ($self, $args) = @_; my ($self, $args) = @_;
my $field = $args->{full_field}; my $field = $args->{full_field};
......
...@@ -929,7 +929,9 @@ sub _bug_to_hash { ...@@ -929,7 +929,9 @@ sub _bug_to_hash {
if ($field->type == FIELD_TYPE_BUG_ID) { if ($field->type == FIELD_TYPE_BUG_ID) {
$item{$name} = $self->type('int', $bug->$name); $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); $item{$name} = $self->type('dateTime', $bug->$name);
} }
elsif ($field->type == FIELD_TYPE_MULTI_SELECT) { elsif ($field->type == FIELD_TYPE_MULTI_SELECT) {
......
...@@ -1023,6 +1023,15 @@ sub process_bug { ...@@ -1023,6 +1023,15 @@ sub process_bug {
push(@query, $custom_field); push(@query, $custom_field);
push(@values, $value); 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 { } else {
$err .= "Type of custom field $custom_field is an unhandled FIELD_TYPE: " . $err .= "Type of custom field $custom_field is an unhandled FIELD_TYPE: " .
$field->type . "\n"; $field->type . "\n";
......
...@@ -41,8 +41,9 @@ ...@@ -41,8 +41,9 @@
value="[% value FILTER html %]" size="40" value="[% value FILTER html %]" size="40"
maxlength="[% constants.MAX_FREETEXT_LENGTH FILTER none %]" maxlength="[% constants.MAX_FREETEXT_LENGTH FILTER none %]"
[% ' aria-required="true"' IF field.is_mandatory %]> [% ' aria-required="true"' IF field.is_mandatory %]>
[% CASE constants.FIELD_TYPE_DATETIME %] [% CASE [constants.FIELD_TYPE_DATETIME, constants.FIELD_TYPE_DATE] %]
<input name="[% field.name FILTER html %]" size="20" [% size = (field.type == constants.FIELD_TYPE_DATE) ? 10 : 20 %]
<input name="[% field.name FILTER html %]" size="[% size FILTER none %]"
id="[% field.name FILTER html %]" id="[% field.name FILTER html %]"
value="[% value FILTER html %]" value="[% value FILTER html %]"
[% ' aria-required="true"' IF field.is_mandatory %] [% ' aria-required="true"' IF field.is_mandatory %]
......
...@@ -43,6 +43,7 @@ ...@@ -43,6 +43,7 @@
${constants.FIELD_TYPE_MULTI_SELECT} => "Multiple-Selection Box", ${constants.FIELD_TYPE_MULTI_SELECT} => "Multiple-Selection Box",
${constants.FIELD_TYPE_TEXTAREA} => "Large Text Box", ${constants.FIELD_TYPE_TEXTAREA} => "Large Text Box",
${constants.FIELD_TYPE_DATETIME} => "Date/Time", ${constants.FIELD_TYPE_DATETIME} => "Date/Time",
${constants.FIELD_TYPE_DATE} => "Date",
${constants.FIELD_TYPE_BUG_ID} => "$terms.Bug ID", ${constants.FIELD_TYPE_BUG_ID} => "$terms.Bug ID",
} %] } %]
......
...@@ -52,7 +52,7 @@ ...@@ -52,7 +52,7 @@
YAHOO.bugzilla.fieldAutocomplete.init('[% field.name FILTER js %]', YAHOO.bugzilla.fieldAutocomplete.init('[% field.name FILTER js %]',
'[% field.name FILTER js %]_autocomplete'); '[% field.name FILTER js %]_autocomplete');
</script> </script>
[% CASE constants.FIELD_TYPE_DATETIME %] [% CASE [constants.FIELD_TYPE_DATETIME, constants.FIELD_TYPE_DATE] %]
[% INCLUDE "bug/field-label.html.tmpl" [% INCLUDE "bug/field-label.html.tmpl"
field = field field = field
tag_name = "span" tag_name = "span"
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment