Commit 16a1c874 authored by mkanat%bugzilla.org's avatar mkanat%bugzilla.org

Bug 357324: Date/Time Custom Fields

Patch By Max Kanat-Alexander <mkanat@bugzilla.org> r=LpSolit, a=LpSolit
parent 212433f2
...@@ -145,6 +145,9 @@ sub VALIDATORS { ...@@ -145,6 +145,9 @@ sub VALIDATORS {
elsif ($field->type == FIELD_TYPE_MULTI_SELECT) { elsif ($field->type == FIELD_TYPE_MULTI_SELECT) {
$validator = \&_check_multi_select_field; $validator = \&_check_multi_select_field;
} }
elsif ($field->type == FIELD_TYPE_DATETIME) {
$validator = \&_check_datetime_field;
}
else { else {
$validator = \&_check_freetext_field; $validator = \&_check_freetext_field;
} }
...@@ -1240,6 +1243,28 @@ sub _check_work_time { ...@@ -1240,6 +1243,28 @@ sub _check_work_time {
# Custom Field Validators # Custom Field Validators
sub _check_datetime_field {
my ($invocant, $date_time) = @_;
# Empty datetimes are empty strings or strings only containing
# 0's, whitespace, and punctuation.
if ($date_time =~ /^[\s0[:punct:]]*$/) {
return undef;
}
$date_time = trim($date_time);
my ($date, $time) = split(' ', $date_time);
if ($date && !validate_date($date)) {
ThrowUserError('illegal_date', { date => $date,
format => 'YYYY-MM-DD' });
}
if ($time && !validate_time($time)) {
ThrowUserError('illegal_time', { 'time' => $time,
format => 'HH:MM:SS' });
}
return $date_time
}
sub _check_multi_select_field { sub _check_multi_select_field {
my ($invocant, $values, $field) = @_; my ($invocant, $values, $field) = @_;
return [] if !$values; return [] if !$values;
......
...@@ -121,6 +121,7 @@ use File::Basename; ...@@ -121,6 +121,7 @@ use File::Basename;
FIELD_TYPE_SINGLE_SELECT FIELD_TYPE_SINGLE_SELECT
FIELD_TYPE_MULTI_SELECT FIELD_TYPE_MULTI_SELECT
FIELD_TYPE_TEXTAREA FIELD_TYPE_TEXTAREA
FIELD_TYPE_DATETIME
USAGE_MODE_BROWSER USAGE_MODE_BROWSER
USAGE_MODE_CMDLINE USAGE_MODE_CMDLINE
...@@ -349,6 +350,7 @@ use constant FIELD_TYPE_FREETEXT => 1; ...@@ -349,6 +350,7 @@ use constant FIELD_TYPE_FREETEXT => 1;
use constant FIELD_TYPE_SINGLE_SELECT => 2; use constant FIELD_TYPE_SINGLE_SELECT => 2;
use constant FIELD_TYPE_MULTI_SELECT => 3; use constant FIELD_TYPE_MULTI_SELECT => 3;
use constant FIELD_TYPE_TEXTAREA => 4; use constant FIELD_TYPE_TEXTAREA => 4;
use constant FIELD_TYPE_DATETIME => 5;
# The maximum number of days a token will remain valid. # The maximum number of days a token will remain valid.
use constant MAX_TOKEN_AGE => 3; use constant MAX_TOKEN_AGE => 3;
......
...@@ -127,6 +127,7 @@ use constant SQL_DEFINITIONS => { ...@@ -127,6 +127,7 @@ use constant SQL_DEFINITIONS => {
FIELD_TYPE_SINGLE_SELECT, { TYPE => 'varchar(64)', NOTNULL => 1, FIELD_TYPE_SINGLE_SELECT, { TYPE => 'varchar(64)', NOTNULL => 1,
DEFAULT => "'---'" }, DEFAULT => "'---'" },
FIELD_TYPE_TEXTAREA, { TYPE => 'MEDIUMTEXT' }, FIELD_TYPE_TEXTAREA, { TYPE => 'MEDIUMTEXT' },
FIELD_TYPE_DATETIME, { TYPE => 'DATETIME' },
}; };
# Field definitions for the fields that ship with Bugzilla. # Field definitions for the fields that ship with Bugzilla.
...@@ -255,7 +256,7 @@ sub _check_type { ...@@ -255,7 +256,7 @@ sub _check_type {
my $saved_type = $type; my $saved_type = $type;
# The constant here should be updated every time a new, # The constant here should be updated every time a new,
# higher field type is added. # higher field type is added.
(detaint_natural($type) && $type <= FIELD_TYPE_TEXTAREA) (detaint_natural($type) && $type <= FIELD_TYPE_DATETIME)
|| ThrowCodeError('invalid_customfield_type', { type => $saved_type }); || ThrowCodeError('invalid_customfield_type', { type => $saved_type });
return $type; return $type;
} }
......
...@@ -40,6 +40,7 @@ use base qw(Exporter); ...@@ -40,6 +40,7 @@ use base qw(Exporter);
diff_arrays diff_strings diff_arrays diff_strings
trim wrap_comment find_wrap_point trim wrap_comment find_wrap_point
format_time format_time_decimal validate_date format_time format_time_decimal validate_date
validate_time
file_mod_time is_7bit_clean file_mod_time is_7bit_clean
bz_crypt generate_random_password bz_crypt generate_random_password
validate_email_syntax clean_text validate_email_syntax clean_text
...@@ -457,6 +458,22 @@ sub validate_date { ...@@ -457,6 +458,22 @@ sub validate_date {
return $ret ? 1 : 0; return $ret ? 1 : 0;
} }
sub validate_time {
my ($time) = @_;
my $time2;
# $ts is undefined if the parser fails.
my $ts = str2time($time);
if ($ts) {
$time2 = time2str("%H:%M:%S", $ts);
$time =~ s/(\d+):(\d+?):(\d+?)/$1:$2:$3/;
$time2 =~ s/(\d+):(\d+?):(\d+?)/$1:$2:$3/;
}
my $ret = ($ts && $time eq $time2);
return $ret ? 1 : 0;
}
sub is_7bit_clean { sub is_7bit_clean {
return $_[0] !~ /[^\x20-\x7E\x0A\x0D]/; return $_[0] !~ /[^\x20-\x7E\x0A\x0D]/;
} }
......
...@@ -41,7 +41,11 @@ ...@@ -41,7 +41,11 @@
[% IF editable %] [% IF editable %]
[% SWITCH field.type %] [% SWITCH field.type %]
[% CASE constants.FIELD_TYPE_FREETEXT %] [% CASE constants.FIELD_TYPE_FREETEXT %]
<input name="[% field.name FILTER html %]" value="[% value FILTER html %]" size="60"> <input name="[% field.name FILTER html %]"
value="[% value FILTER html %]" size="60">
[% CASE constants.FIELD_TYPE_DATETIME %]
<input name="[% field.name FILTER html %]" size="20"
value="[% value FILTER html %]">
[% CASE [ constants.FIELD_TYPE_SINGLE_SELECT [% CASE [ constants.FIELD_TYPE_SINGLE_SELECT
constants.FIELD_TYPE_MULTI_SELECT ] %] constants.FIELD_TYPE_MULTI_SELECT ] %]
<select id="[% field.name FILTER html %]" <select id="[% field.name FILTER html %]"
......
...@@ -83,6 +83,7 @@ ...@@ -83,6 +83,7 @@
${constants.FIELD_TYPE_SINGLE_SELECT} => "Drop Down", ${constants.FIELD_TYPE_SINGLE_SELECT} => "Drop Down",
${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",
} %] } %]
[% status_descs = { "UNCONFIRMED" => "UNCONFIRMED", [% status_descs = { "UNCONFIRMED" => "UNCONFIRMED",
......
...@@ -734,6 +734,13 @@ ...@@ -734,6 +734,13 @@
You are not authorized to edit this series. To do this, you must either You are not authorized to edit this series. To do this, you must either
be its creator, or an administrator. be its creator, or an administrator.
[% ELSIF error == "illegal_time" %]
[% title = "Illegal Time" %]
'<tt>[% time FILTER html %]</tt>' is not a legal time.
[% IF format %]
Please use the format '<tt>[% format FILTER html %]</tt>'.
[% END %]
[% ELSIF error == "insufficient_data_points" %] [% ELSIF error == "insufficient_data_points" %]
[% docslinks = {'reporting.html' => 'Reporting'} %] [% docslinks = {'reporting.html' => 'Reporting'} %]
We don't have enough data points to make a graph (yet). We don't have enough data points to make a graph (yet).
......
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