Tentative final Calendar beta for testing.
This commit is contained in:
parent
92f016eb32
commit
b55266e821
7 changed files with 627 additions and 47 deletions
|
|
@ -40,6 +40,9 @@
|
|||
- WebGUI::TabForm->addTab now returns the WebGUI::HTMLForm created.
|
||||
- WebGUI::AssetLineage::getLineage can now limit the number of records returned
|
||||
- fix: IP addresses for adminModeSubnets not using X-Forwarded-For properly
|
||||
- The Events Calendar is now the new Calendar with some fun new features.
|
||||
All your existing Events Calendars will be migrated automatically.
|
||||
*** PLEASE READ THE GOTCHAS ***
|
||||
|
||||
7.2.3
|
||||
- fix: minor bug with new template vars in Auth::createAccount
|
||||
|
|
|
|||
|
|
@ -23,9 +23,9 @@ addWikiAssets($session);
|
|||
deleteOldFiles($session);
|
||||
addFileFieldsToDataForm($session);
|
||||
makeRSSFromParentAlwaysHidden($session);
|
||||
#addNewCalendar($session);
|
||||
#migrateCalendars($session);
|
||||
#removeOldCalendar($session);
|
||||
addNewCalendar($session);
|
||||
migrateCalendars($session);
|
||||
removeOldCalendar($session);
|
||||
finish($session); # this line required
|
||||
|
||||
#-------------------------------------------------
|
||||
|
|
@ -121,6 +121,7 @@ CREATE TABLE `Event` (
|
|||
`assetId` varchar(22) NOT NULL,
|
||||
`revisionDate` bigint(20) unsigned NOT NULL,
|
||||
`feedId` varchar(22) default NULL,
|
||||
`feedUid` varchar(255) default NULL,
|
||||
`startDate` date default NULL,
|
||||
`endDate` date default NULL,
|
||||
`userDefined1` text,
|
||||
|
|
|
|||
|
|
@ -97,6 +97,14 @@ sub definition {
|
|||
fieldType => "Text",
|
||||
defaultValue => undef,
|
||||
},
|
||||
'feedId' => {
|
||||
fieldType => "Text",
|
||||
defaultValue => undef,
|
||||
},
|
||||
'feedUid' => {
|
||||
fieldType => "Text",
|
||||
defaultValue => undef,
|
||||
},
|
||||
);
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ use WebGUI::DateTime;
|
|||
use base 'WebGUI::Asset::Wobject';
|
||||
|
||||
use DateTime;
|
||||
use JSON;
|
||||
|
||||
|
||||
=head1 Name
|
||||
|
|
@ -348,7 +349,7 @@ sub duplicate
|
|||
my @events = $self->getLineage(["descendents"],
|
||||
{
|
||||
returnObjects => 1,
|
||||
includeOnlyClasses => 'WebGUI::Asset::Event',
|
||||
includeOnlyClasses => ['WebGUI::Asset::Event'],
|
||||
});
|
||||
|
||||
|
||||
|
|
@ -368,7 +369,10 @@ sub duplicate
|
|||
|
||||
=head2 getEditForm
|
||||
|
||||
Adds an additional tab for feeds.
|
||||
Adds an additional tab for feeds.
|
||||
|
||||
TODO: Abstract the Javascript enough to export into extras/yui-webgui for use
|
||||
in other areas.
|
||||
|
||||
=cut
|
||||
|
||||
|
|
@ -379,10 +383,146 @@ sub getEditForm
|
|||
my $form = $self->SUPER::getEditForm;
|
||||
my $i18n = WebGUI::International->new($session,"Asset_Calendar");
|
||||
|
||||
my $tab = $form->addTab("feeds",$i18n->get("feeds"));
|
||||
my $tab = $form->addTab("feeds",$i18n->get("feeds"));
|
||||
$tab->raw("<tr><td>");
|
||||
|
||||
|
||||
$tab->raw(<<'ENDJS');
|
||||
<script type="text/javascript">
|
||||
var FeedsManager = new Object();
|
||||
|
||||
FeedsManager.addFeed = function (table,rowId,params) {
|
||||
// TODO: Verify that feed URL is valid
|
||||
|
||||
|
||||
var table = document.getElementById(table);
|
||||
|
||||
// If id is "new"
|
||||
// Add a number on the end.
|
||||
if (rowId == "new")
|
||||
rowId = "new" + Math.round(Math.random() * 10000000000000000);
|
||||
|
||||
// Create 5 cells
|
||||
var cells = new Array();
|
||||
for (var i = 0; i < 5; i++)
|
||||
cells[i] = document.createElement("td");
|
||||
|
||||
|
||||
/*** [0] - Delete button */
|
||||
var button = document.createElement("img");
|
||||
button.setAttribute("src","/extras/wobject/Calendar/images/delete.gif");
|
||||
button.setAttribute("border","0");
|
||||
|
||||
var deleteLink = document.createElement("a");
|
||||
deleteLink.setAttribute("href","#");
|
||||
deleteLink.setAttribute("onclick","FeedsManager.deleteFeed('feeds','"+rowId+"'); return false;");
|
||||
deleteLink.appendChild(button);
|
||||
|
||||
cells[0].appendChild(deleteLink);
|
||||
|
||||
|
||||
|
||||
/*** [1] - Feed link for teh clicking and form element for teh saving */
|
||||
var feedLink = document.createElement("a");
|
||||
feedLink.setAttribute("href",params.url);
|
||||
feedLink.setAttribute("target","_new"); // TODO: Use JS to open window. target="" is deprecated
|
||||
feedLink.appendChild(document.createTextNode(params.url));
|
||||
|
||||
var formElement = document.createElement("input");
|
||||
formElement.setAttribute("type","hidden");
|
||||
formElement.setAttribute("name","feeds-"+rowId);
|
||||
formElement.setAttribute("value",params.url);
|
||||
|
||||
cells[1].appendChild(feedLink);
|
||||
cells[1].appendChild(formElement);
|
||||
|
||||
|
||||
|
||||
/*** [2] - Result (new) */
|
||||
if (params.lastResult == undefined)
|
||||
params.lastResult = "new";
|
||||
var lastResult = document.createTextNode(params.lastResult);
|
||||
|
||||
cells[2].appendChild(lastResult);
|
||||
|
||||
|
||||
|
||||
/*** [3] - Last updated */
|
||||
if (params.lastUpdated == undefined)
|
||||
params.lastUpdated = "never";
|
||||
var lastUpdated = document.createTextNode(params.lastUpdated);
|
||||
|
||||
cells[3].appendChild(lastUpdated);
|
||||
|
||||
|
||||
|
||||
/*** [4] - Update now! */
|
||||
/* TODO */
|
||||
|
||||
|
||||
/* Add the row to the table */
|
||||
var row = document.createElement("tr");
|
||||
row.setAttribute("id",rowId);
|
||||
for (var i = 0; i < cells.length; i++)
|
||||
row.appendChild(cells[i]);
|
||||
|
||||
table.appendChild(row);
|
||||
FeedsManager.updateFeed(table.getAttribute("id"),rowId);
|
||||
}
|
||||
|
||||
|
||||
FeedsManager.updateFeed = function (table,rowId) {
|
||||
/* TODO */
|
||||
|
||||
}
|
||||
|
||||
|
||||
FeedsManager.deleteFeed = function (table,rowId) {
|
||||
row = document.getElementById(rowId);
|
||||
|
||||
row.parentNode.removeChild(row);
|
||||
}
|
||||
|
||||
|
||||
FeedsManager.setFeed = function (table,rowId,params) {
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
</script>
|
||||
ENDJS
|
||||
|
||||
|
||||
$tab->raw(<<'ENDHTML');
|
||||
<label for="addFeed">Add a feed</label>
|
||||
<input type="text" size="60" id="addFeed" name="addFeed" value="http://google.com" />
|
||||
<input type="button" value="Add" onclick="FeedsManager.addFeed('feeds','new',{ 'url' : this.form.addFeed.value }); this.form.addFeed.value=''" />
|
||||
|
||||
<table id="feeds" style="width: 100%;">
|
||||
<thead>
|
||||
<th style="width: 30px;"> </th>
|
||||
<th style="width: 50%;">Feed URL</th>
|
||||
<th>Status</th>
|
||||
<th>Last Updated</th>
|
||||
<th> </th>
|
||||
</thead>
|
||||
</table>
|
||||
ENDHTML
|
||||
|
||||
|
||||
|
||||
# Add the existing feeds
|
||||
my $feeds = $self->getFeeds();
|
||||
$tab->raw('<script type="text/javascript">'."\n");
|
||||
for my $feedId (keys %$feeds)
|
||||
{
|
||||
$tab->raw("FeedsManager.addFeed('feeds','".$feedId."',".objToJson($feeds->{$feedId}).");\n");
|
||||
}
|
||||
$tab->raw('</script>');
|
||||
|
||||
|
||||
$tab->raw("</td></tr>");
|
||||
return $form;
|
||||
}
|
||||
|
||||
|
|
@ -481,6 +621,31 @@ sub getEventsIn
|
|||
|
||||
|
||||
|
||||
####################################################################
|
||||
|
||||
=head2 getFeeds ( )
|
||||
|
||||
Gets a hashref of hashrefs of all the feeds attached to this calendar.
|
||||
|
||||
TODO: Format lastUpdated into the user's time zone
|
||||
|
||||
=cut
|
||||
|
||||
sub getFeeds
|
||||
{
|
||||
my $self = shift;
|
||||
|
||||
return $self->session->db->buildHashRefOfHashRefs(
|
||||
"select * from Calendar_feeds where assetId=?",
|
||||
[$self->get("assetId")],
|
||||
"feedId"
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
####################################################################
|
||||
|
||||
=head2 getFirstEvent ( )
|
||||
|
|
@ -540,7 +705,7 @@ sub prepareView
|
|||
my $view = ucfirst lc $self->session->form->param("type")
|
||||
|| ucfirst $self->get("defaultView")
|
||||
|| "Month";
|
||||
$self->session->errorHandler->warn("Prepare view ".$view." with template ".$self->get("templateId".$view));
|
||||
#$self->session->errorHandler->warn("Prepare view ".$view." with template ".$self->get("templateId".$view));
|
||||
|
||||
my $template = WebGUI::Asset::Template->new($self->session, $self->get("templateId".$view));
|
||||
$template->prepare;
|
||||
|
|
@ -566,9 +731,9 @@ Adds / removes feeds from the feed trough.
|
|||
|
||||
sub processPropertiesFromFormPost
|
||||
{
|
||||
my $self = shift;
|
||||
|
||||
# The super does most of the real work
|
||||
my $self = shift;
|
||||
my $session = $self->session;
|
||||
my $form = $self->session->form;
|
||||
$self->SUPER::processPropertiesFromFormPost;
|
||||
|
||||
|
||||
|
|
@ -578,6 +743,33 @@ sub processPropertiesFromFormPost
|
|||
}
|
||||
|
||||
|
||||
### Get feeds from the form
|
||||
# Workaround WebGUI::Session::Form->param bug
|
||||
my %feeds;
|
||||
$feeds{$_}++
|
||||
for map { s/^feeds-//; $_; } grep /^feeds-/,($form->param());
|
||||
my @feeds = keys %feeds;
|
||||
|
||||
# Delete old feeds that are not in @feeds
|
||||
for my $feedId ($session->db->buildArray("select feedId from Calendar_feeds where assetId=?",[$self->get("assetId")]))
|
||||
{
|
||||
unless (grep /^$feedId$/, @feeds)
|
||||
{
|
||||
$session->db->write("delete from Calendar_feeds where feedId=? and assetId=?",[$feedId,$self->get("assetId")]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
# Create new feeds
|
||||
for my $feedId (grep /^new(\d+)/, @feeds)
|
||||
{
|
||||
$session->db->setRow("Calendar_feeds","feedId",{
|
||||
feedId => "new",
|
||||
assetId => $self->get("assetId"),
|
||||
url => $form->param("feeds-".$feedId),
|
||||
feedType => "ical",
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -616,26 +808,26 @@ sub view
|
|||
# Set defaults if necessary
|
||||
unless ($params->{start})
|
||||
{
|
||||
if ($self->get("defaultDate") eq "first")
|
||||
{
|
||||
#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")
|
||||
{
|
||||
#}
|
||||
#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
|
||||
{
|
||||
#}
|
||||
#else
|
||||
#{
|
||||
$params->{start} = WebGUI::DateTime->from_epoch(epoch => time(), time_zone => $session->user->profileField("timeZone"))->toMysql;
|
||||
}
|
||||
#}
|
||||
}
|
||||
$params->{type} ||= $self->get("defaultView") || "Month";
|
||||
|
||||
|
|
@ -1172,34 +1364,51 @@ sub www_ical
|
|||
|
||||
#!!! Events from what time period should we show? Default perpage?
|
||||
# By default show the events for a month
|
||||
my $type = $form->param("type") || $self->get("defaultView") || "month";
|
||||
my $type = $form->param("type") || lc($self->get("defaultView")) || "month";
|
||||
my $start = $form->param("start");
|
||||
my $end = $form->param("end");
|
||||
|
||||
|
||||
|
||||
|
||||
#!!! KLUDGE:
|
||||
# An "adminId" may be passed as a parameter in order to facilitate
|
||||
# calls between calendars on the same server getting administrator
|
||||
# privileges
|
||||
# I do not know how dangerous this could possibly be, so THIS MUST
|
||||
# CHANGE
|
||||
my $adminId = $form->param("adminId");
|
||||
if ($adminId
|
||||
&& ($self->session->db->quickArray("SELECT value FROM userSessionScratch WHERE sessionId=? and name=?",[$adminId,$self->get("assetId")]))[0] eq "SPECTRE")
|
||||
{
|
||||
$self->session->user({userId => 3});
|
||||
}
|
||||
#/KLUDGE
|
||||
|
||||
|
||||
my $dt_start;
|
||||
unless ($start)
|
||||
{
|
||||
if ($self->get("defaultDate") eq "first")
|
||||
{
|
||||
#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")
|
||||
{
|
||||
#}
|
||||
#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
|
||||
{
|
||||
#}
|
||||
#else
|
||||
#{
|
||||
$dt_start = WebGUI::DateTime->from_epoch(epoch => time(), time_zone => $session->user->profileField("timeZone"));
|
||||
}
|
||||
#}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -1211,18 +1420,18 @@ sub www_ical
|
|||
my $dt_end;
|
||||
unless ($end)
|
||||
{
|
||||
if ($type eq "month")
|
||||
{
|
||||
#if ($type eq "month")
|
||||
#{
|
||||
$dt_end = $dt_start->clone->add(months => 1);
|
||||
}
|
||||
elsif ($type eq "week")
|
||||
{
|
||||
$dt_end = $dt_start->clone->add(weeks => 1);
|
||||
}
|
||||
elsif ($type eq "day")
|
||||
{
|
||||
$dt_end = $dt_start->clone->add(days => 1);
|
||||
}
|
||||
#}
|
||||
#elsif ($type eq "week")
|
||||
#{
|
||||
# $dt_end = $dt_start->clone->add(weeks => 1);
|
||||
#}
|
||||
#elsif ($type eq "day")
|
||||
#{
|
||||
# $dt_end = $dt_start->clone->add(days => 1);
|
||||
#}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -1246,32 +1455,41 @@ 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."\n";
|
||||
$ical .= qq{UID:}.$event->get("assetId").'@'.$domain."\x0D\x0A";
|
||||
|
||||
# LAST-MODIFIED (revisionDate)
|
||||
$ical .= qq{LAST-MODIFIED:}
|
||||
. WebGUI::DateTime->new($event->get("revisionDate"))->toIcal
|
||||
. "\n";
|
||||
. "\x0D\x0A";
|
||||
|
||||
# CREATED (creationDate)
|
||||
$ical .= qq{CREATED:}
|
||||
. WebGUI::DateTime->new($event->get("creationDate"))->toIcal
|
||||
. "\n";
|
||||
. "\x0D\x0A";
|
||||
|
||||
# DTSTART
|
||||
$ical .= qq{DTSTART:}.$event->getIcalStart."\n";
|
||||
$ical .= qq{DTSTART:}.$event->getIcalStart."\x0D\x0A";
|
||||
|
||||
# DTEND
|
||||
$ical .= qq{DTEND:}.$event->getIcalEnd."\n";
|
||||
$ical .= qq{DTEND:}.$event->getIcalEnd."\x0D\x0A";
|
||||
|
||||
# Summary (the title)
|
||||
# Wrapped at 75 columns
|
||||
$ical .= $self->wrapIcal("SUMMARY:".$event->get("title"))."\n";
|
||||
$ical .= $self->wrapIcal("SUMMARY:".$event->get("title"))."\x0D\x0A";
|
||||
|
||||
# Description (the text)
|
||||
# Wrapped at 75 columns
|
||||
$ical .= $self->wrapIcal("DESCRIPTION:".$event->get("description"))."\n";
|
||||
$ical .= $self->wrapIcal("DESCRIPTION:".$event->get("description"))."\x0D\x0A";
|
||||
|
||||
|
||||
|
||||
# X-WEBGUI lines
|
||||
$ical .= "X-WEBGUI-GROUPIDVIEW:".$event->get("groupIdView")."\x0D\x0A";
|
||||
$ical .= "X-WEBGUI-GROUPIDEDIT:".$event->get("groupIdEdit")."\x0D\x0A";
|
||||
$ical .= "X-WEBGUI-URL:".$event->get("url")."\x0D\x0A";
|
||||
|
||||
|
||||
$ical .= qq{END:VEVENT\n};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@ dealing with time zones.
|
|||
|
||||
=cut
|
||||
|
||||
|
||||
#######################################################################
|
||||
|
||||
=head2 new ( string )
|
||||
|
|
|
|||
341
lib/WebGUI/Workflow/Activity/CalendarUpdateFeeds.pm
Executable file
341
lib/WebGUI/Workflow/Activity/CalendarUpdateFeeds.pm
Executable file
|
|
@ -0,0 +1,341 @@
|
|||
package WebGUI::Workflow::Activity::CalendarUpdateFeeds;
|
||||
|
||||
|
||||
=head1 LEGAL
|
||||
|
||||
-------------------------------------------------------------------
|
||||
WebGUI is Copyright 2001-2006 Plain Black Corporation.
|
||||
-------------------------------------------------------------------
|
||||
Please read the legal notices (docs/legal.txt) and the license
|
||||
(docs/license.txt) that came with this distribution before using
|
||||
this software.
|
||||
-------------------------------------------------------------------
|
||||
http://www.plainblack.com info@plainblack.com
|
||||
-------------------------------------------------------------------
|
||||
|
||||
=cut
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use base 'WebGUI::Workflow::Activity';
|
||||
|
||||
use WebGUI::Asset::Wobject::Calendar;
|
||||
use WebGUI::Asset::Event;
|
||||
use WebGUI::DateTime;
|
||||
|
||||
use LWP::UserAgent;
|
||||
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Package WebGUI::Workflow::Activity::CalendarUpdateFeeds;
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
Imports calendar events from Calendar feeds.
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
See WebGUI::Workflow::Activity for details on how to use any activity.
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
These methods are available from this class:
|
||||
|
||||
=cut
|
||||
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 definition ( session, definition )
|
||||
|
||||
See WebGUI::Workflow::Activity::defintion() for details.
|
||||
|
||||
=cut
|
||||
|
||||
sub definition {
|
||||
my $class = shift;
|
||||
my $session = shift;
|
||||
my $definition = shift;
|
||||
my $i18n = WebGUI::International->new($session, "Asset_Calendar");
|
||||
push(@{$definition}, {
|
||||
name=>$i18n->get("workflow updateFeeds"),
|
||||
properties=> { }
|
||||
});
|
||||
return $class->SUPER::definition($session,$definition);
|
||||
}
|
||||
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 execute ( )
|
||||
|
||||
See WebGUI::Workflow::Activity::execute() for details.
|
||||
|
||||
=cut
|
||||
|
||||
sub execute {
|
||||
my $self = shift;
|
||||
$self->session->user({userId => 3});
|
||||
|
||||
|
||||
my $ua = LWP::UserAgent->new(agent => "WebGUI");
|
||||
my $dt = WebGUI::DateTime->new(time)->toMysql;
|
||||
|
||||
my $sth = $self->session->db->prepare("select * from Calendar_feeds");
|
||||
$sth->execute();
|
||||
|
||||
|
||||
FEED:while (my $feed = $sth->hashRef)
|
||||
{
|
||||
#!!! KLUDGE - If the feed is on the same server, set a scratch value
|
||||
# I do not know how dangerous this is, so THIS MUST CHANGE!
|
||||
# Preferably: Spectre would add a userSession to the database,
|
||||
# and send the appropriate cookie with the request.
|
||||
my $sitename = $self->session->config->get("sitename")->[0];
|
||||
if ($feed->{url} =~ m{http://[^/]*$sitename})
|
||||
{
|
||||
my $sessionId = $self->session->id->generate;
|
||||
$feed->{url} .= ";adminId=".$sessionId;
|
||||
$self->session->db->write("INSERT INTO userSessionScratch (sessionId,name,value) VALUES (?,?,?)",
|
||||
[$sessionId,$feed->{assetId},"SPECTRE"]);
|
||||
}
|
||||
#/KLUDGE
|
||||
#warn "FEED URL: ".$feed->{url} ."\n";
|
||||
|
||||
|
||||
|
||||
## Somebody point me to a DECENT iCalendar parser...
|
||||
# Text::vFile perhaps?
|
||||
|
||||
# Get the feed
|
||||
my $response = $ua->get($feed->{url});
|
||||
|
||||
if ($response->is_success)
|
||||
{
|
||||
my $data = $response->content;
|
||||
|
||||
# If doesn't start with BEGIN:VCALENDAR then error
|
||||
unless ($data =~ /^BEGIN:VCALENDAR/i)
|
||||
{
|
||||
# Update the result and last updated fields
|
||||
$self->session->db->write("update Calendar_feeds set lastResult=?,lastUpdated=? where feedId=?",
|
||||
["Not an iCalendar feed",$dt,$feed->{feedId}]);
|
||||
next FEED;
|
||||
}
|
||||
|
||||
|
||||
my $active = 0; # Parser on/off
|
||||
my %current_event = ();
|
||||
my $current_entry = "";
|
||||
my %events;
|
||||
my $line_number = 0;
|
||||
for my $line (split /[\r\n]+/,$data)
|
||||
{
|
||||
chomp $line;
|
||||
$line_number++;
|
||||
next unless $line =~ /\w/;
|
||||
|
||||
#warn "LINE $line_number: $line\n";
|
||||
|
||||
if ($line =~ /^BEGIN:VEVENT$/i)
|
||||
{
|
||||
$active = 1;
|
||||
}
|
||||
elsif ($line =~ /^END:VEVENT$/i)
|
||||
{
|
||||
$active = 0;
|
||||
# Flush event
|
||||
my $uid = lc $current_event{uid}[1];
|
||||
delete $current_event{uid};
|
||||
$events{$uid} = {%current_event};
|
||||
%current_event = ();
|
||||
}
|
||||
elsif ($line =~ /^ /)
|
||||
{
|
||||
# Add to entry data
|
||||
$current_entry .= substr $line, 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
# Flush old entry
|
||||
# KEY;ATTRIBUTE=VALUE;ATTRIBUTE=VALUE:KEYVALUE
|
||||
my ($key_attrs,$value) = split /:/,$current_entry,2;
|
||||
|
||||
my @attrs = split /;/, $key_attrs;
|
||||
my $key = shift @attrs;
|
||||
my %attrs;
|
||||
while (my $attribute = shift @attrs)
|
||||
{
|
||||
my ($attr_key, $attr_value) = split /=/, $attribute, 2;
|
||||
$attrs{lc $attr_key} = $attr_value;
|
||||
}
|
||||
|
||||
# Unescape value
|
||||
|
||||
|
||||
$current_event{lc $key} = [\%attrs,$value];
|
||||
|
||||
# Start new entry
|
||||
$current_entry = $line;
|
||||
}
|
||||
}
|
||||
|
||||
my $added = 0;
|
||||
my $updated = 0;
|
||||
for my $id (keys %events)
|
||||
{
|
||||
#use Data::Dumper;
|
||||
#warn "EVENT: $id; ".Dumper $events{$id};
|
||||
|
||||
# Prepare event data
|
||||
my $properties = {
|
||||
feedUid => $id,
|
||||
feedId => $feed->{feedId},
|
||||
description => $events{$id}->{description}->[1],
|
||||
title => $events{$id}->{summary}->[1],
|
||||
menuTitle => substr($events{$id}->{summary}->[1],0,15),
|
||||
className => 'WebGUI::Asset::Event',
|
||||
isHidden => 1,
|
||||
};
|
||||
|
||||
# Prepare the date
|
||||
my $dtstart = $events{$id}->{dtstart}->[1];
|
||||
if ($dtstart =~ /T/)
|
||||
{
|
||||
my ($date, $time) = split /T/, $dtstart;
|
||||
|
||||
my ($year, $month, $day) = $date =~ /(\d{4})(\d{2})(\d{2})/;
|
||||
my ($hour, $minute, $second) = $time =~ /(\d{2})(\d{2})(\d{2})/;
|
||||
|
||||
($properties->{startDate}, $properties->{startTime}) =
|
||||
split / /, WebGUI::DateTime(
|
||||
year => $year,
|
||||
month => $month,
|
||||
day => $day,
|
||||
hour => $hour,
|
||||
minute => $minute,
|
||||
second => $second,
|
||||
time_zone => "UTC",
|
||||
)->toMysql;
|
||||
}
|
||||
elsif ($dtstart =~ /(\d{4})(\d{2})(\d{2})/)
|
||||
{
|
||||
my ($year, $month, $day) = $dtstart =~ /(\d{4})(\d{2})(\d{2})/;
|
||||
|
||||
$properties->{startDate} = join "-",$year,$month,$day;
|
||||
}
|
||||
|
||||
my $dtend = $events{$id}->{dtend}->[1];
|
||||
if ($dtend =~ /T/)
|
||||
{
|
||||
my ($date, $time) = split /T/, $dtend;
|
||||
|
||||
my ($year, $month, $day) = $date =~ /(\d{4})(\d{2})(\d{2})/;
|
||||
my ($hour, $minute, $second) = $time =~ /(\d{2})(\d{2})(\d{2})/;
|
||||
|
||||
($properties->{endDate}, $properties->{endTime}) =
|
||||
split / /, WebGUI::DateTime(
|
||||
year => $year,
|
||||
month => $month,
|
||||
day => $day,
|
||||
hour => $hour,
|
||||
minute => $minute,
|
||||
second => $second,
|
||||
time_zone => "UTC",
|
||||
)->toMysql;
|
||||
}
|
||||
elsif ($dtend =~ /(\d{4})(\d{2})(\d{2})/)
|
||||
{
|
||||
my ($year, $month, $day) = $dtend =~ /(\d{4})(\d{2})(\d{2})/;
|
||||
|
||||
$properties->{endDate} = join "-",$year,$month,$day;
|
||||
}
|
||||
|
||||
|
||||
|
||||
# If there are X-WebGUI-* fields
|
||||
for my $key (grep /^X-WEBGUI-/, keys %{$events{$id}})
|
||||
{
|
||||
my $property_name = $key;
|
||||
$property_name =~ s/^X-WEBGUI-//;
|
||||
|
||||
if (lc $property_name eq "groupidedit")
|
||||
{
|
||||
$properties->{groupIdEdit} = $events{$id}->{$key}->[1];
|
||||
}
|
||||
elsif (lc $property_name eq "groupidview")
|
||||
{
|
||||
$properties->{groupIdView} = $events{$id}->{$key}->[1];
|
||||
}
|
||||
elsif (lc $property_name eq "url")
|
||||
{
|
||||
$properties->{url} = $events{$id}->{$key}->[1];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
# Update event
|
||||
my ($assetId) = $self->session->db->quickArray("select assetId from Event where feedUid=?",[$id]);
|
||||
|
||||
# If this event already exists, update
|
||||
if ($assetId)
|
||||
{
|
||||
#warn "Updating $assetId\n";
|
||||
|
||||
my $event = WebGUI::Asset->newByDynamicClass($self->session,$assetId);
|
||||
|
||||
if ($event)
|
||||
{
|
||||
$event->update($properties);
|
||||
$event->requestCommit;
|
||||
$updated++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
my $calendar = WebGUI::Asset->newByDynamicClass($self->session,$feed->{assetId});
|
||||
my $event = $calendar->addChild($properties);
|
||||
$event->requestCommit;
|
||||
$added++;
|
||||
}
|
||||
|
||||
# TODO: Only update if last-updated field is
|
||||
# greater than the event's lastUpdated property
|
||||
}
|
||||
|
||||
# Update the result and last updated fields
|
||||
$self->session->db->write("update Calendar_feeds set lastResult=?,lastUpdated=? where feedId=?",
|
||||
["Success! $added added, $updated updated",$dt,$feed->{feedId}]);
|
||||
}
|
||||
else
|
||||
{
|
||||
# Update the result and last updated fields
|
||||
$self->session->db->write("update Calendar_feeds set lastResult=?,lastUpdated=? where feedId=?",
|
||||
[$response->message,$dt,$feed->{feedId}]);
|
||||
}
|
||||
}
|
||||
|
||||
$sth->finish;
|
||||
|
||||
return $self->COMPLETE;
|
||||
}
|
||||
|
||||
|
||||
=head1 BUGS
|
||||
|
||||
We should probably be using some sort of parser for the iCalendar files. I did
|
||||
not have time to make a decent observation but the following were observed and
|
||||
rejected
|
||||
|
||||
Data::ICal - Best one I saw. Rejected because I've run out of time
|
||||
Text::vFile
|
||||
Net::ICal
|
||||
iCal::Parser - Bad data structure
|
||||
Tie::iCal
|
||||
|
||||
=cut
|
||||
|
||||
1;
|
||||
|
||||
|
||||
|
|
@ -263,6 +263,14 @@ our $I18N = {
|
|||
|
||||
|
||||
|
||||
#################### WORKFLOW ACTIVITIES ####################
|
||||
'workflow updateFeeds' => {
|
||||
message => q{Update Calendar Feeds},
|
||||
lastUpdated => 0,
|
||||
context => q{The name of the CalendarUpdateFeeds workflow activity},
|
||||
},
|
||||
|
||||
|
||||
#################### ASSET NAME ####################
|
||||
'assetName' => {
|
||||
message => q{Calendar},
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue