From: Evan Prodromou Date: Mon, 7 Feb 2011 14:46:26 +0000 (-0500) Subject: Show private messages to groups in a list X-Git-Url: https://git.mxchange.org/?a=commitdiff_plain;h=143cc4bdd08ee363518219f1d0b769028c508e11;p=quix0rs-gnu-social.git Show private messages to groups in a list Shows the messages to a private group in a list. New classes for showing a group private message and list of group private messages. New actions for showing a stream of group private messages and a single group private message. --- diff --git a/plugins/PrivateGroup/Group_message.php b/plugins/PrivateGroup/Group_message.php index b3d34cf287..21147b4629 100644 --- a/plugins/PrivateGroup/Group_message.php +++ b/plugins/PrivateGroup/Group_message.php @@ -212,4 +212,36 @@ class Group_message extends Memcached_DataObject 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/PrivateGroupPlugin.php b/plugins/PrivateGroup/PrivateGroupPlugin.php index 4d8f2b370b..39e788074c 100644 --- a/plugins/PrivateGroup/PrivateGroupPlugin.php +++ b/plugins/PrivateGroup/PrivateGroupPlugin.php @@ -153,6 +153,8 @@ class PrivateGroupPlugin extends Plugin include_once $dir . '/'.$cls.'.php'; return false; case 'GroupMessageCommand': + case 'GroupMessageList': + case 'GroupMessageListItem': include_once $dir . '/'.strtolower($cls).'.php'; return false; default: diff --git a/plugins/PrivateGroup/groupinbox.php b/plugins/PrivateGroup/groupinbox.php index a793ac6de2..8b16e0632a 100644 --- a/plugins/PrivateGroup/groupinbox.php +++ b/plugins/PrivateGroup/groupinbox.php @@ -1,18 +1,12 @@ - * @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 @@ -25,140 +19,140 @@ * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . + * + * @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); } /** - * Give a warm greeting to our friendly user - * - * This sample action shows some basic ways of doing output in an action - * class. - * - * Action classes have several output methods that they override from - * the parent class. + * Show a list of private messages to this group * - * @category Sample - * @package StatusNet - * @author Evan Prodromou - * @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3 - * @link http://status.net/ + * @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 HelloAction extends Action + +class GroupinboxAction extends GroupDesignAction { - var $user = null; - var $gc = null; + var $gm; /** - * Take arguments for running - * - * This method is called first, and it lets the action class get - * all its arguments and validate them. It's also the time - * to fetch any relevant data from the database. + * For initializing members of the class. * - * Action classes should run parent::prepare($args) as the first - * line of this method to make sure the default argument-processing - * happens. + * @param array $argarray misc. arguments * - * @param array $args $_REQUEST args - * - * @return boolean success flag + * @return boolean true */ - function prepare($args) + function prepare($argarray) { - parent::prepare($args); + parent::prepare($argarray); + + $cur = common_current_user(); + + if (empty($cur)) { + throw new ClientException(_('Only for logged-in users'), 403); + } + + $nicknameArg = $this->trimmed('nickname'); - $this->user = common_current_user(); + $nickname = common_canonical_nickname($nicknameArg); - if (!empty($this->user)) { - $this->gc = User_greeting_count::inc($this->user->id); + 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; } - /** - * Handle request - * - * This is the main method for handling a request. Note that - * most preparation should be done in the prepare() method; - * by the time handle() is called the action should be - * more or less ready to go. - * - * @param array $args $_REQUEST args; handled in prepare() - * - * @return void - */ - function handle($args) + function showContent() { - parent::handle($args); - - $this->showPage(); + $gml = new GroupMessageList($this, $this->gm); + $gml->show(); } /** - * Title of this page + * Handler method * - * Override this method to show a custom title. + * @param array $argarray is ignored since it's now passed in in prepare() * - * @return string Title of the page + * @return void */ - function title() + function handle($argarray=null) { - if (empty($this->user)) { - return _m('Hello'); - } else { - return sprintf(_m('Hello, %s!'), $this->user->nickname); - } + $this->showPage(); } /** - * Show content in the content area + * Return true if read only. * - * The default StatusNet page has a lot of decorations: menus, - * logos, tabs, all that jazz. This method is used to show - * content in the content area of the page; it's the main - * thing you want to overload. + * MAY override * - * This method also demonstrates use of a plural localized string. + * @param array $args other arguments * - * @return void + * @return boolean is read only action? */ - function showContent() + function isReadOnly($args) { - if (empty($this->user)) { - $this->element('p', array('class' => 'greeting'), - _m('Hello, stranger!')); - } else { - $this->element('p', array('class' => 'greeting'), - sprintf(_m('Hello, %s'), $this->user->nickname)); - $this->element('p', array('class' => 'greeting_count'), - sprintf(_m('I have greeted you %d time.', - 'I have greeted you %d times.', - $this->gc->greeting_count), - $this->gc->greeting_count)); - } + return true; } /** - * Return true if read only. - * - * Some actions only read from the database; others read and write. - * The simple database load-balancer built into StatusNet will - * direct read-only actions to database mirrors (if they are configured), - * and read-write actions to the master database. - * - * This defaults to false to avoid data integrity issues, but you - * should make sure to overload it for performance gains. + * Title of the page * - * @param array $args other arguments, if RO/RW status depends on them. - * - * @return boolean is read only action? + * @return string page title, with page number */ - function isReadOnly($args) + function title() { - return false; + $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/groupmessagelist.php b/plugins/PrivateGroup/groupmessagelist.php new file mode 100644 index 0000000000..09f453d520 --- /dev/null +++ b/plugins/PrivateGroup/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/PrivateGroup/groupmessagelistitem.php b/plugins/PrivateGroup/groupmessagelistitem.php new file mode 100644 index 0000000000..e7b7c6a8f8 --- /dev/null +++ b/plugins/PrivateGroup/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/PrivateGroup/showgroupmessage.php b/plugins/PrivateGroup/showgroupmessage.php new file mode 100644 index 0000000000..cc0126e03d --- /dev/null +++ b/plugins/PrivateGroup/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)) . '"'; + } +}