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