diff --git a/docs/upgrades/upgrade_7.1.4-7.2.0.pl b/docs/upgrades/upgrade_7.1.4-7.2.0.pl index 82c7722a5..8a0323e9d 100644 --- a/docs/upgrades/upgrade_7.1.4-7.2.0.pl +++ b/docs/upgrades/upgrade_7.1.4-7.2.0.pl @@ -12,7 +12,7 @@ use lib "../../lib"; use strict; use Getopt::Long; use WebGUI::Session; - +use WebGUI::Workflow; my $toVersion = "7.2.0"; # make this match what version you're going to my $quiet; # this line required @@ -23,6 +23,8 @@ my $session = start(); # this line required commerceSalesTax($session); createDictionaryStorage($session); addRssUrlMacroProcessing($session); +addLastExportedAs($session); +addDeletionWorkflows($session); addRSSFromParent($session); finish($session); # this line required @@ -66,6 +68,48 @@ sub createDictionaryStorage { mkdir $dictionaryDirectory.'/oldIds' unless (-e $dictionaryDirectory.'/oldIds'); } +#------------------------------------------------- +sub addLastExportedAs { + my $session = shift; + print "\tAdding lastExportedAs field for assets.\n" unless $quiet; + + $session->db->write($_) for(<<'EOT', + ALTER TABLE asset + ADD COLUMN lastExportedAs varchar(255) NULL DEFAULT NULL +EOT + ); +} + +#------------------------------------------------- +sub addDeletionWorkflows { + my $session = shift; + print "\tAdding deletion workflows and activities.\n" unless $quiet; + + my $nullAssetWorkflow = WebGUI::Workflow->create + ($session, { type => "None", + enabled => 1, + description => "Does nothing extra. Default for deletion workflow settings.", + title => "Do Nothing on Deletion" }, + "DPWwf20061030000000001"); + my $deleteExportsWorkflow = WebGUI::Workflow->create + ($session, { type => "None", + enabled => 1, + description => "Deletes exported files from an asset being deleted or moved.", + title => "Delete Exported Files" }, + "DPWwf20061030000000002"); + my $deleteExportsActivity = $deleteExportsWorkflow->addActivity + ("WebGUI::Workflow::Activity::DeleteExportedFiles", "DPWwfa2006103000000002"); + $deleteExportsActivity->set('title', 'Delete Exported Files'); + + $session->db->write("INSERT INTO settings (name, value) VALUES (?, ?)", $_) for + (['trashWorkflow', $nullAssetWorkflow->getId], ['purgeWorkflow', $nullAssetWorkflow->getId], + ['changeUrlWorkflow', $nullAssetWorkflow->getId]); + + my $activityHash = $session->config->get('workflowActivities'); + push @{$activityHash->{None}}, 'WebGUI::Workflow::Activity::DeleteExportedFiles'; + $session->config->set('workflowActivities', $activityHash); +} + #------------------------------------------------- sub addRSSFromParent { diff --git a/lib/WebGUI/Asset.pm b/lib/WebGUI/Asset.pm index 117924205..7208b24ff 100644 --- a/lib/WebGUI/Asset.pm +++ b/lib/WebGUI/Asset.pm @@ -1947,6 +1947,8 @@ This actually does the change url of the www_changeUrl() function. sub www_changeUrlConfirm { my $self = shift; return $self->session->privilege->insufficient() unless $self->canEdit; + $self->_invokeWorkflowOnExportedFiles($self->session->setting->get('changeUrlWorkflow'), 1); + if ($self->session->form->process("confirm","yesNo") && $self->session->form->process("url","text")) { $self->update({url=>$self->session->form->process("url","text")}); my $rs = $self->session->db->read("select revisionDate from assetData where assetId=? and revisionDate<>?",[$self->getId, $self->get("revisionDate")]); diff --git a/lib/WebGUI/AssetExportHtml.pm b/lib/WebGUI/AssetExportHtml.pm index 3162afbc5..de5ff5c16 100644 --- a/lib/WebGUI/AssetExportHtml.pm +++ b/lib/WebGUI/AssetExportHtml.pm @@ -136,10 +136,13 @@ sub _exportAsHtml { $filename = $index; } + my $fullPath = (length($path)? "$path/" : "").$filename; if ($asset->getId eq $defaultAssetId) { - $defaultAssetPath = $path.'/'.$filename; + $defaultAssetPath = $fullPath; } + $self->session->db->write("UPDATE asset SET lastExportedAs = ? WHERE assetId = ?", [$fullPath, $asset->getId]); + $path = $exportPath . (length($path)? "/$path" : ""); eval { mkpath($path) }; if($@) { diff --git a/lib/WebGUI/AssetTrash.pm b/lib/WebGUI/AssetTrash.pm index 8810323f4..b5b410921 100644 --- a/lib/WebGUI/AssetTrash.pm +++ b/lib/WebGUI/AssetTrash.pm @@ -97,6 +97,8 @@ Deletes an asset from tables and removes anything bound to that asset, including sub purge { my $self = shift; return undef if ($self->getId eq $self->session->setting->get("defaultPage") || $self->getId eq $self->session->setting->get("notFoundPage") || $self->get("isSystem")); + $self->_invokeWorkflowOnExportedFiles($self->session->setting->get('purgeWorkflow'), 1); + my $kids = $self->getLineage(["children"],{returnObjects=>1, statesToInclude=>['published', 'clipboard', 'clipboard-limbo','trash','trash-limbo']}); foreach my $kid (@{$kids}) { $kid->purge; @@ -127,6 +129,10 @@ Removes asset from lineage, places it in trash state. The "gap" in the lineage i sub trash { my $self = shift; return undef if ($self->getId eq $self->session->setting->get("defaultPage") || $self->getId eq $self->session->setting->get("notFoundPage")); + foreach my $asset ($self, @{$self->getLineage(['descendants'], {returnObjects => 1})}) { + $asset->_invokeWorkflowOnExportedFiles($self->session->setting->get('trashWorkflow'), 1); + } + my $db = $self->session->db; $db->beginTransaction; my $sth = $db->read("select assetId from asset where lineage like ?",[$self->get("lineage").'%']); @@ -141,6 +147,16 @@ sub trash { $self->purgeCache; } +sub _invokeWorkflowOnExportedFiles { + my $self = shift; + my $workflowId = shift; + my $clearExportedAs = shift; + + my ($lastExportedAs) = $self->session->db->quickArray("SELECT lastExportedAs FROM asset WHERE assetId = ?", [$self->getId]); + my $wfInstance = WebGUI::Workflow::Instance->create($self->session, { workflowId => $self->session->setting->get('trashWorkflow') }); + $wfInstance->setScratch(WebGUI::Workflow::Activity::DeleteExportedFiles::DELETE_FILES_SCRATCH(), Storable::freeze([defined($lastExportedAs)? ($lastExportedAs) : ()])); + $clearExportedAs and $self->session->db->write("UPDATE asset SET lastExportedAs = NULL WHERE assetId = ?", [$self->getId]); +} #------------------------------------------------------------------- diff --git a/lib/WebGUI/Operation/Settings.pm b/lib/WebGUI/Operation/Settings.pm index 3debf661c..5d2205cfb 100644 --- a/lib/WebGUI/Operation/Settings.pm +++ b/lib/WebGUI/Operation/Settings.pm @@ -68,6 +68,7 @@ sub definition { hoverHelp=>$i18n->get('127 description'), defaultValue=>$session->setting->get("companyURL") }); + # content settings push(@fields, { tab=>"content", @@ -78,6 +79,34 @@ sub definition { label=>$i18n->get("default version tag workflow"), hoverHelp=>$i18n->get('default version tag workflow help') }); + push(@fields, { + tab=>"content", + fieldType=>"workflow", + name=>"trashWorkflow", + defaultValue=>$session->setting->get("trashWorkflow"), + type=>"None", + label=>$i18n->get("trash workflow"), + hoverHelp=>$i18n->get('trash workflow help') + }); + push(@fields, { + tab=>"content", + fieldType=>"workflow", + name=>"purgeWorkflow", + defaultValue=>$session->setting->get("purgeWorkflow"), + type=>"None", + label=>$i18n->get("purge workflow"), + hoverHelp=>$i18n->get('purge workflow help') + }); + push(@fields, { + tab=>"content", + fieldType=>"workflow", + name=>"changeUrlWorkflow", + defaultValue=>$session->setting->get("changeUrlWorkflow"), + type=>"None", + label=>$i18n->get("changeUrl workflow"), + hoverHelp=>$i18n->get('changeUrl workflow help') + }); + my %htmlFilter = ( 'none'=>$i18n->get(420), 'most'=>$i18n->get(421), diff --git a/lib/WebGUI/Workflow/Activity/DeleteExportedFiles.pm b/lib/WebGUI/Workflow/Activity/DeleteExportedFiles.pm new file mode 100644 index 000000000..6d404b959 --- /dev/null +++ b/lib/WebGUI/Workflow/Activity/DeleteExportedFiles.pm @@ -0,0 +1,123 @@ +package WebGUI::Workflow::Activity::DeleteExportedFiles; + + +=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 base 'WebGUI::Workflow::Activity'; +use File::Spec::Functions qw/canonpath/; +require Storable; + +=head1 NAME + +Package WebGUI::Workflow::Activity::DeleteExportedFiles + +=head1 DESCRIPTION + +Deletes an asset's exported files. This must be added to a workflow +that passes the filenames to delete as auxiliary data. + +=head1 SYNOPSIS + +See WebGUI::Workflow::Activity for details on how to use any activity. + +=cut + + +#------------------------------------------------------------------- +sub definition { + my $class = shift; + my $session = shift; + my $definition = shift; + my $i18n = WebGUI::International->new($session, "Workflow_Activity_DeleteExportedFiles"); + push(@{$definition}, + { + name => $i18n->get('activityName'), + properties => {} + }); + return $class->SUPER::definition($session,$definition); +} + + +#------------------------------------------------------------------- +# Can use these from other places. Buggo: POD? +use constant DELETE_FILES_SCRATCH => 'Workflow_Activity_DeleteExportedFiles_deleteFiles'; +use constant PRUNE_DIRS_SCRATCH => 'Workflow_Activity_DeleteExportedFiles_pruneDirs'; + +sub _canonExportPath { + my $self = shift; + my $path = shift; + $self->session->config->get('exportPath').'/'.canonpath($path); +} + +sub _pruneOfFile { + my $self = shift; + my $filename = shift; + my $dirname = $filename; + if ($dirname =~ s(/[^/]+\z)()g) { + return ($dirname) unless glob(quotemeta($self->_canonExportPath($dirname)).'/*'); + } + + return (); +} + +sub execute { + my $self = shift; + my $object = shift; + my $instance = shift; + + unless ($self->session->config->get('exportPath')) { + $self->session->errorHandler->warn("DeleteExportedFiles: no export path, so not doing anything"); + return $self->COMPLETE; + } + + my $time = time; + my $filesRef = Storable::thaw($instance->getScratch(DELETE_FILES_SCRATCH)); + unless ($filesRef) { + $self->session->errorHandler->error("DeleteExportedFiles: can't find list of files to delete"); + return $self->ERROR; + } + + my @files = @$filesRef; + my @dirs = @{$instance->getScratch(PRUNE_DIRS_SCRATCH) || []}; + + while (defined(my $filename = shift @files)) { + my $cfilename = $self->_canonExportPath($filename); + unlink $cfilename or $self->session->errorHandler->warn("DeleteExportedFiles: Couldn't unlink $filename: $!"), next; + push @dirs, $self->_pruneOfFile($filename); + goto pause if (time - $time > 55); + } + + while (defined(my $dirname = shift @dirs)) { + my $cdirname = $self->_canonExportPath($dirname); + rmdir $cdirname or $self->session->errorHandler->warn("DeleteExportedFiles: couldn't rmdir $dirname: $!"), next; + push @dirs, $self->_pruneOfFile($dirname); + goto pause if (time - $time > 55); + } + + done: + $instance->deleteScratch(DELETE_FILES_SCRATCH); + $instance->deleteScratch(PRUNE_DIRS_SCRATCH); + return $self->COMPLETE; + + pause: + $instance->setScratch(DELETE_FILES_SCRATCH, Storable::freeze(\@files)); + $instance->setScratch(PRUNE_DIRS_SCRATCH, Storable::freeze(\@dirs)); + return $self->WAITING; +} + +1; + + diff --git a/lib/WebGUI/i18n/English/WebGUI.pm b/lib/WebGUI/i18n/English/WebGUI.pm index 8bdd8aeb9..4b61f7143 100644 --- a/lib/WebGUI/i18n/English/WebGUI.pm +++ b/lib/WebGUI/i18n/English/WebGUI.pm @@ -31,6 +31,42 @@ our $I18N = { context=>"Settings" }, + 'trash workflow help' => { + message => q|Which workflow to run when an asset is placed in the trash.|, + lastUpdated => 1162242500, + context=>"Settings hover help" + }, + + 'trash workflow' => { + message => q|Trash Workflow|, + lastUpdated => 1162242500, + context=>"Settings" + }, + + 'purge workflow help' => { + message => q|Which workflow to run when an asset is purged.|, + lastUpdated => 1162242500, + context=>"Settings hover help" + }, + + 'purge workflow' => { + message => q|Purge Workflow|, + lastUpdated => 1162242500, + context=>"Settings" + }, + + 'changeUrl workflow help' => { + message => q|Which workflow to run when an asset's URL is changed.|, + lastUpdated => 1162348521, + context=>"Settings hover help" + }, + + 'changeUrl workflow' => { + message => q|Change URL Workflow|, + lastUpdated => 1162348521, + context=>"Settings" + }, + 'expire groupings' => { message => q|Expire User Groupings|, lastUpdated => 0 diff --git a/lib/WebGUI/i18n/English/Workflow_Activity_DeleteExportedFiles.pm b/lib/WebGUI/i18n/English/Workflow_Activity_DeleteExportedFiles.pm new file mode 100644 index 000000000..aca35e829 --- /dev/null +++ b/lib/WebGUI/i18n/English/Workflow_Activity_DeleteExportedFiles.pm @@ -0,0 +1,11 @@ +package WebGUI::i18n::English::Workflow_Activity_DeleteExportedFiles; + +our $I18N = { + 'activityName' => { + message => q|Delete Exported Files|, + context => q|The name of this workflow activity.|, + lastUpdated => 1162238122, + }, +}; + +1;