From cdaef9d5e3583a6241aeca9e47ca95efa1cc340e Mon Sep 17 00:00:00 2001 From: Doug Bell Date: Sat, 23 Dec 2006 02:22:02 +0000 Subject: [PATCH] Multiple fixes in the code Doug wrote for 7.3 - Calendar / DateTime / Event - fix: Calendar now reports proper product ID on iCal feed - fix: Calendar now tries to use the feed ID when sending uid of event on iCal feeds (to prevent over-propagation of events shared between calendars). - fix: Bug in AssetLineage->getLineage documentation. - rfe: Event now has a template var to toggle if an event only lasts one day - rfe: WebGUI::DateTime->toMysql now automatically adjusts to UTC. NOTE: toMysqlDate and toMysqlTime do NOT adjust for timezones. If you are using them you must adjust manually. - fix: Bug in WebGUI::DateTime documentation - fix: Calendar default date of "first event" or "last event" now works. - fix: Calendar now handles Events that have ' in titles appropriately. - rfe: Added a "dateSpan" Event template variable that will show a properly formatted date/time span depending on how the event's start and end are. --- docs/changelog/7.x.x.txt | 14 +++++ lib/WebGUI/Asset/Event.pm | 31 ++++++++-- lib/WebGUI/Asset/Wobject/Calendar.pm | 91 ++++++++++++++++++---------- lib/WebGUI/AssetLineage.pm | 3 +- lib/WebGUI/DateTime.pm | 45 ++++++++++---- 5 files changed, 134 insertions(+), 50 deletions(-) diff --git a/docs/changelog/7.x.x.txt b/docs/changelog/7.x.x.txt index 348777eb2..d8c41c174 100644 --- a/docs/changelog/7.x.x.txt +++ b/docs/changelog/7.x.x.txt @@ -1,5 +1,19 @@ 7.3.3 - fix: Wiki Purge throws fatal + - fix: Calendar now reports proper product ID on iCal feed + - fix: Calendar now tries to use the feed ID when sending uid of event on iCal + feeds (to prevent over-propagation of events shared between calendars). + - fix: Bug in AssetLineage->getLineage documentation. + - rfe: Event now has a template var to toggle if an event only lasts one day + - rfe: WebGUI::DateTime->toMysql now automatically adjusts to UTC. NOTE: + toMysqlDate and toMysqlTime do NOT adjust for timezones. If you are + using them you must adjust manually. + - fix: Bug in WebGUI::DateTime documentation + - fix: Calendar default date of "first event" or "last event" now works. + - fix: Calendar now handles Events that have ' in titles appropriately. + - rfe: Added a "dateSpan" Event template variable that will show a properly + formatted date/time span depending on how the event's start and end are. + 7.3.2 diff --git a/lib/WebGUI/Asset/Event.pm b/lib/WebGUI/Asset/Event.pm index 43984cf56..2298d93c1 100644 --- a/lib/WebGUI/Asset/Event.pm +++ b/lib/WebGUI/Asset/Event.pm @@ -358,18 +358,23 @@ Event object. sub getEventNext { my $self = shift; + my $db = $self->session->db; my $where = 'Event.startDate > "'.$self->get("startDate").'" || (Event.startDate = "'.$self->get("startDate").'" && '; # All day events must either look for null time or greater than 00:00:00 if ($self->isAllDay) { - $where .= "(Event.startTime IS NULL && assetData.title > '".$self->get("title")."') || Event.startTime >= '00:00:00'"; + $where .= "(Event.startTime IS NULL " + . "&& assetData.title > ".$db->quote($self->get("title")).") " + . "|| Event.startTime >= '00:00:00'"; } # Non all-day events must look for greater than time else { - $where .= "(Event.startTime = '".$self->get("startTime")."' && assetData.title > '".$self->get("title")."') || Event.startTime > '".$self->get("startTime")."'"; + $where .= "(Event.startTime = '".$self->get("startTime")."' " + . "&& assetData.title > ".$db->quote($self->get("title")).")" + . "|| Event.startTime > '".$self->get("startTime")."'"; } $where .= ")"; @@ -403,18 +408,22 @@ object. sub getEventPrev { my $self = shift; + my $db = $self->session->db; my $where = 'Event.startDate < "'.$self->get("startDate").'" || (Event.startDate = "'.$self->get("startDate").'" && '; # All day events must either look for null time or greater than 00:00:00 if ($self->isAllDay) { - $where .= "(Event.startTime IS NULL && assetData.title < '".$self->get("title")."')"; + $where .= "(Event.startTime IS NULL " + . "&& assetData.title < ".$db->quote($self->get("title")).")"; } # Non all-day events must look for greater than time else { - $where .= "(Event.startTime = '".$self->get("startTime")."' && assetData.title < '".$self->get("title")."') || Event.startTime < '".$self->get("startTime")."'"; + $where .= "(Event.startTime = '".$self->get("startTime")."' " + . "&& assetData.title < ".$db->quote($self->get("title")).")" + . "|| Event.startTime < '".$self->get("startTime")."'"; } $where .= ")"; @@ -1258,8 +1267,22 @@ sub getTemplateVars $var{isAllDay} = $self->isAllDay; + $var{isOneDay} = 1 if ($var{isAllDay} && $var{startDateDmy} eq $var{endDateDmy}); + # Make a Friendly date span + $var{dateSpan} = $var{startDateDayName}.", " + . $var{startDateMonthName}." " + . $var{startDateDayOfMonth}." " + . ( !$var{isAllDay} ? $var{startDateHour}.":".$var{startDateMinute}." ".$var{startDateM} : "" ) + . ( !$var{isOneDay} ? + ' • ' + . $var{endDateDayName}.", " + .$var{endDateMonthName}." " + .$var{endDateDayOfMonth}." " + . ( !$var{isAllDay} ? $var{endDateHour}.":".$var{endDateMinute}." ".$var{endDateM} : "") + : ""); + # Make some friendly URLs $dtStart->truncate(to=>"day"); $var{"urlDay"} = $self->getParent->getUrl("type=day;start=".$dtStart->toMysql); diff --git a/lib/WebGUI/Asset/Wobject/Calendar.pm b/lib/WebGUI/Asset/Wobject/Calendar.pm index 03e2d6689..12e0ca052 100644 --- a/lib/WebGUI/Asset/Wobject/Calendar.pm +++ b/lib/WebGUI/Asset/Wobject/Calendar.pm @@ -582,7 +582,12 @@ sub getEvent # ? Perhaps use Stow to cache events ? - return Asset::newByDynamicClass($self->session, $assetId); + my $event = WebGUI::Asset->newByDynamicClass($self->session, $assetId); + + $self->session->errorHandler->warn("WebGUI::Asset::Wobject::Calendar->getEvent :: Event '$assetId' not a child of calendar '".$self->getId."'"), return + unless $event->get("parentId") eq $self->getId; + + return $event; } @@ -603,6 +608,11 @@ user's time zone. TODO: Allow WebGUI::DateTime objects to be passed as the parameters. +TODO: Allow for a hashref of options as the third parameter to specify such +things as a limit clause, or additional where clause, or something. + +This is the main way to get events from a calendar, so it must be capable. + =cut sub getEventsIn @@ -688,11 +698,19 @@ Gets the first event in this calendar. Returns the Event object. sub getFirstEvent { my $self = shift; - my $event; + my $lineage = $self->get("lineage"); - $self->session->errorHandler->warn("getFirstEvent is not yet implemented"); + my ($assetId) = $self->session->db->quickArray(<getEvent($assetId); } @@ -710,11 +728,19 @@ Gets the last event in this calendar. Returns the Event object. sub getLastEvent { my $self = shift; - my $event; + my $lineage = $self->get("lineage"); - $self->session->errorHandler->warn("getLastEvent is not yet implemented"); + my ($assetId) = $self->session->db->quickArray(<getEvent($assetId); } @@ -850,26 +876,18 @@ sub view # Set defaults if necessary unless ($params->{start}) { - #if ($self->get("defaultDate") eq "first") - #{ - #!! TODO: Get the first event's date - # select startDate from Events - # join assetLineage - # order by startDate ASC, revisionDate DESC - # limit 1 - #} - #elsif ($self->get("defaultDate") eq "last") - #{ - #!! TODO: Get the last event's date - # select startDate from Events - # join assetLineage - # order by startDate DESC, revisionDate DESC - # limit 1 - #} - #else - #{ + if ($self->get("defaultDate") eq "first" && $self->getFirstEvent) + { + $params->{start} = $self->getFirstEvent->getDateTimeStart; + } + elsif ($self->get("defaultDate") eq "last" && $self->getLastEvent) + { + $params->{start} = $self->getLastEvent->getDateTimeStart; + } + else + { $params->{start} = WebGUI::DateTime->from_epoch(epoch => time(), time_zone => $session->user->profileField("timeZone"))->toMysql; - #} + } } $params->{type} ||= $self->get("defaultView") || "Month"; @@ -898,7 +916,7 @@ sub view # Admin if ($self->session->var->isAdminOn) { - $var->{'admin'} = 1; + $var->{'admin'} = 1; $var->{'adminControls'} = $self->getToolbar; } @@ -906,13 +924,13 @@ sub view if ($self->canAddEvent) { $var->{'editor'} = 1; + $var->{"urlAdd"} = $self->getUrl("func=add;class=WebGUI::Asset::Event"); } # URLs $var->{"urlDay"} = $self->getUrl("type=day;start=".$params->{start}); $var->{"urlWeek"} = $self->getUrl("type=week;start=".$params->{start}); $var->{"urlMonth"} = $self->getUrl("type=month;start=".$params->{start}); - $var->{"urlAdd"} = $self->getUrl("func=add;class=WebGUI::Asset::Event"); $var->{"urlSearch"} = $self->getUrl("func=search"); $var->{"urlPrint"} = $self->getUrl("type=".$params->{type}.";start=".$params->{start}.";print=1"); @@ -1479,7 +1497,7 @@ sub www_ical my $ical = qq{BEGIN:VCALENDAR\r\n} - . qq{PRODID:WebGUI \r\n} # TODO: Get WebGUI version! + . qq{PRODID:WebGUI }.$WebGUI::VERSION."-".$WebGUI::STATUS.qq{\r\n} . qq{VERSION:2.0\r\n}; # VEVENT: @@ -1489,9 +1507,15 @@ sub www_ical # Currently we only need # UID - # TODO: Use feedUid if one exists - my $domain = $session->config->get("sitename")->[0]; - $ical .= qq{UID:}.$event->get("assetId").'@'.$domain."\r\n"; + if ($event->get("feedUid")) # Use feed's UID to prevent over-propagation + { + $ical .= qq{UID:}.$event->get("feedUid")."\r\n"; + } + else # Create a UID for feeds native to this calendar + { + my $domain = $session->config->get("sitename")->[0]; + $ical .= qq{UID:}.$event->get("assetId").'@'.$domain."\r\n"; + } # LAST-MODIFIED (revisionDate) $ical .= qq{LAST-MODIFIED:} @@ -1731,6 +1755,8 @@ page. The templates provided by this Wobject and the parameters they contain +!!! TODO !!! + @@ -1747,7 +1773,6 @@ issues. TODO: More abstraction so that certain methods can be tested. - =cut 1; diff --git a/lib/WebGUI/AssetLineage.pm b/lib/WebGUI/AssetLineage.pm index 4476dbcf9..0523d3018 100644 --- a/lib/WebGUI/AssetLineage.pm +++ b/lib/WebGUI/AssetLineage.pm @@ -306,7 +306,8 @@ A string containing extra where clause information for the query. =head4 orderByClause -A string containing an order by clause (without the "order by"). +A string containing an order by clause (without the "order by"). If specified, +will override the "invertTree" option. =head4 limit diff --git a/lib/WebGUI/DateTime.pm b/lib/WebGUI/DateTime.pm index e920aacea..8d26eacaa 100755 --- a/lib/WebGUI/DateTime.pm +++ b/lib/WebGUI/DateTime.pm @@ -20,18 +20,33 @@ use base 'DateTime'; =head1 NAME -WebGUI::Session::Date - DateTime subclass with additional WebGUI methods +WebGUI::DateTime - DateTime subclass with additional WebGUI methods =head1 SYNOPSIS - my $dt = $session->date->new("2006-11-06 21:12:45"); - my $dt = $session->date->new(time); - my $dt = $session->date->new({ year => 2006, month => 11, day => 6 }); + # Create an object from a MySQL date/time in the UTC time zone + my $dt = WebGUI::DateTime->new("2006-11-06 21:12:45"); + + # Create an object from an epoch time + my $dt = WebGUI::DateTime->new(time); + + # Create an object from a MySQL date/time in a specific time zone + my $dt = WebGUI::DateTime->new( mysql => "2006-11-06 21:12:45", time_zone => "America/Chicago" ); + + # Create an object from a hash of data + my $dt = WebGUI::DateTime->new( year => 2006, month => 11, day => 6 ); + my $mysql = $dt->toMysql; # Make a MySQL date/time string my $mysqlDate = $dt->toMysqlDate; # Make a MySQL date string my $mysqlTime = $dt->toMysqlTime; # Make a MySQL time string + + my $ical = $dt->toIcal; # Make an iCal date/time string + my $icalDate = $dt->toIcalDate; # Make an iCal date string + my $icalTime = $dt->toIcalTime; # Make an iCal time string + + ### See perldoc DateTime for additional methods ### =head1 DESCRIPTION @@ -52,19 +67,25 @@ dealing with time zones. =head2 new ( string ) -Creates a new object from a MySQL Date/Time string with the UTC time zone. +Creates a new object from a MySQL Date/Time string in the format +"2006-11-06 21:12:45". + +This string is assumed to be in the UTC time zone. If it is not, use the +"mysql" => string constructor, below. =head2 new ( integer ) Creates a new object from an epoch time. -=head2 new ( "mysql" => string, "time_zone" => string) +=head2 new ( "mysql" => string, "time_zone" => string ) -Creates a new object from a MySQL Date/Time string with the specified time zone +Creates a new object from a MySQL Date/Time string that is in the specified +time zone =head2 new ( hash ) -Creates a new object from a hash of data passed directly to DateTime. +Creates a new object from a hash of data passed directly to DateTime. See +perldoc DateTime for the proper keys to be used. =cut @@ -164,13 +185,13 @@ sub toIcalDate =head2 toMysql -Returns a MySQL Date/Time string. +Returns a MySQL Date/Time string in the UTC time zone =cut sub toMysql { - return $_[0]->strftime("%Y-%m-%d %H:%M:%S"); + return $_[0]->clone->set_time_zone("UTC")->strftime("%Y-%m-%d %H:%M:%S"); } @@ -181,7 +202,7 @@ sub toMysql =head2 toMysqlDate Returns a MySQL Date string. Any time data stored by this object will be -ignored. +ignored. Is not adjusted for time zone. =cut @@ -198,7 +219,7 @@ sub toMysqlDate =head2 toMysqlTime Returns a MySQL Time string. Any date data stored by this object will be -ignored. +ignored. Is not adjusted for time zone. =cut