Skip to content

Commit

Permalink
Item8370: support synching attachments, filtering on the attachment name
Browse files Browse the repository at this point in the history
git-svn-id: http://svn.foswiki.org/trunk/MirrorWebPlugin@5839 0b4bb1d4-4e5a-0410-9cc4-b2b747904278
  • Loading branch information
CrawfordCurrie authored and CrawfordCurrie committed Dec 21, 2009
1 parent 0a717e5 commit d37c2ca
Show file tree
Hide file tree
Showing 3 changed files with 79 additions and 11 deletions.
12 changes: 10 additions & 2 deletions data/System/MirrorWebPlugin.txt
Expand Up @@ -41,6 +41,9 @@ TaskTeamForm => {
Summary => [],
Status => []
},
FILEATTACHMENT => [
'.*\.gif' => []
],
text => []
},
none {
Expand All @@ -56,7 +59,11 @@ This defines a set of filters for all topics that carry:
1 =none= for topics with no form, or
1 =other= for topics that have a form but it isn't explicitly listed, or if it would match 'none' but 'none' is not defined. If a topic doesn't match any of the defined rule sets, it won't be mirrored.

Each form type maps parts of the topic to another hash or to a filter; at this level the keys 'FIELD' and 'text' can be used, relating to the individual fields in the form and the main body text respectively. 'text' is mapped direct to a filter. Under 'FIELD' the name of each form field is mapped to a list of filter names. =[]= means the same as 'accept this field without modification'. Any fields not listed in the rules will be ignored.
Each form type maps parts of the topic to another hash or to a filter; at this level the keys 'FIELD', 'FILEATTACHMENT' and 'text' can be used, relating to the individual fields in the form and the main body text respectively. 'text' is mapped direct to a filter. Under 'FIELD' and 'FILEATTACHMENT', a list of regular expressions match the _full_ name of each entry, and map them to a list of filter names.
* =[]= means the same as 'accept this without modification'.
* Any fields/attachents not matched by any of the rules will be ignored.
* If a name is matched by more than one set of filters, then only the first match will be applied.
* FIELD matches the field name; FILEATTACHMENT matches the attachment name.

Thus the example defines rules for topics that (1) have the form 'TaskTeamForm', (2) have no form or (3) have a form but it isn't known. If the topic has no form, the text is just copied. If the topic has a form, but it doesn't have any rules, then the transformation is to add the text returned by the 'UNKNOWN' function before the topic text. If the topic has the 'TaskTeamForm', then the body text and the 'Summary', and 'Status' fields from the form are all copied across without modification. The filtering of 'Customer' field is used to create a group name that is then used to set the access controls on the mirror topic.

Expand Down Expand Up @@ -91,7 +98,7 @@ sub execute {
All the functions useable in plugins (such as Foswiki::Func) are also available in filters. The parameters to the =execute= function are:
| =$topicObject= | The Foswiki::Meta object of the source topic |
| =$mirrorObject= | The Foswiki::Meta object of the mirror topic |
| =$data= | For a FIELD, this is the structure representing the field, as stored in =Foswiki::Meta=. For =text=, it is the text of the topic. |
| =$data= | For a FIELD or FILEATTACHMENT, this is the structure representing the field, as stored in =Foswiki::Meta=. For =text=, it is the text of the topic. |
| =@params= | Any additional parameters supplied in the rules, in brackets after the filter name (e.g for a filter =MYFILTER(Master,Slave)= then =@params= will be =('Master', 'Slave')= |
Filters can operate directly on these objects; any changes to the =$topicObject= will be discarded. Filters should return =$data=, which is then passed to the next filter. The return value of the final filter function is used to set the data in the mirror topic. If it is =undef=, then the field will not be set in the mirror topic.

Expand Down Expand Up @@ -126,6 +133,7 @@ Many thanks to the following sponsors for supporting this work:
| Release: | %$RELEASE% |
| Version: | %$VERSION% |
| Change History: | <!-- versions below in reverse order -->&nbsp; |
| 21 Dec 2009 | 1.1.3 Support attachment synching, and make field name matches regexes |
| 11 Dec 2009 | 1.1.2 first released version |
| Dependencies: | %$DEPENDENCIES% |
| Home page: | http://foswiki.org/bin/view/Extensions/MirrorWebPlugin |
Expand Down
3 changes: 3 additions & 0 deletions data/System/MirrorWebPluginExampleRules.txt
Expand Up @@ -31,6 +31,9 @@ JobForm => {
Developer Status' => [],
Customer Status' => []
},
FILEATTACHMENT => [
'.*\.jpg' => []
],
text => [ 'TEXTORCOMMENT' ]
}
</verbatim>
75 changes: 66 additions & 9 deletions lib/Foswiki/Plugins/MirrorWebPlugin.pm
Expand Up @@ -16,7 +16,7 @@ use Foswiki::Func ();
use Foswiki::Plugins ();

our $VERSION = '$Rev: 5154 $';
our $RELEASE = '1.1.2';
our $RELEASE = '1.1.3';
our $SHORTDESCRIPTION =
'Mirror a web to another, with filtering on the topic text and fields.';
our $NO_PREFS_IN_TOPIC = 1;
Expand Down Expand Up @@ -123,8 +123,8 @@ sub _synch {
return 0 unless $rules;
}

foreach my $field ( keys %$rules ) {
if ( $field eq 'text' ) {
foreach my $type ( keys %$rules ) {
if ( $type eq 'text' ) {
my $data = $topicObject->text();
$data =
_applyFilters( $rules->{text}, $topicObject, $mirrorObject,
Expand All @@ -133,13 +133,24 @@ sub _synch {
}
else {
# clear old fields
$mirrorObject->remove($field);
$mirrorObject->remove($type);
# Support for all other keyed types
foreach my $name ( keys %{ $rules->{$field} } ) {
my $data = $topicObject->get( $field, $name );
$data = _applyFilters( $rules->{$field}->{$name},
$topicObject, $mirrorObject, $data );
$mirrorObject->putKeyed( $field, $data ) if ref($data);
foreach my $regex ( keys %{ $rules->{$type} } ) {
# Find fields that match the regex
foreach my $data ($topicObject->find($type)) {
if ($data->{name} =~ /^$regex$/) {
$data = _applyFilters(
$rules->{$type}->{$regex},
$topicObject, $mirrorObject, $data );
if (ref($data)) {
$mirrorObject->putKeyed( $type, $data );
if ($type eq 'FILEATTACHMENT') {
_synchAttachment(
$topicObject, $mirrorWeb, $data->{name});
}
}
}
}
}
}
}
Expand Down Expand Up @@ -169,6 +180,52 @@ sub _applyFilters {
return $data;
}

sub _synchAttachment {
my ( $topicObject, $mirrorWeb, $name ) = @_;

# If we are using a file database, do a simple
# copy, including the history.
if (-f $Foswiki::cfg{PubDir} . '/' . $topicObject->web() . '/'
. $topicObject->topic() . '/' . $name) {
mkdir($Foswiki::cfg{PubDir} . '/' . $mirrorWeb);
mkdir($Foswiki::cfg{PubDir} . '/' . $mirrorWeb . '/'
. $topicObject->topic());
File::Copy::copy(
$Foswiki::cfg{PubDir} . '/' . $topicObject->web() . '/'
. $topicObject->topic() . '/' . $name,
$Foswiki::cfg{PubDir} . '/' . $mirrorWeb . '/'
. $topicObject->topic() . '/' . $name);
if (-f $Foswiki::cfg{PubDir} . '/' . $topicObject->web() . '/'
. $topicObject->topic() . '/' . $name . ',v') {
File::Copy::copy(
$Foswiki::cfg{PubDir} . '/' . $topicObject->web() . '/'
. $topicObject->topic() . '/' . $name . ',v',
$Foswiki::cfg{PubDir} . '/' . $mirrorWeb . '/'
. $topicObject->topic() . '/' . $name . ',v');
}
print "Synched ".$topicObject->topic()."/$name\n";
} else {
# Otherwise copy over the latest
my $data = Foswiki::Func::readAttachment(
$topicObject->web(),
$topicObject->topic(),
$name);
my $tmpfile = new File::Temp();
print $tmpfile($data);
$tmpfile->close();
Foswiki::Func::saveAttachment(
$mirrorWeb,
$topicObject->topic(),
$data->{name},
{
dontlog => 1,
comment => "synched",
file => $tmpfile->filename(),
notopicchange => 1,
});
}
}

# Handle the mirror, if required
sub afterSaveHandler {
my ( $text, $topic, $web, $error, $meta ) = @_;
Expand Down

0 comments on commit d37c2ca

Please sign in to comment.