]> CyberLeo.Net >> Repos - SourceForge/phpwiki.git/blob - lib/MailNotify.php
Move mailer functions into seperate MailNotify.php
[SourceForge/phpwiki.git] / lib / MailNotify.php
1 <?php //-*-php-*-
2 rcs_id('$Id: MailNotify.php,v 1.1 2006-12-22 17:59:55 rurban Exp $');
3
4 /**
5  * Handle the pagelist pref[notifyPages] logic for users
6  * and notify => hash ( page => (userid => userhash) ) for pages.
7  * Generate notification emails.
8  *
9  * We add WikiDB handlers and register ourself there:
10  *   onDeletePage, onRenamePage
11  * Administrative actions:
12  *   [Watch] WatchPage - add a page, or delete watch handlers into the users 
13  *                       pref[notifyPages] slot.
14  *   My WatchList      - view or edit list/regex of pref[notifyPages].
15  *
16  * Helper functions:
17  *   getPageChangeEmails
18  *   MailAdmin
19  *   ? handle emailed confirmation links (EmailSignup, ModeratedPage)
20  *
21  * @package MailNotify
22  * @author  Reini Urban
23  */
24
25 class MailNotify {
26
27     function MailNotify($pagename) {
28         $this->pagename = $pagename; /* which page */
29         $this->emails  = array();    /* to whch addresses */
30         $this->userids = array();    /* corresponding array of displayed names, 
31                                       dont display the email addersses */
32         /* from: from which the mail appears to be */
33         $this->from = $this->fromId();
34     }
35
36     function fromId() {
37         global $request;
38         return $request->_user->getId() . '@' .  $request->get('REMOTE_HOST');
39     }
40
41     function userEmail($userid, $doverify = true) {
42         global $request;
43         $u = $request->getUser();
44         if ($u->UserName() == $userid) { // lucky: current user
45             $prefs = $u->getPreferences();
46             $email = $prefs->get('email');
47             // do a dynamic emailVerified check update
48             if ($doverify and !$request->_prefs->get('emailVerified'))
49                 $email = '';
50         } else {  // not current user
51             if (ENABLE_USER_NEW) {
52                 $u = WikiUser($userid);
53                 $u->getPreferences();
54                 $prefs = &$u->_prefs;
55             } else {
56                 $u = new WikiUser($request, $userid);
57                 $prefs = $u->getPreferences();
58             }
59             $email = $prefs->get('email');
60             if ($doverify and !$prefs->get('emailVerified')) {
61                 $email = '';
62             }
63         }
64         return $email;
65     }
66
67     /**
68      * getPageChangeEmails($notify)
69      * @param  $notify: hash ( page => (userid => userhash) )
70      * @return array
71      *         unique array of ($emails, $userids)
72      */
73     function getPageChangeEmails($notify) {
74         global $request;
75         $emails = array(); $userids = array();
76         foreach ($notify as $page => $users) {
77             if (glob_match($page, $this->pagename)) {
78                 foreach ($users as $userid => $user) {
79                     if (!$user) { // handle the case for ModeratePage: 
80                                   // no prefs, just userid's.
81                         $emails[] = $this->userEmail($userid, false);
82                         $userids[] = $userid;
83                     } else {
84                         if (!empty($user['verified']) and !empty($user['email'])) {
85                             $emails[]  = $user['email'];
86                             $userids[] = $userid;
87                         } elseif (!empty($user['email'])) {
88                             // do a dynamic emailVerified check update
89                             $email = $this->userEmail($userid, true);
90                             if ($email) {
91                                 $notify[$page][$userid]['verified'] = 1;
92                                 $request->_dbi->set('notify', $notify);
93                                 $emails[] = $email;
94                                 $userids[] = $userid;
95                             }
96                         }
97                         // ignore verification
98                         /*
99                         if (DEBUG) {
100                             if (!in_array($user['email'],$emails))
101                                 $emails[] = $user['email'];
102                         }
103                         */
104                     }
105                 }
106             }
107         }
108         $this->emails = array_unique($emails);
109         $this->userids = array_unique($userids);
110         return array($this->emails, $this->userids);
111     }
112
113     function sendMail($subject, $content) {
114         global $request;
115         $emails = $this->emails;
116         $from = $this->from;
117         if (mail(array_shift($emails),
118                  "[".WIKI_NAME."] ".$subject, 
119                  $subject."\n".$content,
120                  "From: $from\r\nBcc: ".join(',', $emails)
121                  )) 
122         {
123             trigger_error(sprintf(_("PageChange Notification of %s sent to %s"),
124                                   $this->pagename, join(',',$this->userids)), E_USER_NOTICE);
125             return true;
126         } else {
127             trigger_error(sprintf(_("PageChange Notification of %s Error: Couldn't send to %s"),
128                                   $this->pagename, join(',',$this->userids)), E_USER_WARNING);
129             return false;
130         }
131     }
132
133     /**
134      * Send udiff for a changed page to multiple users.
135      * See rename and remove methods also
136      */
137     function sendPageChangeNotification(&$wikitext, $version, &$meta) {
138
139         global $request;
140
141         if (@is_array($request->_deferredPageChangeNotification)) {
142             // collapse multiple changes (loaddir) into one email
143             $request->_deferredPageChangeNotification[] = 
144                 array($this->pagename, $this->emails, $this->userids);
145             return;
146         }
147         $backend = &$this->_wikidb->_backend;
148         //$backend = &$request->_dbi->_backend;
149         $subject = _("Page change").' '.urlencode($this->pagename);
150         $previous = $backend->get_previous_version($this->pagename, $version);
151         if (!isset($meta['mtime'])) $meta['mtime'] = time();
152         if ($previous) {
153             $difflink = WikiURL($this->pagename, array('action'=>'diff'), true);
154             $dbh = &$request->getDbh();
155             $cache = &$dbh->_wikidb->_cache;
156             //$cache = &$request->_dbi->_cache;
157             $content = explode("\n", $wikitext);
158             $prevdata = $cache->get_versiondata($this->pagename, $previous, true);
159             if (empty($prevdata['%content']))
160                 $prevdata = $backend->get_versiondata($this->pagename, $previous, true);
161             $other_content = explode("\n", $prevdata['%content']);
162             
163             include_once("lib/difflib.php");
164             $diff2 = new Diff($other_content, $this_content);
165             //$context_lines = max(4, count($other_content) + 1,
166             //                     count($this_content) + 1);
167             $fmt = new UnifiedDiffFormatter(/*$context_lines*/);
168             $content  = $this->pagename . " " . $previous . " " . 
169                 Iso8601DateTime($prevdata['mtime']) . "\n";
170             $content .= $this->pagename . " " . $version . " " .  
171                 Iso8601DateTime($meta['mtime']) . "\n";
172             $content .= $fmt->format($diff2);
173             
174         } else {
175             $difflink = WikiURL($this->pagename,array(),true);
176             $content = $this->pagename . " " . $version . " " .  
177                 Iso8601DateTime($meta['mtime']) . "\n";
178             $content .= _("New page");
179         }
180         $editedby = sprintf(_("Edited by: %s"), $this->from);
181         //$editedby = sprintf(_("Edited by: %s"), $meta['author']);
182         $this->sendMail($subject, 
183                         $editedby."\n".$difflink."\n\n".$content);
184     }
185
186     /** 
187      * support mass rename / remove (not yet tested)
188      */
189     function sendPageRenameNotification ($to, &$meta) {
190         global $request;
191
192         if (@is_array($request->_deferredPageRenameNotification)) {
193             $request->_deferredPageRenameNotification[] = 
194                 array($this->pagename, $to, $meta, $this->emails, $this->userids);
195         } else {
196             $pagename = $this->pagename;
197             //$editedby = sprintf(_("Edited by: %s"), $meta['author']) . ' ' . $meta['author_id'];
198             $editedby = sprintf(_("Edited by: %s"), $this->from);
199             $subject = sprintf(_("Page rename %s to %s"), urlencode($pagename), urlencode($to));
200             $link = WikiURL($to, true);
201             $this->sendMail($subject, 
202                             $editedby."\n".$link."\n\n"."Renamed $pagename to $to");
203         }
204     }
205
206     /**
207      * The handlers:
208      */
209     function onChangePage (&$wikidb, &$wikitext, $version, &$meta) {
210         $result = true;
211         if (!isa($GLOBALS['request'],'MockRequest')) {
212             $notify = $wikidb->_wikidb->get('notify');
213             /* Generate notification emails? */
214             if (!empty($notify) and is_array($notify)) {
215                 if (empty($this->pagename))
216                     $this->pagename = $meta['pagename'];
217                 //TODO: defer it (quite a massive load if you MassRevert some pages).
218                 //TODO: notification class which catches all changes,
219                 //  and decides at the end of the request what to mail. (type, page, who, what, users, emails)
220                 // could be used for PageModeration and RSS2 Cloud xml-rpc also.
221                 $this->getPageChangeEmails($notify);
222                 if (!empty($this->emails)) {
223                     $result = $this->sendPageChangeNotification($wikitext, $version, $meta);
224                 }
225             }
226         }
227         return $result;
228     }
229
230     function onDeletePage (&$wikidb, $pagename) {
231         /* Generate notification emails? */
232         if (! $wikidb->isWikiPage($pagename) and !isa($GLOBALS['request'],'MockRequest')) {
233             $notify = $wikidb->get('notify');
234             if (!empty($notify) and is_array($notify)) {
235                 //TODO: deferr it (quite a massive load if you remove some pages).
236                 //TODO: notification class which catches all changes,
237                 //  and decides at the end of the request what to mail. (type, page, who, what, users, emails)
238                 // could be used for PageModeration and RSS2 Cloud xml-rpc also.
239                 $page = new WikiDB_Page($wikidb, $pagename);
240                 $page->getPageChangeEmails($notify);
241                 if (!empty($this->emails)) {
242                     $editedby = sprintf(_("Removed by: %s"), $this->from); // Todo: host_id
243                     $emails = join(',', $emails);
244                     $subject = sprintf(_("Page removed %s"), urlencode($pagename));
245                     $result = $this->sendMail($subject, 
246                                               $editedby."\n"."Deleted $pagename"."\n\n".$content);
247                 }
248             }
249         }
250         //How to create a RecentChanges entry with explaining summary? Dynamically
251         /*
252           $page = $this->getPage($pagename);
253           $current = $page->getCurrentRevision();
254           $meta = $current->_data;
255           $version = $current->getVersion();
256           $meta['summary'] = _("removed");
257           $page->save($current->getPackedContent(), $version + 1, $meta);
258         */
259         return $result;
260     }
261
262     function onRenamePage (&$wikidb, $oldpage, $new_pagename) {
263         $result = true;
264         if (!isa($GLOBALS['request'], 'MockRequest')) {
265             $notify = $wikidb->get('notify');
266             if (!empty($notify) and is_array($notify)) {
267                 $this->getPageChangeEmails($notify);
268                 if (!empty($this->emails)) {
269                     $newpage = $wikidb->getPage($new_pagename);
270                     $current = $newpage->getCurrentRevision();
271                     $meta = $current->_data;
272                     $this->pagename = $oldpage;
273                     $result = $this->sendPageRenameNotification($new_pagename, $meta);
274                 }
275             }
276         }
277     }
278 }
279
280
281 // $Log: not supported by cvs2svn $
282
283 // Local Variables:
284 // mode: php
285 // tab-width: 8
286 // c-basic-offset: 4
287 // c-hanging-comment-ender-p: nil
288 // indent-tabs-mode: nil
289 // End:   
290 ?>