diff --git a/docs/changelog/7.x.x.txt b/docs/changelog/7.x.x.txt index 50fa1b368..ba117cf69 100644 --- a/docs/changelog/7.x.x.txt +++ b/docs/changelog/7.x.x.txt @@ -60,6 +60,10 @@ - fixed: Thingy: Problem with add_url tmpl_var permissions - fixed: WeatherData asset is broken - fixed: Calendar multi-day events exported wrong in ical feed + - add: Move revisions from one version tag to another + - add: Delete multiple revisions from a version tag at the same time + - add: Approval activities now have a better parent class and more + flexibility (multiple groups to approve, do on approve) 7.5.10 - fix: Syntax error in GetCsMail diff --git a/docs/upgrades/upgrade_7.5.10-7.5.11.pl b/docs/upgrades/upgrade_7.5.10-7.5.11.pl index fe21a1986..a224a984e 100644 --- a/docs/upgrades/upgrade_7.5.10-7.5.11.pl +++ b/docs/upgrades/upgrade_7.5.10-7.5.11.pl @@ -201,6 +201,13 @@ sub addPurgeOldInboxActivity { my $session = shift; print "\tAdding Purge Old Inbox Messages workflow activity... " unless $quiet; + my $activity = $session->config->get( "workflowActivities" ); + push @{ $activity->{"None"} }, 'WebGUI::Workflow::Activity::PurgeOldInboxMessages'; + $session->config->set( "workflowActivities", $activity ); + + print "DONE!\n" unless $quiet; +} + #------------------------------------------------- sub addingInStoreCredit { my $session = shift; @@ -215,13 +222,6 @@ sub addingInStoreCredit { )"); } - my $activity = $session->config->get( "workflowActivities" ); - push @{ $activity->{"None"} }, 'WebGUI::Workflow::Activity::PurgeOldInboxMessages'; - $session->config->set( "workflowActivities", $activity ); - - print "DONE!\n" unless $quiet; -} - #------------------------------------------------- sub upgradeEMS { my $session = shift; diff --git a/lib/WebGUI/Asset/Wobject/GalleryAlbum.pm b/lib/WebGUI/Asset/Wobject/GalleryAlbum.pm index 3159378cd..a4b462c84 100644 --- a/lib/WebGUI/Asset/Wobject/GalleryAlbum.pm +++ b/lib/WebGUI/Asset/Wobject/GalleryAlbum.pm @@ -448,7 +448,8 @@ return undef. sub getThumbnailUrl { my $self = shift; my $asset = undef; - + + # Try to get the asset if ( $self->get("assetIdThumbnail") ) { $asset = WebGUI::Asset->newByDynamicClass( $self->session, $self->get("assetIdThumbnail") ); } @@ -459,6 +460,13 @@ sub getThumbnailUrl { return undef; } + # It is possible to get here and still not have an asset in cases of + # "pending" assets, so just return + if ( !$asset ) { + return undef; + } + + # Get the URL for the asset's thumbnail if ( $asset->can("getThumbnailUrl") ) { return $asset->getThumbnailUrl; } diff --git a/lib/WebGUI/AssetVersioning.pm b/lib/WebGUI/AssetVersioning.pm index b692cf660..4a22dbe79 100644 --- a/lib/WebGUI/AssetVersioning.pm +++ b/lib/WebGUI/AssetVersioning.pm @@ -92,11 +92,17 @@ sub addRevision { my $autoCommitId = $self->getAutoCommitWorkflowId() unless ($options->{skipAutoCommitWorkflows}); - my $workingTag - = ($autoCommitId) - ? WebGUI::VersionTag->create($self->session, {groupToUse=>'12', workflowId=>$autoCommitId}) - : WebGUI::VersionTag->getWorking($self->session) - ; + my $workingTag; + if ( $autoCommitId ) { + $workingTag + = WebGUI::VersionTag->create( $self->session, { + groupToUse => '12', # Turn Admin On (for lack of something better) + workflowId => $autoCommitId, + } ); + } + else { + $workingTag = WebGUI::VersionTag->getWorking($self->session); + } #Create a dummy revision to be updated with real data later $self->session->db->beginTransaction; diff --git a/lib/WebGUI/Form/Workflow.pm b/lib/WebGUI/Form/Workflow.pm index 085d7d5c7..fa50987db 100644 --- a/lib/WebGUI/Form/Workflow.pm +++ b/lib/WebGUI/Form/Workflow.pm @@ -100,6 +100,9 @@ sub definition { none=>{ defaulValue=>0 }, + noneLabel => { + defaultValue => $i18n->get("form control none label"), + }, includeRealtime => { defaultValue => 0 }, @@ -153,11 +156,16 @@ Renders a template picker control. =cut sub toHtml { - my $self = shift; - my $workflowList = WebGUI::Workflow->getList($self->session, $self->get("type"), $self->get("includeRealtime")); - $workflowList->{""} = "None" if ($self->get("none")); - $self->set("options", $workflowList); - return $self->SUPER::toHtml(); + my $self = shift; + my $workflowList = WebGUI::Workflow->getList($self->session, $self->get("type"), $self->get("includeRealtime")); + + if ( $self->get("none") ) { + my $noneLabel = $self->get("noneLabel"); + $workflowList->{""} = $noneLabel; + } + + $self->set("options", $workflowList); + return $self->SUPER::toHtml(); } #------------------------------------------------------------------- @@ -169,13 +177,13 @@ Renders the form field to HTML as a table row complete with labels, subtext, hov =cut sub toHtmlWithWrapper { - my $self = shift; - my $returnUrl = ";proceed=goBackToPage;returnUrl=".$self->session->url->escape($self->session->asset->getUrl) if $self->session->asset; - my $buttons; - # This edit button will not work with multiple workflows. - $buttons .= $self->session->icon->manage("op=manageWorkflows".$returnUrl); - $self->set("subtext",$buttons . $self->get("subtext")); - return $self->SUPER::toHtmlWithWrapper; + my $self = shift; + my $returnUrl = ";proceed=goBackToPage;returnUrl=".$self->session->url->escape($self->session->asset->getUrl) if $self->session->asset; + my $buttons; + # This edit button will not work with multiple workflows. + $buttons .= $self->session->icon->manage("op=manageWorkflows".$returnUrl); + $self->set("subtext",$buttons . $self->get("subtext")); + return $self->SUPER::toHtmlWithWrapper; } diff --git a/lib/WebGUI/Operation/VersionTag.pm b/lib/WebGUI/Operation/VersionTag.pm index a19431324..81636e0be 100644 --- a/lib/WebGUI/Operation/VersionTag.pm +++ b/lib/WebGUI/Operation/VersionTag.pm @@ -43,6 +43,67 @@ These methods are available from this class: #---------------------------------------------------------------------------- +=head2 canApproveVersionTag ( session, tag [, user] ) + +Returns true if the user is allowed to approve this version tag. C +is a WebGUI::Session, C is a WebGUI::VersionTag, C is a +WebGUI::User. If C is not specified, users the default user from the +session. + +A user is allowed to approve a version tag if they are in the current +C. If this version tag does not currently need approval, +this returns false. + +=cut + +sub canApproveVersionTag { + my $session = shift; + my $tag = shift; + my $user = shift || $session->user; + my $instance = $tag->getWorkflowInstance; + my $activity = $instance->getNextActivity; + + # Check if this person is in one of the allowed groups + my $groupToApprove = $activity->can( 'getGroupToApprove' ) + # New way returns an array reference + ? $activity->getGroupToApprove( $tag, $instance ) + # Old way has a single group + : [ $activity->get( 'groupToApprove' ) ] + ; + + return 1 + if grep { $user->isInGroup( $_ ) } @{ $groupToApprove }; +} + +#---------------------------------------------------------------------------- + +=head2 canViewVersionTag ( session, tag [, user] ) + +Returns true if the user is allowed to view this version tag. C +is a WebGUI::Session, C is a WebGUI::VersionTag, C is a +WebGUI::User. If C is not specified, uses the default user from the +session. + +A user is allowed to view a version tag if they are in the groupToUse +of the version tag, or if they canView. + +=cut + +sub canViewVersionTag { + my $session = shift; + my $tag = shift; + my $user = shift || $session->user; + + if ( $user->isInGroup( $tag->get("groupToUse") ) ) { + return 1; + } + else { + return canView( $session, $user ); + } +} + +#---------------------------------------------------------------------------- + =head2 canView ( session [, user] ) Returns true if the user can administrate this operation. user defaults to @@ -56,9 +117,28 @@ sub canView { return $user->isInGroup( $session->setting->get("groupIdAdminVersionTag") ); } +#---------------------------------------------------------------------------- + +=head2 getVersionTagOptions ( session ) + +Gets a hash of tagId => name for all open version tags + +=cut + +sub getVersionTagOptions { + my $session = shift; + tie my %tag, 'Tie::IxHash'; + + for my $tag ( @{ WebGUI::VersionTag->getOpenTags( $session ) } ) { + $tag{ $tag->getId } = $tag->get('name'); + } + + return %tag; +} + #------------------------------------------------------------------- -=head2 www_editVersionTag ( session ) +=head2 www_approveVersionTag ( session ) Sets an approval for a version tag. @@ -69,18 +149,24 @@ A reference to the current session. =cut sub www_approveVersionTag { - my $session = shift; - my $tag = WebGUI::VersionTag->new($session, $session->form->param("tagId")); - my $instance = $tag->getWorkflowInstance; - my $activity = $instance->getNextActivity; - return $session->privilege->insufficient() unless ($session->user->isInGroup($activity->get("groupToApprove"))); - if ($session->form->process("status", "selectBox") eq "approve") { - $activity->setApproved($instance); - } else { - $activity->setDenied($instance); - } - $tag->set({comments=>$session->form->process("comments", "textarea")}); - return www_manageVersions($session); + my $session = shift; + my $tag = WebGUI::VersionTag->new( $session, $session->form->param("tagId") ); + + return $session->privilege->insufficient + unless canApproveVersionTag( $session, $tag ); + + if ( $session->form->process("status", "selectBox") eq "approve" ) { + $activity->setApproved( $instance ); + } + else { + $activity->setDenied( $instance ); + } + + $tag->set( { + comments => $session->form->process("comments", "textarea"), + }); + + return www_manageVersions($session); } #------------------------------------------------------------------- @@ -476,6 +562,9 @@ sub www_manageVersions { Displays a list of the revsions associated with this tag. +Optionally performs an action related to the revisions in this version +tag, such as purging or moving to another version tag. + =head3 session A reference to the current session. @@ -483,75 +572,165 @@ A reference to the current session. =cut sub www_manageRevisionsInTag { - my $session = shift; - my $tagId = $session->form->get("tagId"); - my $tag = WebGUI::VersionTag->new($session, $tagId); - return www_manageVersions($session) unless (defined $tag); - return $session->privilege->insufficient() unless ($session->user->isInGroup($tag->get("groupToUse"))); - my $ac = WebGUI::AdminConsole->new($session,"versions"); - my $i18n = WebGUI::International->new($session,"VersionTag"); - $ac->addSubmenuItem($session->url->page('op=editVersionTag'), $i18n->get("add a version tag")); - $ac->addSubmenuItem($session->url->page('op=manageCommittedVersions'), $i18n->get("manage committed versions")) if canView($session); - $ac->addSubmenuItem($session->url->page('op=manageVersions'), $i18n->get("manage versions")); - my $output = ""; - if ($session->form->param("workflowInstanceId")) { - my $instance = WebGUI::Workflow::Instance->new($session, $session->form->param("workflowInstanceId")); - if (defined $instance) { - my $form = WebGUI::HTMLForm->new($session); - $form->submit; - $form->hidden( - name=>"tagId", - value=>$tagId - ); - $form->hidden( - name=>"op", - value=>"approveVersionTag" - ); - $form->selectBox( - name=>"status", - defaultValue=>"approve", - label=>$i18n->get("approve/deny"), - hoverHelp=>$i18n->get("approve/deny help"), - options=>{ - approve=>$i18n->get("approve"), - deny=>$i18n->get("deny") - }, - ); - $form->textarea( - name=>"comments", - label=>$i18n->get("comments"), - hoverHelp=>$i18n->get("comments help") - ); - $form->submit; - $output .= $form->print; - } - } - if ($tag->get("comments")) { - my $comments = $tag->get("comments"); - $comments =~ s/\n/
/g; - $output .= $comments; - } - $output .= ' - '; - my $p = WebGUI::Paginator->new($session,$session->url->page("op=manageRevisionsInTag;tagId=".$tag->getId)); - $p->setDataByQuery("select assetData.revisionDate, users.username, asset.assetId, asset.className from assetData - left join asset on assetData.assetId=asset.assetId left join users on assetData.revisedBy=users.userId - where assetData.tagId=?",undef, undef, [$tag->getId]); - foreach my $row (@{$p->getPageData}) { - my ($date,$by,$id, $class) = ($row->{revisionDate}, $row->{username}, $row->{assetId}, $row->{className}); - my $asset = WebGUI::Asset->new($session,$id,$class,$date); - $output .= ' - - - - '; + my $session = shift; + my $tagId = $session->form->get("tagId"); + my $tag = WebGUI::VersionTag->new($session, $tagId); + return www_manageVersions( $session ) unless $tag; + + ### Permissions check + # This screen is also used to approve/deny the tag, so check that first + if ( !canApproveVersionTag( $session, $tag ) && !canViewVersionTag( $session, $tag ) { + return $session->privilege->insufficient; + } + + my $ac = WebGUI::AdminConsole->new($session,"versions"); + my $i18n = WebGUI::International->new($session,"VersionTag"); + $ac->addSubmenuItem($session->url->page('op=editVersionTag'), $i18n->get("add a version tag")); + $ac->addSubmenuItem($session->url->page('op=manageCommittedVersions'), $i18n->get("manage committed versions")) if canView($session); + $ac->addSubmenuItem($session->url->page('op=manageVersions'), $i18n->get("manage versions")); + + # Process any actions + if ( $session->form->get('action') eq "purge" ) { + # Purge these revisions + my @assetInfo = $session->form->get('assetInfo'); + for my $assetInfo ( @assetInfo ) { + ( my $assetId, my $revisionDate ) = split ":", $assetInfo; + my $asset = WebGUI::Asset->new( $session, $assetId, undef, $revisionDate ); + $asset->purgeRevision; } - $output .= '
'.$i18n->get(99,"Asset").''.$i18n->get("type","Asset").''.$i18n->get("revision date","Asset").''.$i18n->get("revised by","Asset").'
' - .$session->icon->delete("func=purgeRevision;proceed=manageRevisionsInTag;tagId=".$tag->getId.";revisionDate=".$date,$asset->get("url"),$i18n->get("purge revision prompt")) - .$session->icon->view("func=view;revision=".$date, $asset->get("url")) - .''.$asset->getTitle.''.$asset->getName.''.$asset->getName.''.$session->datetime->epochToHuman($date).''.$by.'
'.$p->getBarSimple; - $tag = $session->db->getRow("assetVersionTag","tagId",$tag->getId); - return $ac->render($output,$i18n->get("revisions in tag").": ".$tag->{name}); + + # If no revisions remain, delete the version tag + if ( $tag->getRevisionCount <= 0 ) { + $tag->delete; + return www_manageVersions( $session ); + } + } + elsif ( $session->form->get('action') eq "move" ) { + # Get the new version tag + my $moveToTagId = $session->form->get('moveToTagId'); + my $moveToTag; + if ( $moveToTagId eq "new" ) { + # Create a copy of the old version tag + $moveToTag = WebGUI::VersionTag->create( $session, $tag->get ); + # But update the name + $moveToTag->set( { "name" => $tag->get('name') . ' ( copy )' } ); + } + else { + $moveToTag = WebGUI::VersionTag->new( $session, $moveToTagId ); + } + + # Move these revisions + my @assetInfo = $session->form->get('assetInfo'); + for my $assetInfo ( @assetInfo ) { + ( my $assetId, my $revisionDate ) = split ":", $assetInfo; + my $asset = WebGUI::Asset->new( $session, $assetId, undef, $revisionDate ); + $asset->setVersionTag( $moveToTag->getId ); + } + + # If no revisions remain, delete the version tag + if ( $tag->getRevisionCount <= 0 ) { + $tag->delete; + return www_manageVersions( $session ); + } + } + + my $output = ""; + # FIXME: Do we really need the workflowInstanceId? It's a property of the VersionTag... + # Then we wouldn't need to click the inbox message, if we used canApproveVersionTag we'd only + # need to have permission to approve in order to see the right form. + if ($session->form->param("workflowInstanceId")) { + my $instance = WebGUI::Workflow::Instance->new($session, $session->form->param("workflowInstanceId")); + if (defined $instance) { + my $form = WebGUI::HTMLForm->new($session); + $form->submit; + $form->hidden( + name=>"tagId", + value=>$tagId + ); + $form->hidden( + name=>"op", + value=>"approveVersionTag" + ); + $form->selectBox( + name=>"status", + defaultValue=>"approve", + label=>$i18n->get("approve/deny"), + hoverHelp=>$i18n->get("approve/deny help"), + options=>{ + approve=>$i18n->get("approve"), + deny=>$i18n->get("deny") + }, + ); + $form->textarea( + name=>"comments", + label=>$i18n->get("comments"), + hoverHelp=>$i18n->get("comments help") + ); + $form->submit; + $output .= $form->print; + } + } + if ($tag->get("comments")) { + my $comments = $tag->get("comments"); + $comments =~ s/\n/
/g; + $output .= $comments; + } + + # The options for tags to move to + tie my %moveToTagOptions, 'Tie::IxHash', ( + "new" => $i18n->get( "manageRevisionsInTag moveTo new" ), + ( getVersionTagOptions( $session ) ), + ); + + # Output the revisions + $output + .= WebGUI::Form::formHeader( $session, {} ) + . WebGUI::Form::hidden( $session, { name => 'op', value=> 'manageRevisionsInTag' } ) + . WebGUI::Form::hidden( $session, { name => 'tagId', value => $tag->getId } ) + . '' + . '' + . '' + . '' + . '' + . '' + . '' + . '' + . '' + . '' + . ' ' + ; + my $p = WebGUI::Paginator->new($session,$session->url->page("op=manageRevisionsInTag;tagId=".$tag->getId)); + $p->setDataByQuery("select assetData.revisionDate, users.username, asset.assetId, asset.className from assetData + left join asset on assetData.assetId=asset.assetId left join users on assetData.revisedBy=users.userId + where assetData.tagId=?",undef, undef, [$tag->getId]); + foreach my $row (@{$p->getPageData}) { + my ($date,$by,$id, $class) = ($row->{revisionDate}, $row->{username}, $row->{assetId}, $row->{className}); + my $asset = WebGUI::Asset->new($session,$id,$class,$date); + # A checkbox for delete and move actions + my $checkbox = WebGUI::Form::checkbox( $session, { + name => 'assetInfo', + value => join( ":", $id, $date ), + }); + $output .= ' + + + + '; + } + $output .= '
' + . $i18n->get("manageRevisionsInTag with selected") + . '' + . '' + . WebGUI::Form::SelectBox( $session, { + name => 'moveToTagId', + options => \%moveToTagOptions, + } ) + . '
'.$i18n->get(99,"Asset").''.$i18n->get("type","Asset").''.$i18n->get("revision date","Asset").''.$i18n->get("revised by","Asset").'
' + . $checkbox + .$session->icon->view("func=view;revision=".$date, $asset->get("url")) + .''.$asset->getTitle.''.$asset->getName.''.$asset->getName.''.$session->datetime->epochToHuman($date).''.$by.'
'.$p->getBarSimple.WebGUI::Form::formFooter( $session ); + $tag = $session->db->getRow("assetVersionTag","tagId",$tag->getId); + return $ac->render($output,$i18n->get("revisions in tag").": ".$tag->{name}); } diff --git a/lib/WebGUI/VersionTag.pm b/lib/WebGUI/VersionTag.pm index be239fe3d..51fe48a6a 100644 --- a/lib/WebGUI/VersionTag.pm +++ b/lib/WebGUI/VersionTag.pm @@ -125,9 +125,12 @@ sub commit { #------------------------------------------------------------------- -=head2 get ( name ) +=head2 get ( [ name ] ) -Returns the value for a given property. An incomplete list of properties is below: +Returns the value for a given property. If C is not specified, returns +all the properties. + +An incomplete list of properties is below: =head3 name @@ -170,9 +173,15 @@ Some text about this version tag, what it's for, why it was committed, why it wa =cut sub get { - my $self = shift; - my $name = shift; - return $self->{_data}{$name}; + my $self = shift; + my $name = shift; + + if ( $name ) { + return $self->{_data}{$name}; + } + else { + return \%{ $self->{_data} }, + } } #------------------------------------------------------------------- diff --git a/lib/WebGUI/Workflow/Activity/RequestApprovalForVersionTag.pm b/lib/WebGUI/Workflow/Activity/RequestApprovalForVersionTag.pm index a6848bbcc..5135eea90 100644 --- a/lib/WebGUI/Workflow/Activity/RequestApprovalForVersionTag.pm +++ b/lib/WebGUI/Workflow/Activity/RequestApprovalForVersionTag.pm @@ -28,7 +28,8 @@ Package WebGUI::Workflow::Activity::RequestApprovalForVersionTag =head1 DESCRIPTION -Ask someone for approval of a version tag. If they approve then the workflow continues. If not, it is cancelled. +Ask someone for approval of a version tag. If they approve then the workflow +continues. If not, it is cancelled. =head1 SYNOPSIS @@ -49,97 +50,250 @@ 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, "VersionTag"); - push(@{$definition}, { - name=>$i18n->get("request approval for version tag"), - properties=> { - groupToApprove => { - fieldType=>"group", - defaultValue=>["4"], - label=>$i18n->get("group to approve"), - hoverHelp=>$i18n->get("group to approve help") - }, - message => { - fieldType=>"textarea", - defaultValue => "", - label=> $i18n->get("approval message"), - hoverHelp => $i18n->get("approval message help") - }, - doOnDeny => { - fieldType=>"workflow", - defaultValue=>"pbworkflow000000000006", - label=>$i18n->get("do on deny"), - type=>"WebGUI::VersionTag", - hoverHelp => $i18n->get("do on deny help") - } - } - }); - return $class->SUPER::definition($session,$definition); + my $class = shift; + my $session = shift; + my $definition = shift; + my $i18n = WebGUI::International->new($session, "VersionTag"); + push @{$definition}, { + name => $i18n->get("request approval for version tag"), + properties => { + groupToApprove => { + fieldType => "group", + defaultValue => ["4"], # Content managers + label => $i18n->get("group to approve"), + hoverHelp => $i18n->get("group to approve help"), + }, + message => { + fieldType => "textarea", + defaultValue => "", + label => $i18n->get("approval message"), + hoverHelp => $i18n->get("approval message help"), + }, + doOnDeny => { + fieldType => "workflow", + defaultValue => "pbworkflow000000000006", # Unlock version tag and notify owner + label => $i18n->get("do on deny"), + type => "WebGUI::VersionTag", + hoverHelp => $i18n->get("do on deny help"), + none => 1, + noneLabel => $i18n->get('continue with workflow'), + }, + doOnApprove => { + fieldType => "workflow", + defaultValue => "", # Continue with workflow + label => $i18n->get("do on approve"), + type => "WebGUI::VersionTag", + hoverHelp => $i18n->get("do on approve help"), + none => 1, + noneLabel => $i18n->get('continue with workflow'), + }, + }, + }; + return $class->SUPER::definition($session,$definition); +} + +#---------------------------------------------------------------------------- + +=head2 doOnApprove ( versionTag, instance ) + +Does what is necessary when the tag gets approved. C is the +WebGUI::VersionTag we're working with. C is the workflow instance +we're a part of. + +Returns the notification code to be given to SPECTRE. + +=cut + +sub doOnApprove { + my $self = shift; + my $versionTag = shift; + my $instance = shift; + + # Make the new workflow, if necessary + if ( $self->get("doOnApprove") ) { + my $newInstance + = WebGUI::Workflow::Instance->create($self->session, { + workflowId => $self->get("doOnApprove"), + methodName => $instance->get("methodName"), + className => $instance->get("className"), + parameters => $instance->get("parameters"), + priority => $instance->get("priority"), + })->start(1); + $instance->delete; + } + + # We're done here + return $self->COMPLETE; +} + +#---------------------------------------------------------------------------- + +=head2 doOnDeny ( versionTag, instance ) + +Does what is necessary when the tag gets denied. C is the +WebGUI::VersionTag we're working with. C is the workflow instance +we're a part of. + +Returns the notification code to be given to SPECTRE. + +=cut + +sub doOnDeny { + my $self = shift; + my $versionTag = shift; + my $instance = shift; + + # Make the new workflow, if necessary + if ( $self->get("doOnDeny") ) { + my $newInstance + = WebGUI::Workflow::Instance->create($self->session, { + workflowId => $self->get("doOnDeny"), + methodName => $instance->get("methodName"), + className => $instance->get("className"), + parameters => $instance->get("parameters"), + priority => $instance->get("priority"), + })->start(1); + $instance->delete; + } + + # We're done here + return $self->COMPLETE; } -#------------------------------------------------------------------- +#---------------------------------------------------------------------------- -=head2 execute ( ) +=head2 execute ( versionTag, instance ) See WebGUI::Workflow::Activity::execute() for details. =cut sub execute { - my $self = shift; - my $versionTag = shift; - my $instance = shift; - my $i18n = WebGUI::International->new($self->session, "VersionTag"); - my $inbox = WebGUI::Inbox->new($self->session); - if ($instance->getScratch("status") eq "") { - my $u = WebGUI::User->new($self->session, $versionTag->get("committedBy")); - if ($u->isInGroup($self->get("groupToApprove"))) { - return $self->COMPLETE; - } else { - my $message = $inbox->addMessage({ - subject=>$i18n->get("approve/deny").": ".$versionTag->get("name"), - message=>join("\n\n",$self->get("message"), - $self->session->url->getSiteURL().$self->session->url->page("op=manageRevisionsInTag;workflowInstanceId=".$instance->getId.";tagId=".$versionTag->getId), - $versionTag->get("comments")), - groupId=>$self->get("groupToApprove"), - status=>'pending' - }); - $instance->setScratch("status","notified"); - $instance->setScratch("messageId",$message->getId); - return $self->WAITING; - } - } elsif ($instance->getScratch("status") eq "denied") { - my $message = $inbox->getMessage($instance->getScratch("messageId")); - $message->setCompleted; - my $newInstance = WebGUI::Workflow::Instance->create($self->session, { - workflowId=>$self->get("doOnDeny"), - methodName=>$instance->get("methodName"), - className=>$instance->get("className"), - parameters=>$instance->get("parameters"), - priority=>$instance->get("priority") - })->start(1); - $instance->delete; - return $self->COMPLETE; - } elsif ($instance->getScratch("status") eq "approved") { - my $message = $inbox->getMessage($instance->getScratch("messageId")); - $message->setCompleted; - $instance->deleteScratch("messageId"); - $instance->deleteScratch("status"); - return $self->COMPLETE; - } - return $self->WAITING; + my $self = shift; + my $versionTag = shift; + my $instance = shift; + my $i18n = WebGUI::International->new( $self->session, "VersionTag" ); + my $inbox = WebGUI::Inbox->new( $self->session ); + + # First time through, send the message(s) + if ( $instance->getScratch("status") eq "" ) { + my $committedBy = WebGUI::User->new( $self->session, $versionTag->get("committedBy") ); + my $groupIds = $self->getGroupToApprove; + + # If user is in an approval group, they're auto-approved + for my $groupId ( @{ $groupIds } ) { + if ( $committedBy->isInGroup( $groupId ) ) { + return $self->doOnApprove( $versionTag, $instance ); + } + } + + # If not yet approved, send out the message + $self->sendMessage( $versionTag, $instance ); + + # Update approval status + $instance->setScratch( "status", "notified" ); + + return $self->WAITING; + } + # Second and subsequent times, check status + # Tag is denied + elsif ( $instance->getScratch("status") eq "denied" ) { + # Clean up after ourselves + $self->setMessageCompleted( $instance ); + $instance->deleteScratch( "status" ); + + # We're done here + return $self->doOnDeny( $versionTag, $instance ); + } + # Tag is approved + elsif ( $instance->getScratch("status") eq "approved" ) { + # Clean up after ourselves + $self->setMessageCompleted( $instance ); + $instance->deleteScratch( "status" ); + + # We're done here + return $self->doOnApprove( $versionTag, $instance ); + } + + # If we haven't done anything, spin the wheel again + return $self->WAITING; } +#---------------------------------------------------------------------------- -#------------------------------------------------------------------- +=head2 getGroupToApprove ( versionTag, instance ) -=head2 setApproved ( insstance ) +Returns an array reference of group IDs that could approve this tag. Only +ONE of the members of these group(s) needs to approve the version tag to +make it past this activity. -Marks this approved so that the workflow engine knows it can continue on as approved. +C is the version tag we're working with. C is the +workflow instance we're part of + +=cut + +sub getGroupToApprove { + my $self = shift; + return [ $self->get('groupToApprove') ]; +} + +#---------------------------------------------------------------------------- + +=head2 sendMessage ( versionTag, instance ) + +Send out approval messages to the necessary groups. Keep track of the +message IDs so that we can refer to them later. + +=cut + +sub sendMessage { + my $self = shift; + my $versionTag = shift; + my $instance = shift; + my $inbox = WebGUI::Inbox->new( $self->session ); + my $i18n = WebGUI::International->new( $self->session, "VersionTag" ); + my $messageIds = $instance->getScratch( "messageId" ); + + # FIXME: Do we need the workflowInstanceId here? See the check for + # it in WebGUI::Operation::VersionTag sub www_manageRevisionsInTag + + my $approvalUrl + = $self->session->url->getSiteURL + . $self->session->url->page( + "op=manageRevisionsInTag;workflowInstanceId=" . $instance->getId + . ";tagId=" . $versionTag->getId + ); + my $messageText + = join "\n\n", + $self->get("message"), + $approvalUrl, + $versionTag->get("comments"), + ; + + for my $groupId ( @{ $self->getGroupToApprove } ) { + my $message + = $inbox->addMessage({ + subject => $i18n->get("approve/deny") . ": " . $versionTag->get("name"), + message => $messageText, + groupId => $groupId, + status => 'pending', + }); + $messageIds = join ",", $messageIds, $message->getId; + } + + # Keep track of message Ids so we can complete them + $instance->setScratch( "messageId", $messageIds ); + + return; +} + +#---------------------------------------------------------------------------- + +=head2 setApproved ( instance ) + +Marks this approved so that the workflow engine knows it can continue on as +approved. =head3 instance @@ -148,16 +302,17 @@ A reference to the instance that you wish to set this approved. =cut sub setApproved { - my $self = shift; - my $instance = shift; - $instance->setScratch("status","approved"); + my $self = shift; + my $instance = shift; + $instance->setScratch( "status", "approved" ); } -#------------------------------------------------------------------- +#---------------------------------------------------------------------------- -=head2 setDenied ( insstance ) +=head2 setDenied ( instance ) -Marks this approved so that the workflow engine knows it can continue on as denied. +Marks this approved so that the workflow engine knows it can continue on as +denied. =head3 instance @@ -166,12 +321,36 @@ A reference to the instance that you wish to set this denied. =cut sub setDenied { - my $self = shift; - my $instance = shift; - $instance->setScratch("status","denied"); + my $self = shift; + my $instance = shift; + $instance->setScratch( "status", "denied" ); } +#---------------------------------------------------------------------------- + +=head2 setMessageCompleted ( instance ) + +Sets all the messages sent by this activity to completed. C is the +workflow instance we're part of. + +=cut + +sub setMessageCompleted { + my $self = shift; + my $instance = shift; + my $inbox = WebGUI::Inbox->new( $self->session ); + + # Set all messages to completed + for my $messageId ( split /,/, $instance->getScratch("messageId") ) { + my $message = $inbox->getMessage( $messageId ); + $message->setCompleted; + } + + $instance->deleteScratch( "messageId" ); + + return; +} + 1; - diff --git a/lib/WebGUI/i18n/English/VersionTag.pm b/lib/WebGUI/i18n/English/VersionTag.pm index 7aab8adb0..7db8d1496 100644 --- a/lib/WebGUI/i18n/English/VersionTag.pm +++ b/lib/WebGUI/i18n/English/VersionTag.pm @@ -338,6 +338,49 @@ our $I18N = { lastUpdated => 0, }, + + 'manageRevisionsInTag moveTo new' => { + message => q{-> New Version Tag}, + lastUpdated => 0, + context => q{Option to move revisions to a new version tag}, + }, + + 'manageRevisionsInTag with selected' => { + message => q{With Selected: }, + lastUpdated => 0, + context => q{Lead-in for actions to perform after selecting revisions}, + }, + + 'manageRevisionsInTag purge' => { + message => q{Purge}, + lastUpdated => 0, + context => q{Label for button to purge revisions}, + }, + + 'manageRevisionsInTag move' => { + message => q{Move To:}, + lastUpdated => 0, + context => q{Label for button to move revisions}, + }, + + 'continue with workflow' => { + message => q{-- Continue with this workflow}, + lastUpdated => 0, + context => q{Label to disable branching in workflow}, + }, + + 'do on approve' => { + message => q{Do On Approve}, + lastUpdated => 0, + context => q{Label for activity property}, + }, + + 'do on approve help' => { + message => q{The workflow to perform when the version tag is approved by this activity.}, + lastUpdated => 0, + context => q{Help for activity property}, + }, + 'topicName' => { message => q|Version Control|, lastUpdated => 1148360141, diff --git a/lib/WebGUI/i18n/English/Workflow.pm b/lib/WebGUI/i18n/English/Workflow.pm index cceee1f9d..1750ac620 100644 --- a/lib/WebGUI/i18n/English/Workflow.pm +++ b/lib/WebGUI/i18n/English/Workflow.pm @@ -250,6 +250,12 @@ our $I18N = { lastUpdated => 0, }, + 'form control none label' => { + message => q{None}, + context => q{Default label to select "None" for a workflow}, + lastUpdated => 0, + }, + 'topicName' => { message => q|Workflow|, context => q|The title of the workflow interface.|,