]> git.mxchange.org Git - quix0rs-gnu-social.git/blob - plugins/GroupPrivateMessage/GroupPrivateMessagePlugin.php
Poll plugin: make the polling response form submit via AJAX and return the results.
[quix0rs-gnu-social.git] / plugins / GroupPrivateMessage / GroupPrivateMessagePlugin.php
1 <?php
2 /**
3  * StatusNet - the distributed open-source microblogging tool
4  * Copyright (C) 2011, StatusNet, Inc.
5  *
6  * Private groups for StatusNet 0.9.x
7  *
8  * PHP version 5
9  *
10  * This program is free software: you can redistribute it and/or modify
11  * it under the terms of the GNU Affero General Public License as published by
12  * the Free Software Foundation, either version 3 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Affero General Public License for more details.
19  *
20  * You should have received a copy of the GNU Affero General Public License
21  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
22  *
23  * @category  Privacy
24  * @package   StatusNet
25  * @author    Evan Prodromou <evan@status.net>
26  * @copyright 2011 StatusNet, Inc.
27  * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
28  * @link      http://status.net/
29  */
30
31 if (!defined('STATUSNET')) {
32     // This check helps protect against security problems;
33     // your code file can't be executed directly from the web.
34     exit(1);
35 }
36
37 /**
38  * Private groups
39  *
40  * This plugin allows users to send private messages to a group.
41  *
42  * @category  Privacy
43  * @package   StatusNet
44  * @author    Evan Prodromou <evan@status.net>
45  * @copyright 2011 StatusNet, Inc.
46  * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
47  * @link      http://status.net/
48  */
49
50 class GroupPrivateMessagePlugin extends Plugin
51 {
52     /**
53      * Database schema setup
54      *
55      * @see Schema
56      * @see ColumnDef
57      *
58      * @return boolean hook value
59      */
60
61     function onCheckSchema()
62     {
63         $schema = Schema::get();
64
65         // For storing user-submitted flags on profiles
66
67         $schema->ensureTable('group_privacy_settings',
68                              array(new ColumnDef('group_id',
69                                                  'integer',
70                                                  null,
71                                                  false,
72                                                  'PRI'),
73                                    new ColumnDef('allow_privacy',
74                                                  'integer'),
75                                    new ColumnDef('allow_sender',
76                                                  'integer'),
77                                    new ColumnDef('created',
78                                                  'datetime'),
79                                    new ColumnDef('modified',
80                                                  'timestamp')));
81                              
82         $schema->ensureTable('group_message',
83                              array(new ColumnDef('id',
84                                                  'char',
85                                                  36,
86                                                  false,
87                                                  'PRI'),
88                                    new ColumnDef('uri',
89                                                  'varchar',
90                                                  255,
91                                                  false,
92                                                  'UNI'),
93                                    new ColumnDef('from_profile',
94                                                  'integer',
95                                                  null,
96                                                  false,
97                                                  'MUL'),
98                                    new ColumnDef('to_group',
99                                                  'integer',
100                                                  null,
101                                                  false,
102                                                  'MUL'),
103                                    new ColumnDef('content',
104                                                  'text'),
105                                    new ColumnDef('rendered',
106                                                  'text'),
107                                    new ColumnDef('url',
108                                                  'varchar',
109                                                  255,
110                                                  false,
111                                                  'UNI'),
112                                    new ColumnDef('created',
113                                                  'datetime')));
114
115         $schema->ensureTable('group_message_profile',
116                              array(new ColumnDef('to_profile',
117                                                  'integer',
118                                                  null,
119                                                  false,
120                                                  'PRI'),
121                                    new ColumnDef('group_message_id',
122                                                  'char',
123                                                  36,
124                                                  false,
125                                                  'PRI'),
126                                    new ColumnDef('created',
127                                                  'datetime')));
128
129         return true;
130     }
131
132     /**
133      * Load related modules when needed
134      *
135      * @param string $cls Name of the class to be loaded
136      *
137      * @return boolean hook value
138      */
139
140     function onAutoload($cls)
141     {
142         $dir = dirname(__FILE__);
143
144         switch ($cls)
145         {
146         case 'GroupinboxAction':
147         case 'ShowgroupmessageAction':
148         case 'NewgroupmessageAction':
149             include_once $dir . '/' . strtolower(mb_substr($cls, 0, -6)) . '.php';
150             return false;
151         case 'Group_privacy_settings':
152         case 'Group_message':
153         case 'Group_message_profile':
154             include_once $dir . '/'.$cls.'.php';
155             return false;
156         case 'GroupMessageCommand':
157         case 'GroupMessageList':
158         case 'GroupMessageListItem':
159         case 'GroupMessageForm':
160             include_once $dir . '/'.strtolower($cls).'.php';
161             return false;
162         default:
163             return true;
164         }
165     }
166
167     /**
168      * Map URLs to actions
169      *
170      * @param Net_URL_Mapper $m path-to-action mapper
171      *
172      * @return boolean hook value
173      */
174
175     function onRouterInitialized($m)
176     {
177         $m->connect('group/:nickname/inbox',
178                     array('action' => 'groupinbox'),
179                     array('nickname' => Nickname::DISPLAY_FMT));
180
181         $m->connect('group/message/:id',
182                     array('action' => 'showgroupmessage'),
183                     array('id' => '[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}'));
184
185         $m->connect('group/:nickname/message/new',
186                     array('action' => 'newgroupmessage'),
187                     array('nickname' => Nickname::DISPLAY_FMT));
188
189         return true;
190     }
191
192     /**
193      * Add group inbox to the menu
194      *
195      * @param Action $action The current action handler. Use this to
196      *                       do any output.
197      *
198      * @return boolean hook value; true means continue processing, false means stop.
199      *
200      * @see Action
201      */
202
203     function onEndGroupGroupNav($groupnav)
204     {
205         $action = $groupnav->action;
206         $group  = $groupnav->group;
207
208         $action->menuItem(common_local_url('groupinbox',
209                                            array('nickname' => $group->nickname)),
210                           _m('Inbox'),
211                           _m('Private messages for this group'),
212                           $action->trimmed('action') == 'groupinbox',
213                           'nav_group_inbox');
214         return true;
215     }
216
217     /**
218      * Create default group privacy settings at group create time
219      *
220      * @param User_group $group Group that was just created
221      *
222      * @result boolean hook value
223      */
224
225     function onEndGroupSave($group)
226     {
227         $gps = new Group_privacy_settings();
228
229         $gps->group_id      = $group->id;
230         $gps->allow_privacy = Group_privacy_settings::SOMETIMES;
231         $gps->allow_sender  = Group_privacy_settings::MEMBER;
232         $gps->created       = common_sql_now();
233         $gps->modified      = $gps->created;
234
235         // This will throw an exception on error
236
237         $gps->insert();
238
239         return true;
240     }
241
242     /**
243      * Show group privacy controls on group edit form
244      *
245      * @param GroupEditForm $form form being shown
246      */
247
248     function onEndGroupEditFormData($form)
249     {
250         $gps = null;
251
252         if (!empty($form->group)) {
253             $gps = Group_privacy_settings::staticGet('group_id', $form->group->id);
254         }
255
256         $form->out->elementStart('li');
257         $form->out->dropdown('allow_privacy',
258                              _('Private messages'),
259                              array(Group_privacy_settings::SOMETIMES => _('Sometimes'),
260                                    Group_privacy_settings::ALWAYS => _('Always'),
261                                    Group_privacy_settings::NEVER => _('Never')),
262                              _('Whether to allow private messages to this group'),
263                              false,
264                              (empty($gps)) ? Group_privacy_settings::SOMETIMES : $gps->allow_privacy);
265         $form->out->elementEnd('li');
266         $form->out->elementStart('li');
267         $form->out->dropdown('allow_sender',
268                              _('Private sender'),
269                              array(Group_privacy_settings::EVERYONE => _('Everyone'),
270                                    Group_privacy_settings::MEMBER => _('Member'),
271                                    Group_privacy_settings::ADMIN => _('Admin')),
272                              _('Who can send private messages to the group'),
273                              false,
274                              (empty($gps)) ? Group_privacy_settings::MEMBER : $gps->allow_sender);
275         $form->out->elementEnd('li');
276         return true;
277     }
278
279     function onEndGroupSaveForm($action)
280     {
281         $gps = null;
282
283         if (!empty($action->group)) {
284             $gps = Group_privacy_settings::staticGet('group_id', $action->group->id);
285         }
286
287         $orig = null;
288
289         if (empty($gps)) {
290             $gps = new Group_privacy_settings();
291             $gps->group_id = $action->group->id;
292         } else {
293             $orig = clone($gps);
294         }
295         
296         $gps->allow_privacy = $action->trimmed('allow_privacy');
297         $gps->allow_sender  = $action->trimmed('allow_sender');
298
299         if (empty($orig)) {
300             $gps->created = common_sql_now();
301             $gps->insert();
302         } else {
303             $gps->update($orig);
304         }
305         
306         return true;
307     }
308
309     /**
310      * Overload 'd' command to send private messages to groups.
311      * 
312      * 'd !group word word word' will send the private message
313      * 'word word word' to the group 'group'.
314      * 
315      * @param string  $cmd     Command being run
316      * @param string  $arg     Rest of the message (including address)
317      * @param User    $user    User sending the message
318      * @param Command &$result The resulting command object to be run.
319      * 
320      * @return boolean hook value
321      */
322     function onStartIntepretCommand($cmd, $arg, $user, &$result)
323     {
324         if ($cmd == 'd' || $cmd == 'dm') {
325
326             $this->debug('Got a d command');
327
328             // Break off the first word as the address
329
330             $pieces = explode(' ', $arg, 2);
331
332             if (count($pieces) == 1) {
333                 $pieces[] = null;
334             }
335
336             list($addr, $msg) = $pieces;
337
338             if (!empty($addr) && $addr[0] == '!') {
339                 $result = new GroupMessageCommand($user, substr($addr, 1), $msg);
340                 Event::handle('EndInterpretCommand', array($cmd, $arg, $user, $result));
341                 return false;
342             }
343         }
344
345         return true;
346     }
347
348     /**
349      * To add a "Message" button to the group profile page
350      *
351      * @param Action     $action The showgroup action being shown
352      * @param User_group $group  The current group
353      * 
354      * @return boolean hook value
355      */
356     function onEndGroupActionsList($action, $group)
357     {
358         $cur = common_current_user();
359
360         if (empty($cur)) {
361             return true;
362         }
363
364         try {
365             Group_privacy_settings::ensurePost($cur, $group);
366         } catch (Exception $e) {
367             return true;
368         }
369
370         $action->elementStart('li', 'entity_send-a-message');
371         $action->element('a', array('href' => common_local_url('newgroupmessage', array('nickname' => $group->nickname)),
372                                     'title' => _('Send a direct message to this group')),
373                          _('Message'));
374         // $form = new GroupMessageForm($action, $group);
375         // $form->hidden = true;
376         // $form->show();
377         $action->elementEnd('li');
378         return true;
379     }
380
381     /**
382      * When saving a notice, check its groups. If any of them has
383      * privacy == always, force a group private message to all mentioned groups.
384      * If any of the groups disallows private messages, skip it.
385      *
386      * @param 
387      *
388      */
389
390     function onStartNoticeSave(&$notice) {
391
392         // Look for group tags
393         // FIXME: won't work for remote groups
394         // @fixme if Notice::saveNew is refactored so we can just pull its list
395         // of groups between processing and saving, make use of it
396
397         $count = preg_match_all('/(?:^|\s)!(' . Nickname::DISPLAY_FMT . ')/',
398                                 strtolower($notice->content),
399                                 $match);
400
401         $groups = array();
402         $ignored = array();
403
404         $forcePrivate = false;
405
406         if ($count > 0) {
407
408             /* Add them to the database */
409
410             foreach (array_unique($match[1]) as $nickname) {
411
412                 $group = User_group::getForNickname($nickname, $profile);
413
414                 if (empty($group)) {
415                     continue;
416                 }
417
418                 $gps = Group_privacy_settings::forGroup($group);
419
420                 switch ($gps->allow_privacy) {
421                 case Group_privacy_settings::ALWAYS:
422                     $forcePrivate = true;
423                     // fall through
424                 case Group_privacy_settings::SOMETIMES:
425                     $groups[] = $group;
426                     break;
427                 case Group_privacy_settings::NEVER:
428                     $ignored[] = $group;
429                     break;
430                 }
431             }
432
433             if ($forcePrivate) {
434
435                 foreach ($ignored as $group) {
436                     common_log(LOG_NOTICE,
437                                "Notice forced to group direct message ".
438                                "but group ".$group->nickname." does not allow them.");
439                 }
440
441                 $user = User::staticGet('id', $notice->profile_id);
442
443                 if (empty($user)) {
444                     common_log(LOG_WARNING,
445                                "Notice forced to group direct message ".
446                                "but profile ".$notice->profile_id." is not a local user.");
447                 } else {
448                     foreach ($groups as $group) {
449                         Group_message::send($user, $group, $notice->content);
450                     }
451                 }
452
453                 // Don't save the notice!
454                 // FIXME: this is probably cheating.
455                 throw new ClientException(sprintf(_('Forced notice to private group message.')),
456                                           200);
457             }
458         }
459         
460         return true;
461     }
462
463     /**
464      * Show an indicator that the group is (essentially) private on the group page
465      *
466      * @param Action     $action The action being shown
467      * @param User_group $group  The group being shown
468      *
469      * @return boolean hook value
470      */
471
472     function onEndGroupProfileElements($action, $group)
473     {
474         $gps = Group_privacy_settings::forGroup($group);
475         
476         if ($gps->allow_privacy == Group_privacy_settings::ALWAYS) {
477             $action->element('p', 'privategroupindicator', _('Private'));
478         }
479
480         return true;
481     }
482
483     function onStartShowExportData($action)
484     {
485         if ($action instanceof ShowgroupAction) {
486             $gps = Group_privacy_settings::forGroup($action->group);
487         
488             if ($gps->allow_privacy == Group_privacy_settings::ALWAYS) {
489                 return false;
490             }
491         }
492         return true;
493     }
494
495     function onPluginVersion(&$versions)
496     {
497         $versions[] = array('name' => 'GroupPrivateMessage',
498                             'version' => STATUSNET_VERSION,
499                             'author' => 'Evan Prodromou',
500                             'homepage' => 'http://status.net/wiki/Plugin:GroupPrivateMessage',
501                             'rawdescription' =>
502                             _m('Allow posting DMs to a group.'));
503         return true;
504     }
505 }