]> git.mxchange.org Git - quix0rs-gnu-social.git/commitdiff
Rename PrivateGroup to GroupPrivateMessage to be clearer
authorEvan Prodromou <evan@status.net>
Mon, 7 Feb 2011 16:57:34 +0000 (11:57 -0500)
committerEvan Prodromou <evan@status.net>
Mon, 7 Feb 2011 16:57:34 +0000 (11:57 -0500)
22 files changed:
plugins/GroupPrivateMessage/GroupPrivateMessagePlugin.php [new file with mode: 0644]
plugins/GroupPrivateMessage/Group_message.php [new file with mode: 0644]
plugins/GroupPrivateMessage/Group_message_profile.php [new file with mode: 0644]
plugins/GroupPrivateMessage/Group_privacy_settings.php [new file with mode: 0644]
plugins/GroupPrivateMessage/groupinbox.php [new file with mode: 0644]
plugins/GroupPrivateMessage/groupmessagecommand.php [new file with mode: 0644]
plugins/GroupPrivateMessage/groupmessageform.php [new file with mode: 0644]
plugins/GroupPrivateMessage/groupmessagelist.php [new file with mode: 0644]
plugins/GroupPrivateMessage/groupmessagelistitem.php [new file with mode: 0644]
plugins/GroupPrivateMessage/newgroupmessage.php [new file with mode: 0644]
plugins/GroupPrivateMessage/showgroupmessage.php [new file with mode: 0644]
plugins/PrivateGroup/Group_message.php [deleted file]
plugins/PrivateGroup/Group_message_profile.php [deleted file]
plugins/PrivateGroup/Group_privacy_settings.php [deleted file]
plugins/PrivateGroup/PrivateGroupPlugin.php [deleted file]
plugins/PrivateGroup/groupinbox.php [deleted file]
plugins/PrivateGroup/groupmessagecommand.php [deleted file]
plugins/PrivateGroup/groupmessageform.php [deleted file]
plugins/PrivateGroup/groupmessagelist.php [deleted file]
plugins/PrivateGroup/groupmessagelistitem.php [deleted file]
plugins/PrivateGroup/newgroupmessage.php [deleted file]
plugins/PrivateGroup/showgroupmessage.php [deleted file]

diff --git a/plugins/GroupPrivateMessage/GroupPrivateMessagePlugin.php b/plugins/GroupPrivateMessage/GroupPrivateMessagePlugin.php
new file mode 100644 (file)
index 0000000..9707c08
--- /dev/null
@@ -0,0 +1,391 @@
+<?php
+/**
+ * StatusNet - the distributed open-source microblogging tool
+ * Copyright (C) 2010, StatusNet, Inc.
+ *
+ * Private groups for StatusNet 0.9.x
+ *
+ * PHP version 5
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @category  Privacy
+ * @package   StatusNet
+ * @author    Evan Prodromou <evan@status.net>
+ * @copyright 2010 StatusNet, Inc.
+ * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
+ * @link      http://status.net/
+ */
+
+if (!defined('STATUSNET')) {
+    // This check helps protect against security problems;
+    // your code file can't be executed directly from the web.
+    exit(1);
+}
+
+/**
+ * Private groups
+ *
+ * This plugin allows users to send private messages to a group.
+ *
+ * @category  Privacy
+ * @package   StatusNet
+ * @author    Evan Prodromou <evan@status.net>
+ * @copyright 2010 StatusNet, Inc.
+ * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
+ * @link      http://status.net/
+ */
+
+class GroupPrivateMessagePlugin extends Plugin
+{
+    /**
+     * Database schema setup
+     *
+     * @see Schema
+     * @see ColumnDef
+     *
+     * @return boolean hook value
+     */
+
+    function onCheckSchema()
+    {
+        $schema = Schema::get();
+
+        // For storing user-submitted flags on profiles
+
+        $schema->ensureTable('group_privacy_settings',
+                             array(new ColumnDef('group_id',
+                                                 'integer',
+                                                 null,
+                                                 false,
+                                                 'PRI'),
+                                   new ColumnDef('allow_privacy',
+                                                 'integer'),
+                                   new ColumnDef('allow_sender',
+                                                 'integer'),
+                                   new ColumnDef('created',
+                                                 'datetime'),
+                                   new ColumnDef('modified',
+                                                 'timestamp')));
+                             
+        $schema->ensureTable('group_message',
+                             array(new ColumnDef('id',
+                                                 'char',
+                                                 36,
+                                                 false,
+                                                 'PRI'),
+                                   new ColumnDef('uri',
+                                                 'varchar',
+                                                 255,
+                                                 false,
+                                                 'UNI'),
+                                   new ColumnDef('from_profile',
+                                                 'integer',
+                                                 null,
+                                                 false,
+                                                 'MUL'),
+                                   new ColumnDef('to_group',
+                                                 'integer',
+                                                 null,
+                                                 false,
+                                                 'MUL'),
+                                   new ColumnDef('content',
+                                                 'text'),
+                                   new ColumnDef('rendered',
+                                                 'text'),
+                                   new ColumnDef('url',
+                                                 'varchar',
+                                                 255,
+                                                 false,
+                                                 'UNI'),
+                                   new ColumnDef('created',
+                                                 'datetime')));
+
+        $schema->ensureTable('group_message_profile',
+                             array(new ColumnDef('to_profile',
+                                                 'integer',
+                                                 null,
+                                                 false,
+                                                 'PRI'),
+                                   new ColumnDef('group_message_id',
+                                                 'char',
+                                                 36,
+                                                 false,
+                                                 'PRI'),
+                                   new ColumnDef('created',
+                                                 'datetime')));
+
+        return true;
+    }
+
+    /**
+     * Load related modules when needed
+     *
+     * @param string $cls Name of the class to be loaded
+     *
+     * @return boolean hook value
+     */
+
+    function onAutoload($cls)
+    {
+        $dir = dirname(__FILE__);
+
+        switch ($cls)
+        {
+        case 'GroupinboxAction':
+        case 'ShowgroupmessageAction':
+        case 'NewgroupmessageAction':
+            include_once $dir . '/' . strtolower(mb_substr($cls, 0, -6)) . '.php';
+            return false;
+        case 'Group_privacy_settings':
+        case 'Group_message':
+        case 'Group_message_profile':
+            include_once $dir . '/'.$cls.'.php';
+            return false;
+        case 'GroupMessageCommand':
+        case 'GroupMessageList':
+        case 'GroupMessageListItem':
+        case 'GroupMessageForm':
+            include_once $dir . '/'.strtolower($cls).'.php';
+            return false;
+        default:
+            return true;
+        }
+    }
+
+    /**
+     * Map URLs to actions
+     *
+     * @param Net_URL_Mapper $m path-to-action mapper
+     *
+     * @return boolean hook value
+     */
+
+    function onRouterInitialized($m)
+    {
+        $m->connect('group/:nickname/inbox',
+                    array('action' => 'groupinbox'),
+                    array('nickname' => Nickname::DISPLAY_FMT));
+
+        $m->connect('group/message/:id',
+                    array('action' => 'showgroupmessage'),
+                    array('id' => '[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}'));
+
+        $m->connect('group/:nickname/message/new',
+                    array('action' => 'newgroupmessage'),
+                    array('nickname' => Nickname::DISPLAY_FMT));
+
+        return true;
+    }
+
+    /**
+     * Add group inbox to the menu
+     *
+     * @param Action $action The current action handler. Use this to
+     *                       do any output.
+     *
+     * @return boolean hook value; true means continue processing, false means stop.
+     *
+     * @see Action
+     */
+
+    function onEndGroupGroupNav($groupnav)
+    {
+        $action = $groupnav->action;
+        $group  = $groupnav->group;
+
+        $action->menuItem(common_local_url('groupinbox',
+                                           array('nickname' => $group->nickname)),
+                          _m('Inbox'),
+                          _m('Private messages for this group'),
+                          $action->trimmed('action') == 'groupinbox',
+                          'nav_group_inbox');
+        return true;
+    }
+
+    /**
+     * Create default group privacy settings at group create time
+     *
+     * @param User_group $group Group that was just created
+     *
+     * @result boolean hook value
+     */
+
+    function onEndGroupSave($group)
+    {
+        $gps = new Group_privacy_settings();
+
+        $gps->group_id      = $group->id;
+        $gps->allow_privacy = Group_privacy_settings::SOMETIMES;
+        $gps->allow_sender  = Group_privacy_settings::MEMBER;
+        $gps->created       = common_sql_now();
+        $gps->modified      = $gps->created;
+
+        // This will throw an exception on error
+
+        $gps->insert();
+
+        return true;
+    }
+
+    /**
+     * Show group privacy controls on group edit form
+     *
+     * @param GroupEditForm $form form being shown
+     */
+
+    function onEndGroupEditFormData($form)
+    {
+        $gps = null;
+
+        if (!empty($form->group)) {
+            $gps = Group_privacy_settings::staticGet('group_id', $form->group->id);
+        }
+
+        $form->out->elementStart('li');
+        $form->out->dropdown('allow_privacy',
+                             _('Private messages'),
+                             array(Group_privacy_settings::SOMETIMES => _('Sometimes'),
+                                   Group_privacy_settings::ALWAYS => _('Always'),
+                                   Group_privacy_settings::NEVER => _('Never')),
+                             _('Whether to allow private messages to this group'),
+                             false,
+                             (empty($gps)) ? Group_privacy_settings::SOMETIMES : $gps->allow_privacy);
+        $form->out->elementEnd('li');
+        $form->out->elementStart('li');
+        $form->out->dropdown('allow_sender',
+                             _('Private sender'),
+                             array(Group_privacy_settings::EVERYONE => _('Everyone'),
+                                   Group_privacy_settings::MEMBER => _('Member'),
+                                   Group_privacy_settings::ADMIN => _('Admin')),
+                             _('Who can send private messages to the group'),
+                             false,
+                             (empty($gps)) ? Group_privacy_settings::MEMBER : $gps->allow_sender);
+        $form->out->elementEnd('li');
+        return true;
+    }
+
+    function onEndGroupSaveForm($action)
+    {
+        $gps = null;
+
+        if (!empty($action->group)) {
+            $gps = Group_privacy_settings::staticGet('group_id', $action->group->id);
+        }
+
+        $orig = null;
+
+        if (empty($gps)) {
+            $gps = new Group_privacy_settings();
+            $gps->group_id = $action->group->id;
+        } else {
+            $orig = clone($gps);
+        }
+        
+        $gps->allow_privacy = $action->trimmed('allow_privacy');
+        $gps->allow_sender  = $action->trimmed('allow_sender');
+
+        if (empty($orig)) {
+            $gps->created = common_sql_now();
+            $gps->insert();
+        } else {
+            $gps->update($orig);
+        }
+        
+        return true;
+    }
+
+    /**
+     * Overload 'd' command to send private messages to groups.
+     * 
+     * 'd !group word word word' will send the private message
+     * 'word word word' to the group 'group'.
+     * 
+     * @param string  $cmd     Command being run
+     * @param string  $arg     Rest of the message (including address)
+     * @param User    $user    User sending the message
+     * @param Command &$result The resulting command object to be run.
+     * 
+     * @return boolean hook value
+     */
+    function onStartIntepretCommand($cmd, $arg, $user, &$result)
+    {
+        if ($cmd == 'd' || $cmd == 'dm') {
+
+            $this->debug('Got a d command');
+
+            // Break off the first word as the address
+
+            $pieces = explode(' ', $arg, 2);
+
+            if (count($pieces) == 1) {
+                $pieces[] = null;
+            }
+
+            list($addr, $msg) = $pieces;
+
+            if (!empty($addr) && $addr[0] == '!') {
+                $result = new GroupMessageCommand($user, substr($addr, 1), $msg);
+                Event::handle('EndInterpretCommand', array($cmd, $arg, $user, $result));
+                return false;
+            }
+        }
+
+        return true;
+    }
+
+    /**
+     * To add a "Message" button to the group profile page
+     *
+     * @param Action     $action The showgroup action being shown
+     * @param User_group $group  The current group
+     * 
+     * @return boolean hook value
+     */
+    function onEndGroupActionsList($action, $group)
+    {
+        $cur = common_current_user();
+
+        if (empty($cur)) {
+            return true;
+        }
+
+        try {
+            Group_privacy_settings::ensurePost($cur, $group);
+        } catch (Exception $e) {
+            return true;
+        }
+
+        $action->elementStart('li', 'entity_send-a-message');
+        $action->element('a', array('href' => common_local_url('newgroupmessage', array('nickname' => $group->nickname)),
+                                    'title' => _('Send a direct message to this group')),
+                         _('Message'));
+        // $form = new GroupMessageForm($action, $group);
+        // $form->hidden = true;
+        // $form->show();
+        $action->elementEnd('li');
+        return true;
+    }
+    function onPluginVersion(&$versions)
+    {
+        $versions[] = array('name' => 'GroupPrivateMessage',
+                            'version' => STATUSNET_VERSION,
+                            'author' => 'Evan Prodromou',
+                            'homepage' => 'http://status.net/wiki/Plugin:GroupPrivateMessage',
+                            'rawdescription' =>
+                            _m('Allow posting DMs to a group.'));
+        return true;
+    }
+}
diff --git a/plugins/GroupPrivateMessage/Group_message.php b/plugins/GroupPrivateMessage/Group_message.php
new file mode 100644 (file)
index 0000000..07d4c57
--- /dev/null
@@ -0,0 +1,208 @@
+<?php
+/**
+ * Data class for group direct messages
+ *
+ * PHP version 5
+ *
+ * @category Data
+ * @package  StatusNet
+ * @author   Evan Prodromou <evan@status.net>
+ * @license  http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
+ * @link     http://status.net/
+ *
+ * StatusNet - the distributed open-source microblogging tool
+ * Copyright (C) 2009, StatusNet, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.     See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+if (!defined('STATUSNET')) {
+    exit(1);
+}
+
+require_once INSTALLDIR . '/classes/Memcached_DataObject.php';
+
+/**
+ * Data class for group direct messages
+ *
+ * @category PrivateGroup
+ * @package  StatusNet
+ * @author   Evan Prodromou <evan@status.net>
+ * @license  http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
+ * @link     http://status.net/
+ *
+ * @see      DB_DataObject
+ */
+
+class Group_message extends Memcached_DataObject
+{
+    public $__table = 'group_message'; // table name
+    public $id;                        // char(36)  primary_key not_null
+    public $uri;                       // varchar(255)
+    public $from_profile;              // int
+    public $to_group;                  // int
+    public $content;
+    public $rendered;
+    public $url;
+    public $created;
+
+    /**
+     * Get an instance by key
+     *
+     * This is a utility method to get a single instance with a given key value.
+     *
+     * @param string $k Key to use to lookup (usually 'user_id' for this class)
+     * @param mixed  $v Value to lookup
+     *
+     * @return Group_message object found, or null for no hits
+     *
+     */
+    function staticGet($k, $v=null)
+    {
+        return Memcached_DataObject::staticGet('Group_message', $k, $v);
+    }
+
+    /**
+     * return table definition for DB_DataObject
+     *
+     * DB_DataObject needs to know something about the table to manipulate
+     * instances. This method provides all the DB_DataObject needs to know.
+     *
+     * @return array array of column definitions
+     */
+    function table()
+    {
+        return array('id' => DB_DATAOBJECT_STR + DB_DATAOBJECT_NOTNULL,
+                     'uri' => DB_DATAOBJECT_STR + DB_DATAOBJECT_NOTNULL,
+                     'from_profile' => DB_DATAOBJECT_INT + DB_DATAOBJECT_NOTNULL,
+                     'to_group' => DB_DATAOBJECT_INT + DB_DATAOBJECT_NOTNULL,
+                     'content' => DB_DATAOBJECT_STR + DB_DATAOBJECT_NOTNULL,
+                     'rendered' => DB_DATAOBJECT_STR + DB_DATAOBJECT_NOTNULL,
+                     'url' => DB_DATAOBJECT_STR,
+                     'created' => DB_DATAOBJECT_STR + DB_DATAOBJECT_DATE + DB_DATAOBJECT_TIME + DB_DATAOBJECT_NOTNULL);
+    }
+
+    /**
+     * return key definitions for DB_DataObject
+     *
+     * DB_DataObject needs to know about keys that the table has, since it
+     * won't appear in StatusNet's own keys list. In most cases, this will
+     * simply reference your keyTypes() function.
+     *
+     * @return array list of key field names
+     */
+    function keys()
+    {
+        return array_keys($this->keyTypes());
+    }
+
+    /**
+     * return key definitions for Memcached_DataObject
+     *
+     * @return array associative array of key definitions, field name to type:
+     *         'K' for primary key: for compound keys, add an entry for each component;
+     *         'U' for unique keys: compound keys are not well supported here.
+     */
+    function keyTypes()
+    {
+        return array('id' => 'K', 'uri' => 'U');
+    }
+
+    static function send($user, $group, $text)
+    {
+        if (!$user->hasRight(Right::NEWMESSAGE)) {
+            // XXX: maybe break this out into a separate right
+            throw new Exception(sprintf(_('User %s not allowed to send private messages.'),
+                                        $user->nickname));
+        }
+
+        Group_privacy_settings::ensurePost($user, $group);
+
+        $text = $user->shortenLinks($text);
+
+        // We use the same limits as for 'regular' private messages.
+
+        if (Message::contentTooLong($text)) {
+            throw new Exception(sprintf(_m('That\'s too long. Maximum message size is %d character.',
+                                           'That\'s too long. Maximum message size is %d characters.',
+                                           Message::maxContent()),
+                                        Message::maxContent()));
+        }
+
+        // Valid! Let's do this thing!
+
+        $gm = new Group_message();
+        
+        $gm->id           = UUID::gen();
+        $gm->uri          = common_local_url('showgroupmessage', array('id' => $gm->id));
+        $gm->from_profile = $user->id;
+        $gm->to_group     = $group->id;
+        $gm->content      = $text; // XXX: is this cool?!
+        $gm->rendered     = common_render_text($text);
+        $gm->url          = $gm->uri;
+        $gm->created      = common_sql_now();
+
+        // This throws a conniption if there's a problem
+
+        $gm->insert();
+
+        $gm->distribute();
+
+        return $gm;
+    }
+
+    function distribute()
+    {
+        $group = User_group::staticGet('id', $this->to_group);
+        
+        $member = $group->getMembers();
+
+        while ($member->fetch()) {
+            Group_message_profile::send($this, $member);
+        }
+    }
+
+    function getGroup()
+    {
+        $group = User_group::staticGet('id', $this->to_group);
+        if (empty($group)) {
+            throw new ServerException(_('No group for group message'));
+        }
+        return $group;
+    }
+
+    function getSender()
+    {
+        $sender = Profile::staticGet('id', $this->from_profile);
+        if (empty($sender)) {
+            throw new ServerException(_('No sender for group message'));
+        }
+        return $sender;
+    }
+
+    static function forGroup($group, $offset, $limit)
+    {
+        // XXX: cache
+        $gm = new Group_message();
+
+        $gm->to_group = $group->id;
+        $gm->orderBy('created DESC');
+        $gm->limit($offset, $limit);
+
+        $gm->find();
+
+        return $gm;
+    }
+
+}
diff --git a/plugins/GroupPrivateMessage/Group_message_profile.php b/plugins/GroupPrivateMessage/Group_message_profile.php
new file mode 100644 (file)
index 0000000..3323374
--- /dev/null
@@ -0,0 +1,189 @@
+<?php
+/**
+ * Who received a group message
+ *
+ * PHP version 5
+ *
+ * @category Data
+ * @package  StatusNet
+ * @author   Evan Prodromou <evan@status.net>
+ * @license  http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
+ * @link     http://status.net/
+ *
+ * StatusNet - the distributed open-source microblogging tool
+ * Copyright (C) 2010, StatusNet, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.     See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+if (!defined('STATUSNET')) {
+    exit(1);
+}
+
+require_once INSTALLDIR . '/classes/Memcached_DataObject.php';
+
+/**
+ * Data class for group direct messages for users
+ *
+ * @category PrivateGroup
+ * @package  StatusNet
+ * @author   Evan Prodromou <evan@status.net>
+ * @license  http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
+ * @link     http://status.net/
+ *
+ * @see      DB_DataObject
+ */
+
+class Group_message_profile extends Memcached_DataObject
+{
+    public $__table = 'group_message_profile'; // table name
+    public $to_profile;                        // int
+    public $group_message_id;                  // char(36)  primary_key not_null
+    public $created;
+
+    /**
+     * Get an instance by key
+     *
+     * This is a utility method to get a single instance with a given key value.
+     *
+     * @param string $k Key to use to lookup (usually 'user_id' for this class)
+     * @param mixed  $v Value to lookup
+     *
+     * @return Group_message object found, or null for no hits
+     *
+     */
+    function staticGet($k, $v=null)
+    {
+        return Memcached_DataObject::staticGet('Group_message_profile', $k, $v);
+    }
+
+    /**
+     * return table definition for DB_DataObject
+     *
+     * DB_DataObject needs to know something about the table to manipulate
+     * instances. This method provides all the DB_DataObject needs to know.
+     *
+     * @return array array of column definitions
+     */
+    function table()
+    {
+        return array('to_profile' => DB_DATAOBJECT_INT + DB_DATAOBJECT_NOTNULL,
+                     'group_message_id' => DB_DATAOBJECT_STR + DB_DATAOBJECT_NOTNULL,
+                     'created' => DB_DATAOBJECT_STR + DB_DATAOBJECT_DATE + DB_DATAOBJECT_TIME + DB_DATAOBJECT_NOTNULL);
+    }
+
+    /**
+     * return key definitions for DB_DataObject
+     *
+     * DB_DataObject needs to know about keys that the table has, since it
+     * won't appear in StatusNet's own keys list. In most cases, this will
+     * simply reference your keyTypes() function.
+     *
+     * @return array list of key field names
+     */
+    function keys()
+    {
+        return array_keys($this->keyTypes());
+    }
+
+    /**
+     * return key definitions for Memcached_DataObject
+     *
+     * @return array associative array of key definitions, field name to type:
+     *         'K' for primary key: for compound keys, add an entry for each component;
+     *         'U' for unique keys: compound keys are not well supported here.
+     */
+    function keyTypes()
+    {
+        return array('to_profile' => 'K', 'group_message_id' => 'K');
+    }
+
+    /**
+     * No sequence keys in this table.
+     */
+    function sequenceKey()
+    {
+        return array(false, false, false);
+    }
+
+    function send($gm, $profile)
+    {
+        $gmp = new Group_message_profile();
+        
+        $gmp->group_message_id = $gm->id;
+        $gmp->to_profile       = $profile->id;
+        $gmp->created          = common_sql_now();
+
+        $gmp->insert();
+
+        $gmp->notify();
+
+        return $gmp;
+    }
+
+    function notify()
+    {
+        // XXX: add more here
+        $this->notifyByMail();
+    }
+
+    function notifyByMail() 
+    {
+        $to = User::staticGet('id', $this->to_profile);
+
+        if (empty($to) || is_null($to->email) || !$to->emailnotifymsg) {
+            return true;
+        }
+
+        $gm = Group_message::staticGet('id', $this->group_message_id);
+
+        $from_profile = Profile::staticGet('id', $gm->from_profile);
+
+        $group = $gm->getGroup();
+
+        common_switch_locale($to->language);
+
+        // TRANS: Subject for direct-message notification email.
+        // TRANS: %s is the sending user's nickname.
+        $subject = sprintf(_('New private message from %s to group %s'), $from->nickname, $group->nickname);
+
+        $from_profile = $from->getProfile();
+
+        // TRANS: Body for direct-message notification email.
+        // TRANS: %1$s is the sending user's long name, %2$s is the sending user's nickname,
+        // TRANS: %3$s is the message content, %4$s a URL to the message,
+        // TRANS: %5$s is the StatusNet sitename.
+        $body = sprintf(_("%1\$s (%2\$s) sent a private message to group %3\$s:\n\n".
+                          "------------------------------------------------------\n".
+                          "%4\$s\n".
+                          "------------------------------------------------------\n\n".
+                          "You can reply to their message here:\n\n".
+                          "%5\$s\n\n".
+                          "Don't reply to this email; it won't get to them.\n\n".
+                          "With kind regards,\n".
+                          "%6\$s\n"),
+                        $from_profile->getBestName(),
+                        $from->nickname,
+                        $group->nickname,
+                        $this->content,
+                        common_local_url('newmessage', array('to' => $from->id)),
+                        common_config('site', 'name'));
+
+        $headers = _mail_prepare_headers('message', $to->nickname, $from->nickname);
+
+        common_switch_locale();
+
+        return mail_to_user($to, $subject, $body, $headers);
+    }
+}
diff --git a/plugins/GroupPrivateMessage/Group_privacy_settings.php b/plugins/GroupPrivateMessage/Group_privacy_settings.php
new file mode 100644 (file)
index 0000000..898ac26
--- /dev/null
@@ -0,0 +1,194 @@
+<?php
+/**
+ * Data class for group privacy settings
+ *
+ * PHP version 5
+ *
+ * @category Data
+ * @package  StatusNet
+ * @author   Evan Prodromou <evan@status.net>
+ * @license  http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
+ * @link     http://status.net/
+ *
+ * StatusNet - the distributed open-source microblogging tool
+ * Copyright (C) 2011, StatusNet, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.     See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+if (!defined('STATUSNET')) {
+    exit(1);
+}
+
+/**
+ * Data class for group privacy
+ *
+ * Stores admin preferences about the group.
+ *
+ * @category Action
+ * @package  StatusNet
+ * @author   Evan Prodromou <evan@status.net>
+ * @license  http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
+ * @link     http://status.net/
+ *
+ * @see      DB_DataObject
+ */
+
+class Group_privacy_settings extends Memcached_DataObject
+{
+    public $__table = 'group_privacy_settings';
+    /** ID of the group. */
+    public $group_id;      
+    /** When to allow privacy: always, sometimes, or never. */
+    public $allow_privacy;
+    /** Who can send private messages: everyone, member, admin */
+    public $allow_sender; 
+    /** row creation timestamp */
+    public $created;
+    /** Last-modified timestamp */
+    public $modified;
+
+    /** NEVER is */
+
+    const SOMETIMES = -1;
+    const NEVER  = 0;
+    const ALWAYS = 1;
+
+    /** These are bit-mappy, as a hedge against the future. */
+
+    const EVERYONE = 1;
+    const MEMBER   = 2;
+    const ADMIN    = 4;
+
+    /**
+     * Get an instance by key
+     *
+     * This is a utility method to get a single instance with a given key value.
+     *
+     * @param string $k Key to use to lookup (usually 'user_id' for this class)
+     * @param mixed  $v Value to lookup
+     *
+     * @return User_greeting_count object found, or null for no hits
+     */
+
+    function staticGet($k, $v=null)
+    {
+        return Memcached_DataObject::staticGet('Group_privacy_settings', $k, $v);
+    }
+
+    /**
+     * return table definition for DB_DataObject
+     *
+     * DB_DataObject needs to know something about the table to manipulate
+     * instances. This method provides all the DB_DataObject needs to know.
+     *
+     * @return array array of column definitions
+     */
+
+    function table()
+    {
+        return array('group_id' => DB_DATAOBJECT_INT + DB_DATAOBJECT_NOTNULL,
+                     'allow_privacy' => DB_DATAOBJECT_INT,
+                     'allow_sender' => DB_DATAOBJECT_INT,
+                     'created' => DB_DATAOBJECT_STR + DB_DATAOBJECT_DATE + DB_DATAOBJECT_TIME + DB_DATAOBJECT_NOTNULL,
+                     'modified' => DB_DATAOBJECT_STR + DB_DATAOBJECT_DATE + DB_DATAOBJECT_TIME + DB_DATAOBJECT_NOTNULL);
+                     
+    }
+
+    /**
+     * return key definitions for DB_DataObject
+     *
+     * DB_DataObject needs to know about keys that the table has, since it
+     * won't appear in StatusNet's own keys list. In most cases, this will
+     * simply reference your keyTypes() function.
+     *
+     * @return array list of key field names
+     */
+
+    function keys()
+    {
+        return array_keys($this->keyTypes());
+    }
+
+    /**
+     * return key definitions for Memcached_DataObject
+     *
+     * @return array associative array of key definitions, field name to type:
+     *         'K' for primary key: for compound keys, add an entry for each component;
+     *         'U' for unique keys: compound keys are not well supported here.
+     */
+
+    function keyTypes()
+    {
+        return array('group_id' => 'K');
+    }
+
+    /**
+     * Magic formula for non-autoincrementing integer primary keys
+     *
+     * @return array magic three-false array that stops auto-incrementing.
+     */
+
+    function sequenceKey()
+    {
+        return array(false, false, false);
+    }
+
+    function ensurePost($user, $group)
+    {
+        $gps = Group_privacy_settings::staticGet('group_id', $group->id);
+
+        if (empty($gps)) {
+            // make a fake one with defaults
+            $gps = new Group_privacy_settings();
+            $gps->allow_privacy = Group_privacy_settings::SOMETIMES;
+            $gps->allow_sender  = Group_privacy_settings::MEMBER;
+        }
+
+        if ($gps->allow_privacy == Group_privacy_settings::NEVER) {
+            throw new Exception(sprintf(_('Group %s does not allow private messages.'),
+                                        $group->nickname));
+        }
+
+        switch ($gps->allow_sender) {
+        case Group_privacy_settings::EVERYONE:
+            $profile = $user->getProfile();
+            if (Group_block::isBlocked($group, $profile)) {
+                throw new Exception(sprintf(_('User %s is blocked from group %s.'),
+                                            $user->nickname,
+                                            $group->nickname));
+            }
+            break;
+        case Group_privacy_settings::MEMBER:
+            if (!$user->isMember($group)) {
+                throw new Exception(sprintf(_('User %s is not a member of group %s.'),
+                                            $user->nickname,
+                                            $group->nickname));
+            }
+            break;
+        case Group_privacy_settings::ADMIN:
+            if (!$user->isAdmin($group)) {
+                throw new Exception(sprintf(_('User %s is not an administrator of group %s.'),
+                                            $user->nickname,
+                                            $group->nickname));
+            }
+            break;
+        default:
+            throw new Exception(sprintf(_('Unknown privacy settings for group %s.'),
+                                        $group->nickname));
+        }
+
+        return true;
+    }
+}
diff --git a/plugins/GroupPrivateMessage/groupinbox.php b/plugins/GroupPrivateMessage/groupinbox.php
new file mode 100644 (file)
index 0000000..55bf4b0
--- /dev/null
@@ -0,0 +1,170 @@
+<?php
+/**
+ * StatusNet - the distributed open-source microblogging tool
+ * Copyright (C) 2010, StatusNet, Inc.
+ *
+ * List of private messages to this group
+ * 
+ * PHP version 5
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @category  PrivateGroup
+ * @package   StatusNet
+ * @author    Evan Prodromou <evan@status.net>
+ * @copyright 2010 StatusNet, Inc.
+ * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
+ * @link      http://status.net/
+ */
+
+if (!defined('STATUSNET')) {
+    // This check helps protect against security problems;
+    // your code file can't be executed directly from the web.
+    exit(1);
+}
+
+/**
+ * Show a list of private messages to this group
+ *
+ * @category  PrivateGroup
+ * @package   StatusNet
+ * @author    Evan Prodromou <evan@status.net>
+ * @copyright 2010 StatusNet, Inc.
+ * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
+ * @link      http://status.net/
+ */
+
+class GroupinboxAction extends GroupDesignAction
+{
+    var $gm;
+
+    /**
+     * For initializing members of the class.
+     *
+     * @param array $argarray misc. arguments
+     *
+     * @return boolean true
+     */
+    function prepare($argarray)
+    {
+        parent::prepare($argarray);
+
+        $cur = common_current_user();
+
+        if (empty($cur)) {
+            throw new ClientException(_('Only for logged-in users'), 403);
+        }
+
+        $nicknameArg = $this->trimmed('nickname');
+
+        $nickname = common_canonical_nickname($nicknameArg);
+
+        if ($nickname != $nicknameArg) {
+            $url = common_local_url('groupinbox', array('nickname' => $nickname));
+            common_redirect($url);
+            return false;
+        }
+
+        $localGroup = Local_group::staticGet('nickname', $nickname);
+
+        if (empty($localGroup)) {
+            throw new ClientException(_('No such group'), 404);
+        }
+
+        $this->group = User_group::staticGet('id', $localGroup->group_id);
+
+        if (empty($this->group)) {
+            throw new ClientException(_('No such group'), 404);
+        }
+
+        if (!$cur->isMember($this->group)) {
+            throw new ClientException(_('Only for members'), 403);
+        }
+
+        $this->page = $this->trimmed('page');
+
+        if (!$this->page) {
+            $this->page = 1;
+        }
+        
+        $this->gm = Group_message::forGroup($this->group, 
+                                            ($this->page - 1) * MESSAGES_PER_PAGE,
+                                            MESSAGES_PER_PAGE + 1);
+        return true;
+    }
+
+    function showLocalNav()
+    {
+        $nav = new GroupNav($this, $this->group);
+        $nav->show();
+    }
+
+    function showNoticeForm()
+    {
+        $form = new GroupMessageForm($this, $this->group);
+        $form->show();
+    }
+
+    function showContent()
+    {
+        $gml = new GroupMessageList($this, $this->gm);
+        $gml->show();
+    }
+
+    /**
+     * Handler method
+     *
+     * @param array $argarray is ignored since it's now passed in in prepare()
+     *
+     * @return void
+     */
+    function handle($argarray=null)
+    {
+        $this->showPage();
+    }
+
+    /**
+     * Return true if read only.
+     *
+     * MAY override
+     *
+     * @param array $args other arguments
+     *
+     * @return boolean is read only action?
+     */
+    function isReadOnly($args)
+    {
+        return true;
+    }
+
+    /**
+     * Title of the page
+     *
+     * @return string page title, with page number
+     */
+    function title()
+    {
+        $base = $this->group->getFancyName();
+
+        if ($this->page == 1) {
+            return sprintf(_('%s group inbox'), $base);
+        } else {
+            // TRANS: Page title for any but first group page.
+            // TRANS: %1$s is a group name, $2$s is a page number.
+            return sprintf(_('%1$s group inbox, page %2$d'),
+                           $base,
+                           $this->page);
+        }
+    }
+}
diff --git a/plugins/GroupPrivateMessage/groupmessagecommand.php b/plugins/GroupPrivateMessage/groupmessagecommand.php
new file mode 100644 (file)
index 0000000..19136f1
--- /dev/null
@@ -0,0 +1,85 @@
+<?php
+/**
+ * StatusNet - the distributed open-source microblogging tool
+ * Copyright (C) 2010, StatusNet, Inc.
+ *
+ * Command object for messages to groups
+ * 
+ * PHP version 5
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @category  Command
+ * @package   StatusNet
+ * @author    Evan Prodromou <evan@status.net>
+ * @copyright 2010 StatusNet, Inc.
+ * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
+ * @link      http://status.net/
+ */
+
+if (!defined('STATUSNET')) {
+    // This check helps protect against security problems;
+    // your code file can't be executed directly from the web.
+    exit(1);
+}
+
+/**
+ * Command object for messages to groups
+ *
+ * @category  General
+ * @package   StatusNet
+ * @author    Evan Prodromou <evan@status.net>
+ * @copyright 2010 StatusNet, Inc.
+ * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
+ * @link      http://status.net/
+ */
+
+class GroupMessageCommand extends Command
+{
+    /** User sending the message. */
+    var $user;
+    /** Nickname of the group they're sending to. */
+    var $nickname;
+    /** Text of the message. */
+    var $text;
+
+    /**
+     * Constructor
+     *
+     * @param User   $user     User sending the message
+     * @param string $nickname Nickname of the group
+     * @param string $text     Text of message
+     */
+
+    function __construct($user, $nickname, $text)
+    {
+        $this->user     = $user;
+        $this->nickname = $nickname;
+        $this->text     = $text;
+    }
+
+    function handle($channel)
+    {
+        // Throws a command exception if group not found
+        $group = $this->getGroup($this->nickname);
+
+        $gm = Group_message::send($this->user, $group, $this->text);
+
+        $channel->output($this->user, 
+                         sprintf(_('Direct message to group %s sent.'), 
+                                 $group->nickname));
+
+        return true;
+    }
+}
diff --git a/plugins/GroupPrivateMessage/groupmessageform.php b/plugins/GroupPrivateMessage/groupmessageform.php
new file mode 100644 (file)
index 0000000..4564a60
--- /dev/null
@@ -0,0 +1,166 @@
+<?php
+/**
+ * StatusNet - the distributed open-source microblogging tool
+ * Copyright (C) 2011, StatusNet, Inc.
+ *
+ * Form for posting a group message
+ * 
+ * PHP version 5
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @category  PrivateGroup
+ * @package   StatusNet
+ * @author    Evan Prodromou <evan@status.net>
+ * @copyright 2011 StatusNet, Inc.
+ * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
+ * @link      http://status.net/
+ */
+
+if (!defined('STATUSNET')) {
+    // This check helps protect against security problems;
+    // your code file can't be executed directly from the web.
+    exit(1);
+}
+
+/**
+ * Form for posting a group message
+ *
+ * @category  PrivateGroup
+ * @package   StatusNet
+ * @author    Evan Prodromou <evan@status.net>
+ * @copyright 2011 StatusNet, Inc.
+ * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
+ * @link      http://status.net/
+ */
+
+class GroupMessageForm extends Form
+{
+    var $group;
+    var $content;
+
+    /**
+     * Constructor
+     *
+     * @param HTMLOutputter $out   Output context
+     * @param User_group    $group Group to post to
+     *
+     * @todo add a drop-down list to post to any group
+     */
+
+    function __construct($out, $group, $content=null)
+    {
+        parent::__construct($out);
+
+        $this->group   = $group;
+        $this->content = $content;
+    }
+
+    /**
+     * Action for the form
+     */
+    function action()
+    { 
+        return common_local_url('newgroupmessage',
+                                array('nickname' => $this->group->nickname));
+    }
+
+    /**
+     * Legend for the form
+     *
+     * @param
+     *
+     * @return
+     */
+    function formLegend()
+    {
+        $this->out->element('legend',
+                            null,
+                            sprintf(_('Message to %s'), $this->group->nickname));
+    }
+
+    /**
+     * id for the form
+     *
+     * @param
+     *
+     * @return
+     */
+
+    function id()
+    {
+        return 'form_notice-group-message';
+    }
+
+    /**
+     * class for the form
+     *
+     * @param
+     *
+     * @return
+     */
+
+    function formClass()
+    {
+        return 'form_notice';
+    }
+
+    /**
+     * Entry data
+     *
+     * @param
+     *
+     * @return
+     */
+
+    function formData()
+    {
+        $this->out->element('label', array('for' => 'notice_data-text',
+                                           'id' => 'notice_data-text-label'),
+                            sprintf(_('Direct message to %s'), $this->group->nickname));
+
+        $this->out->element('textarea', array('id' => 'notice_data-text',
+                                              'cols' => 35,
+                                              'rows' => 4,
+                                              'name' => 'content'),
+                            ($this->content) ? $this->content : '');
+
+        $contentLimit = Message::maxContent();
+
+        if ($contentLimit > 0) {
+            $this->out->elementStart('dl', 'form_note');
+            $this->out->element('dt', null, _('Available characters'));
+            $this->out->element('dd', array('id' => 'notice_text-count'),
+                                $contentLimit);
+            $this->out->elementEnd('dl');
+        }
+    }
+
+    /**
+     * Legend for the form
+     *
+     * @param
+     *
+     * @return
+     */
+
+    function formActions()
+    {
+        $this->out->element('input', array('id' => 'notice_action-submit',
+                                           'class' => 'submit',
+                                           'name' => 'message_send',
+                                           'type' => 'submit',
+                                           'value' => _m('Send button for sending notice', 'Send')));
+    }
+}
diff --git a/plugins/GroupPrivateMessage/groupmessagelist.php b/plugins/GroupPrivateMessage/groupmessagelist.php
new file mode 100644 (file)
index 0000000..09f453d
--- /dev/null
@@ -0,0 +1,77 @@
+<?php
+/**
+ * StatusNet - the distributed open-source microblogging tool
+ * Copyright (C) 2010, StatusNet, Inc.
+ *
+ * Widget for showing list of group messages
+ * 
+ * PHP version 5
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @category  PrivateGroup
+ * @package   StatusNet
+ * @author    Evan Prodromou <evan@status.net>
+ * @copyright 2010 StatusNet, Inc.
+ * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
+ * @link      http://status.net/
+ */
+
+if (!defined('STATUSNET')) {
+    // This check helps protect against security problems;
+    // your code file can't be executed directly from the web.
+    exit(1);
+}
+
+/**
+ * Widget for showing list of group messages
+ *
+ * @category  PrivateGroup
+ * @package   StatusNet
+ * @author    Evan Prodromou <evan@status.net>
+ * @copyright 2010 StatusNet, Inc.
+ * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
+ * @link      http://status.net/
+ */
+class GroupMessageList extends Widget
+{
+    var $gm;
+
+    /**
+     * Constructor
+     *
+     * @param HTMLOutputter $out output context
+     * @param Group_message $gm  Group message stream
+     */
+    function __construct($out, $gm)
+    {
+        parent::__construct($out);
+        $this->gm = $gm;
+    }
+
+    /**
+     * Show the list
+     *
+     * @return void
+     */
+    function show()
+    {
+        $this->out->elementStart('ul', 'notices messages group-messages');
+        while ($this->gm->fetch()) {
+            $gmli = new GroupMessageListItem($this->out, $this->gm);
+            $gmli->show();
+        }
+        $this->out->elementEnd('ul');
+    }
+}
diff --git a/plugins/GroupPrivateMessage/groupmessagelistitem.php b/plugins/GroupPrivateMessage/groupmessagelistitem.php
new file mode 100644 (file)
index 0000000..e7b7c6a
--- /dev/null
@@ -0,0 +1,113 @@
+<?php
+/**
+ * StatusNet - the distributed open-source microblogging tool
+ * Copyright (C) 2010, StatusNet, Inc.
+ *
+ * Widget for showing an individual group message
+ * 
+ * PHP version 5
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @category  PrivateGroup
+ * @package   StatusNet
+ * @author    Evan Prodromou <evan@status.net>
+ * @copyright 2010 StatusNet, Inc.
+ * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
+ * @link      http://status.net/
+ */
+
+if (!defined('STATUSNET')) {
+    // This check helps protect against security problems;
+    // your code file can't be executed directly from the web.
+    exit(1);
+}
+
+/**
+ * Widget for showing a single group message
+ *
+ * @category  PrivateGroup
+ * @package   StatusNet
+ * @author    Evan Prodromou <evan@status.net>
+ * @copyright 2010 StatusNet, Inc.
+ * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
+ * @link      http://status.net/
+ */
+class GroupMessageListItem extends Widget
+{
+    var $gm;
+
+    /**
+     * Constructor
+     *
+     * @param HTMLOutputter $out output context
+     * @param Group_message $gm  Group message
+     */
+    function __construct($out, $gm)
+    {
+        parent::__construct($out);
+        $this->gm = $gm;
+    }
+
+    /**
+     * Show the item
+     *
+     * @return void
+     */
+    function show()
+    {
+        $group  = $this->gm->getGroup();
+        $sender = $this->gm->getSender();
+        $this->out->elementStart('li', array('class' => 'hentry notice message group-message',
+                                         'id' => 'message-' . $this->gm->id));
+
+        $this->out->elementStart('div', 'entry-title');
+        $this->out->elementStart('span', 'vcard author');
+        $this->out->elementStart('a', 
+                                 array('href' => $sender->profileurl,
+                                       'class' => 'url'));
+        $avatar = $sender->getAvatar(AVATAR_STREAM_SIZE);
+        $this->out->element('img', array('src' => ($avatar) ?
+                                    $avatar->displayUrl() :
+                                    Avatar::defaultImage(AVATAR_STREAM_SIZE),
+                                    'width' => AVATAR_STREAM_SIZE,
+                                    'height' => AVATAR_STREAM_SIZE,
+                                    'class' => 'photo avatar',
+                                    'alt' => $sender->getBestName()));
+        $this->out->element('span',
+                            array('class' => 'nickname fn'),
+                            $sender->nickname);
+        $this->out->elementEnd('a');
+        $this->out->elementEnd('span');
+
+        $this->out->elementStart('p', array('class' => 'entry-content message-content'));
+        $this->out->raw($this->gm->rendered);
+        $this->out->elementEnd('p');
+        $this->out->elementEnd('div');
+
+        $this->out->elementStart('div', 'entry-content');
+        $this->out->elementStart('a', array('rel' => 'bookmark',
+                                            'class' => 'timestamp',
+                                            'href' => $this->gm->url));
+        $dt = common_date_iso8601($this->gm->created);
+        $this->out->element('abbr', array('class' => 'published',
+                                          'title' => $dt),
+                            common_date_string($this->gm->created));
+        $this->out->elementEnd('a');
+        $this->out->elementEnd('div');
+
+        $this->out->elementEnd('li');
+    }
+}
diff --git a/plugins/GroupPrivateMessage/newgroupmessage.php b/plugins/GroupPrivateMessage/newgroupmessage.php
new file mode 100644 (file)
index 0000000..a2c5dfd
--- /dev/null
@@ -0,0 +1,161 @@
+<?php
+/**
+ * StatusNet - the distributed open-source microblogging tool
+ * Copyright (C) 2010, StatusNet, Inc.
+ *
+ * Action for adding a new group message
+ * 
+ * PHP version 5
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @category  Cache
+ * @package   StatusNet
+ * @author    Evan Prodromou <evan@status.net>
+ * @copyright 2010 StatusNet, Inc.
+ * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
+ * @link      http://status.net/
+ */
+
+if (!defined('STATUSNET')) {
+    // This check helps protect against security problems;
+    // your code file can't be executed directly from the web.
+    exit(1);
+}
+
+/**
+ * Action for adding a new group message
+ *
+ * @category  Action
+ * @package   StatusNet
+ * @author    Evan Prodromou <evan@status.net>
+ * @copyright 2010 StatusNet, Inc.
+ * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
+ * @link      http://status.net/
+ */
+
+class NewgroupmessageAction extends Action
+{
+    var $group;
+    var $user;
+    var $text;
+
+    /**
+     * For initializing members of the class.
+     *
+     * @param array $argarray misc. arguments
+     *
+     * @return boolean true
+     */
+
+    function prepare($argarray)
+    {
+        parent::prepare($argarray);
+
+        $this->user = common_current_user();
+
+        if (empty($this->user)) {
+            throw new ClientException(_('Must be logged in.'), 403);
+        }
+
+        if (!$this->user->hasRight(Right::NEWMESSAGE)) {
+            throw new Exception(sprintf(_('User %s not allowed to send private messages.'),
+                                        $this->user->nickname));
+        }
+
+        $nicknameArg = $this->trimmed('nickname');
+
+        $nickname = common_canonical_nickname($nicknameArg);
+
+        if ($nickname != $nicknameArg) {
+            $url = common_local_url('newgroupmessage', array('nickname' => $nickname));
+            common_redirect($url, 301);
+            return false;
+        }
+
+        $localGroup = Local_group::staticGet('nickname', $nickname);
+
+        if (empty($localGroup)) {
+            throw new ClientException(_('No such group'), 404);
+        }
+
+        $this->group = User_group::staticGet('id', $localGroup->group_id);
+
+        if (empty($this->group)) {
+            throw new ClientException(_('No such group'), 404);
+        }
+
+        // This throws an exception on error
+
+        Group_privacy_settings::ensurePost($this->user, $this->group);
+
+        // If we're posted to, check session token and get text
+
+        if ($this->isPost()) {
+            $this->checkSessionToken();
+            $this->text = $this->trimmed('content');
+        }
+
+        return true;
+    }
+
+    /**
+     * Handler method
+     *
+     * @param array $argarray is ignored since it's now passed in in prepare()
+     *
+     * @return void
+     */
+
+    function handle($argarray=null)
+    {
+        if ($this->isPost()) {
+            $this->sendNewMessage();
+        } else {
+            $this->showPage();
+        }
+    }
+
+    function showNoticeForm()
+    {
+        $form = new GroupMessageForm($this, $this->group);
+        $form->show();
+    }
+
+    function sendNewMessage()
+    {
+        $gm = Group_message::send($this->user, $this->group, $this->text);
+
+        if ($this->boolean('ajax')) {
+            $this->startHTML('text/xml;charset=utf-8');
+            $this->elementStart('head');
+            $this->element('title', null, _('Message sent'));
+            $this->elementEnd('head');
+            $this->elementStart('body');
+            $this->element('p',
+                           array('id' => 'command_result'),
+                           sprintf(_('Direct message to %s sent.'),
+                                   $this->group->nickname));
+            $this->elementEnd('body');
+            $this->elementEnd('html');
+        } else {
+            common_redirect($gm->url, 303);
+        }
+    }
+
+    function title()
+    {
+        return sprintf(_('New message to group %s'), $this->group->nickname);
+    }
+}
diff --git a/plugins/GroupPrivateMessage/showgroupmessage.php b/plugins/GroupPrivateMessage/showgroupmessage.php
new file mode 100644 (file)
index 0000000..cc0126e
--- /dev/null
@@ -0,0 +1,188 @@
+<?php
+/**
+ * StatusNet - the distributed open-source microblogging tool
+ * Copyright (C) 2010, StatusNet, Inc.
+ *
+ * Show a single group message
+ * 
+ * PHP version 5
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @category  PrivateGroup
+ * @package   StatusNet
+ * @author    Evan Prodromou <evan@status.net>
+ * @copyright 2010 StatusNet, Inc.
+ * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
+ * @link      http://status.net/
+ */
+
+if (!defined('STATUSNET')) {
+    // This check helps protect against security problems;
+    // your code file can't be executed directly from the web.
+    exit(1);
+}
+
+/**
+ * Show a single private group message
+ *
+ * @category  PrivateGroup
+ * @package   StatusNet
+ * @author    Evan Prodromou <evan@status.net>
+ * @copyright 2010 StatusNet, Inc.
+ * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
+ * @link      http://status.net/
+ */
+
+class ShowgroupmessageAction extends Action
+{
+    var $gm;
+    var $group;
+    var $sender;
+    var $user;
+
+    /**
+     * For initializing members of the class.
+     *
+     * @param array $argarray misc. arguments
+     *
+     * @return boolean true
+     */
+
+    function prepare($argarray)
+    {
+        parent::prepare($argarray);
+
+        $this->user = common_current_user();
+
+        if (empty($this->user)) {
+            throw new ClientException(_('Only logged-in users can view private messages.'),
+                                      403);
+        }
+
+        $id = $this->trimmed('id');
+
+        $this->gm = Group_message::staticGet('id', $id);
+
+        if (empty($this->gm)) {
+            throw new ClientException(_('No such message'), 404);
+        }
+
+        $this->group = User_group::staticGet('id', $this->gm->to_group);
+
+        if (empty($this->group)) {
+            throw new ServerException(_('Group not found.'));
+        }
+
+        if (!$this->user->isMember($this->group)) {
+            throw new ClientException(_('Cannot read message.'), 403);
+        }
+
+        $this->sender = Profile::staticGet('id', $this->gm->from_profile);
+
+        if (empty($this->sender)) {
+            throw new ServerException(_('No sender found.'));
+        }
+
+        return true;
+    }
+
+    /**
+     * Handler method
+     *
+     * @param array $argarray is ignored since it's now passed in in prepare()
+     *
+     * @return void
+     */
+
+    function handle($argarray=null)
+    {
+        $this->showPage();
+    }
+
+    /**
+     * Title of the page
+     */
+
+    function title()
+    {
+        return sprintf(_('Message from %1$s to group %2$s on %3$s'),
+                       $this->sender->nickname,
+                       $this->group->nickname,
+                       common_exact_date($this->gm->created));
+    }
+
+    /**
+     * Show the content area.
+     */
+
+    function showContent()
+    {
+        $this->elementStart('ul', 'notices messages');
+        $gmli = new GroupMessageListItem($this, $this->gm);
+        $gmli->show();
+        $this->elementEnd('ul');
+    }
+
+    /**
+     * Return true if read only.
+     *
+     * MAY override
+     *
+     * @param array $args other arguments
+     *
+     * @return boolean is read only action?
+     */
+
+    function isReadOnly($args)
+    {
+        return true;
+    }
+
+    /**
+     * Return last modified, if applicable.
+     *
+     * MAY override
+     *
+     * @return string last modified http header
+     */
+    function lastModified()
+    {
+        return max(strtotime($this->group->modified),
+                   strtotime($this->sender->modified),
+                   strtotime($this->gm->modified));
+    }
+
+    /**
+     * Return etag, if applicable.
+     *
+     * MAY override
+     *
+     * @return string etag http header
+     */
+    function etag()
+    {
+        $avatar = $this->sender->getAvatar(AVATAR_STREAM_SIZE);
+
+        $avtime = ($avatar) ? strtotime($avatar->modified) : 0;
+
+        return 'W/"' . implode(':', array($this->arg('action'),
+                                          common_user_cache_hash(),
+                                          common_language(),
+                                          $this->gm->id,
+                                          strtotime($this->sender->modified),
+                                          strtotime($this->group->modified),
+                                          $avtime)) . '"';
+    }
+}
diff --git a/plugins/PrivateGroup/Group_message.php b/plugins/PrivateGroup/Group_message.php
deleted file mode 100644 (file)
index 07d4c57..0000000
+++ /dev/null
@@ -1,208 +0,0 @@
-<?php
-/**
- * Data class for group direct messages
- *
- * PHP version 5
- *
- * @category Data
- * @package  StatusNet
- * @author   Evan Prodromou <evan@status.net>
- * @license  http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
- * @link     http://status.net/
- *
- * StatusNet - the distributed open-source microblogging tool
- * Copyright (C) 2009, StatusNet, Inc.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.     See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-if (!defined('STATUSNET')) {
-    exit(1);
-}
-
-require_once INSTALLDIR . '/classes/Memcached_DataObject.php';
-
-/**
- * Data class for group direct messages
- *
- * @category PrivateGroup
- * @package  StatusNet
- * @author   Evan Prodromou <evan@status.net>
- * @license  http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
- * @link     http://status.net/
- *
- * @see      DB_DataObject
- */
-
-class Group_message extends Memcached_DataObject
-{
-    public $__table = 'group_message'; // table name
-    public $id;                        // char(36)  primary_key not_null
-    public $uri;                       // varchar(255)
-    public $from_profile;              // int
-    public $to_group;                  // int
-    public $content;
-    public $rendered;
-    public $url;
-    public $created;
-
-    /**
-     * Get an instance by key
-     *
-     * This is a utility method to get a single instance with a given key value.
-     *
-     * @param string $k Key to use to lookup (usually 'user_id' for this class)
-     * @param mixed  $v Value to lookup
-     *
-     * @return Group_message object found, or null for no hits
-     *
-     */
-    function staticGet($k, $v=null)
-    {
-        return Memcached_DataObject::staticGet('Group_message', $k, $v);
-    }
-
-    /**
-     * return table definition for DB_DataObject
-     *
-     * DB_DataObject needs to know something about the table to manipulate
-     * instances. This method provides all the DB_DataObject needs to know.
-     *
-     * @return array array of column definitions
-     */
-    function table()
-    {
-        return array('id' => DB_DATAOBJECT_STR + DB_DATAOBJECT_NOTNULL,
-                     'uri' => DB_DATAOBJECT_STR + DB_DATAOBJECT_NOTNULL,
-                     'from_profile' => DB_DATAOBJECT_INT + DB_DATAOBJECT_NOTNULL,
-                     'to_group' => DB_DATAOBJECT_INT + DB_DATAOBJECT_NOTNULL,
-                     'content' => DB_DATAOBJECT_STR + DB_DATAOBJECT_NOTNULL,
-                     'rendered' => DB_DATAOBJECT_STR + DB_DATAOBJECT_NOTNULL,
-                     'url' => DB_DATAOBJECT_STR,
-                     'created' => DB_DATAOBJECT_STR + DB_DATAOBJECT_DATE + DB_DATAOBJECT_TIME + DB_DATAOBJECT_NOTNULL);
-    }
-
-    /**
-     * return key definitions for DB_DataObject
-     *
-     * DB_DataObject needs to know about keys that the table has, since it
-     * won't appear in StatusNet's own keys list. In most cases, this will
-     * simply reference your keyTypes() function.
-     *
-     * @return array list of key field names
-     */
-    function keys()
-    {
-        return array_keys($this->keyTypes());
-    }
-
-    /**
-     * return key definitions for Memcached_DataObject
-     *
-     * @return array associative array of key definitions, field name to type:
-     *         'K' for primary key: for compound keys, add an entry for each component;
-     *         'U' for unique keys: compound keys are not well supported here.
-     */
-    function keyTypes()
-    {
-        return array('id' => 'K', 'uri' => 'U');
-    }
-
-    static function send($user, $group, $text)
-    {
-        if (!$user->hasRight(Right::NEWMESSAGE)) {
-            // XXX: maybe break this out into a separate right
-            throw new Exception(sprintf(_('User %s not allowed to send private messages.'),
-                                        $user->nickname));
-        }
-
-        Group_privacy_settings::ensurePost($user, $group);
-
-        $text = $user->shortenLinks($text);
-
-        // We use the same limits as for 'regular' private messages.
-
-        if (Message::contentTooLong($text)) {
-            throw new Exception(sprintf(_m('That\'s too long. Maximum message size is %d character.',
-                                           'That\'s too long. Maximum message size is %d characters.',
-                                           Message::maxContent()),
-                                        Message::maxContent()));
-        }
-
-        // Valid! Let's do this thing!
-
-        $gm = new Group_message();
-        
-        $gm->id           = UUID::gen();
-        $gm->uri          = common_local_url('showgroupmessage', array('id' => $gm->id));
-        $gm->from_profile = $user->id;
-        $gm->to_group     = $group->id;
-        $gm->content      = $text; // XXX: is this cool?!
-        $gm->rendered     = common_render_text($text);
-        $gm->url          = $gm->uri;
-        $gm->created      = common_sql_now();
-
-        // This throws a conniption if there's a problem
-
-        $gm->insert();
-
-        $gm->distribute();
-
-        return $gm;
-    }
-
-    function distribute()
-    {
-        $group = User_group::staticGet('id', $this->to_group);
-        
-        $member = $group->getMembers();
-
-        while ($member->fetch()) {
-            Group_message_profile::send($this, $member);
-        }
-    }
-
-    function getGroup()
-    {
-        $group = User_group::staticGet('id', $this->to_group);
-        if (empty($group)) {
-            throw new ServerException(_('No group for group message'));
-        }
-        return $group;
-    }
-
-    function getSender()
-    {
-        $sender = Profile::staticGet('id', $this->from_profile);
-        if (empty($sender)) {
-            throw new ServerException(_('No sender for group message'));
-        }
-        return $sender;
-    }
-
-    static function forGroup($group, $offset, $limit)
-    {
-        // XXX: cache
-        $gm = new Group_message();
-
-        $gm->to_group = $group->id;
-        $gm->orderBy('created DESC');
-        $gm->limit($offset, $limit);
-
-        $gm->find();
-
-        return $gm;
-    }
-
-}
diff --git a/plugins/PrivateGroup/Group_message_profile.php b/plugins/PrivateGroup/Group_message_profile.php
deleted file mode 100644 (file)
index 3323374..0000000
+++ /dev/null
@@ -1,189 +0,0 @@
-<?php
-/**
- * Who received a group message
- *
- * PHP version 5
- *
- * @category Data
- * @package  StatusNet
- * @author   Evan Prodromou <evan@status.net>
- * @license  http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
- * @link     http://status.net/
- *
- * StatusNet - the distributed open-source microblogging tool
- * Copyright (C) 2010, StatusNet, Inc.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.     See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-if (!defined('STATUSNET')) {
-    exit(1);
-}
-
-require_once INSTALLDIR . '/classes/Memcached_DataObject.php';
-
-/**
- * Data class for group direct messages for users
- *
- * @category PrivateGroup
- * @package  StatusNet
- * @author   Evan Prodromou <evan@status.net>
- * @license  http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
- * @link     http://status.net/
- *
- * @see      DB_DataObject
- */
-
-class Group_message_profile extends Memcached_DataObject
-{
-    public $__table = 'group_message_profile'; // table name
-    public $to_profile;                        // int
-    public $group_message_id;                  // char(36)  primary_key not_null
-    public $created;
-
-    /**
-     * Get an instance by key
-     *
-     * This is a utility method to get a single instance with a given key value.
-     *
-     * @param string $k Key to use to lookup (usually 'user_id' for this class)
-     * @param mixed  $v Value to lookup
-     *
-     * @return Group_message object found, or null for no hits
-     *
-     */
-    function staticGet($k, $v=null)
-    {
-        return Memcached_DataObject::staticGet('Group_message_profile', $k, $v);
-    }
-
-    /**
-     * return table definition for DB_DataObject
-     *
-     * DB_DataObject needs to know something about the table to manipulate
-     * instances. This method provides all the DB_DataObject needs to know.
-     *
-     * @return array array of column definitions
-     */
-    function table()
-    {
-        return array('to_profile' => DB_DATAOBJECT_INT + DB_DATAOBJECT_NOTNULL,
-                     'group_message_id' => DB_DATAOBJECT_STR + DB_DATAOBJECT_NOTNULL,
-                     'created' => DB_DATAOBJECT_STR + DB_DATAOBJECT_DATE + DB_DATAOBJECT_TIME + DB_DATAOBJECT_NOTNULL);
-    }
-
-    /**
-     * return key definitions for DB_DataObject
-     *
-     * DB_DataObject needs to know about keys that the table has, since it
-     * won't appear in StatusNet's own keys list. In most cases, this will
-     * simply reference your keyTypes() function.
-     *
-     * @return array list of key field names
-     */
-    function keys()
-    {
-        return array_keys($this->keyTypes());
-    }
-
-    /**
-     * return key definitions for Memcached_DataObject
-     *
-     * @return array associative array of key definitions, field name to type:
-     *         'K' for primary key: for compound keys, add an entry for each component;
-     *         'U' for unique keys: compound keys are not well supported here.
-     */
-    function keyTypes()
-    {
-        return array('to_profile' => 'K', 'group_message_id' => 'K');
-    }
-
-    /**
-     * No sequence keys in this table.
-     */
-    function sequenceKey()
-    {
-        return array(false, false, false);
-    }
-
-    function send($gm, $profile)
-    {
-        $gmp = new Group_message_profile();
-        
-        $gmp->group_message_id = $gm->id;
-        $gmp->to_profile       = $profile->id;
-        $gmp->created          = common_sql_now();
-
-        $gmp->insert();
-
-        $gmp->notify();
-
-        return $gmp;
-    }
-
-    function notify()
-    {
-        // XXX: add more here
-        $this->notifyByMail();
-    }
-
-    function notifyByMail() 
-    {
-        $to = User::staticGet('id', $this->to_profile);
-
-        if (empty($to) || is_null($to->email) || !$to->emailnotifymsg) {
-            return true;
-        }
-
-        $gm = Group_message::staticGet('id', $this->group_message_id);
-
-        $from_profile = Profile::staticGet('id', $gm->from_profile);
-
-        $group = $gm->getGroup();
-
-        common_switch_locale($to->language);
-
-        // TRANS: Subject for direct-message notification email.
-        // TRANS: %s is the sending user's nickname.
-        $subject = sprintf(_('New private message from %s to group %s'), $from->nickname, $group->nickname);
-
-        $from_profile = $from->getProfile();
-
-        // TRANS: Body for direct-message notification email.
-        // TRANS: %1$s is the sending user's long name, %2$s is the sending user's nickname,
-        // TRANS: %3$s is the message content, %4$s a URL to the message,
-        // TRANS: %5$s is the StatusNet sitename.
-        $body = sprintf(_("%1\$s (%2\$s) sent a private message to group %3\$s:\n\n".
-                          "------------------------------------------------------\n".
-                          "%4\$s\n".
-                          "------------------------------------------------------\n\n".
-                          "You can reply to their message here:\n\n".
-                          "%5\$s\n\n".
-                          "Don't reply to this email; it won't get to them.\n\n".
-                          "With kind regards,\n".
-                          "%6\$s\n"),
-                        $from_profile->getBestName(),
-                        $from->nickname,
-                        $group->nickname,
-                        $this->content,
-                        common_local_url('newmessage', array('to' => $from->id)),
-                        common_config('site', 'name'));
-
-        $headers = _mail_prepare_headers('message', $to->nickname, $from->nickname);
-
-        common_switch_locale();
-
-        return mail_to_user($to, $subject, $body, $headers);
-    }
-}
diff --git a/plugins/PrivateGroup/Group_privacy_settings.php b/plugins/PrivateGroup/Group_privacy_settings.php
deleted file mode 100644 (file)
index 898ac26..0000000
+++ /dev/null
@@ -1,194 +0,0 @@
-<?php
-/**
- * Data class for group privacy settings
- *
- * PHP version 5
- *
- * @category Data
- * @package  StatusNet
- * @author   Evan Prodromou <evan@status.net>
- * @license  http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
- * @link     http://status.net/
- *
- * StatusNet - the distributed open-source microblogging tool
- * Copyright (C) 2011, StatusNet, Inc.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.     See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-if (!defined('STATUSNET')) {
-    exit(1);
-}
-
-/**
- * Data class for group privacy
- *
- * Stores admin preferences about the group.
- *
- * @category Action
- * @package  StatusNet
- * @author   Evan Prodromou <evan@status.net>
- * @license  http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
- * @link     http://status.net/
- *
- * @see      DB_DataObject
- */
-
-class Group_privacy_settings extends Memcached_DataObject
-{
-    public $__table = 'group_privacy_settings';
-    /** ID of the group. */
-    public $group_id;      
-    /** When to allow privacy: always, sometimes, or never. */
-    public $allow_privacy;
-    /** Who can send private messages: everyone, member, admin */
-    public $allow_sender; 
-    /** row creation timestamp */
-    public $created;
-    /** Last-modified timestamp */
-    public $modified;
-
-    /** NEVER is */
-
-    const SOMETIMES = -1;
-    const NEVER  = 0;
-    const ALWAYS = 1;
-
-    /** These are bit-mappy, as a hedge against the future. */
-
-    const EVERYONE = 1;
-    const MEMBER   = 2;
-    const ADMIN    = 4;
-
-    /**
-     * Get an instance by key
-     *
-     * This is a utility method to get a single instance with a given key value.
-     *
-     * @param string $k Key to use to lookup (usually 'user_id' for this class)
-     * @param mixed  $v Value to lookup
-     *
-     * @return User_greeting_count object found, or null for no hits
-     */
-
-    function staticGet($k, $v=null)
-    {
-        return Memcached_DataObject::staticGet('Group_privacy_settings', $k, $v);
-    }
-
-    /**
-     * return table definition for DB_DataObject
-     *
-     * DB_DataObject needs to know something about the table to manipulate
-     * instances. This method provides all the DB_DataObject needs to know.
-     *
-     * @return array array of column definitions
-     */
-
-    function table()
-    {
-        return array('group_id' => DB_DATAOBJECT_INT + DB_DATAOBJECT_NOTNULL,
-                     'allow_privacy' => DB_DATAOBJECT_INT,
-                     'allow_sender' => DB_DATAOBJECT_INT,
-                     'created' => DB_DATAOBJECT_STR + DB_DATAOBJECT_DATE + DB_DATAOBJECT_TIME + DB_DATAOBJECT_NOTNULL,
-                     'modified' => DB_DATAOBJECT_STR + DB_DATAOBJECT_DATE + DB_DATAOBJECT_TIME + DB_DATAOBJECT_NOTNULL);
-                     
-    }
-
-    /**
-     * return key definitions for DB_DataObject
-     *
-     * DB_DataObject needs to know about keys that the table has, since it
-     * won't appear in StatusNet's own keys list. In most cases, this will
-     * simply reference your keyTypes() function.
-     *
-     * @return array list of key field names
-     */
-
-    function keys()
-    {
-        return array_keys($this->keyTypes());
-    }
-
-    /**
-     * return key definitions for Memcached_DataObject
-     *
-     * @return array associative array of key definitions, field name to type:
-     *         'K' for primary key: for compound keys, add an entry for each component;
-     *         'U' for unique keys: compound keys are not well supported here.
-     */
-
-    function keyTypes()
-    {
-        return array('group_id' => 'K');
-    }
-
-    /**
-     * Magic formula for non-autoincrementing integer primary keys
-     *
-     * @return array magic three-false array that stops auto-incrementing.
-     */
-
-    function sequenceKey()
-    {
-        return array(false, false, false);
-    }
-
-    function ensurePost($user, $group)
-    {
-        $gps = Group_privacy_settings::staticGet('group_id', $group->id);
-
-        if (empty($gps)) {
-            // make a fake one with defaults
-            $gps = new Group_privacy_settings();
-            $gps->allow_privacy = Group_privacy_settings::SOMETIMES;
-            $gps->allow_sender  = Group_privacy_settings::MEMBER;
-        }
-
-        if ($gps->allow_privacy == Group_privacy_settings::NEVER) {
-            throw new Exception(sprintf(_('Group %s does not allow private messages.'),
-                                        $group->nickname));
-        }
-
-        switch ($gps->allow_sender) {
-        case Group_privacy_settings::EVERYONE:
-            $profile = $user->getProfile();
-            if (Group_block::isBlocked($group, $profile)) {
-                throw new Exception(sprintf(_('User %s is blocked from group %s.'),
-                                            $user->nickname,
-                                            $group->nickname));
-            }
-            break;
-        case Group_privacy_settings::MEMBER:
-            if (!$user->isMember($group)) {
-                throw new Exception(sprintf(_('User %s is not a member of group %s.'),
-                                            $user->nickname,
-                                            $group->nickname));
-            }
-            break;
-        case Group_privacy_settings::ADMIN:
-            if (!$user->isAdmin($group)) {
-                throw new Exception(sprintf(_('User %s is not an administrator of group %s.'),
-                                            $user->nickname,
-                                            $group->nickname));
-            }
-            break;
-        default:
-            throw new Exception(sprintf(_('Unknown privacy settings for group %s.'),
-                                        $group->nickname));
-        }
-
-        return true;
-    }
-}
diff --git a/plugins/PrivateGroup/PrivateGroupPlugin.php b/plugins/PrivateGroup/PrivateGroupPlugin.php
deleted file mode 100644 (file)
index 6ead696..0000000
+++ /dev/null
@@ -1,391 +0,0 @@
-<?php
-/**
- * StatusNet - the distributed open-source microblogging tool
- * Copyright (C) 2010, StatusNet, Inc.
- *
- * Private groups for StatusNet 0.9.x
- *
- * PHP version 5
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- *
- * @category  Privacy
- * @package   StatusNet
- * @author    Evan Prodromou <evan@status.net>
- * @copyright 2010 StatusNet, Inc.
- * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
- * @link      http://status.net/
- */
-
-if (!defined('STATUSNET')) {
-    // This check helps protect against security problems;
-    // your code file can't be executed directly from the web.
-    exit(1);
-}
-
-/**
- * Private groups
- *
- * This plugin allows users to send private messages to a group.
- *
- * @category  Privacy
- * @package   StatusNet
- * @author    Evan Prodromou <evan@status.net>
- * @copyright 2010 StatusNet, Inc.
- * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
- * @link      http://status.net/
- */
-
-class PrivateGroupPlugin extends Plugin
-{
-    /**
-     * Database schema setup
-     *
-     * @see Schema
-     * @see ColumnDef
-     *
-     * @return boolean hook value
-     */
-
-    function onCheckSchema()
-    {
-        $schema = Schema::get();
-
-        // For storing user-submitted flags on profiles
-
-        $schema->ensureTable('group_privacy_settings',
-                             array(new ColumnDef('group_id',
-                                                 'integer',
-                                                 null,
-                                                 false,
-                                                 'PRI'),
-                                   new ColumnDef('allow_privacy',
-                                                 'integer'),
-                                   new ColumnDef('allow_sender',
-                                                 'integer'),
-                                   new ColumnDef('created',
-                                                 'datetime'),
-                                   new ColumnDef('modified',
-                                                 'timestamp')));
-                             
-        $schema->ensureTable('group_message',
-                             array(new ColumnDef('id',
-                                                 'char',
-                                                 36,
-                                                 false,
-                                                 'PRI'),
-                                   new ColumnDef('uri',
-                                                 'varchar',
-                                                 255,
-                                                 false,
-                                                 'UNI'),
-                                   new ColumnDef('from_profile',
-                                                 'integer',
-                                                 null,
-                                                 false,
-                                                 'MUL'),
-                                   new ColumnDef('to_group',
-                                                 'integer',
-                                                 null,
-                                                 false,
-                                                 'MUL'),
-                                   new ColumnDef('content',
-                                                 'text'),
-                                   new ColumnDef('rendered',
-                                                 'text'),
-                                   new ColumnDef('url',
-                                                 'varchar',
-                                                 255,
-                                                 false,
-                                                 'UNI'),
-                                   new ColumnDef('created',
-                                                 'datetime')));
-
-        $schema->ensureTable('group_message_profile',
-                             array(new ColumnDef('to_profile',
-                                                 'integer',
-                                                 null,
-                                                 false,
-                                                 'PRI'),
-                                   new ColumnDef('group_message_id',
-                                                 'char',
-                                                 36,
-                                                 false,
-                                                 'PRI'),
-                                   new ColumnDef('created',
-                                                 'datetime')));
-
-        return true;
-    }
-
-    /**
-     * Load related modules when needed
-     *
-     * @param string $cls Name of the class to be loaded
-     *
-     * @return boolean hook value
-     */
-
-    function onAutoload($cls)
-    {
-        $dir = dirname(__FILE__);
-
-        switch ($cls)
-        {
-        case 'GroupinboxAction':
-        case 'ShowgroupmessageAction':
-        case 'NewgroupmessageAction':
-            include_once $dir . '/' . strtolower(mb_substr($cls, 0, -6)) . '.php';
-            return false;
-        case 'Group_privacy_settings':
-        case 'Group_message':
-        case 'Group_message_profile':
-            include_once $dir . '/'.$cls.'.php';
-            return false;
-        case 'GroupMessageCommand':
-        case 'GroupMessageList':
-        case 'GroupMessageListItem':
-        case 'GroupMessageForm':
-            include_once $dir . '/'.strtolower($cls).'.php';
-            return false;
-        default:
-            return true;
-        }
-    }
-
-    /**
-     * Map URLs to actions
-     *
-     * @param Net_URL_Mapper $m path-to-action mapper
-     *
-     * @return boolean hook value
-     */
-
-    function onRouterInitialized($m)
-    {
-        $m->connect('group/:nickname/inbox',
-                    array('action' => 'groupinbox'),
-                    array('nickname' => Nickname::DISPLAY_FMT));
-
-        $m->connect('group/message/:id',
-                    array('action' => 'showgroupmessage'),
-                    array('id' => '[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}'));
-
-        $m->connect('group/:nickname/message/new',
-                    array('action' => 'newgroupmessage'),
-                    array('nickname' => Nickname::DISPLAY_FMT));
-
-        return true;
-    }
-
-    /**
-     * Add group inbox to the menu
-     *
-     * @param Action $action The current action handler. Use this to
-     *                       do any output.
-     *
-     * @return boolean hook value; true means continue processing, false means stop.
-     *
-     * @see Action
-     */
-
-    function onEndGroupGroupNav($groupnav)
-    {
-        $action = $groupnav->action;
-        $group  = $groupnav->group;
-
-        $action->menuItem(common_local_url('groupinbox',
-                                           array('nickname' => $group->nickname)),
-                          _m('Inbox'),
-                          _m('Private messages for this group'),
-                          $action->trimmed('action') == 'groupinbox',
-                          'nav_group_inbox');
-        return true;
-    }
-
-    /**
-     * Create default group privacy settings at group create time
-     *
-     * @param User_group $group Group that was just created
-     *
-     * @result boolean hook value
-     */
-
-    function onEndGroupSave($group)
-    {
-        $gps = new Group_privacy_settings();
-
-        $gps->group_id      = $group->id;
-        $gps->allow_privacy = Group_privacy_settings::SOMETIMES;
-        $gps->allow_sender  = Group_privacy_settings::MEMBER;
-        $gps->created       = common_sql_now();
-        $gps->modified      = $gps->created;
-
-        // This will throw an exception on error
-
-        $gps->insert();
-
-        return true;
-    }
-
-    /**
-     * Show group privacy controls on group edit form
-     *
-     * @param GroupEditForm $form form being shown
-     */
-
-    function onEndGroupEditFormData($form)
-    {
-        $gps = null;
-
-        if (!empty($form->group)) {
-            $gps = Group_privacy_settings::staticGet('group_id', $form->group->id);
-        }
-
-        $form->out->elementStart('li');
-        $form->out->dropdown('allow_privacy',
-                             _('Private messages'),
-                             array(Group_privacy_settings::SOMETIMES => _('Sometimes'),
-                                   Group_privacy_settings::ALWAYS => _('Always'),
-                                   Group_privacy_settings::NEVER => _('Never')),
-                             _('Whether to allow private messages to this group'),
-                             false,
-                             (empty($gps)) ? Group_privacy_settings::SOMETIMES : $gps->allow_privacy);
-        $form->out->elementEnd('li');
-        $form->out->elementStart('li');
-        $form->out->dropdown('allow_sender',
-                             _('Private sender'),
-                             array(Group_privacy_settings::EVERYONE => _('Everyone'),
-                                   Group_privacy_settings::MEMBER => _('Member'),
-                                   Group_privacy_settings::ADMIN => _('Admin')),
-                             _('Who can send private messages to the group'),
-                             false,
-                             (empty($gps)) ? Group_privacy_settings::MEMBER : $gps->allow_sender);
-        $form->out->elementEnd('li');
-        return true;
-    }
-
-    function onEndGroupSaveForm($action)
-    {
-        $gps = null;
-
-        if (!empty($action->group)) {
-            $gps = Group_privacy_settings::staticGet('group_id', $action->group->id);
-        }
-
-        $orig = null;
-
-        if (empty($gps)) {
-            $gps = new Group_privacy_settings();
-            $gps->group_id = $action->group->id;
-        } else {
-            $orig = clone($gps);
-        }
-        
-        $gps->allow_privacy = $action->trimmed('allow_privacy');
-        $gps->allow_sender  = $action->trimmed('allow_sender');
-
-        if (empty($orig)) {
-            $gps->created = common_sql_now();
-            $gps->insert();
-        } else {
-            $gps->update($orig);
-        }
-        
-        return true;
-    }
-
-    /**
-     * Overload 'd' command to send private messages to groups.
-     * 
-     * 'd !group word word word' will send the private message
-     * 'word word word' to the group 'group'.
-     * 
-     * @param string  $cmd     Command being run
-     * @param string  $arg     Rest of the message (including address)
-     * @param User    $user    User sending the message
-     * @param Command &$result The resulting command object to be run.
-     * 
-     * @return boolean hook value
-     */
-    function onStartIntepretCommand($cmd, $arg, $user, &$result)
-    {
-        if ($cmd == 'd' || $cmd == 'dm') {
-
-            $this->debug('Got a d command');
-
-            // Break off the first word as the address
-
-            $pieces = explode(' ', $arg, 2);
-
-            if (count($pieces) == 1) {
-                $pieces[] = null;
-            }
-
-            list($addr, $msg) = $pieces;
-
-            if (!empty($addr) && $addr[0] == '!') {
-                $result = new GroupMessageCommand($user, substr($addr, 1), $msg);
-                Event::handle('EndInterpretCommand', array($cmd, $arg, $user, $result));
-                return false;
-            }
-        }
-
-        return true;
-    }
-
-    /**
-     * To add a "Message" button to the group profile page
-     *
-     * @param Action     $action The showgroup action being shown
-     * @param User_group $group  The current group
-     * 
-     * @return boolean hook value
-     */
-    function onEndGroupActionsList($action, $group)
-    {
-        $cur = common_current_user();
-
-        if (empty($cur)) {
-            return true;
-        }
-
-        try {
-            Group_privacy_settings::ensurePost($cur, $group);
-        } catch (Exception $e) {
-            return true;
-        }
-
-        $action->elementStart('li', 'entity_send-a-message');
-        $action->element('a', array('href' => common_local_url('newgroupmessage', array('nickname' => $group->nickname)),
-                                    'title' => _('Send a direct message to this group')),
-                         _('Message'));
-        // $form = new GroupMessageForm($action, $group);
-        // $form->hidden = true;
-        // $form->show();
-        $action->elementEnd('li');
-        return true;
-    }
-    function onPluginVersion(&$versions)
-    {
-        $versions[] = array('name' => 'PrivateGroup',
-                            'version' => STATUSNET_VERSION,
-                            'author' => 'Evan Prodromou',
-                            'homepage' => 'http://status.net/wiki/Plugin:PrivateGroup',
-                            'rawdescription' =>
-                            _m('Allow posting DMs to a group.'));
-        return true;
-    }
-}
diff --git a/plugins/PrivateGroup/groupinbox.php b/plugins/PrivateGroup/groupinbox.php
deleted file mode 100644 (file)
index 55bf4b0..0000000
+++ /dev/null
@@ -1,170 +0,0 @@
-<?php
-/**
- * StatusNet - the distributed open-source microblogging tool
- * Copyright (C) 2010, StatusNet, Inc.
- *
- * List of private messages to this group
- * 
- * PHP version 5
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- *
- * @category  PrivateGroup
- * @package   StatusNet
- * @author    Evan Prodromou <evan@status.net>
- * @copyright 2010 StatusNet, Inc.
- * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
- * @link      http://status.net/
- */
-
-if (!defined('STATUSNET')) {
-    // This check helps protect against security problems;
-    // your code file can't be executed directly from the web.
-    exit(1);
-}
-
-/**
- * Show a list of private messages to this group
- *
- * @category  PrivateGroup
- * @package   StatusNet
- * @author    Evan Prodromou <evan@status.net>
- * @copyright 2010 StatusNet, Inc.
- * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
- * @link      http://status.net/
- */
-
-class GroupinboxAction extends GroupDesignAction
-{
-    var $gm;
-
-    /**
-     * For initializing members of the class.
-     *
-     * @param array $argarray misc. arguments
-     *
-     * @return boolean true
-     */
-    function prepare($argarray)
-    {
-        parent::prepare($argarray);
-
-        $cur = common_current_user();
-
-        if (empty($cur)) {
-            throw new ClientException(_('Only for logged-in users'), 403);
-        }
-
-        $nicknameArg = $this->trimmed('nickname');
-
-        $nickname = common_canonical_nickname($nicknameArg);
-
-        if ($nickname != $nicknameArg) {
-            $url = common_local_url('groupinbox', array('nickname' => $nickname));
-            common_redirect($url);
-            return false;
-        }
-
-        $localGroup = Local_group::staticGet('nickname', $nickname);
-
-        if (empty($localGroup)) {
-            throw new ClientException(_('No such group'), 404);
-        }
-
-        $this->group = User_group::staticGet('id', $localGroup->group_id);
-
-        if (empty($this->group)) {
-            throw new ClientException(_('No such group'), 404);
-        }
-
-        if (!$cur->isMember($this->group)) {
-            throw new ClientException(_('Only for members'), 403);
-        }
-
-        $this->page = $this->trimmed('page');
-
-        if (!$this->page) {
-            $this->page = 1;
-        }
-        
-        $this->gm = Group_message::forGroup($this->group, 
-                                            ($this->page - 1) * MESSAGES_PER_PAGE,
-                                            MESSAGES_PER_PAGE + 1);
-        return true;
-    }
-
-    function showLocalNav()
-    {
-        $nav = new GroupNav($this, $this->group);
-        $nav->show();
-    }
-
-    function showNoticeForm()
-    {
-        $form = new GroupMessageForm($this, $this->group);
-        $form->show();
-    }
-
-    function showContent()
-    {
-        $gml = new GroupMessageList($this, $this->gm);
-        $gml->show();
-    }
-
-    /**
-     * Handler method
-     *
-     * @param array $argarray is ignored since it's now passed in in prepare()
-     *
-     * @return void
-     */
-    function handle($argarray=null)
-    {
-        $this->showPage();
-    }
-
-    /**
-     * Return true if read only.
-     *
-     * MAY override
-     *
-     * @param array $args other arguments
-     *
-     * @return boolean is read only action?
-     */
-    function isReadOnly($args)
-    {
-        return true;
-    }
-
-    /**
-     * Title of the page
-     *
-     * @return string page title, with page number
-     */
-    function title()
-    {
-        $base = $this->group->getFancyName();
-
-        if ($this->page == 1) {
-            return sprintf(_('%s group inbox'), $base);
-        } else {
-            // TRANS: Page title for any but first group page.
-            // TRANS: %1$s is a group name, $2$s is a page number.
-            return sprintf(_('%1$s group inbox, page %2$d'),
-                           $base,
-                           $this->page);
-        }
-    }
-}
diff --git a/plugins/PrivateGroup/groupmessagecommand.php b/plugins/PrivateGroup/groupmessagecommand.php
deleted file mode 100644 (file)
index 19136f1..0000000
+++ /dev/null
@@ -1,85 +0,0 @@
-<?php
-/**
- * StatusNet - the distributed open-source microblogging tool
- * Copyright (C) 2010, StatusNet, Inc.
- *
- * Command object for messages to groups
- * 
- * PHP version 5
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- *
- * @category  Command
- * @package   StatusNet
- * @author    Evan Prodromou <evan@status.net>
- * @copyright 2010 StatusNet, Inc.
- * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
- * @link      http://status.net/
- */
-
-if (!defined('STATUSNET')) {
-    // This check helps protect against security problems;
-    // your code file can't be executed directly from the web.
-    exit(1);
-}
-
-/**
- * Command object for messages to groups
- *
- * @category  General
- * @package   StatusNet
- * @author    Evan Prodromou <evan@status.net>
- * @copyright 2010 StatusNet, Inc.
- * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
- * @link      http://status.net/
- */
-
-class GroupMessageCommand extends Command
-{
-    /** User sending the message. */
-    var $user;
-    /** Nickname of the group they're sending to. */
-    var $nickname;
-    /** Text of the message. */
-    var $text;
-
-    /**
-     * Constructor
-     *
-     * @param User   $user     User sending the message
-     * @param string $nickname Nickname of the group
-     * @param string $text     Text of message
-     */
-
-    function __construct($user, $nickname, $text)
-    {
-        $this->user     = $user;
-        $this->nickname = $nickname;
-        $this->text     = $text;
-    }
-
-    function handle($channel)
-    {
-        // Throws a command exception if group not found
-        $group = $this->getGroup($this->nickname);
-
-        $gm = Group_message::send($this->user, $group, $this->text);
-
-        $channel->output($this->user, 
-                         sprintf(_('Direct message to group %s sent.'), 
-                                 $group->nickname));
-
-        return true;
-    }
-}
diff --git a/plugins/PrivateGroup/groupmessageform.php b/plugins/PrivateGroup/groupmessageform.php
deleted file mode 100644 (file)
index 4564a60..0000000
+++ /dev/null
@@ -1,166 +0,0 @@
-<?php
-/**
- * StatusNet - the distributed open-source microblogging tool
- * Copyright (C) 2011, StatusNet, Inc.
- *
- * Form for posting a group message
- * 
- * PHP version 5
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- *
- * @category  PrivateGroup
- * @package   StatusNet
- * @author    Evan Prodromou <evan@status.net>
- * @copyright 2011 StatusNet, Inc.
- * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
- * @link      http://status.net/
- */
-
-if (!defined('STATUSNET')) {
-    // This check helps protect against security problems;
-    // your code file can't be executed directly from the web.
-    exit(1);
-}
-
-/**
- * Form for posting a group message
- *
- * @category  PrivateGroup
- * @package   StatusNet
- * @author    Evan Prodromou <evan@status.net>
- * @copyright 2011 StatusNet, Inc.
- * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
- * @link      http://status.net/
- */
-
-class GroupMessageForm extends Form
-{
-    var $group;
-    var $content;
-
-    /**
-     * Constructor
-     *
-     * @param HTMLOutputter $out   Output context
-     * @param User_group    $group Group to post to
-     *
-     * @todo add a drop-down list to post to any group
-     */
-
-    function __construct($out, $group, $content=null)
-    {
-        parent::__construct($out);
-
-        $this->group   = $group;
-        $this->content = $content;
-    }
-
-    /**
-     * Action for the form
-     */
-    function action()
-    { 
-        return common_local_url('newgroupmessage',
-                                array('nickname' => $this->group->nickname));
-    }
-
-    /**
-     * Legend for the form
-     *
-     * @param
-     *
-     * @return
-     */
-    function formLegend()
-    {
-        $this->out->element('legend',
-                            null,
-                            sprintf(_('Message to %s'), $this->group->nickname));
-    }
-
-    /**
-     * id for the form
-     *
-     * @param
-     *
-     * @return
-     */
-
-    function id()
-    {
-        return 'form_notice-group-message';
-    }
-
-    /**
-     * class for the form
-     *
-     * @param
-     *
-     * @return
-     */
-
-    function formClass()
-    {
-        return 'form_notice';
-    }
-
-    /**
-     * Entry data
-     *
-     * @param
-     *
-     * @return
-     */
-
-    function formData()
-    {
-        $this->out->element('label', array('for' => 'notice_data-text',
-                                           'id' => 'notice_data-text-label'),
-                            sprintf(_('Direct message to %s'), $this->group->nickname));
-
-        $this->out->element('textarea', array('id' => 'notice_data-text',
-                                              'cols' => 35,
-                                              'rows' => 4,
-                                              'name' => 'content'),
-                            ($this->content) ? $this->content : '');
-
-        $contentLimit = Message::maxContent();
-
-        if ($contentLimit > 0) {
-            $this->out->elementStart('dl', 'form_note');
-            $this->out->element('dt', null, _('Available characters'));
-            $this->out->element('dd', array('id' => 'notice_text-count'),
-                                $contentLimit);
-            $this->out->elementEnd('dl');
-        }
-    }
-
-    /**
-     * Legend for the form
-     *
-     * @param
-     *
-     * @return
-     */
-
-    function formActions()
-    {
-        $this->out->element('input', array('id' => 'notice_action-submit',
-                                           'class' => 'submit',
-                                           'name' => 'message_send',
-                                           'type' => 'submit',
-                                           'value' => _m('Send button for sending notice', 'Send')));
-    }
-}
diff --git a/plugins/PrivateGroup/groupmessagelist.php b/plugins/PrivateGroup/groupmessagelist.php
deleted file mode 100644 (file)
index 09f453d..0000000
+++ /dev/null
@@ -1,77 +0,0 @@
-<?php
-/**
- * StatusNet - the distributed open-source microblogging tool
- * Copyright (C) 2010, StatusNet, Inc.
- *
- * Widget for showing list of group messages
- * 
- * PHP version 5
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- *
- * @category  PrivateGroup
- * @package   StatusNet
- * @author    Evan Prodromou <evan@status.net>
- * @copyright 2010 StatusNet, Inc.
- * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
- * @link      http://status.net/
- */
-
-if (!defined('STATUSNET')) {
-    // This check helps protect against security problems;
-    // your code file can't be executed directly from the web.
-    exit(1);
-}
-
-/**
- * Widget for showing list of group messages
- *
- * @category  PrivateGroup
- * @package   StatusNet
- * @author    Evan Prodromou <evan@status.net>
- * @copyright 2010 StatusNet, Inc.
- * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
- * @link      http://status.net/
- */
-class GroupMessageList extends Widget
-{
-    var $gm;
-
-    /**
-     * Constructor
-     *
-     * @param HTMLOutputter $out output context
-     * @param Group_message $gm  Group message stream
-     */
-    function __construct($out, $gm)
-    {
-        parent::__construct($out);
-        $this->gm = $gm;
-    }
-
-    /**
-     * Show the list
-     *
-     * @return void
-     */
-    function show()
-    {
-        $this->out->elementStart('ul', 'notices messages group-messages');
-        while ($this->gm->fetch()) {
-            $gmli = new GroupMessageListItem($this->out, $this->gm);
-            $gmli->show();
-        }
-        $this->out->elementEnd('ul');
-    }
-}
diff --git a/plugins/PrivateGroup/groupmessagelistitem.php b/plugins/PrivateGroup/groupmessagelistitem.php
deleted file mode 100644 (file)
index e7b7c6a..0000000
+++ /dev/null
@@ -1,113 +0,0 @@
-<?php
-/**
- * StatusNet - the distributed open-source microblogging tool
- * Copyright (C) 2010, StatusNet, Inc.
- *
- * Widget for showing an individual group message
- * 
- * PHP version 5
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- *
- * @category  PrivateGroup
- * @package   StatusNet
- * @author    Evan Prodromou <evan@status.net>
- * @copyright 2010 StatusNet, Inc.
- * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
- * @link      http://status.net/
- */
-
-if (!defined('STATUSNET')) {
-    // This check helps protect against security problems;
-    // your code file can't be executed directly from the web.
-    exit(1);
-}
-
-/**
- * Widget for showing a single group message
- *
- * @category  PrivateGroup
- * @package   StatusNet
- * @author    Evan Prodromou <evan@status.net>
- * @copyright 2010 StatusNet, Inc.
- * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
- * @link      http://status.net/
- */
-class GroupMessageListItem extends Widget
-{
-    var $gm;
-
-    /**
-     * Constructor
-     *
-     * @param HTMLOutputter $out output context
-     * @param Group_message $gm  Group message
-     */
-    function __construct($out, $gm)
-    {
-        parent::__construct($out);
-        $this->gm = $gm;
-    }
-
-    /**
-     * Show the item
-     *
-     * @return void
-     */
-    function show()
-    {
-        $group  = $this->gm->getGroup();
-        $sender = $this->gm->getSender();
-        $this->out->elementStart('li', array('class' => 'hentry notice message group-message',
-                                         'id' => 'message-' . $this->gm->id));
-
-        $this->out->elementStart('div', 'entry-title');
-        $this->out->elementStart('span', 'vcard author');
-        $this->out->elementStart('a', 
-                                 array('href' => $sender->profileurl,
-                                       'class' => 'url'));
-        $avatar = $sender->getAvatar(AVATAR_STREAM_SIZE);
-        $this->out->element('img', array('src' => ($avatar) ?
-                                    $avatar->displayUrl() :
-                                    Avatar::defaultImage(AVATAR_STREAM_SIZE),
-                                    'width' => AVATAR_STREAM_SIZE,
-                                    'height' => AVATAR_STREAM_SIZE,
-                                    'class' => 'photo avatar',
-                                    'alt' => $sender->getBestName()));
-        $this->out->element('span',
-                            array('class' => 'nickname fn'),
-                            $sender->nickname);
-        $this->out->elementEnd('a');
-        $this->out->elementEnd('span');
-
-        $this->out->elementStart('p', array('class' => 'entry-content message-content'));
-        $this->out->raw($this->gm->rendered);
-        $this->out->elementEnd('p');
-        $this->out->elementEnd('div');
-
-        $this->out->elementStart('div', 'entry-content');
-        $this->out->elementStart('a', array('rel' => 'bookmark',
-                                            'class' => 'timestamp',
-                                            'href' => $this->gm->url));
-        $dt = common_date_iso8601($this->gm->created);
-        $this->out->element('abbr', array('class' => 'published',
-                                          'title' => $dt),
-                            common_date_string($this->gm->created));
-        $this->out->elementEnd('a');
-        $this->out->elementEnd('div');
-
-        $this->out->elementEnd('li');
-    }
-}
diff --git a/plugins/PrivateGroup/newgroupmessage.php b/plugins/PrivateGroup/newgroupmessage.php
deleted file mode 100644 (file)
index a2c5dfd..0000000
+++ /dev/null
@@ -1,161 +0,0 @@
-<?php
-/**
- * StatusNet - the distributed open-source microblogging tool
- * Copyright (C) 2010, StatusNet, Inc.
- *
- * Action for adding a new group message
- * 
- * PHP version 5
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- *
- * @category  Cache
- * @package   StatusNet
- * @author    Evan Prodromou <evan@status.net>
- * @copyright 2010 StatusNet, Inc.
- * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
- * @link      http://status.net/
- */
-
-if (!defined('STATUSNET')) {
-    // This check helps protect against security problems;
-    // your code file can't be executed directly from the web.
-    exit(1);
-}
-
-/**
- * Action for adding a new group message
- *
- * @category  Action
- * @package   StatusNet
- * @author    Evan Prodromou <evan@status.net>
- * @copyright 2010 StatusNet, Inc.
- * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
- * @link      http://status.net/
- */
-
-class NewgroupmessageAction extends Action
-{
-    var $group;
-    var $user;
-    var $text;
-
-    /**
-     * For initializing members of the class.
-     *
-     * @param array $argarray misc. arguments
-     *
-     * @return boolean true
-     */
-
-    function prepare($argarray)
-    {
-        parent::prepare($argarray);
-
-        $this->user = common_current_user();
-
-        if (empty($this->user)) {
-            throw new ClientException(_('Must be logged in.'), 403);
-        }
-
-        if (!$this->user->hasRight(Right::NEWMESSAGE)) {
-            throw new Exception(sprintf(_('User %s not allowed to send private messages.'),
-                                        $this->user->nickname));
-        }
-
-        $nicknameArg = $this->trimmed('nickname');
-
-        $nickname = common_canonical_nickname($nicknameArg);
-
-        if ($nickname != $nicknameArg) {
-            $url = common_local_url('newgroupmessage', array('nickname' => $nickname));
-            common_redirect($url, 301);
-            return false;
-        }
-
-        $localGroup = Local_group::staticGet('nickname', $nickname);
-
-        if (empty($localGroup)) {
-            throw new ClientException(_('No such group'), 404);
-        }
-
-        $this->group = User_group::staticGet('id', $localGroup->group_id);
-
-        if (empty($this->group)) {
-            throw new ClientException(_('No such group'), 404);
-        }
-
-        // This throws an exception on error
-
-        Group_privacy_settings::ensurePost($this->user, $this->group);
-
-        // If we're posted to, check session token and get text
-
-        if ($this->isPost()) {
-            $this->checkSessionToken();
-            $this->text = $this->trimmed('content');
-        }
-
-        return true;
-    }
-
-    /**
-     * Handler method
-     *
-     * @param array $argarray is ignored since it's now passed in in prepare()
-     *
-     * @return void
-     */
-
-    function handle($argarray=null)
-    {
-        if ($this->isPost()) {
-            $this->sendNewMessage();
-        } else {
-            $this->showPage();
-        }
-    }
-
-    function showNoticeForm()
-    {
-        $form = new GroupMessageForm($this, $this->group);
-        $form->show();
-    }
-
-    function sendNewMessage()
-    {
-        $gm = Group_message::send($this->user, $this->group, $this->text);
-
-        if ($this->boolean('ajax')) {
-            $this->startHTML('text/xml;charset=utf-8');
-            $this->elementStart('head');
-            $this->element('title', null, _('Message sent'));
-            $this->elementEnd('head');
-            $this->elementStart('body');
-            $this->element('p',
-                           array('id' => 'command_result'),
-                           sprintf(_('Direct message to %s sent.'),
-                                   $this->group->nickname));
-            $this->elementEnd('body');
-            $this->elementEnd('html');
-        } else {
-            common_redirect($gm->url, 303);
-        }
-    }
-
-    function title()
-    {
-        return sprintf(_('New message to group %s'), $this->group->nickname);
-    }
-}
diff --git a/plugins/PrivateGroup/showgroupmessage.php b/plugins/PrivateGroup/showgroupmessage.php
deleted file mode 100644 (file)
index cc0126e..0000000
+++ /dev/null
@@ -1,188 +0,0 @@
-<?php
-/**
- * StatusNet - the distributed open-source microblogging tool
- * Copyright (C) 2010, StatusNet, Inc.
- *
- * Show a single group message
- * 
- * PHP version 5
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- *
- * @category  PrivateGroup
- * @package   StatusNet
- * @author    Evan Prodromou <evan@status.net>
- * @copyright 2010 StatusNet, Inc.
- * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
- * @link      http://status.net/
- */
-
-if (!defined('STATUSNET')) {
-    // This check helps protect against security problems;
-    // your code file can't be executed directly from the web.
-    exit(1);
-}
-
-/**
- * Show a single private group message
- *
- * @category  PrivateGroup
- * @package   StatusNet
- * @author    Evan Prodromou <evan@status.net>
- * @copyright 2010 StatusNet, Inc.
- * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
- * @link      http://status.net/
- */
-
-class ShowgroupmessageAction extends Action
-{
-    var $gm;
-    var $group;
-    var $sender;
-    var $user;
-
-    /**
-     * For initializing members of the class.
-     *
-     * @param array $argarray misc. arguments
-     *
-     * @return boolean true
-     */
-
-    function prepare($argarray)
-    {
-        parent::prepare($argarray);
-
-        $this->user = common_current_user();
-
-        if (empty($this->user)) {
-            throw new ClientException(_('Only logged-in users can view private messages.'),
-                                      403);
-        }
-
-        $id = $this->trimmed('id');
-
-        $this->gm = Group_message::staticGet('id', $id);
-
-        if (empty($this->gm)) {
-            throw new ClientException(_('No such message'), 404);
-        }
-
-        $this->group = User_group::staticGet('id', $this->gm->to_group);
-
-        if (empty($this->group)) {
-            throw new ServerException(_('Group not found.'));
-        }
-
-        if (!$this->user->isMember($this->group)) {
-            throw new ClientException(_('Cannot read message.'), 403);
-        }
-
-        $this->sender = Profile::staticGet('id', $this->gm->from_profile);
-
-        if (empty($this->sender)) {
-            throw new ServerException(_('No sender found.'));
-        }
-
-        return true;
-    }
-
-    /**
-     * Handler method
-     *
-     * @param array $argarray is ignored since it's now passed in in prepare()
-     *
-     * @return void
-     */
-
-    function handle($argarray=null)
-    {
-        $this->showPage();
-    }
-
-    /**
-     * Title of the page
-     */
-
-    function title()
-    {
-        return sprintf(_('Message from %1$s to group %2$s on %3$s'),
-                       $this->sender->nickname,
-                       $this->group->nickname,
-                       common_exact_date($this->gm->created));
-    }
-
-    /**
-     * Show the content area.
-     */
-
-    function showContent()
-    {
-        $this->elementStart('ul', 'notices messages');
-        $gmli = new GroupMessageListItem($this, $this->gm);
-        $gmli->show();
-        $this->elementEnd('ul');
-    }
-
-    /**
-     * Return true if read only.
-     *
-     * MAY override
-     *
-     * @param array $args other arguments
-     *
-     * @return boolean is read only action?
-     */
-
-    function isReadOnly($args)
-    {
-        return true;
-    }
-
-    /**
-     * Return last modified, if applicable.
-     *
-     * MAY override
-     *
-     * @return string last modified http header
-     */
-    function lastModified()
-    {
-        return max(strtotime($this->group->modified),
-                   strtotime($this->sender->modified),
-                   strtotime($this->gm->modified));
-    }
-
-    /**
-     * Return etag, if applicable.
-     *
-     * MAY override
-     *
-     * @return string etag http header
-     */
-    function etag()
-    {
-        $avatar = $this->sender->getAvatar(AVATAR_STREAM_SIZE);
-
-        $avtime = ($avatar) ? strtotime($avatar->modified) : 0;
-
-        return 'W/"' . implode(':', array($this->arg('action'),
-                                          common_user_cache_hash(),
-                                          common_language(),
-                                          $this->gm->id,
-                                          strtotime($this->sender->modified),
-                                          strtotime($this->group->modified),
-                                          $avtime)) . '"';
-    }
-}