add Subscriptions field to prefs
[ikiwiki.git] / IkiWiki / Plugin / changemail.pm
1 #!/usr/bin/perl
2 package IkiWiki::Plugin::changemail;
3
4 use warnings;
5 use strict;
6 use IkiWiki 3.00;
7
8 sub import {
9         hook(type => "formbuilder_setup", id => "changemail", call => \&formbuilder_setup);
10         hook(type => "formbuilder", id => "changemail", call => \&formbuilder);
11         hook(type => "getsetup", id => "changemail",  call => \&getsetup);
12         hook(type => "change", id => "changemail", call => \&notify);
13 }
14
15 sub getsetup () {
16         return
17                 plugin => {
18                         safe => 1,
19                         rebuild => 0,
20                         section => "misc",
21                 },
22 }
23
24 sub formbuilder_setup (@) {
25         my %params=@_;
26
27         my $form=$params{form};
28         return unless $form->title eq "preferences";
29         my $session=$params{session};
30         my $user_name=$session->param("name");
31         eval q{use IkiWiki::UserInfo};
32         error $@ if $@;
33         $form->field(name => "subscriptions", force => 1, size => 50,
34                 fieldset => "preferences",
35                 comment => "(".htmllink("", "", "ikiwiki/PageSpec", noimageinline => 1).")",
36                 value => IkiWiki::userinfo_get($user_name, "subscriptions"));
37 }
38
39 sub formbuilder (@) {
40         my %params=@_;
41         my $form=$params{form};
42         return unless $form->title eq "preferences" &&
43                 $form->submitted eq "Save Preferences" && $form->validate &&
44                 defined $form->field("subscriptions");
45         setsubscriptions($form->field('name'), $form->field('subscriptions'));
46 }
47
48 sub setsubscriptions ($$) {
49         my $user=shift;
50         my $subscriptions=shift;
51         eval q{use IkiWiki::UserInfo};
52         error $@ if $@;
53         IkiWiki::userinfo_set($user, "subscriptions", $subscriptions);
54 }
55
56 sub notify (@) {
57         my @files=@_;
58         return unless @files;
59
60         eval q{use Mail::Sendmail};
61         error $@ if $@;
62         eval q{use IkiWiki::UserInfo};
63         error $@ if $@;
64
65         # Daemonize, in case the mail sending takes a while.
66         defined(my $pid = fork) or error("Can't fork: $!");
67         return if $pid; # parent
68         chdir '/';
69         open STDIN, '/dev/null';
70         open STDOUT, '>/dev/null';
71         POSIX::setsid() or error("Can't start a new session: $!");
72         open STDERR, '>&STDOUT' or error("Can't dup stdout: $!");
73
74         # Don't need to keep a lock on the wiki as a daemon.
75         IkiWiki::unlockwiki();
76
77         my $userinfo=IkiWiki::userinfo_retrieve();
78         exit 0 unless defined $userinfo;
79
80         foreach my $user (keys %$userinfo) {
81                 my $pagespec=$userinfo->{$user}->{"subscriptions"};
82                 next unless defined $pagespec && length $pagespec;
83                 my $email=$userinfo->{$user}->{email};
84                 next unless defined $email && length $email;
85
86                 foreach my $file (@files) {
87                         my $page=pagename($file);
88                         next unless pagespec_match($page, $pagespec);
89                         my $ispage=defined pagetype($file);
90                         my $url;
91                         if (! IkiWiki::isinternal($page)) {
92                                 $url=urlto($page, undef, 1);
93                         }
94                         elsif (defined $pagestate{$page}{meta}{permalink}) {
95                                 # need to use permalink for an internal page
96                                 $url=$pagestate{$page}{meta}{permalink};
97                         }
98                         else {
99                                 $url=$config{wikiurl}; # crummy fallback url
100                         }
101                         my $template=template("changemail.tmpl");
102                         $template->param(
103                                 wikiname => $config{wikiname},
104                                 url => $url,
105                                 prefsurl => IkiWiki::cgiurl(do => "prefs"),
106                                 ispage => $ispage,
107                                 content => $ispage ? readfile(srcfile($file)) : "",
108                         );
109                         #translators: The two variables are the name of the wiki,
110                         #translators: and a page that was changed.
111                         #translators: This is used as the subject of a commit email.
112                         my $subject=sprintf(gettext("%s: change notification for %s"),
113                                 $config{wikiname}, $page);
114                         sendmail(
115                                 To => $email,
116                                 From => "$config{wikiname} <$config{adminemail}>",
117                                 Subject => $subject,
118                                 Message => $template->output,
119                         );
120                 }
121         }
122
123         exit 0; # daemon child
124 }
125
126 1