]> CyberLeo.Net >> Repos - SourceForge/phpwiki.git/blob - lib/plugin/ModeratedPage.php
added ModeratedPage POST action hook (part 2/3)
[SourceForge/phpwiki.git] / lib / plugin / ModeratedPage.php
1 <?php // -*-php-*-
2 rcs_id('$Id: ModeratedPage.php,v 1.2 2004-11-30 17:46:49 rurban Exp $');
3 /*
4  Copyright 2004 $ThePhpWikiProgrammingTeam
5  
6  This file is part of PhpWiki.
7
8  PhpWiki is free software; you can redistribute it and/or modify
9  it under the terms of the GNU General Public License as published by
10  the Free Software Foundation; either version 2 of the License, or
11  (at your option) any later version.
12
13  PhpWiki is distributed in the hope that it will be useful,
14  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  GNU General Public License for more details.
17
18  You should have received a copy of the GNU General Public License
19  along with PhpWiki; if not, write to the Free Software
20  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21  */
22 /**
23  * This plugin requires an action page (Default: ModeratedPage)
24  * and provides delayed execution of restricted actions, after
25  * a special moderators request:
26  *   http://mywiki/SomeModeratedPage?action=ModeratedPage&id=kdclcr78431zr43uhrn&pass=approve
27  *
28  * Author: ReiniUrban
29  */
30
31 require_once("lib/WikiPlugin.php");
32
33 class WikiPlugin_ModeratedPage
34 extends WikiPlugin
35 {
36     function getName () {
37         return _("ModeratedPage");
38     }
39     function getDescription () {
40         return _("Support moderated pages");
41     }
42     function getVersion() {
43         return preg_replace("/[Revision: $]/", '',
44                             "\$Revision: 1.2 $");
45     }
46     function getDefaultArguments() {
47         return array('page'          => '[pagename]',
48                      'moderators'    => false,
49                      'require_level' => false,   // 1=bogo
50                      'require_access' => 'edit,remove,change',
51                      'id'   => '',
52                      'pass' => '',
53                     );
54     }
55
56     function run($dbi, $argstr, &$request, $basepage) {
57         $args = $this->getArgs($argstr, $request);
58
59         // handle moderation request from the email
60         if (!empty($args['id']) and !empty($args['pass'])) {
61             if (!$args['page'])
62                 return $this->error("No page specified");
63             $page = $dbi->getPage($args['page']);
64             $moderation = $page->get("moderation");
65             if ($moderation) {
66               if (isset($moderation['id']) and $moderation['id'] == $args['id']) {
67                 // handle defaults:
68                 //   approve or reject
69                 if ($args['pass'] == 'approve')
70                     return $this->approve($args, $moderation);
71                 elseif ($args['pass'] == 'reject')
72                     return $this->reject($args, $moderation);
73                 else
74                     return $this->error("Wrong pass ".$args['pass']);
75               } else {
76                 return $this->error("Wrong id");
77               }
78             }
79         }
80         return '';
81     }
82
83     /**
84      * resolve moderators and require_access (not yet) from actionpage plugin argstr
85      */
86     function resolve_argstr(&$request, $argstr) {
87         $args = $this->getArgs($argstr);
88         $group = $request->getGroup();
89         if (empty($args['moderators'])) {
90             $admins = $group->getSpecialMembersOf(GROUP_ADMIN);
91             // email or usernames?
92             $args['moderators'] = array_merge($admins, array(ADMIN_USER));
93         } else { 
94             // resolve possible group names
95             $moderators = explode(',', $args['moderators']); 
96             for ($i=0; $i < count($moderators); $i++) {
97                 $members = $group->getMembersOf($moderators[$i]);
98                 if (!empty($members)) {
99                     array_splice($moderators, $i, 1, $members);
100                 }
101             }
102             if (!$moderators) $moderators = array(ADMIN_USER);
103             $args['moderators'] = $moderators;
104         }
105         //resolve email for $args['moderators']
106         $page = $request->getPage();
107         $users = array();
108         foreach ($args['moderators'] as $userid) {
109             $users[$userid] = 0;
110         }
111         list($args['emails'], $args['moderators']) = $page->getPageChangeEmails(array($page->getName() => $users));
112         unset($args['id']);
113         unset($args['page']);
114         unset($args['pass']);
115         return $args;
116     }
117     
118     /**
119      * Handle client-side moderation change request.
120      * Hook called on the lock action, if moderation metadata already exists.
121      */
122     function lock_check(&$request, &$page, $moderated) {
123         $action_page = $request->getPage(_("ModeratedPage"));
124         $status = $this->getSiteStatus($request, $action_page);
125         if (is_array($status)) {
126             if (!empty($status['emails'])) {
127                 trigger_error(_("ModeratedPage: No emails for the moderators defined"), E_USER_WARNING);
128                 return false;
129             }
130             $page->set('moderation', array('_status' => $status));
131             return $this->notice(
132                        fmt("ModeratedPage status update:\n  Moderators: '%s'\n  require_access: '%s'", 
133                        join(',', $status['moderators']), $status['require_access']));
134         } else {
135             $page->set('moderation', false);
136             return $this->notice(HTML($status,
137                         fmt("'%s' is no ModeratedPage anymore.", $page->getName()))); 
138         }
139     }
140
141     /**
142      * Handle client-side moderation change request by the user.
143      * Hook called on the lock action, if moderation metadata should be added.
144      * Need to store the the plugin args (who, when) in the page meta-data
145      */
146     function lock_add(&$request, &$page, &$action_page) {
147         $status = $this->getSiteStatus($request, $action_page);
148         if (is_array($status)) {
149             if (!empty($status['emails'])) {
150                 trigger_error(_("ModeratedPage: No emails for the moderators defined"), E_USER_WARNING);
151                 return false;
152             }
153             $page->set('moderation', array('_status' => $status));
154             return $this->notice(
155                        fmt("ModeratedPage status update: '%s' is now a ModeratedPage.\n  Moderators: '%s'\n  require_access: '%s'", 
156                        $page->getName(), join(',', $status['moderators']), $status['require_access']));
157         }
158         else { // error
159             return $status;
160         }
161     }
162     
163     function notice($msg) {
164         return HTML::div(array('class' => 'wiki-edithelp'), $msg);
165     }
166
167     function generateId() {
168         better_srand();
169         $s = "";
170         for ($i = 1; $i <= 16; $i++) {
171             $r = function_exists('mt_rand') ? mt_rand(55, 90) : rand(55, 90);
172             $s .= chr($r < 65 ? $r-17 : $r);
173         }
174         return $s;
175     }
176
177     /** 
178      * Handle client-side moderation request on any moderated page.
179      *   if ($page->get('moderation')) WikiPlugin_ModeratedPage::handler(...);
180      * return false if not handled (pass through), true if handled and displayed.
181      */
182     function handler(&$request, &$page) {
183         $action = $request->getArg('action');
184         $moderated = $page->get('moderated');
185         // cached version, need re-lock of each page to update moderators
186         if (!empty($moderated['_status'])) 
187             $status = $moderated['_status'];
188         else {
189             $action_page = $request->getPage(_("ModeratedPage"));
190             $status = $this->getSiteStatus($request, $action_page);
191             $moderated['_status'] = $status;
192         }
193         if (!empty($status['emails'])) {
194             trigger_error(_("ModeratedPage: No emails for the moderators defined"), E_USER_WARNING);
195             return true;
196         }
197         // which action?
198         if ($action == 'edit') {
199             //$moderated = $page->get('moderated');
200             $id = $this->generateId();
201             while (!empty($moderated[$id])) $id = $this->generateId(); // avoid duplicates
202             $moderated['id'] = $id;
203             $moderated['data'][$id] = array('args' => $request->getArgs(),
204                                             'timestamp' => time(),
205                                             'userid' => $request->_user->getId());
206             $this->_tokens['CONTENT'] = HTML::div(array('class' => 'wikitext'),
207                                                   fmt("%s: action forwarded to moderator %s", 
208                                                       $action, 
209                                                       join(", ", $status['moderators'])
210                                                       ));
211             //send email
212             $pagename = $page->getName();
213             $subject = "[".WIKI_NAME.'] '.$action.': '._("ModeratedPage").' '.$pagename;
214             if (mail(join(",", $status['emails']), 
215                      $subject, 
216                      $action.': '._("ModeratedPage").' '.$pagename."\n"
217                      . serialize($moderated['data'][$id])
218                      ."\n<".WikiURL($pagename, array('id' => $id,'pass' => 'approve'),1).">"
219                      ."\n<".WikiURL($pagename, array('id' => $id,'pass' => 'reject'),1).">\n"
220                      )) {
221                 $page->set('moderated', $moderated);
222                 return false; // pass thru
223             } else {
224                 //FIXME: This will msg get lost on the edit redirect
225                 trigger_error(_("ModeratedPage Notification Error: Couldn't send email"), E_USER_WARNING);
226                 return true;
227             }
228         }
229         return false;
230     }
231
232     /** 
233      * Handle admin-side moderation resolve.
234      */
235     function approve($args, $moderation) {
236         ;
237     }
238     /** 
239      * Handle admin-side moderation resolve.
240      */
241     function reject($args, $moderation) {
242         ;
243     }
244     
245     /**
246      * Get the side-wide ModeratedPage status, reading the action-page args.
247      * Who are the moderators? What actions should be moderated?
248      */
249     function getSiteStatus(&$request, &$action_page) {
250         $loader = new WikiPluginLoader();
251         $rev = $action_page->getCurrentRevision();
252         $content = $rev->getPackedContent();
253         list($pi) = explode("\n", $content, 2); // plugin ModeratedPage must be first line!
254         if ($parsed = $loader->parsePI($pi)) {
255             $plugin =& $parsed[1];
256             if ($plugin->getName() != _("ModeratedPage"))
257                 return $this->error(sprintf(_("<?plugin ModeratedPage ... ?> not found in first line of %s"),
258                                             $action_page->getName()));
259             if (!$action_page->get('locked'))
260                 return $this->error(sprintf(_("%s is not locked!"),
261                                             $action_page->getName()));
262             return $plugin->resolve_argstr($request, $parsed[2]);
263         } else {
264             return $this->error(sprintf(_("<?plugin ModeratedPage ... ?> not found in first line of %s"),
265                                         $action_page->getName()));
266         }
267     }
268     
269 };
270
271 // $Log: not supported by cvs2svn $
272 // Revision 1.1  2004/11/19 19:22:35  rurban
273 // ModeratePage part1: change status
274 //
275
276 // For emacs users
277 // Local Variables:
278 // mode: php
279 // tab-width: 8
280 // c-basic-offset: 4
281 // c-hanging-comment-ender-p: nil
282 // indent-tabs-mode: nil
283 // End:
284 ?>