Merge commit 'v7.10.15' into 8
Conflicts: docs/gotcha.txt docs/previousVersion.sql docs/templates.txt lib/WebGUI.pm lib/WebGUI/Asset.pm lib/WebGUI/Asset/Event.pm lib/WebGUI/Asset/File.pm lib/WebGUI/Asset/MapPoint.pm lib/WebGUI/Asset/RichEdit.pm lib/WebGUI/Asset/Sku/Product.pm lib/WebGUI/Asset/Snippet.pm lib/WebGUI/Asset/Story.pm lib/WebGUI/Asset/Template.pm lib/WebGUI/Asset/Template/TemplateToolkit.pm lib/WebGUI/Asset/Wobject/Calendar.pm lib/WebGUI/Asset/Wobject/Carousel.pm lib/WebGUI/Asset/Wobject/Collaboration.pm lib/WebGUI/Asset/Wobject/Dashboard.pm lib/WebGUI/Asset/Wobject/DataForm.pm lib/WebGUI/Asset/Wobject/Folder.pm lib/WebGUI/Asset/Wobject/Map.pm lib/WebGUI/Asset/Wobject/Search.pm lib/WebGUI/Asset/Wobject/Shelf.pm lib/WebGUI/Asset/Wobject/StockData.pm lib/WebGUI/Asset/Wobject/StoryTopic.pm lib/WebGUI/Asset/Wobject/SyndicatedContent.pm lib/WebGUI/Asset/Wobject/Thingy.pm lib/WebGUI/Asset/Wobject/WeatherData.pm lib/WebGUI/AssetClipboard.pm lib/WebGUI/AssetCollateral/DataForm/Entry.pm lib/WebGUI/AssetExportHtml.pm lib/WebGUI/AssetLineage.pm lib/WebGUI/AssetMetaData.pm lib/WebGUI/AssetTrash.pm lib/WebGUI/AssetVersioning.pm lib/WebGUI/Auth.pm lib/WebGUI/Cache/CHI.pm lib/WebGUI/Content/AssetManager.pm lib/WebGUI/Fork/ProgressBar.pm lib/WebGUI/Form/JsonTable.pm lib/WebGUI/Form/TimeField.pm lib/WebGUI/Form/Zipcode.pm lib/WebGUI/Group.pm lib/WebGUI/International.pm lib/WebGUI/Macro/AssetProxy.pm lib/WebGUI/Macro/FileUrl.pm lib/WebGUI/Operation/SSO.pm lib/WebGUI/Operation/User.pm lib/WebGUI/Role/Asset/Subscribable.pm lib/WebGUI/Shop/Cart.pm lib/WebGUI/Shop/Transaction.pm lib/WebGUI/Shop/TransactionItem.pm lib/WebGUI/Test.pm lib/WebGUI/URL/Content.pm lib/WebGUI/URL/Uploads.pm lib/WebGUI/User.pm lib/WebGUI/Workflow/Activity/ExtendCalendarRecurrences.pm lib/WebGUI/Workflow/Activity/SendNewsletters.pm lib/WebGUI/i18n/English/Asset.pm lib/WebGUI/i18n/English/WebGUI.pm sbin/installClass.pl sbin/rebuildLineage.pl sbin/search.pl sbin/testEnvironment.pl t/Asset/Asset.t t/Asset/AssetClipboard.t t/Asset/AssetLineage.t t/Asset/AssetMetaData.t t/Asset/Event.t t/Asset/File.t t/Asset/File/Image.t t/Asset/Post/notification.t t/Asset/Sku.t t/Asset/Story.t t/Asset/Template.t t/Asset/Wobject/Collaboration/templateVariables.t t/Asset/Wobject/Collaboration/unarchiveAll.t t/Asset/Wobject/Shelf.t t/Auth.t t/Macro/EditableToggle.t t/Macro/FilePump.t t/Shop/Cart.t t/Shop/Transaction.t t/Storage.t t/User.t t/Workflow.t
This commit is contained in:
commit
277faae8a1
783 changed files with 32041 additions and 25495 deletions
|
|
@ -23,6 +23,7 @@ use WebGUI::Asset::Event;
|
|||
use WebGUI::DateTime;
|
||||
use DateTime::TimeZone;
|
||||
use Data::Dumper;
|
||||
use Data::ICal;
|
||||
|
||||
use LWP::UserAgent;
|
||||
use JSON ();
|
||||
|
|
@ -124,10 +125,6 @@ sub execute {
|
|||
$session->db->write("REPLACE INTO userSessionScratch (sessionId,name,value) VALUES (?,?,?)",
|
||||
[$session->getId,$calendar->getId,"SPECTRE"]);
|
||||
}
|
||||
#/KLUDGE
|
||||
|
||||
## Somebody point me to a DECENT iCalendar parser...
|
||||
# Text::vFile perhaps?
|
||||
|
||||
# Get the feed
|
||||
$session->log->info( "Trying Calendar feed ".$feed->{url}." for $calendarTitle" );
|
||||
|
|
@ -142,88 +139,52 @@ sub execute {
|
|||
next FEED;
|
||||
}
|
||||
|
||||
my $data = $response->content;
|
||||
# If doesn't start with BEGIN:VCALENDAR then error
|
||||
unless ($data =~ /^BEGIN:VCALENDAR/i) {
|
||||
my $data = $response->content;
|
||||
my $cal = Data::ICal->new( data => $data );
|
||||
if (!$cal) {
|
||||
# Update the result and last updated fields
|
||||
$feed->{lastResult} = "Not an iCalendar feed";
|
||||
$feed->{lastResult} = "Error parsing iCal feed";
|
||||
$feed->{lastUpdated} = $dt;
|
||||
$calendar->setFeed($feed->{feedId}, $feed);
|
||||
next FEED;
|
||||
#next FEED;
|
||||
}
|
||||
|
||||
my $active = 0; # Parser on/off
|
||||
my %current_event = ();
|
||||
my %events;
|
||||
my $line_number = 0;
|
||||
$data =~ s/[ \t]?[\r\n]+[ \t]+/ /msg; #Process line continuations
|
||||
LINE: 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;
|
||||
next LINE;
|
||||
}
|
||||
elsif ($line =~ /^END:VEVENT$/i) {
|
||||
$active = 0;
|
||||
# Flush event
|
||||
my $uid = lc $current_event{uid}[1];
|
||||
delete $current_event{uid};
|
||||
$events{$uid} = {%current_event};
|
||||
$session->log->info( "Found event $uid from feed " . $feed->{feedId} );
|
||||
%current_event = ();
|
||||
next LINE;
|
||||
}
|
||||
else {
|
||||
# Flush old entry
|
||||
# KEY;ATTRIBUTE=VALUE;ATTRIBUTE=VALUE:KEYVALUE
|
||||
my ($key_attrs,$value) = split /:/,$line,2;
|
||||
my @attrs = $key_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;
|
||||
}
|
||||
|
||||
$current_event{lc $key} = [\%attrs,$value];
|
||||
}
|
||||
}
|
||||
|
||||
my $feedData = $feedList->{$feed->{feedId}} = {
|
||||
added => 0,
|
||||
updated => 0,
|
||||
errored => 0,
|
||||
assetId => $calendar->getId,
|
||||
};
|
||||
EVENT: for my $id (keys %events) {
|
||||
EVENT: foreach my $entry (@{ $cal->entries }) {
|
||||
next EVENT unless $entry->ical_entry_type eq 'VEVENT';
|
||||
#use Data::Dumper;
|
||||
#warn "EVENT: $id; ".Dumper $events{$id};
|
||||
my $event_properties = $entry->properties;
|
||||
|
||||
# Prepare event data
|
||||
my $properties = {
|
||||
feedUid => $id,
|
||||
feedId => $feed->{feedId},
|
||||
description => _unwrapIcalText($events{$id}->{description}->[1]),
|
||||
title => _unwrapIcalText($events{$id}->{summary}->[1]),
|
||||
location => _unwrapIcalText($events{$id}->{location}->[1]),
|
||||
menuTitle => substr($events{$id}->{summary}->[1],0,15),
|
||||
className => 'WebGUI::Asset::Event',
|
||||
isHidden => 1,
|
||||
};
|
||||
PROPERTY: foreach my $property (qw/uid description summary location/) {
|
||||
next PROPERTY unless exists $event_properties->{$property};
|
||||
$properties->{$property} = $event_properties->{$property}->[0]->value;
|
||||
}
|
||||
##Fixup
|
||||
$properties->{title} = delete $properties->{summary};
|
||||
$properties->{feedUid} = delete $properties->{uid};
|
||||
|
||||
# Prepare the date
|
||||
my $dtstart = $events{$id}->{dtstart}->[1];
|
||||
my $dtstart = $event_properties->{dtstart}->[0]->value;
|
||||
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})/;
|
||||
my $tz = $events{$id}->{dtstart}->[0]->{tzid};
|
||||
my $tz = '';
|
||||
if ($event_properties->{dtstart}->[0]->{tzid}) {
|
||||
$tz = $event_properties->{dtstart}->[0]->{tzid};
|
||||
}
|
||||
if (!$tz || !DateTime::TimeZone->is_valid_name($tz)) {
|
||||
$tz = "UTC";
|
||||
}
|
||||
|
|
@ -253,14 +214,14 @@ sub execute {
|
|||
next EVENT;
|
||||
}
|
||||
|
||||
my $dtend = $events{$id}->{dtend}->[1];
|
||||
my $duration = $events{$id}->{duration}->[1];
|
||||
my $dtend = exists $event_properties->{dtend} ? $event_properties->{dtend}->[0]->value : undef;
|
||||
my $duration = exists $event_properties->{duration} ? $event_properties->{duration}->[0]->value : undef;
|
||||
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})/;
|
||||
my $tz = $events{$id}->{dtend}->[0]->{tzid};
|
||||
my $tz = '';
|
||||
if (!$tz || !DateTime::TimeZone->is_valid_name($tz)) {
|
||||
$tz = "UTC";
|
||||
}
|
||||
|
|
@ -330,28 +291,15 @@ sub execute {
|
|||
}
|
||||
|
||||
# If there are X-WebGUI-* fields
|
||||
for my $key (grep /^x-webgui-/, keys %{$events{$id}}) {
|
||||
my $property_name = $key;
|
||||
$property_name =~ s/^x-webgui-//;
|
||||
$property_name = lc $property_name;
|
||||
|
||||
if ($property_name eq "groupidedit") {
|
||||
$properties->{groupIdEdit} = $events{$id}->{$key}->[1];
|
||||
}
|
||||
elsif ($property_name eq "groupidview") {
|
||||
$properties->{groupIdView} = $events{$id}->{$key}->[1];
|
||||
}
|
||||
elsif ($property_name eq "url") {
|
||||
$properties->{url} = $events{$id}->{$key}->[1];
|
||||
}
|
||||
elsif ($property_name eq "menutitle") {
|
||||
$properties->{menuTitle} = $events{$id}->{$key}->[1];
|
||||
}
|
||||
PROPERTY: foreach my $key (qw/groupIdEdit groupIdView url menuTitle timeZone/) {
|
||||
my $property_name = 'x-webgui-'.lc $key;
|
||||
next PROPERTY unless exists $event_properties->{$property_name};
|
||||
$properties->{$key} = $event_properties->{$property_name}->[0]->value;
|
||||
}
|
||||
|
||||
my $recur;
|
||||
if ($events{$id}->{rrule}) {
|
||||
$recur = _icalToRecur($session, $properties->{startDate}, $events{$id}->{rrule}->[1]);
|
||||
if (exists $event_properties->{rrule}) {
|
||||
$recur = _icalToRecur($session, $properties->{startDate}, $event_properties->{rrule}->[0]->value);
|
||||
}
|
||||
|
||||
# save events for later
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ use strict;
|
|||
use base 'WebGUI::Workflow::Activity';
|
||||
use WebGUI::International;
|
||||
use WebGUI::Asset;
|
||||
use WebGUI::VersionTag;
|
||||
use DateTime;
|
||||
|
||||
=head1 NAME
|
||||
|
|
@ -74,8 +75,8 @@ sub execute {
|
|||
return $self->COMPLETE unless $piped;
|
||||
my ( $recurId, $rest ) = split /\|/, $piped, 2;
|
||||
|
||||
$self->processRecurrence( $recurId, $timeLimit )
|
||||
and $piped = $rest;
|
||||
$self->processRecurrence( $recurId, $timeLimit );
|
||||
$piped = $rest;
|
||||
}
|
||||
|
||||
$instance->setScratch( recurrences => $piped );
|
||||
|
|
@ -165,20 +166,36 @@ sub processRecurrence {
|
|||
my ( $self, $recurId, $timeLimit ) = @_;
|
||||
my $eventId = $self->findLastEventId($recurId);
|
||||
my $event = WebGUI::Asset::Event->newById( $self->session, $eventId );
|
||||
if (! $event) {
|
||||
$self->session->log->warn("Unable to instanciate event with assetId $eventId");
|
||||
return 0;
|
||||
}
|
||||
##Ignore assets in the trash. Same with assets in the clipboard since they would not be
|
||||
##put into the clipboard.
|
||||
if ($event->state ne 'published') {
|
||||
return 0;
|
||||
}
|
||||
my $recur = $event->getRecurrence;
|
||||
|
||||
my $versionTag = WebGUI::VersionTag->create($self->session, {name => 'Extend Calendar Recurrence for assetId '.$event->getId, });
|
||||
$versionTag->setWorking();
|
||||
my $start = $event->getDateTimeStart->truncate(to => 'day');
|
||||
my $limit = DateTime->today->add( years => 2 );
|
||||
my $end = $event->limitedEndDate($limit);
|
||||
my $set = $event->dateSet( $recur, $start, $end );
|
||||
my $i = $set->iterator;
|
||||
|
||||
while ( my $d = $i->next ) {
|
||||
return if ( time > $timeLimit );
|
||||
my $time_limit = 0;
|
||||
DATE: while ( my $d = $i->next ) {
|
||||
if ( time > $timeLimit ) {
|
||||
$time_limit = 1;
|
||||
last DATE;
|
||||
}
|
||||
$event->generateRecurrence($d);
|
||||
}
|
||||
|
||||
return 1;
|
||||
$versionTag->commit;
|
||||
return $time_limit ? 1 : 0;
|
||||
} ## end sub processRecurrence
|
||||
|
||||
1;
|
||||
|
|
|
|||
|
|
@ -108,7 +108,7 @@ sub execute {
|
|||
comments => $versionTag->get('comments'),
|
||||
url => $urlOfSingleAsset,
|
||||
};
|
||||
my $template = WebGUI::Asset->newByDynamicClass($self->session, $self->get('templateId'));
|
||||
my $template = WebGUI::Asset->newById($self->session, $self->get('templateId'));
|
||||
my $message = $template->process($var);
|
||||
my $properties = {
|
||||
status=>"completed",
|
||||
|
|
|
|||
|
|
@ -295,7 +295,7 @@ sub sendMessage {
|
|||
comments => $versionTag->get('comments'),
|
||||
url => $approvalUrl,
|
||||
};
|
||||
my $template = WebGUI::Asset->newByDynamicClass($self->session, $self->get('templateId'));
|
||||
my $template = WebGUI::Asset->newById($self->session, $self->get('templateId'));
|
||||
my $messageText = $template->process($var);
|
||||
for my $groupId ( @{ $self->getGroupToApprove } ) {
|
||||
my $message
|
||||
|
|
|
|||
|
|
@ -99,9 +99,20 @@ sub execute {
|
|||
$log->info("Found subscription $subscription");
|
||||
my ($fieldId, $value) = split("~", $subscription);
|
||||
$log->info("Searching for threads that match $subscription");
|
||||
my $matchingThreads = $db->read("select metaData_values.assetId from metaData_values
|
||||
left join asset using (assetId) where fieldId=? and value like ? and creationDate > ?
|
||||
and className like ? and lineage like ? and state = ?",
|
||||
my $matchingThreads = $db->read("
|
||||
select mv.assetId
|
||||
from metaData_values mv
|
||||
left join asset a using (assetId)
|
||||
left join assetData d on
|
||||
mv.assetId = d.assetId
|
||||
and mv.revisionDate = d.revisionDate
|
||||
and d.revisionDate = (
|
||||
select max(revisionDate)
|
||||
from assetData d2
|
||||
where d2.assetId = d.assetId
|
||||
)
|
||||
where mv.fieldId=? and mv.value like ? and a.creationDate > ?
|
||||
and a.className like ? and a.lineage like ? and a.state = ?",
|
||||
[$fieldId, '%'.$value.'%', $lastTimeSent, 'WebGUI::Asset::Post::Thread%', $newsletter->get("lineage").'%', 'published']);
|
||||
while (my ($threadId) = $matchingThreads->array) {
|
||||
next
|
||||
|
|
|
|||
100
lib/WebGUI/Workflow/Activity/UpdateAssetSubscribers.pm
Normal file
100
lib/WebGUI/Workflow/Activity/UpdateAssetSubscribers.pm
Normal file
|
|
@ -0,0 +1,100 @@
|
|||
package WebGUI::Workflow::Activity::UpdateAssetSubscribers;
|
||||
|
||||
|
||||
=head1 LEGAL
|
||||
|
||||
-------------------------------------------------------------------
|
||||
WebGUI is Copyright 2001-2009 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 base 'WebGUI::Workflow::Activity';
|
||||
use WebGUI::User;
|
||||
use WebGUI::Group;
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Package WebGUI::Workflow::Activity::UpdateCollaborationSubscribers
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
This workflow activity should be called whenever permissions to view a Collaboration System
|
||||
are changed. It will remove users who are no longer able to view the CS.
|
||||
|
||||
=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::definition() for details.
|
||||
|
||||
=cut
|
||||
|
||||
sub definition {
|
||||
my $class = shift;
|
||||
my $session = shift;
|
||||
my $definition = shift;
|
||||
my $i18n = WebGUI::International->new($session, "Workflow_Activity_UpdateAssetSubscribers");
|
||||
push(@{$definition}, {
|
||||
name => $i18n->get("name"),
|
||||
properties => { }
|
||||
});
|
||||
return $class->SUPER::definition($session,$definition);
|
||||
}
|
||||
|
||||
|
||||
#-------------------------------------------------------------------
|
||||
|
||||
=head2 execute ( )
|
||||
|
||||
See WebGUI::Workflow::Activity::execute() for details.
|
||||
|
||||
=cut
|
||||
|
||||
sub execute {
|
||||
my $self = shift;
|
||||
my $asset = shift;
|
||||
|
||||
return unless $asset->get('subscriptionGroupId');
|
||||
|
||||
my $expireTime = time() + $self->getTTL();
|
||||
my $subscriptionGroup = WebGUI::Group->new($self->session, $asset->get('subscriptionGroupId'));
|
||||
|
||||
##Deserialize from scratch
|
||||
my @users = @{ $subscriptionGroup->getUsers }; ##Cache
|
||||
my @usersToDelete = (); ##Cache
|
||||
##Note, we could use grep here, but we can't interrupt if the workflow runs too long
|
||||
USER: foreach my $userId (@users) {
|
||||
if (time() > $expireTime) {
|
||||
#return $self->WAITING(1);
|
||||
}
|
||||
next USER if $asset->canView($userId);
|
||||
push @usersToDelete, $userId;
|
||||
}
|
||||
if (@usersToDelete) {
|
||||
$subscriptionGroup->deleteUsers(\@usersToDelete);
|
||||
}
|
||||
#Clear scratch
|
||||
return $self->COMPLETE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
1;
|
||||
|
|
@ -53,9 +53,10 @@ is singleton and an instance of it already exists.
|
|||
A reference to the current session.
|
||||
|
||||
=head3 properties
|
||||
|
||||
The settable properties of the workflow instance. See the set() method for details.
|
||||
|
||||
A key/value for C<workflowId> is required in the properties for this method.
|
||||
|
||||
=cut
|
||||
|
||||
sub create {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue