Skip to content

Commit

Permalink
Item14089: mode application extension
Browse files Browse the repository at this point in the history
  • Loading branch information
BramVan-Oosterhout committed Mar 25, 2017
1 parent 8bcc45f commit 18f40d1
Show file tree
Hide file tree
Showing 7 changed files with 416 additions and 24 deletions.
31 changes: 23 additions & 8 deletions data/System/CopyContrib.txt
@@ -1,4 +1,4 @@
%META:TOPICINFO{author="ProjectContributor" date="1443363950" format="1.1" version="1"}%
%META:TOPICINFO{author="BramVanOosterhout" comment="" date="1490246301" format="1.1" version="5"}%
---+!! %TOPIC%
%FORMFIELD{"Description"}%

Expand Down Expand Up @@ -42,7 +42,9 @@ a copy agent is created to perform the actual operation. The basic skeleton for
| =mode= | select the type of operation; possible values are: <ul>\
<li> =topic=: copy one topic or parts of it to a destination topic </li>\
<li> =topics=: copy a list of topic to a destination </li>\
<li> =web=: copy a web to a destination </li> </ul> | |
<li> =web=: copy a web to a destination </li>\
<li> =application>=: Create a web suported by a given application </li>\
<li> =stub=: create a stub for a given application topic </li> </ul> | |
| =debug= | boolean flag to switch on/off debug output; messages are printed to the error log of the web browser | =off= |
| =dry= | boolean flag to switch on/off a dry mode; if enabled none of the operations will actually be saved permanently | =off= |
| =onlynew= | boolean flag to enable/disable a check for the destination to already exist; an exception will be raised if enabled and the target object already; the target object will be overwritten in case it already exists and the flag is disabled; to be precise, a new revision will be created in this case | =on= |
Expand Down Expand Up @@ -80,6 +82,19 @@ All parameters of the [[##Mode:_61topic_61][topic mode]] apply to each topic in
| =include= | regular expression topics in the source web must match to be included in the copy process | |
| =exclude= | regluar expression; excludes matching topics from the source web | |

---+++ Mode: =application=

| *Name* | *Description* | *Default* |
| =source= | the source topicsto be copied | =%<nop>BASEWEB%= |
| =destination= | the destination web where to copy all source topicsto | |
| =template= | a template web to be used in case the destination web does not exist yet and needs to be created on the base of a template | =_default= |

---+++ Mode: =stub=

| *Name* | *Description* | *Default* |
| =source= | the source topic to be copied | =%<nop>BASEWEB%.%<nop>BASETOPIC%= |
| =destination= | the destination topic where to copy =source= to | =source= |

---++ Examples

---+++ Copy one or more topics to a destination
Expand Down Expand Up @@ -120,7 +135,7 @@ All parameters of the [[##Mode:_61topic_61][topic mode]] apply to each topic in
<label><input type="checkbox" name="forcenewrevision" value="off">%MAKETEXT{"Force a new revision"}%</label> %BR%
<label><input type="checkbox" name="minor" value="off">%MAKETEXT{"Minor change, don't notify others"}%</label> %BR%
<label><input type="checkbox" name="dontlog" value="off">%MAKETEXT{"Don't log changes"}%</label> %BR%
<label><input type="checkbox" name="clear" vlaue="on">%MAKETEXT{"Clear before copying"}%</label>
<label><input type="checkbox" name="clear" value="on">%MAKETEXT{"Clear before copying"}%</label>
</div>
<div class="foswikiFormStep">
%BUTTON{"%MAKETEXT{"Submit"}%" icon="tick" type="submit"}%%CLEAR%
Expand Down Expand Up @@ -174,11 +189,11 @@ All parameters of the [[##Mode:_61topic_61][topic mode]] apply to each topic in

%META:FORM{name="PackageForm"}%
%META:FIELD{name="Author" title="Author" value="Michael Daum"}%
%META:FIELD{name="Version" title="Version" value="%25$VERSION%25"}%
%META:FIELD{name="Release" title="Release" value="%25$RELEASE%25"}%
%META:FIELD{name="Description" title="Description" value="%25$SHORTDESCRIPTION%25"}%
%META:FIELD{name="Repository" title="Repository" value="https://github.com/foswiki/CopyContrib"}%
%META:FIELD{name="Copyright" title="Copyright" value="&copy; 2013-2015, Michael Daum http://michaeldaumconsulting.com"}%
%META:FIELD{name="Description" title="Description" value="%$SHORTDESCRIPTION%"}%
%META:FIELD{name="Home" title="Home" value="http://foswiki.org/Extensions/CopyContrib"}%
%META:FIELD{name="License" title="License" value="[[http://www.gnu.org/licenses/gpl.html][GPL (Gnu General Public License)]]"}%
%META:FIELD{name="Release" title="Release" value="%$RELEASE%"}%
%META:FIELD{name="Repository" title="Repository" value="https://github.com/foswiki/CopyContrib"}%
%META:FIELD{name="Home" title="Home" value="http://foswiki.org/Extensions/CopyContrib"}%
%META:FIELD{name="Support" title="Support" value="http://foswiki.org/Support/CopyContrib"}%
%META:FIELD{name="Version" title="Version" value="%$VERSION%"}%
2 changes: 2 additions & 0 deletions lib/Foswiki/Contrib/CopyContrib.pm
Expand Up @@ -28,7 +28,9 @@ our $SHORTDESCRIPTION = 'Copies webs, topics, attachments, or part of them';
our %agentImpls = (
'topic' => 'Foswiki::Contrib::CopyContrib::TopicAgent',
'topics' => 'Foswiki::Contrib::CopyContrib::TopicListAgent',
'stub' => 'Foswiki::Contrib::CopyContrib::TopicStubAgent',
'web' => 'Foswiki::Contrib::CopyContrib::WebAgent',
'application' => 'Foswiki::Contrib::CopyContrib::ApplicationAgent',
# 'webs' => 'Foswiki::Contrib::CopyContrib::WebListAgent',
);

Expand Down
180 changes: 180 additions & 0 deletions lib/Foswiki/Contrib/CopyContrib/ApplicationAgent.pm
@@ -0,0 +1,180 @@
# Copyright (C) 2013-2015 Michael Daum http://michaeldaumconsulting.com
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details, published at
# http://www.gnu.org/copyleft/gpl.html

package Foswiki::Contrib::CopyContrib::ApplicationAgent;

use strict;
use warnings;

use Foswiki::Func();
use Foswiki::Contrib::CopyContrib::CopyAgent ();
use Foswiki::Contrib::CopyContrib::TopicAgent ();
use Error qw( :try );

use Data::Dumper;

our @ISA = qw( Foswiki::Contrib::CopyContrib::CopyAgent );

###############################################################################
sub parseRequestObject {
my ( $this, $request ) = @_;

$this->SUPER::parseRequestObject($request);

#used parameters: mode, source, destination, template

unless ( defined $this->{srcTopics} ) {
$this->{srcTopics} = ();

# Get source parameter. Use current topic if source is not defined.

my @source = $request->multi_param('source');
@source = ( $this->{baseWeb} . '.' . $this->{baseTopic} )
unless @source;
$request->delete('source');

$this->writeDebug("source topics:");
foreach (@source) {
foreach my $item ( split(/\s*,\s*/) ) {

# $item is of the form: source_topic_name => target_topic_name [copy_type]
$this->writeDebug("... item: $item");
my ( $from, $to, $type ) = ( $item =~
m!\A\s*([\/\.\w]+)\s*(?:=>\s*(\w+))?\s*(\[\w+\])?\s*\Z! );
unless ($from) {
$this->writeDebug(
" >>> not a valid input source parameter. Ignored.");
next;
}

my ( $web, $topic ) =
Foswiki::Func::normalizeWebTopicName( $this->{baseWeb},
$from );
$to = $topic unless $to;
$type = '[topic]' unless $type;
push @{ $this->{srcTopics} },
{
web => $web,
topic => $topic,
target => $to,
type => $type
};
$this->writeDebug("... web.topic=>target: $web.$topic => $to");
}
}
}

# Get the destination parameter and put it in dstWeb
unless ( defined $this->{dstWeb} ) {
$this->{dstWeb} = $request->param('destination');
$request->delete('destination');
$this->writeDebug("dstWeb=$this->{dstWeb}") if defined $this->{dstWeb};
}

# Get the template web. SMELL: Why don't we delete the parameter?
$this->{templateWeb} = $request->param('template')
unless defined $this->{templateWeb};

return $this;
}

###############################################################################
sub copy {
my $this = shift;

$this->writeDebug(
"called copy() " . ( $this->{dry} ? '...dry run' : '' ) );

## check destination web. If it does not exists. create it as is done in the WebAgent (Can't use web agent. It expects source topics.)
## check source list and use topic agent to copy each [normal] topic
## Consider a StubAgent, which copies a given topic to a stub. Web must extist.

throw Error::Simple("No destination") unless defined $this->{dstWeb};

my $count = 0;
my $request = Foswiki::Func::getRequestObject();

unless ( Foswiki::Func::webExists( $this->{dstWeb} ) ) {
my $template = $this->{templateWeb} || '_default';
$this->writeDebug(
"creating destination web '$this->{dstWeb}' using template '$template'"
);
Foswiki::Func::createWeb( $this->{dstWeb}, $template )
unless $this->{dry};
}

#print "=== Sleeping...\n"; sleep(60);

if ( Foswiki::Func::webExists( $this->{dstWeb} ) ) {

# copy all topics to a destination web
#BvO $this->{dstWeb} = $this->{dst};

foreach my $item ( @{ $this->{srcTopics} } ) {
if ( $item->{type} eq '[stub]' ) {
$count++;
$this->writeDebug(
"... copying $item->{web}.$item->{topic} to $this->{dstWeb}.$item->{target} AS STUB"
);
copyStub( $this, $item );
}
else { # else[topic]
my $agent = new Foswiki::Contrib::CopyContrib::TopicAgent(
$this->{session},
srcWeb => $item->{web},
srcTopic => $item->{topic},
dstWeb => $this->{dstWeb},
dstTopic => $item->{target},
doClear => $this->{doClear},
dry => $this->{dry},
debug => $this->{debug},
);

$count++;
$this->writeDebug(
"... copying $item->{web}.$item->{topic} to $this->{dstWeb}.$item->{target}"
);
$agent->parseRequestObject($request)->copy();
}
}

return ( "topiclist_success", $count, $this->{dstWeb} );
}
}

sub copyStub {
my ( $this, $item ) = @_;

# Foswiki::Func::saveTopic( $web, $topic, $meta, $text );
Foswiki::Func::saveTopic( $this->{dstWeb}, $item->{target}, undef(),
topicStubTemplate( $item->{web}, $item->{web} . '.' . $item->{topic} )
);

}

sub topicStubTemplate {
my ( $application, $target ) = @_;
my $text = <<"END_HERE";
%META:FORM{name="Applications.TopicStub"}%
%META:FIELD{name="TopicType" title="TopicType" value="TopicStub, TopicType"}%
%META:FIELD{name="TopicTitle" title="<nop>TopicTitle" value=""}%
%META:FIELD{name="Summary" title="Summary" value=""}%
%META:FIELD{name="WikiApplication" title="WikiApplication" value="$application"}%
%META:FIELD{name="Target" title="Target" value="$target"}%
END_HERE

return $text;
}

1;

14 changes: 7 additions & 7 deletions lib/Foswiki/Contrib/CopyContrib/CopyAgent.pm
Expand Up @@ -46,27 +46,27 @@ sub writeDebug {
sub parseRequestObject {
my ($this, $request) = @_;

$this->{debug} = Foswiki::Func::isTrue($request->param('debug'), $this->{debug})
$this->{debug} = Foswiki::Func::isTrue(scalar $request->param('debug'), $this->{debug})
unless defined $this->{debug};

#$this->writeDebug("called parseRequestObject()");

$this->{dry} = Foswiki::Func::isTrue($request->param('dry'), $this->{dry})
$this->{dry} = Foswiki::Func::isTrue(scalar $request->param('dry'), $this->{dry})
unless defined $this->{dry};

$this->{onlyNew} = Foswiki::Func::isTrue($request->param('onlynew'), 1)
$this->{onlyNew} = Foswiki::Func::isTrue(scalar $request->param('onlynew'), 1)
unless defined $this->{onlyNew};

$this->{doClear} = Foswiki::Func::isTrue($request->param('clear'), 0)
$this->{doClear} = Foswiki::Func::isTrue(scalar $request->param('clear'), 0)
unless defined $this->{doClear};

$this->{forceNewRevision} = Foswiki::Func::isTrue($request->param('forcenewrevision'), 0)
$this->{forceNewRevision} = Foswiki::Func::isTrue(scalar $request->param('forcenewrevision'), 0)
unless defined $this->{forceNewRevision};

$this->{dontLog} = Foswiki::Func::isTrue($request->param('dontlog'), 0)
$this->{dontLog} = Foswiki::Func::isTrue(scalar $request->param('dontlog'), 0)
unless defined $this->{dontLog};

$this->{minor} = Foswiki::Func::isTrue($request->param('minor'), 0)
$this->{minor} = Foswiki::Func::isTrue(scalar $request->param('minor'), 0)
unless defined $this->{minor};


Expand Down
16 changes: 8 additions & 8 deletions lib/Foswiki/Contrib/CopyContrib/TopicAgent.pm
Expand Up @@ -42,8 +42,8 @@ sub parseRequestObject {
($this->{dstWeb}, $this->{dstTopic}) = Foswiki::Func::normalizeWebTopicName($this->{baseWeb}, $this->{dst})
unless defined $this->{dstWeb} && defined $this->{dstTopic};

#$this->writeDebug("srcWeb=$this->{srcWeb}, srcTopic=$this->{srcTopic}");
#$this->writeDebug("dstWeb=$this->{dstWeb}, dstTopic=$this->{dstTopic}");
$this->writeDebug("srcWeb=$this->{srcWeb}, srcTopic=$this->{srcTopic}");
$this->writeDebug("dstWeb=$this->{dstWeb}, dstTopic=$this->{dstTopic}");

my @includeParts = ();
my $includeParts = $request->param('includeparts');
Expand Down Expand Up @@ -148,7 +148,7 @@ sub checkAccess {
sub read {
my ($this, $doReload) = @_;

#$this->writeDebug("called read");
$this->writeDebug("called read");

# read/create destination object
if (!defined($this->{dstMeta}) || $doReload) {
Expand Down Expand Up @@ -178,7 +178,7 @@ sub copyPart {
!$this->{excludeparts}{$partId}
);

#$this->writeDebug("called copyPart($partId)");
$this->writeDebug("called copyPart($partId)");
$this->read;

# special handling of attachments
Expand All @@ -204,7 +204,7 @@ sub copyPart {
throw Error::Simple("Unknown meta data id '$partId'")
unless defined $metaDataName;

#$this->writeDebug("metaDataName=$metaDataName");
$this->writeDebug("metaDataName=$metaDataName");

my $exclude = $this->{'exclude'.$partId};
my $include = $this->{'include'.$partId};
Expand All @@ -230,7 +230,7 @@ sub copyPart {
$count++;
}

#$this->writeDebug("copied $count $partId item(s)") if $count;
$this->writeDebug("copied $count $partId item(s)") if $count;
}

###############################################################################
Expand Down Expand Up @@ -281,8 +281,8 @@ sub copyAttachments {
sub copy {
my $this = shift;

#$this->writeDebug("called copy() ".($this->{dry}?'...dry run':''));
#$this->writeDebug("doClear=".$this->{doClear});
$this->writeDebug("called copy() ".($this->{dry}?'...dry run':''));
$this->writeDebug("doClear=".$this->{doClear});

throw Error::Simple("Topic $this->{srcWeb}.$this->{srcTopic} does not exist")
unless Foswiki::Func::topicExists($this->{srcWeb}, $this->{srcTopic});
Expand Down

0 comments on commit 18f40d1

Please sign in to comment.