From: Evan Prodromou Date: Mon, 7 Feb 2011 16:57:34 +0000 (-0500) Subject: Rename PrivateGroup to GroupPrivateMessage to be clearer X-Git-Url: https://git.mxchange.org/?a=commitdiff_plain;h=20824292c986733d3efb71fb4aaf411e5b008b94;p=quix0rs-gnu-social.git Rename PrivateGroup to GroupPrivateMessage to be clearer --- diff --git a/plugins/GroupPrivateMessage/GroupPrivateMessagePlugin.php b/plugins/GroupPrivateMessage/GroupPrivateMessagePlugin.php new file mode 100644 index 0000000000..9707c08107 --- /dev/null +++ b/plugins/GroupPrivateMessage/GroupPrivateMessagePlugin.php @@ -0,0 +1,391 @@ +. + * + * @category Privacy + * @package StatusNet + * @author Evan Prodromou + * @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 + * @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 index 0000000000..07d4c57c08 --- /dev/null +++ b/plugins/GroupPrivateMessage/Group_message.php @@ -0,0 +1,208 @@ + + * @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 . + */ + +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 + * @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 index 0000000000..332337423a --- /dev/null +++ b/plugins/GroupPrivateMessage/Group_message_profile.php @@ -0,0 +1,189 @@ + + * @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 . + */ + +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 + * @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 index 0000000000..898ac266ce --- /dev/null +++ b/plugins/GroupPrivateMessage/Group_privacy_settings.php @@ -0,0 +1,194 @@ + + * @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 . + */ + +if (!defined('STATUSNET')) { + exit(1); +} + +/** + * Data class for group privacy + * + * Stores admin preferences about the group. + * + * @category Action + * @package StatusNet + * @author Evan Prodromou + * @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 index 0000000000..55bf4b0ee2 --- /dev/null +++ b/plugins/GroupPrivateMessage/groupinbox.php @@ -0,0 +1,170 @@ +. + * + * @category PrivateGroup + * @package StatusNet + * @author Evan Prodromou + * @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 + * @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 index 0000000000..19136f1318 --- /dev/null +++ b/plugins/GroupPrivateMessage/groupmessagecommand.php @@ -0,0 +1,85 @@ +. + * + * @category Command + * @package StatusNet + * @author Evan Prodromou + * @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 + * @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 index 0000000000..4564a60761 --- /dev/null +++ b/plugins/GroupPrivateMessage/groupmessageform.php @@ -0,0 +1,166 @@ +. + * + * @category PrivateGroup + * @package StatusNet + * @author Evan Prodromou + * @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 + * @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 index 0000000000..09f453d520 --- /dev/null +++ b/plugins/GroupPrivateMessage/groupmessagelist.php @@ -0,0 +1,77 @@ +. + * + * @category PrivateGroup + * @package StatusNet + * @author Evan Prodromou + * @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 + * @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 index 0000000000..e7b7c6a8f8 --- /dev/null +++ b/plugins/GroupPrivateMessage/groupmessagelistitem.php @@ -0,0 +1,113 @@ +. + * + * @category PrivateGroup + * @package StatusNet + * @author Evan Prodromou + * @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 + * @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 index 0000000000..a2c5dfdbdb --- /dev/null +++ b/plugins/GroupPrivateMessage/newgroupmessage.php @@ -0,0 +1,161 @@ +. + * + * @category Cache + * @package StatusNet + * @author Evan Prodromou + * @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 + * @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 index 0000000000..cc0126e03d --- /dev/null +++ b/plugins/GroupPrivateMessage/showgroupmessage.php @@ -0,0 +1,188 @@ +. + * + * @category PrivateGroup + * @package StatusNet + * @author Evan Prodromou + * @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 + * @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 index 07d4c57c08..0000000000 --- a/plugins/PrivateGroup/Group_message.php +++ /dev/null @@ -1,208 +0,0 @@ - - * @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 . - */ - -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 - * @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 index 332337423a..0000000000 --- a/plugins/PrivateGroup/Group_message_profile.php +++ /dev/null @@ -1,189 +0,0 @@ - - * @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 . - */ - -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 - * @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 index 898ac266ce..0000000000 --- a/plugins/PrivateGroup/Group_privacy_settings.php +++ /dev/null @@ -1,194 +0,0 @@ - - * @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 . - */ - -if (!defined('STATUSNET')) { - exit(1); -} - -/** - * Data class for group privacy - * - * Stores admin preferences about the group. - * - * @category Action - * @package StatusNet - * @author Evan Prodromou - * @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 index 6ead6965ec..0000000000 --- a/plugins/PrivateGroup/PrivateGroupPlugin.php +++ /dev/null @@ -1,391 +0,0 @@ -. - * - * @category Privacy - * @package StatusNet - * @author Evan Prodromou - * @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 - * @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 index 55bf4b0ee2..0000000000 --- a/plugins/PrivateGroup/groupinbox.php +++ /dev/null @@ -1,170 +0,0 @@ -. - * - * @category PrivateGroup - * @package StatusNet - * @author Evan Prodromou - * @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 - * @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 index 19136f1318..0000000000 --- a/plugins/PrivateGroup/groupmessagecommand.php +++ /dev/null @@ -1,85 +0,0 @@ -. - * - * @category Command - * @package StatusNet - * @author Evan Prodromou - * @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 - * @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 index 4564a60761..0000000000 --- a/plugins/PrivateGroup/groupmessageform.php +++ /dev/null @@ -1,166 +0,0 @@ -. - * - * @category PrivateGroup - * @package StatusNet - * @author Evan Prodromou - * @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 - * @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 index 09f453d520..0000000000 --- a/plugins/PrivateGroup/groupmessagelist.php +++ /dev/null @@ -1,77 +0,0 @@ -. - * - * @category PrivateGroup - * @package StatusNet - * @author Evan Prodromou - * @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 - * @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 index e7b7c6a8f8..0000000000 --- a/plugins/PrivateGroup/groupmessagelistitem.php +++ /dev/null @@ -1,113 +0,0 @@ -. - * - * @category PrivateGroup - * @package StatusNet - * @author Evan Prodromou - * @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 - * @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 index a2c5dfdbdb..0000000000 --- a/plugins/PrivateGroup/newgroupmessage.php +++ /dev/null @@ -1,161 +0,0 @@ -. - * - * @category Cache - * @package StatusNet - * @author Evan Prodromou - * @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 - * @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 index cc0126e03d..0000000000 --- a/plugins/PrivateGroup/showgroupmessage.php +++ /dev/null @@ -1,188 +0,0 @@ -. - * - * @category PrivateGroup - * @package StatusNet - * @author Evan Prodromou - * @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 - * @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)) . '"'; - } -}