rename hook: run once per file to be renamed
authorintrigeri <intrigeri@boum.org>
Sun, 8 Mar 2009 10:44:00 +0000 (11:44 +0100)
committerintrigeri <intrigeri@boum.org>
Sun, 8 Mar 2009 10:44:00 +0000 (11:44 +0100)
... as Joey suggested on todo/need_global_renamepage_hook

This hook is applied recursively to returned additional rename
hashes, so that it handles the case where two plugins use the hook:
plugin A would see when plugin B adds a new file to be renamed.

The full set of rename hashes can no longer be changed by hook functions, that
are only allowed to return any additional rename hashes it wants to add.
Rationale: the correct behavior of the recursion would be hard, if not
impossible, to define, if already considered pages were changing on the run.

Signed-off-by: intrigeri <intrigeri@boum.org>
IkiWiki/Plugin/po.pm
IkiWiki/Plugin/rename.pm
doc/plugins/write.mdwn

index 9a3df79ac2fd2498a56801c624f722a2f9d435b8..f25beba7236c69c742686d0f7ade6daa0f24a25d 100644 (file)
@@ -295,7 +295,7 @@ sub pagetemplate (@) {
 sub renamepages(@) {
        my %params = @_;
 
-       my @torename = @{$params{torename}};
+       my %torename = %{$params{torename}};
        my $session = $params{session};
 
        # Save the page(s) the user asked to rename, so that our
@@ -305,24 +305,25 @@ sub renamepages(@) {
        #  - a user trying to directly rename a translation
        # This is why this hook has to be run first, before the list of pages
        # to rename is modified by other plugins.
-       $session->param(po_orig_torename => \@torename);
+       my @orig_torename;
+       @orig_torename=@{$session->param("po_orig_torename")}
+               if defined $session->param("po_orig_torename");
+       push @orig_torename, $torename{src};
+       $session->param(po_orig_torename => \@orig_torename);
        IkiWiki::cgi_savesession($session);
 
-       my @ret=@torename;
-       # iterate on @torename and push onto @ret, so that we don't iterate
-       # on the items we added ourselves
-       foreach my $rename (@torename) {
-               next unless istranslatable($rename->{src});
-               my %otherpages=%{otherlanguages($rename->{src})};
-               while (my ($lang, $otherpage) = each %otherpages) {
-                       push @ret, {
-                               src => $otherpage,
-                               srcfile => $pagesources{$otherpage},
-                               dest => otherlanguage($rename->{dest}, $lang),
-                               destfile => $rename->{dest}.".".$lang.".po",
-                               required => 0,
-                       };
-               }
+       return () unless istranslatable($torename{src});
+
+       my @ret;
+       my %otherpages=%{otherlanguages($torename{src})};
+       while (my ($lang, $otherpage) = each %otherpages) {
+               push @ret, {
+                       src => $otherpage,
+                       srcfile => $pagesources{$otherpage},
+                       dest => otherlanguage($torename{dest}, $lang),
+                       destfile => $torename{dest}.".".$lang.".po",
+                       required => 0,
+               };
        }
        return @ret;
 }
@@ -443,7 +444,7 @@ sub canrename (@) {
                # by looking for the master page in the list of to-be-renamed pages we
                # saved early in the renaming process.
                my $orig_torename = $session->param("po_orig_torename");
-               unless (grep { $_->{src} eq $masterpage } @{$orig_torename}) {
+               unless (grep { $_ eq $masterpage } @{$orig_torename}) {
                        return gettext("Can not rename a translation. Renaming the master page, ".
                                       "though, renames its translations as well.");
                }
index f39c93332e311fd3cc452e06525c2d4827eef984..ccbf09c3f90ad3ab848ea0a354bdd6fdd903ca08 100644 (file)
@@ -312,14 +312,6 @@ sub sessioncgi ($$) {
                                required => 1,
                        };
 
-                       IkiWiki::run_hooks(rename => sub {
-                               @torename=shift->(
-                                       torename => \@torename,
-                                       cgi => $q,
-                                       session => $session
-                               );
-                       });
-
                        # See if any subpages need to be renamed.
                        if ($q->param("subpages") && $src ne $dest) {
                                foreach my $p (keys %pagesources) {
@@ -341,6 +333,13 @@ sub sessioncgi ($$) {
                                }
                        }
                        
+                       @torename=rename_hook(
+                               torename => \@torename,
+                               done => {},
+                               cgi => $q,
+                               session => $session,
+                       );
+
                        require IkiWiki::Render;
                        IkiWiki::disable_commit_hook() if $config{rcs};
                        my %origpagesources=%pagesources;
@@ -466,6 +465,42 @@ sub renamepage_hook ($$$$) {
 
        return $content;
 }
+
+sub rename_hook (@) {
+       my %params = @_;
+
+       my @torename=@{$params{torename}};
+       my %done=%{$params{done}};
+       my $q=$params{cgi};
+       my $session=$params{session};
+
+       debug("rename_hook called with ".scalar(@torename)." args.");
+       my @nextset;
+       if (@torename) {
+               foreach my $torename (@torename) {
+                       unless (exists $done{$torename->{src}} && $done{$torename->{src}}) {
+                               IkiWiki::run_hooks(rename => sub {
+                                       push @nextset, shift->(
+                                               torename => $torename,
+                                               cgi => $q,
+                                               session => $session,
+                                       );
+                               });
+                               $done{$torename->{src}}=1;
+                       }
+               }
+               push @torename, rename_hook(
+                       torename => \@nextset,
+                       done => \%done,
+                       cgi => $q,
+                       session => $session,
+               );
+               return @torename;
+       }
+       else {
+               return ();
+       }
+}
                        
 sub do_rename ($$$) {
        my $rename=shift;
index be01605e83568ac633a94749b36001ec5e6689a1..cccfb9bbaab048e2d04631d13b3b0c740d95c421 100644 (file)
@@ -422,14 +422,18 @@ new page.
        hook(type => "rename", id => "foo", call => \&rename);
 
 When a page or set of pages is renamed, the referenced function is
-called, and is passed named parameters:
+called for every page, and is passed named parameters:
 
-* `torename`: a reference to an array of hashes with keys: `src`, `srcfile`,
-  `dest`, `destfile`, `required`. Such a hook function can either return the
-  array content unchanged, or modify it and return the modified version.
+* `torename`: a reference to a hash with keys: `src`, `srcfile`,
+  `dest`, `destfile`, `required`.
 * `cgi`: a CGI object
 * `session`: a session object.
 
+Such a hook function returns any additional rename hashes it wants to
+add. This hook is applied recursively to returned additional rename
+hashes, so that it handles the case where two plugins use the hook:
+plugin A would see when plugin B adds a new file to be renamed.
+
 ### getsetup
 
        hook(type => "getsetup", id => "foo", call => \&getsetup);