Move trash functions to Fork

This commit is contained in:
Paul Driver 2010-10-04 15:51:23 -07:00
parent e238f72278
commit 895ce37917
7 changed files with 257 additions and 151 deletions

View file

@ -4,6 +4,7 @@
- Added WebGUI::Fork api
- Moved html export to Fork
- Moved clipboard functions to Fork
- Moved trash functions to Fork
- fixed #11884: Editing Templates impossible / Code editor not loaded
- recommitted ukplayer. Removal broke Matrix. Licencing information was available but overlooked.
- fixed #11883: Wiki "Add page" link does not encode special chars

View file

@ -835,6 +835,54 @@ sub fixUrlFromParent {
return $url;
}
#-------------------------------------------------------------------
=head2 forkWithProgressTree ($args)
Kicks off a WebGUI::Fork running $method with $args (from the args hashref)
and redirects to a ProgressTree status page to show the progress. The
following arguments are required in $args:
=head3 method
The name of the WebGUI::Asset method to call
=head3 args
The arguments to pass that method (see WebGUI::Fork)
=head3 title
An key in Asset's i18n hash for the title of the rendered console page
=head3 redirect
The full url to redirect to after the fork has finished.
=cut
sub forkWithProgressTree {
my ( $self, $args ) = @_;
my $session = $self->session;
my $process = WebGUI::Fork->start( $session, 'WebGUI::Asset', $args->{method}, $args->{args} );
if ( my $groupId = $args->{groupId} ) {
$process->setGroup($groupId);
}
my $method = $session->form->get('proceed') || 'manageTrash';
my $i18n = WebGUI::International->new( $session, 'Asset' );
my $pairs = $process->contentPairs(
'ProgressTree', {
title => $i18n->get( $args->{title} ),
icon => 'assets',
proceed => $args->{redirect} || '',
}
);
$session->http->setRedirect( $self->getUrl($pairs) );
return 'redirect';
} ## end sub forkWithProgressTree
#-------------------------------------------------------------------

View file

@ -212,7 +212,7 @@ copy.
sub duplicate {
my $self = shift;
my $newTemplate = $self->SUPER::duplicate;
my $newTemplate = $self->SUPER::duplicate(@_);
$newTemplate->update({isDefault => 0});
if ( my $storageId = $self->get('storageIdExample') ) {
my $newStorage = WebGUI::Storage->get( $self->session, $storageId )->copy;

View file

@ -51,13 +51,13 @@ sub canPaste {
#-------------------------------------------------------------------
=head2 copyInBackground ( $process, $args )
=head2 copyInFork ( $process, $args )
WebGUI::Fork method called by www_copy
=cut
sub copyInBackground {
sub copyInFork {
my ($process, $args) = @_;
my $session = $process->session;
my $asset = WebGUI::Asset->new($session, $args->{assetId});
@ -72,23 +72,26 @@ sub copyInBackground {
}
my $ids = $asset->getLineage(\@pedigree);
my $tree = WebGUI::ProgressTree->new($session, $ids);
my $patch = Monkey::Patch::patch_class 'WebGUI::Asset', 'duplicate', sub {
my $duplicate = shift;
my $self = shift;
my $id = $self->getId;
my $asset = eval { $self->$duplicate(@_) };
my $e = $@;
if ($e) {
$tree->note($id, $e);
$tree->failure($id, 'Died');
my $patch = Monkey::Patch::patch_class(
'WebGUI::Asset', 'duplicate', sub {
my $duplicate = shift;
my $self = shift;
my $id = $self->getId;
$tree->focus($id);
my $asset = eval { $self->$duplicate(@_) };
my $e = $@;
if ($e) {
$tree->note($id, $e);
$tree->failure($id, 'Died');
}
else {
$tree->success($id);
}
$process->update(sub { $tree->json });
die $e if $e;
return $asset;
}
else {
$tree->success($id);
}
$process->update(sub { $tree->json });
die $e if $e;
return $asset;
};
);
my $newAsset = $asset->duplicateBranch($childrenOnly, 'clipboard');
$newAsset->update({ title => $newAsset->getTitle . ' (copy)'});
if ($args->{commit}) {
@ -303,53 +306,50 @@ sub paste {
#-------------------------------------------------------------------
=head2 pasteInBackground ( )
=head2 pasteInFork ( )
WebGUI::Fork method called by www_pasteList
=cut
sub pasteInBackground {
my ($process, $args) = @_;
sub pasteInFork {
my ( $process, $args ) = @_;
my $session = $process->session;
my $self = WebGUI::Asset->new($session, $args->{assetId});
my $self = WebGUI::Asset->new( $session, $args->{assetId} );
my @roots = grep { $_ && $_->canEdit }
map { WebGUI::Asset->newPending($session, $_) }
@{ $args->{list} };
map { WebGUI::Asset->newPending( $session, $_ ) } @{ $args->{list} };
my @ids;
for my $r (@roots) {
my $these = $r->getLineage(
['self', 'descendants'], {
statesToInclude => ['clipboard', 'clipboard-limbo']
}
);
push(@ids, @$these);
}
my @ids = map {
my $list
= $_->getLineage( [ 'self', 'descendants' ], { statesToInclude => [ 'clipboard', 'clipboard-limbo' ] } );
@$list;
} @roots;
my $tree = WebGUI::ProgressTree->new($session, \@ids);
my $tree = WebGUI::ProgressTree->new( $session, \@ids );
my $patch = Monkey::Patch::patch_class(
'WebGUI::Asset', 'indexContent', sub {
'WebGUI::Asset',
'indexContent',
sub {
my $indexContent = shift;
my $self = shift;
my $id = $self->getId;
$tree->focus($id);
my $ret = eval { $self->$indexContent(@_) };
my $e = $@;
my $e = $@;
if ($e) {
$tree->note($id, $e);
$tree->failure($id, 'Died');
$tree->note( $id, $e );
$tree->failure( $id, 'Died' );
}
else {
$tree->success($id);
}
$process->update(sub { $tree->json });
$process->update( sub { $tree->json } );
die $e if $e;
return $ret;
}
);
$self->paste($_->getId) for @roots;
}
$self->paste( $_->getId ) for @roots;
} ## end sub pasteInFork
#-------------------------------------------------------------------
@ -400,19 +400,13 @@ sub www_copy {
}
$args{assetId} = $self->getId;
my $process = WebGUI::Fork->start(
$session, 'WebGUI::Asset', 'copyInBackground', \%args
);
my $i18n = WebGUI::International->new($session, 'Asset');
my $pairs = $process->contentPairs(
'ProgressTree', {
title => $i18n->get('Copy Assets'),
icon => 'assets',
proceed => $redir
$self->forkWithProgressTree({
title => 'Copy Assets',
redirect => $redir,
method => 'copyInFork',
args => \%args
}
);
$http->setRedirect($self->getUrl($pairs));
return 'redirect';
}
#-------------------------------------------------------------------
@ -730,30 +724,24 @@ the Asset Manager.
sub www_pasteList {
my $self = shift;
my $session = $self->session;
my $form = $session->form;
return $session->privilege->insufficient() unless $self->canEdit && $session->form->validToken;
my $form = $session->form;
my $process = WebGUI::Fork->start(
$session, 'WebGUI::Asset', 'pasteInBackground', {
assetId => $self->getId,
list => [ $form->get('assetId') ],
$self->forkWithProgressTree( {
title => 'Paste Assets',
redirect => $self->getUrl(
$form->get('proceed') eq 'manageAssets'
? 'op=assetManager'
: ()
),
method => 'pasteInFork',
args => {
assetId => $self->getId,
list => [ $form->get('assetId') ],
}
}
);
my $redir = $self->getUrl(
($form->get('proceed') eq 'manageAssets') ? 'op=assetManager' : ()
);
my $i18n = WebGUI::International->new($session, 'Asset');
my $pairs = $process->contentPairs(
'ProgressTree', {
title => $i18n->get('Paste Assets'),
icon => 'assets',
proceed => $redir,
}
);
$session->http->setRedirect($self->getUrl($pairs));
return 'redirect';
}
} ## end sub www_pasteList
1;

View file

@ -1015,21 +1015,16 @@ sub www_exportStatus {
my @vars = qw(
index depth userId extrasUploadsAction rootUrlAction exportUrl
);
my $process = WebGUI::Fork->start(
$session, 'WebGUI::Asset', 'exportInFork', {
assetId => $self->getId,
map { $_ => scalar $form->get($_) } @vars
$self->forkWithProgressTree({
title => 'Page Export Status',
method => 'exportInFork',
groupId => 13,
args => {
assetId => $self->getId,
map { $_ => scalar $form->get($_) } @vars
}
}
);
$process->setGroup(13);
my $i18n = WebGUI::International->new( $session, 'Asset' );
my $pairs = $process->contentPairs('ProgressTree', {
icon => 'assets',
title => $i18n->get('Page Export Status'),
}
);
$session->http->setRedirect($self->getUrl($pairs));
return 'redirect';
}
#-------------------------------------------------------------------

View file

@ -200,6 +200,63 @@ sub purge {
return 1;
}
#-------------------------------------------------------------------
=head2 purgeInFork
WebGUI::Fork method called by www_purgeList
=cut
sub purgeInFork {
my ( $process, $list ) = @_;
my $session = $process->session;
my @roots = grep { $_ && $_->canEdit }
map { WebGUI::Asset->newPending( $session, $_ ) } @$list;
my @ids = map {
my $list = $_->getLineage(
[ 'self', 'descendants' ], {
statesToInclude => [qw(published clipboard clipboard-limbo trash trash-limbo)],
statusToInclude => [qw(approved archived pending)],
}
);
@$list;
} @roots;
my $tree = WebGUI::ProgressTree->new( $session, \@ids );
my $patch = Monkey::Patch::patch_class(
'WebGUI::Asset',
'purge',
sub {
my ( $purge, $self, $options ) = @_;
my $id = $self->getId;
my $zero = '';
$tree->focus($id);
$options ||= {};
local $options->{outputSub} = sub { $zero .= $_[0] };
my $ret = eval { $self->$purge($options) };
my $e = $@;
$tree->focus($id);
if ($e) {
$tree->failure( $id, 'Died' );
$tree->note( $id, $e );
}
elsif ( !$ret ) {
$tree->failure( $id, 'Failed' );
$tree->note( $id, $zero );
}
else {
$tree->success($id);
}
$process->update( sub { $tree->json } );
die $e if $e;
return $ret;
}
);
$_->purge for @roots;
} ## end sub purgeInFork
#-------------------------------------------------------------------
@ -246,7 +303,15 @@ sub trash {
return undef;
}
my $assetIter = $self->getLineageIterator(['self','descendants']);
my $assetIter = $self->getLineageIterator(
['self','descendants'], {
statesToInclude => [qw(published clipboard clipboard-limbo trash trash-limbo)],
statusToInclude => [qw(approved archived pending)],
}
);
my $rootId = $self->getId;
my $db = $session->db;
$db->beginTransaction;
while ( 1 ) {
my $asset;
eval { $asset = $assetIter->() };
@ -263,7 +328,9 @@ sub trash {
$outputSub->($i18n->get('Clearing cache'));
$asset->purgeCache;
$asset->updateHistory("trashed");
$asset->setState($asset->getId eq $rootId ? 'trash' : 'trash-limbo');
}
$db->commit;
# Trash any shortcuts to this asset
my $shortcuts
@ -273,16 +340,6 @@ sub trash {
$shortcut->trash({ outputSub => $outputSub, });
}
# Raw database work is more efficient than $asset->update
my $db = $session->db;
$db->beginTransaction;
$outputSub->($i18n->get('Clearing asset tables'));
$db->write("update asset set state='trash-limbo' where lineage like ?",[$self->get("lineage").'%']);
$db->write("update asset set state='trash', stateChangedBy=?, stateChanged=? where assetId=?",[$session->user->userId, time(), $self->getId]);
$db->commit;
# Update ourselves since we didn't use update()
$self->{_properties}{state} = "trash";
return 1;
}
@ -315,7 +372,7 @@ sub _invokeWorkflowOnExportedFiles {
=head2 www_delete
Moves self to trash, returns www_view() method of Container or Parent if canEdit.
Moves self to trash in fork, redirects to Container or Parent if canEdit.
Otherwise returns AdminConsole rendered insufficient privilege.
=cut
@ -325,13 +382,18 @@ sub www_delete {
return $self->session->privilege->insufficient() unless ($self->canEdit && $self->canEditIfLocked);
return $self->session->privilege->vitalComponent() if $self->get('isSystem');
return $self->session->privilege->vitalComponent() if (isIn($self->getId, $self->session->setting->get("defaultPage"), $self->session->setting->get("notFoundPage")));
$self->trash;
my $asset = $self->getContainer;
if ($self->getId eq $asset->getId) {
$asset = $self->getParent;
}
$self->session->asset($asset);
return $asset->www_view;
$self->forkWithProgressTree({
title => 'Delete Assets',
redirect => $asset->getUrl,
method => 'trashInFork',
args => [ $self->getId ],
}
);
}
#-------------------------------------------------------------------
@ -343,35 +405,57 @@ Checks to see if a valid CSRF token was received. If not, then it returns insuf
Moves list of assets to trash, checking each to see if the user canEdit,
and canEditIfLocked. Returns the user to manageTrash, or to the screen set
by the form variable C<proceeed>.
=cut
sub www_deleteList {
my $self = shift;
my $session = $self->session;
my $pb = WebGUI::ProgressBar->new($session);
my $i18n = WebGUI::International->new($session, 'Asset');
my $form = $session->form;
my @assetIds = $form->param('assetId');
$pb->start($i18n->get('Delete Assets'), $session->url->extras('adminConsole/assets.gif'));
return $self->session->privilege->insufficient() unless $session->form->validToken;
ASSETID: foreach my $assetId (@assetIds) {
my $asset = eval { WebGUI::Asset->newPending($session,$assetId); };
if ($@) {
$pb->update(sprintf $i18n->get('Error getting asset with assetId %s'), $assetId);
next ASSETID;
}
if (! ($asset->canEdit && $asset->canEditIfLocked) ) {
$pb->update(sprintf $i18n->get('You cannot edit the asset %s, skipping'), $asset->getTitle);
}
else {
$asset->trash({outputSub => sub { $pb->update(@_); } });
}
}
my $method = ($session->form->process("proceed")) ? $session->form->process('proceed') : 'manageTrash';
$pb->finish($self->getUrl('func='.$method));
}
sub trashInFork {
my ( $process, $list ) = @_;
my $session = $process->session;
my @roots = grep { $_->canEdit && $_->canEditIfLocked }
map {
eval { WebGUI::Asset->newPending( $session, $_ ) }
} @$list;
my @ids = map {
my $list = $_->getLineage(
[ 'self', 'descendants' ], {
statesToInclude => [qw(published clipboard clipboard-limbo trash trash-limbo)],
statusToInclude => [qw(approved archived pending)],
}
);
@$list;
} @roots;
my $tree = WebGUI::ProgressTree->new( $session, \@ids );
my $patch = Monkey::Patch::patch_class(
'WebGUI::Asset',
'setState',
sub {
my ( $setState, $self, $state ) = @_;
my $id = $self->getId;
$tree->focus($id);
my $ret = $self->$setState($state);
$tree->success($id);
$process->update(sub { $tree->json });
return $ret;
}
);
$_->trash() for @roots;
} ## end sub trashInFork
sub www_deleteList {
my $self = shift;
my $session = $self->session;
my $form = $session->form;
return $session->privilege->insufficient() unless $session->form->validToken;
my $method = $form->get('proceed') || 'manageTrash';
$self->forkWithProgressTree({
title => 'Delete Assets',
redirect => $self->getUrl("func=$method"),
method => 'trashInFork',
args => [ $form->get('assetId') ],
}
);
} ## end sub www_deleteList
#-------------------------------------------------------------------
@ -478,29 +562,17 @@ Returns insufficient privileges unless the submitted form passes the validToken
sub www_purgeList {
my $self = shift;
my $session = $self->session;
my $form = $session->form;
return $session->privilege->insufficient() unless $session->form->validToken;
my $pb = WebGUI::ProgressBar->new($session);
my $i18n = WebGUI::International->new($session, 'Asset');
$pb->start($i18n->get('purge'), $session->url->extras('adminConsole/assets.gif'));
ASSETID: foreach my $id ($session->form->param("assetId")) {
my $asset = eval { WebGUI::Asset->newPending($session,$id); };
if ($@) {
$pb->update(sprintf $i18n->get('Error getting asset with assetId %s'), $id);
next ASSETID;
my $method = $form->get('proceed') || 'manageTrash';
$method .= ';systemTrash=1' if $form->get('systemTrash');
$self->forkWithProgressTree({
title => 'purge',
redirect => $self->getUrl("func=$method"),
method => 'purgeInFork',
args => [ $form->get('assetId') ],
}
if (! $asset->canEdit) {
$pb->update(sprintf $i18n->get('You cannot edit the asset %s, skipping'), $asset->getTitle);
}
else {
$asset->purge({outputSub => sub { $pb->update(@_); } });
}
}
my $method = ($session->form->process("proceed")) ? $session->form->process('proceed') : 'manageTrash';
if ($session->form->process('systemTrash') ) {
$method .= ';systemTrash=1';
}
$pb->finish($self->getUrl('func='.$method));
);
}
#-------------------------------------------------------------------

View file

@ -278,11 +278,11 @@ sub forkAndExec {
my $class = ref $self;
my $json = JSON::encode_json($request);
my @inc = map {"-I$_"} @INC;
my @argv = ( "webgui-fork-$id", @inc, "-M$class", "-e$class->runCmd()" );
my @argv = (@inc, "-M$class", "-e$class->runCmd()" );
$class->daemonize(
$json,
sub {
exec { $Config{perlpath} } @argv or die "Could not exec: $!";
exec ($Config{perlpath}, @argv) or die "Could not exec: $!";
}
);
}
@ -541,8 +541,10 @@ sub runRequest {
my ( $class, $args ) = @_;
my ( $root, $config, $sid ) = @{$args}{qw(webguiRoot configFile sessionId)};
my $session = WebGUI::Session->open( $root, $config, undef, undef, $sid );
my $self = $class->new( $session, $args->{id} );
my $id = $args->{id};
my $self = $class->new( $session, $id );
$self->set( { startTime => time } );
$0 = "webgui-fork-$id";
eval {
my ( $module, $subname, $data ) = @{$args}{qw(module subname data)};
WebGUI::Pluggable::run( $module, $subname, [ $self, $data ] );