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