From da1a49f1836ee0df64a78372a2bcc7e5bb4fdd63 Mon Sep 17 00:00:00 2001 From: Drake Date: Fri, 29 Sep 2006 00:18:43 +0000 Subject: [PATCH] Improve robustness of Stock Data asset on erroneous or absent data, and add a timeout. Associated refactoring. --- docs/changelog/7.x.x.txt | 1 + lib/WebGUI/Asset/Wobject/StockData.pm | 172 ++++++++++++-------------- 2 files changed, 81 insertions(+), 92 deletions(-) diff --git a/docs/changelog/7.x.x.txt b/docs/changelog/7.x.x.txt index 66987c538..c9770edf0 100644 --- a/docs/changelog/7.x.x.txt +++ b/docs/changelog/7.x.x.txt @@ -2,6 +2,7 @@ - partial fix: invalid Message-ID headers in outgoing mail - fix: HttpProxy not doing file uploads correctly - fix: leftover discussion template variables in Default Article template + - fix: Stock Data asset insufficiently robust handling erroneous data 7.0.8 - Fixed a couple of minor bugs with the default values of the Request diff --git a/lib/WebGUI/Asset/Wobject/StockData.pm b/lib/WebGUI/Asset/Wobject/StockData.pm index 1245bb9b4..eaaae531c 100644 --- a/lib/WebGUI/Asset/Wobject/StockData.pm +++ b/lib/WebGUI/Asset/Wobject/StockData.pm @@ -152,7 +152,11 @@ sub _convertToEpoch { my $self = shift; my $date = $_[0]; my $time = $_[1]; - + + unless ($date =~ m{^\d+/\d+/\d+} and $time =~ m{^\d+:\d+}) { + return undef; + } + my ($month,$day,$year) = split("/",$date); $month = $self->_appendZero($month); $day = $self->_appendZero($day); @@ -180,14 +184,19 @@ List of stock symbols to find passed in as an array reference. Stock symbols sh sub _getStocks { my $self = shift; - my $stocks = $_[0]; - #Create a new Finance::Quote object + my $stocks = $_[0]; + + # Create a new Finance::Quote object my $q = Finance::Quote->new; - #Disable failover if specified + # Disable failover if specified unless ($self->getValue("failover")) { - $q->failover(0); + $q->failover(0); } - #Fetch the stock information and return the results + + # Hardcoded timeout for now. + $q->timeout(15); + + # Fetch the stock information and return the results return $q->fetch($self->getValue("source"),@{$stocks}); } @@ -195,25 +204,24 @@ sub _getStocks { =head2 _getStockSources ( ) -Private method which retrieves the list of available stock sources from Finance::Quote package -and returns the results as a hash reference for the selectList Form API +Class method which retrieves the list of available stock sources from +Finance::Quote package and returns the results as a hash reference for +the selectList Form API. =cut sub _getStockSources { - my $self = shift; - #Instantiate Finance::Quote - my $q = Finance::Quote->new; - #Retrieve array of available sources and sort them - my @srcs = sort $q->sources; - #Create a hash reference with the name referencing itself - my %sources; - #Tie to IxHash to preserve alphabetical order - tie %sources, "Tie::IxHash"; - foreach my $src (@srcs) { - $sources{$src} = $src; - } - return \%sources; + my $class = shift; + my @srcs = Finance::Quote->new->sources; + my %sources; + + # Tie to IxHash to preserve alphabetical order + tie %sources, "Tie::IxHash"; + foreach my $src (@srcs) { + $sources{$src} = $src; + } + + return \%sources; } #------------------------------------------------------------------- @@ -267,95 +275,64 @@ sub definition { my $class = shift; my $session = shift; my $definition = shift; - my $properties = { + my $i18n = WebGUI::International->new($session,"Asset_StockData"); + + my %properties; + tie %properties, 'Tie::IxHash'; + %properties = ( templateId =>{ fieldType=>"template", - defaultValue=>'StockDataTMPL000000001' + defaultValue=>'StockDataTMPL000000001', + tab=>'display', + namespace=>'StockData', + label=>$i18n->get("template_label"), + hoverHelp=>$i18n->get("template_label_description"), }, displayTemplateId=>{ fieldType=>"template", - defaultValue=>'StockDataTMPL000000002' + defaultValue=>'StockDataTMPL000000002', + tab=>'display', + namespace=>"StockData/Display", + label=>$i18n->get("display_template_label"), + hoverHelp=>$i18n->get("display_template_label_description"), }, defaultStocks=>{ fieldType=>"textarea", - defaultValue=>"DELL\nMSFT\nORCL\nSUNW\nYHOO" + defaultValue=>"DELL\nMSFT\nORCL\nSUNW\nYHOO", + tab=>'properties', + label=> $i18n->get("default_stock_label"), + hoverHelp=> $i18n->get("default_stock_label_description"), }, source=>{ fieldType=>"selectList", - defaultValue=>"usa" + defaultValue=>"usa", + tab=>'properties', + label=> $i18n->get("stock_source"), + options=>$class->_getStockSources(), + hoverHelp=>$i18n->get("stock_source_description"), }, failover=>{ - fieldType=>"checkbox", - defaultValue=>undef + fieldType=>"yesNo", + defaultValue=>undef, + label=> $i18n->get("failover_label"), + hoverHelp=> $i18n->get("failover_description") } - }; - my $i18n = WebGUI::International->new($session,"Asset_StockData"); + ); + push(@{$definition}, { tableName=>'StockData', className=>'WebGUI::Asset::Wobject::StockData', icon=>'stockData.gif', assetName=>$i18n->get("assetName"), - properties=>$properties + autoGenerateForms=>1, + properties=>\%properties }); + return $class->SUPER::definition($session, $definition); } #------------------------------------------------------------------- -=head2 getEditForm - -Returns the tabform object that will be used in generating the edit page for Stock Lists - -=cut - -sub getEditForm { - my $self = shift; - my $tabform = $self->SUPER::getEditForm(); - my $i18n = WebGUI::International->new($self->session,"Asset_StockData"); - - $tabform->getTab("display")->template( - -name=>"templateId", - -value=>$self->get("templateId"), - -label=>$i18n->get("template_label"), - -hoverHelp=>$i18n->get("template_label_description"), - -namespace=>"StockData" - ); - - $tabform->getTab("display")->template( - -name=>"displayTemplateId", - -value=>$self->get("displayTemplateId"), - -label=>$i18n->get("display_template_label"), - -hoverHelp=>$i18n->get("display_template_label_description"), - -namespace=>"StockData/Display" - ); - - $tabform->getTab("properties")->textarea( - -name => "defaultStocks", - -label=> $i18n->get("default_stock_label"), - -hoverHelp=> $i18n->get("default_stock_label_description"), - -value=> $self->getValue("defaultStocks") - ); - - $tabform->getTab("properties")->selectList( - -name => "source", - -label=> $i18n->get("stock_source"), - -options=>$self->_getStockSources(), - -value=> [$self->getValue("source")], - -hoverHelp=>$i18n->get("stock_source_description") - ); - - $tabform->getTab("properties")->yesNo( - -name=> "failover", - -label=> $i18n->get("failover_label"), - -value=>$self->getValue("failover"), - -hoverHelp=> $i18n->get("failover_description") - ); - - return $tabform; -} - -#------------------------------------------------------------------- - =head2 prepareView ( ) See WebGUI::Asset::prepareView() for details. @@ -423,11 +400,16 @@ sub view { #Create last update date formats unless ($var->{'lastUpdate.default'}) { - my $luEpoch = $self->_convertToEpoch($hash->{'stocks.date'},$hash->{'stocks.time'}); - $var->{'lastUpdate.intl'} = $self->session->datetime->epochToHuman($luEpoch,"%y-%m-%d %j:%n"); - $var->{'lastUpdate.us'} = $self->session->datetime->epochToHuman($luEpoch,"%m/%d/%y %h:%n %p"); - $var->{'lastUpdate.default'} = $self->session->datetime->epochToHuman($luEpoch,"%C %d %H:%n %P"); - } + my $luEpoch = $self->_convertToEpoch($hash->{'stocks.date'},$hash->{'stocks.time'}); + if (defined $luEpoch) { + @$var{'lastUpdate.intl', 'lastUpdate.us', 'lastUpdate.default'} = + map {$self->session->datetime->epochToHuman($luEpoch, $_)} + ("%y-%m-%d %j:%n", "%m/%d/%y %h:%n %p", "%C %d %H:%n %P"); + } else { + @$var{'lastUpdate.intl', 'lastUpdate.us', 'lastUpdate.default'} = + ('(not available)') x 3; + } + } push (@stocks, $hash); } @@ -457,8 +439,14 @@ sub www_displayStock { #Configure last update dates my $luEpoch = $self->_convertToEpoch($var->{'stocks.date'},$var->{'stocks.time'}); - $var->{'lastUpdate.intl'} = $self->session->datetime->epochToHuman($luEpoch,"%y-%m-%d"); - $var->{'lastUpdate.us'} = $self->session->datetime->epochToHuman($luEpoch,"%m/%d/%y"); + if (defined $luEpoch) { + @$var{'lastUpdate.intl', 'lastUpdate.us'} = + map {$self->session->datetime->epochToHuman($luEpoch, $_)} + ("%y-%m-%d", "%m/%d/%y"); + } else { + @$var{'lastUpdate.intl', 'lastUpdate.us'} = + ('(not available)') x 2; + } return $self->processTemplate($var, $self->get("displayTemplateId")); }