diff options
-rwxr-xr-x | Bugzilla/Bug.pm | 25 | ||||
-rw-r--r-- | Bugzilla/Constants.pm | 2 | ||||
-rw-r--r-- | Bugzilla/Field.pm | 3 | ||||
-rw-r--r-- | Bugzilla/Util.pm | 17 | ||||
-rw-r--r-- | template/en/default/bug/field.html.tmpl | 6 | ||||
-rw-r--r-- | template/en/default/global/field-descs.none.tmpl | 1 | ||||
-rw-r--r-- | template/en/default/global/user-error.html.tmpl | 7 |
7 files changed, 59 insertions, 2 deletions
diff --git a/Bugzilla/Bug.pm b/Bugzilla/Bug.pm index ed398f0fe..ba66e846f 100755 --- a/Bugzilla/Bug.pm +++ b/Bugzilla/Bug.pm @@ -145,6 +145,9 @@ sub VALIDATORS { elsif ($field->type == FIELD_TYPE_MULTI_SELECT) { $validator = \&_check_multi_select_field; } + elsif ($field->type == FIELD_TYPE_DATETIME) { + $validator = \&_check_datetime_field; + } else { $validator = \&_check_freetext_field; } @@ -1240,6 +1243,28 @@ sub _check_work_time { # 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 { my ($invocant, $values, $field) = @_; return [] if !$values; diff --git a/Bugzilla/Constants.pm b/Bugzilla/Constants.pm index 827bb2d4b..12d54abee 100644 --- a/Bugzilla/Constants.pm +++ b/Bugzilla/Constants.pm @@ -121,6 +121,7 @@ use File::Basename; FIELD_TYPE_SINGLE_SELECT FIELD_TYPE_MULTI_SELECT FIELD_TYPE_TEXTAREA + FIELD_TYPE_DATETIME USAGE_MODE_BROWSER USAGE_MODE_CMDLINE @@ -349,6 +350,7 @@ use constant FIELD_TYPE_FREETEXT => 1; use constant FIELD_TYPE_SINGLE_SELECT => 2; use constant FIELD_TYPE_MULTI_SELECT => 3; use constant FIELD_TYPE_TEXTAREA => 4; +use constant FIELD_TYPE_DATETIME => 5; # The maximum number of days a token will remain valid. use constant MAX_TOKEN_AGE => 3; diff --git a/Bugzilla/Field.pm b/Bugzilla/Field.pm index 34a1818de..5ad5e51d3 100644 --- a/Bugzilla/Field.pm +++ b/Bugzilla/Field.pm @@ -127,6 +127,7 @@ use constant SQL_DEFINITIONS => { FIELD_TYPE_SINGLE_SELECT, { TYPE => 'varchar(64)', NOTNULL => 1, DEFAULT => "'---'" }, FIELD_TYPE_TEXTAREA, { TYPE => 'MEDIUMTEXT' }, + FIELD_TYPE_DATETIME, { TYPE => 'DATETIME' }, }; # Field definitions for the fields that ship with Bugzilla. @@ -255,7 +256,7 @@ sub _check_type { 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_TEXTAREA) + (detaint_natural($type) && $type <= FIELD_TYPE_DATETIME) || ThrowCodeError('invalid_customfield_type', { type => $saved_type }); return $type; } diff --git a/Bugzilla/Util.pm b/Bugzilla/Util.pm index 5c68a9092..ffc2af95a 100644 --- a/Bugzilla/Util.pm +++ b/Bugzilla/Util.pm @@ -40,6 +40,7 @@ use base qw(Exporter); diff_arrays diff_strings trim wrap_comment find_wrap_point format_time format_time_decimal validate_date + validate_time file_mod_time is_7bit_clean bz_crypt generate_random_password validate_email_syntax clean_text @@ -457,6 +458,22 @@ sub validate_date { 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 { return $_[0] !~ /[^\x20-\x7E\x0A\x0D]/; } diff --git a/template/en/default/bug/field.html.tmpl b/template/en/default/bug/field.html.tmpl index 7de659742..f79af3541 100644 --- a/template/en/default/bug/field.html.tmpl +++ b/template/en/default/bug/field.html.tmpl @@ -41,7 +41,11 @@ [% IF editable %] [% SWITCH field.type %] [% 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 constants.FIELD_TYPE_MULTI_SELECT ] %] <select id="[% field.name FILTER html %]" diff --git a/template/en/default/global/field-descs.none.tmpl b/template/en/default/global/field-descs.none.tmpl index 64bf546e6..178a68444 100644 --- a/template/en/default/global/field-descs.none.tmpl +++ b/template/en/default/global/field-descs.none.tmpl @@ -83,6 +83,7 @@ ${constants.FIELD_TYPE_SINGLE_SELECT} => "Drop Down", ${constants.FIELD_TYPE_MULTI_SELECT} => "Multiple-Selection Box", ${constants.FIELD_TYPE_TEXTAREA} => "Large Text Box", + ${constants.FIELD_TYPE_DATETIME} => "Date/Time", } %] [% status_descs = { "UNCONFIRMED" => "UNCONFIRMED", diff --git a/template/en/default/global/user-error.html.tmpl b/template/en/default/global/user-error.html.tmpl index 77ce40f72..16bc0f7af 100644 --- a/template/en/default/global/user-error.html.tmpl +++ b/template/en/default/global/user-error.html.tmpl @@ -733,6 +733,13 @@ [% docslinks = {'reporting.html' => 'Reporting'} %] You are not authorized to edit this series. To do this, you must either 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" %] [% docslinks = {'reporting.html' => 'Reporting'} %] |