package WebGUI::Workflow::Activity::ExtendCalendarRecurrences; =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::International; use WebGUI::Asset; use WebGUI::VersionTag; use DateTime; =head1 NAME WebGUI::Workflow::Activity::ExtendCalendarRecurrences =head1 DESCRIPTION Generates events for all active calendar recurring events up to 2 years in the future. =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, $session, $definition ) = @_; my $i18n = WebGUI::International->new( $session, 'Activity_ExtendCalendarRecurrences' ); push( @$definition, { name => $i18n->get('topicName') } ); return $class->SUPER::definition( $session, $definition ); } #------------------------------------------------------------------- =head2 execute ( [ object ] ) See WebGUI::Workflow::Activity::execute() for details. =cut sub execute { my ( $self, $obj, $instance ) = @_; my $timeLimit = time + $self->getTTL; my $piped = $instance->getScratch('recurrences') || $self->generateRecurrenceList(); while (time < $timeLimit ) { return $self->COMPLETE unless $piped; my ( $recurId, $rest ) = split /\|/, $piped, 2; $self->processRecurrence( $recurId, $timeLimit ); $piped = $rest; } $instance->setScratch( recurrences => $piped ); return $self->WAITING(1); } ## end sub execute #------------------------------------------------------------------- =head2 findRecurrenceIds ( calendarId ) Find all recurIds for the given calendarId. =cut sub findRecurrenceIds { my ( $self, $calendarId ) = @_; my $sql = q{ SELECT r.recurId FROM Event_recur r INNER JOIN Event e ON r.recurId = e.recurId INNER JOIN asset a ON e.assetId = a.assetId WHERE a.parentId = ? }; return $self->session->db->buildArrayRef( $sql, [ $calendarId ] ); } #------------------------------------------------------------------- =head2 findCalendarIds Returns an arrayref of assetIds for all Calendar assets in the asset tree. =cut sub findCalendarIds { my $self = shift; my $root = WebGUI::Asset->getRoot( $self->session ); return $root->getLineage( ['descendants'], { includeOnlyClasses => ['WebGUI::Asset::Wobject::Calendar'] } ); } #------------------------------------------------------------------- =head2 findLastEventId ( recurId ) Returns the assetId of the most WebGUI::Asset::Event generated for the given recurrence. =cut sub findLastEventId { my ( $self, $recurId ) = @_; my $sql = q{ SELECT assetId FROM Event WHERE recurId = ? ORDER BY startDate LIMIT 1 }; return $self->session->db->quickScalar( $sql, [$recurId] ); } #------------------------------------------------------------------- =head2 generateRecurrenceList () Returns a string of pipe-seperated recurrence IDs for all the calendars in the asset tree. This is called exactly once per workflow instance. =cut sub generateRecurrenceList { my $self = shift; return join( '|', map { @{ $self->findRecurrenceIds($_) } } @{ $self->findCalendarIds } ); } #------------------------------------------------------------------- =head2 processRecurrence (recurId, timeLimit) Generates as many WebGUI::Asset::Event objects as it can before timeLimit is up or the recurrence is finished for the given recurId. Returns true if it exhausted the recurrence, false otherwise. =cut sub processRecurrence { my ( $self, $recurId, $timeLimit ) = @_; my $eventId = $self->findLastEventId($recurId); my $event = WebGUI::Asset::Event->new( $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->get('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; my $time_limit = 0; DATE: while ( my $d = $i->next ) { if ( time > $timeLimit ) { $time_limit = 1; last DATE; } $event->generateRecurrence($d); } ##If nothing needed to happen, then don't keep the tag around. if ($versionTag->getAssetCount > 0) { $versionTag->commit; } else { $versionTag->rollback; } return $time_limit ? 1 : 0; } ## end sub processRecurrence 1;