2 rcs_id('$Id: ModeratedPage.php,v 1.2 2004-11-30 17:46:49 rurban Exp $');
4 Copyright 2004 $ThePhpWikiProgrammingTeam
6 This file is part of PhpWiki.
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.
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.
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
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
31 require_once("lib/WikiPlugin.php");
33 class WikiPlugin_ModeratedPage
37 return _("ModeratedPage");
39 function getDescription () {
40 return _("Support moderated pages");
42 function getVersion() {
43 return preg_replace("/[Revision: $]/", '',
46 function getDefaultArguments() {
47 return array('page' => '[pagename]',
48 'moderators' => false,
49 'require_level' => false, // 1=bogo
50 'require_access' => 'edit,remove,change',
56 function run($dbi, $argstr, &$request, $basepage) {
57 $args = $this->getArgs($argstr, $request);
59 // handle moderation request from the email
60 if (!empty($args['id']) and !empty($args['pass'])) {
62 return $this->error("No page specified");
63 $page = $dbi->getPage($args['page']);
64 $moderation = $page->get("moderation");
66 if (isset($moderation['id']) and $moderation['id'] == $args['id']) {
69 if ($args['pass'] == 'approve')
70 return $this->approve($args, $moderation);
71 elseif ($args['pass'] == 'reject')
72 return $this->reject($args, $moderation);
74 return $this->error("Wrong pass ".$args['pass']);
76 return $this->error("Wrong id");
84 * resolve moderators and require_access (not yet) from actionpage plugin argstr
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));
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);
102 if (!$moderators) $moderators = array(ADMIN_USER);
103 $args['moderators'] = $moderators;
105 //resolve email for $args['moderators']
106 $page = $request->getPage();
108 foreach ($args['moderators'] as $userid) {
111 list($args['emails'], $args['moderators']) = $page->getPageChangeEmails(array($page->getName() => $users));
113 unset($args['page']);
114 unset($args['pass']);
119 * Handle client-side moderation change request.
120 * Hook called on the lock action, if moderation metadata already exists.
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);
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']));
135 $page->set('moderation', false);
136 return $this->notice(HTML($status,
137 fmt("'%s' is no ModeratedPage anymore.", $page->getName())));
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
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);
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']));
163 function notice($msg) {
164 return HTML::div(array('class' => 'wiki-edithelp'), $msg);
167 function generateId() {
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);
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.
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'];
189 $action_page = $request->getPage(_("ModeratedPage"));
190 $status = $this->getSiteStatus($request, $action_page);
191 $moderated['_status'] = $status;
193 if (!empty($status['emails'])) {
194 trigger_error(_("ModeratedPage: No emails for the moderators defined"), E_USER_WARNING);
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",
209 join(", ", $status['moderators'])
212 $pagename = $page->getName();
213 $subject = "[".WIKI_NAME.'] '.$action.': '._("ModeratedPage").' '.$pagename;
214 if (mail(join(",", $status['emails']),
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"
221 $page->set('moderated', $moderated);
222 return false; // pass thru
224 //FIXME: This will msg get lost on the edit redirect
225 trigger_error(_("ModeratedPage Notification Error: Couldn't send email"), E_USER_WARNING);
233 * Handle admin-side moderation resolve.
235 function approve($args, $moderation) {
239 * Handle admin-side moderation resolve.
241 function reject($args, $moderation) {
246 * Get the side-wide ModeratedPage status, reading the action-page args.
247 * Who are the moderators? What actions should be moderated?
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]);
264 return $this->error(sprintf(_("<?plugin ModeratedPage ... ?> not found in first line of %s"),
265 $action_page->getName()));
271 // $Log: not supported by cvs2svn $
272 // Revision 1.1 2004/11/19 19:22:35 rurban
273 // ModeratePage part1: change status
281 // c-hanging-comment-ender-p: nil
282 // indent-tabs-mode: nil