From 78661204595338f0f394862797265af536eb8670 Mon Sep 17 00:00:00 2001 From: Colin Kuskie Date: Thu, 15 Oct 2009 12:53:39 -0700 Subject: [PATCH] Handle bad dates in datetime related form plugins. Fixes bug #11128 Also, better date parsing by _splitMysql and reformat Thingy. --- docs/changelog/7.x.x.txt | 1 + lib/WebGUI/Asset/Wobject/Thingy.pm | 101 +++++++++++++++-------------- lib/WebGUI/DateTime.pm | 30 +++++---- lib/WebGUI/Form/Date.pm | 5 +- lib/WebGUI/Form/DateTime.pm | 6 +- t/DateTime.t | 11 +++- t/Form/Date.t | 10 ++- t/Form/DateTime.t | 8 ++- 8 files changed, 100 insertions(+), 72 deletions(-) diff --git a/docs/changelog/7.x.x.txt b/docs/changelog/7.x.x.txt index 53eaf4ead..c467087fc 100644 --- a/docs/changelog/7.x.x.txt +++ b/docs/changelog/7.x.x.txt @@ -18,6 +18,7 @@ - fixed #10914: Shop: No email notifications sent when the cart has net value 0 - fixed #11126: WebGUI database has varchar fields - fixed #10989: DataForm List: No pagination + - fixed #11128: Thing breaks w/ default value for date field 7.8.1 - mark $session->datetime->time as deprecated and remove its use from core code diff --git a/lib/WebGUI/Asset/Wobject/Thingy.pm b/lib/WebGUI/Asset/Wobject/Thingy.pm index 618294733..2f8b33f79 100644 --- a/lib/WebGUI/Asset/Wobject/Thingy.pm +++ b/lib/WebGUI/Asset/Wobject/Thingy.pm @@ -41,12 +41,13 @@ always taken from the field hashref. sub addField { - my $self = shift; - my $field = shift; - my $isImport = shift; + my $self = shift; + my $field = shift; + my $isImport = shift; my $dbDataType = shift || $self->_getDbDataType($field->{fieldType}); - my $db = $self->session->db; - my $error = $self->session->errorHandler; + my $session = $self->session; + my $db = $session->db; + my $error = $session->errorHandler; my ($oldFieldId, $newFieldId,$useAssetId,$useSequence); $error->info("Adding Field, label: ".$field->{label}.", fieldId: ".$field->{fieldId}.",thingId: ".$field->{thingId}); @@ -970,14 +971,14 @@ sub getFormPlugin { my $i18n = WebGUI::International->new($session,"Asset_Thingy"); $param{name} = "field_".$data->{fieldId}; - my $name = $param{name}; + my $name = $param{name}; $name =~ s/\^.*?\;//xgs ; # remove macro's from user input - $param{value} = $data->{value} || $data->{defaultValue}; - $param{size} = $data->{size}; - $param{height} = $data->{height}; - $param{width} = $data->{width}; - $param{extras} = $data->{extras}; - $param{vertical} = $data->{vertical}; + $param{value} = $data->{value} || $data->{defaultValue}; + $param{size} = $data->{size}; + $param{height} = $data->{height}; + $param{width} = $data->{width}; + $param{extras} = $data->{extras}; + $param{vertical} = $data->{vertical}; $param{fieldType} = $data->{fieldType}; if ($data->{fieldType} eq "Checkbox") { @@ -1034,14 +1035,14 @@ sub getFormPlugin { } if ($data->{fieldType} =~ m/^otherThing/x){ - my $otherThingId = $data->{fieldType}; - $otherThingId =~ s/^otherThing_(.*)/$1/x; - $param{fieldType} = "SelectList"; - $class = 'WebGUI::Form::'. $param{fieldType}; + my $otherThingId = $data->{fieldType}; + $otherThingId =~ s/^otherThing_(.*)/$1/x; + $param{fieldType} = "SelectList"; + $class = 'WebGUI::Form::'. $param{fieldType}; my $options = (); - my $tableName = 'Thingy_'.$otherThingId; - my $fieldName = 'field_'.$data->{fieldInOtherThingId}; + my $tableName = 'Thingy_'.$otherThingId; + my $fieldName = 'field_'.$data->{fieldInOtherThingId}; my $errorMessage = $self->badOtherThing($tableName, $fieldName); return $errorMessage if $errorMessage; @@ -1060,10 +1061,10 @@ sub getFormPlugin { .$dbh->quote_identifier($fieldName) .' from '.$dbh->quote_identifier($tableName) .' where thingDataId = ?',[$value]); - $param{size} = 1; + $param{size} = 1; $param{multiple} = 0; - $param{options} = $options; - $param{value} = $data->{value} || $data->{defaultValue}; + $param{options} = $options; + $param{value} = $data->{value} || $data->{defaultValue}; } my $formElement = eval { WebGUI::Pluggable::instanciate($class, "new", [$session, \%param ])}; @@ -2220,53 +2221,53 @@ Processes and saves a field. Returns the edited/added fieldId and the inner html sub www_editFieldSave { - my $self = shift; + my $self = shift; my $session = $self->session; return $session->privilege->insufficient() unless $self->canEdit; my ($fieldId, $fieldTypeChanged, $newFieldId, $formClass, $dbDataType, $thingyTableName, $columnName); my (%properties,$listItemHTML,$formElement); - my $i18n = WebGUI::International->new($self->session, "Asset_Thingy"); - my $label = $session->form->process("label"); - my $thingId = $self->session->form->process("thingId"); - my $error = $self->session->errorHandler; + my $i18n = WebGUI::International->new($session, "Asset_Thingy"); + my $label = $session->form->process("label"); + my $thingId = $session->form->process("thingId"); + my $log = $session->log; my $defaultValue = $session->form->process("defaultValue"); - my $fieldType = $session->form->process("fieldType") || "ReadOnly"; + my $fieldType = $session->form->process("fieldType") || "ReadOnly"; if ($fieldType =~ m/^otherThing/){ $defaultValue = $session->form->process("defaultFieldInThing"); } - $fieldId = $self->session->form->process("fieldId"); + $fieldId = $session->form->process("fieldId"); %properties = ( - fieldId=>$fieldId, - thingId=>$thingId, - label=>$label, - fieldType=>$fieldType, - defaultValue=>$defaultValue, - possibleValues=>$self->session->form->process("possibleValues"), - pretext=>$self->session->form->process("pretext"), - subtext=>$self->session->form->process("subtext"), - status=>$self->session->form->process("status"), - size=>$self->session->form->process("size"), - width=>$self->session->form->process("width"), - height=>$self->session->form->process("height"), - vertical=>$self->session->form->process("vertical"), - extras=>$self->session->form->process("extras"), - display=>$self->session->form->process("display") || 1, - viewScreenTitle=>$self->session->form->process("viewScreenTitle") || 0, - fieldInOtherThingId=>$session->form->process("fieldInOtherThingId") || "", + fieldId => $fieldId, + thingId => $thingId, + label => $label, + fieldType => $fieldType, + defaultValue => $defaultValue, + possibleValues => $session->form->process("possibleValues"), + pretext => $session->form->process("pretext"), + subtext => $session->form->process("subtext"), + status => $session->form->process("status"), + size => $session->form->process("size"), + width => $session->form->process("width"), + height => $session->form->process("height"), + vertical => $session->form->process("vertical"), + extras => $session->form->process("extras"), + display => $session->form->process("display") || 1, + viewScreenTitle => $session->form->process("viewScreenTitle") || 0, + fieldInOtherThingId => $session->form->process("fieldInOtherThingId") || "", ); # Get the field's data type $dbDataType = $self->_getDbDataType($properties{fieldType}); if ($fieldId eq "new") { $properties{dateCreated} = time(); - $properties{createdBy} = $self->session->user->userId; + $properties{createdBy} = $session->user->userId; $newFieldId = $self->addField(\%properties,0,$dbDataType); } else{ $properties{dateUpdated} = time(); - $properties{updatedBy} = $self->session->user->userId; + $properties{updatedBy} = $session->user->userId; # Check if column has to be altered for existing fields. $self->_updateFieldType($fieldType,$fieldId,$thingId,$self->get('assetId'),$dbDataType); $newFieldId = $self->setCollateral("Thingy_fields","fieldId",\%properties,1,1,"thingId",$thingId); @@ -2290,13 +2291,13 @@ sub www_editFieldSave { $listItemHTML = "\n\n\n" ."\n" - ."\n\n
".$label."".$formElement." session->url->page() + ." url->page() ."?func=editField;fieldId=".$newFieldId.";thingId=".$properties{thingId}."','".$newFieldId."')\" value='".$i18n->get('Edit','Icon')."' type='button'>" - ."session->url->page()."','".$newFieldId + ."url->page()."','".$newFieldId ."','".$properties{thingId}."')\" value='".$i18n->get('Delete','Icon')."' type='button'>
"; # Make sure we send debug information along with the field. - $session->log->preventDebugOutput; + $log->preventDebugOutput; $session->output->print($newFieldId.$listItemHTML); return "chunked"; diff --git a/lib/WebGUI/DateTime.pm b/lib/WebGUI/DateTime.pm index b320c0731..f21d8a7f6 100644 --- a/lib/WebGUI/DateTime.pm +++ b/lib/WebGUI/DateTime.pm @@ -594,23 +594,27 @@ sub _splitMysql @hash{ qw( year month day hour minute second ) } = $string =~ m{ - (\d+) # Year + ^ \D* - (\d+) # Month - \D* - (\d+) # Day - (?: \D* - (\d+) # Hours - \D* - (\d+) # Minutes - \D* - (\d+) # Seconds + (\d{1,4}) # Year + \D+ + (\d{1,2}) # Month + \D+ + (\d{1,2}) # Day + (?: \D+ + (\d{1,2}) # Hours + \D+ + (\d{1,2}) # Minutes + \D+ + (\d{1,2}) # Seconds )? + \D* + $ }x; - foreach my $unit (qw/hour minute second/) { - $hash{$unit} = 0 if ($hash{$unit} eq ''); - } + $hash{ hour } ||= 0; + $hash{ minute } ||= 0; + $hash{ second } ||= 0; return %hash; } diff --git a/lib/WebGUI/Form/Date.pm b/lib/WebGUI/Form/Date.pm index a3c62a0fd..501a4135d 100644 --- a/lib/WebGUI/Form/Date.pm +++ b/lib/WebGUI/Form/Date.pm @@ -217,13 +217,14 @@ sub toHtml { $value = $self->set("value",''); } else { - $value = WebGUI::DateTime->new($session, $self->getOriginalValue)->toMysqlDate; + $value = eval { WebGUI::DateTime->new($session, $self->getOriginalValue)->toMysqlDate; }; + $value = WebGUI::DateTime->new($session,0)->toMysqlDate if $value eq ''; } my $style = $session->style; my $url = $session->url; $style->setLink($url->extras('yui/build/calendar/assets/skins/sam/calendar.css'), { rel=>"stylesheet", type=>"text/css", media=>"all" }); - $style->setScript($url->extras('/yui/build/utilities/utilities.js'), { type => 'text/javascript' }); + $style->setScript($url->extras('yui/build/utilities/utilities.js'), { type => 'text/javascript' }); $style->setScript($url->extras('yui/build/json/json-min.js'), { type => 'text/javascript' }); $style->setScript($url->extras('yui/build/yahoo/yahoo-min.js'), { type => 'text/javascript' }); $style->setScript($url->extras('yui/build/dom/dom-min.js'), { type => 'text/javascript' }); diff --git a/lib/WebGUI/Form/DateTime.pm b/lib/WebGUI/Form/DateTime.pm index 8938654c6..ff5e16b29 100644 --- a/lib/WebGUI/Form/DateTime.pm +++ b/lib/WebGUI/Form/DateTime.pm @@ -220,9 +220,9 @@ Renders a date picker control. sub toHtml { my $self = shift; my $session = $self->session; - my $value = WebGUI::DateTime->new($session, $self->getOriginalValue) - ->set_time_zone($self->get("timeZone")) - ->strftime("%Y-%m-%d %H:%M:%S"); + my $value = eval { WebGUI::DateTime->new($session, $self->getOriginalValue); }; + $value = WebGUI::DateTime->new($session,0) if $value eq ''; + $value = $value->set_time_zone($self->get("timeZone"))->strftime("%Y-%m-%d %H:%M:%S"); my $style = $session->style; my $url = $session->url; diff --git a/t/DateTime.t b/t/DateTime.t index 07cb7976e..ac3c59c48 100644 --- a/t/DateTime.t +++ b/t/DateTime.t @@ -26,7 +26,7 @@ my $session = WebGUI::Test->session; # put your tests here -plan tests => 25; +plan tests => 28; my $timeZoneUser = addUser($session); @@ -84,6 +84,13 @@ is( '... has correct epoch' ); +my $badday = eval { WebGUI::DateTime->new($session, '2001-08-161'); }; +ok($@, 'new croaks on a bad date'); +my $badday = eval { WebGUI::DateTime->new($session, '2001-08-16 99:99:99'); }; +ok($@, 'new croaks on an out of range time'); +my $badday = eval { WebGUI::DateTime->new($session, '2001-08-16 99:199:99'); }; +ok($@, 'new croaks on an illegal time'); + sub addUser { my $session = shift; my $user = WebGUI::User->new($session, "new"); @@ -92,6 +99,6 @@ sub addUser { ##so the test will not fail in the summer $user->profileField("timeZone","America/Hermosillo"); $user->username("Time Zone"); - WebGUI::Test->usersToDelete($user); + addToCleanup($user); return $user; } diff --git a/t/Form/Date.t b/t/Form/Date.t index 6e2ef04fa..93f6056aa 100644 --- a/t/Form/Date.t +++ b/t/Form/Date.t @@ -50,7 +50,7 @@ my $testBlock = [ my $formType = 'date'; -my $numTests = 25 + scalar @{ $testBlock } ; +my $numTests = 26 + scalar @{ $testBlock } ; plan tests => $numTests; @@ -141,6 +141,14 @@ is( '2008-08-01', "toHtml: defaultValue in epoch format, returns date in mysql format" ); + +$date2 = WebGUI::Form::Date->new($session, {defaultValue => '2008-008-001'}); +is( + getValueFromForm($session, $date2->toHtml), + '1970-01-01', + "toHtml: defaultValue in bad mysql format returns date from epoch 0" +); + $date2 = WebGUI::Form::Date->new($session, {defaultValue => -1}); is($date2->getValueAsHtml(), '12/31/1969', "getValueAsHtml: defaultValue as negative epoch, returns in users's format"); diff --git a/t/Form/DateTime.t b/t/Form/DateTime.t index 8b9365659..3504fa3b0 100644 --- a/t/Form/DateTime.t +++ b/t/Form/DateTime.t @@ -29,7 +29,7 @@ my $session = WebGUI::Test->session; my $formType = 'datetime'; -my $numTests = 34; +my $numTests = 35; plan tests => $numTests; @@ -182,6 +182,12 @@ is( '2001-08-16 08:00:00', "toHtml: defaultValue in mysql format, value as mysql returns date in mysql format, adjusted for time zone" ); +$date2 = WebGUI::Form::DateTime->new($session, {defaultValue => '2008-081-01 11:34:26',}); +is( + getValueFromForm($session, $date2->toHtml), + '1969-12-31 18:00:00', + "toHtml: defaultValue in bad mysql format, returns value from epoch 0, adjusted for user time zone" +); sub getValueFromForm { my ($session, $textForm) = @_;