Create and use MessageList widget

Our mailbox actions (inbox and outbox) were doing their own display of
messages. This was causing issues with especially showmessage, which
since the more rigourous nickname checks were added, no longer works as
a mailbox subclass.

I've taken the time to rip out the message listing code from MailboxAction
and moved it to a MessageList widget. The different mailboxes now have their
own subclasses that show the correct profile in the list.
This commit is contained in:
Evan Prodromou 2011-02-08 11:11:21 -05:00
parent c858e2bc34
commit f500d4ea5b
5 changed files with 306 additions and 133 deletions

View File

@ -90,18 +90,9 @@ class InboxAction extends MailboxAction
} }
} }
/** function getMessageList($message)
* Returns the profile we want to show with the message
*
* For inboxes, we show the sender; for outboxes, the recipient.
*
* @param Message $message The message to get the profile for
*
* @return Profile The profile that matches the message
*/
function getMessageProfile($message)
{ {
return $message->getFrom(); return new InboxMessageList($this, $message);
} }
/** /**
@ -115,3 +106,24 @@ class InboxAction extends MailboxAction
return _('This is your inbox, which lists your incoming private messages.'); return _('This is your inbox, which lists your incoming private messages.');
} }
} }
class InboxMessageList extends MessageList
{
function newItem($message)
{
return new InboxMessageListItem($this->out, $message);
}
}
class InboxMessageListItem extends MessageListItem
{
/**
* Returns the profile we want to show with the message
*
* @return Profile The profile that matches the message
*/
function getMessageProfile()
{
return $this->message->getFrom();
}
}

View File

@ -88,21 +88,9 @@ class OutboxAction extends MailboxAction
} }
} }
/** function getMessageList($message)
* returns the profile we want to show with the message
*
* For outboxes, we show the recipient.
*
* @param Message $message The message to get the profile for
*
* @return Profile The profile of the message recipient
*
* @see MailboxAction::getMessageProfile()
*/
function getMessageProfile($message)
{ {
return $message->getTo(); return new OutboxMessageList($this, $message);
} }
/** /**
@ -116,3 +104,24 @@ class OutboxAction extends MailboxAction
return _('This is your outbox, which lists private messages you have sent.'); return _('This is your outbox, which lists private messages you have sent.');
} }
} }
class OutboxMessageList extends MessageList
{
function newItem($message)
{
return new OutboxMessageListItem($this->out, $message);
}
}
class OutboxMessageListItem extends MessageListItem
{
/**
* Returns the profile we want to show with the message
*
* @return Profile The profile that matches the message
*/
function getMessageProfile()
{
return $this->message->getTo();
}
}

View File

@ -109,32 +109,22 @@ class MailboxAction extends CurrentUserDesignAction
$message = $this->getMessages(); $message = $this->getMessages();
if ($message) { if ($message) {
$cnt = 0;
$this->elementStart('div', array('id' =>'notices_primary'));
$this->element('h2', null, _('Notices'));
$this->elementStart('ul', 'notices');
while ($message->fetch() && $cnt <= MESSAGES_PER_PAGE) { $ml = $this->getMessageList($message);
$cnt++;
if ($cnt > MESSAGES_PER_PAGE) { $cnt = $ml->show();
break;
}
$this->showMessage($message); $this->pagination($this->page > 1,
} $cnt > MESSAGES_PER_PAGE,
$this->page,
$this->elementEnd('ul'); $this->trimmed('action'),
$this->pagination($this->page > 1, $cnt > MESSAGES_PER_PAGE,
$this->page, $this->trimmed('action'),
array('nickname' => $this->user->nickname)); array('nickname' => $this->user->nickname));
$this->elementEnd('div'); } else {
$message->free(); $this->element('p',
unset($message); 'guide',
} _('You have no private messages. '.
else { 'You can send private message to engage other users in conversation. '.
$this->element('p', 'guide', _('You have no private messages. You can send private message to engage other users in conversation. People can send you messages for your eyes only.')); 'People can send you messages for your eyes only.'));
} }
} }
@ -143,95 +133,11 @@ class MailboxAction extends CurrentUserDesignAction
return null; return null;
} }
/** function getMessageList($message)
* returns the profile we want to show with the message
*
* For inboxes, we show the sender; for outboxes, the recipient.
*
* @param Message $message The message to get the profile for
*
* @return Profile The profile that matches the message
*/
function getMessageProfile($message)
{ {
return null; return null;
} }
/**
* show a single message in the list format
*
* XXX: This needs to be extracted out into a MessageList similar
* to NoticeList.
*
* @param Message $message the message to show
*
* @return void
*/
function showMessage($message)
{
$this->elementStart('li', array('class' => 'hentry notice',
'id' => 'message-' . $message->id));
$profile = $this->getMessageProfile($message);
$this->elementStart('div', 'entry-title');
$this->elementStart('span', 'vcard author');
$this->elementStart('a', array('href' => $profile->profileurl,
'class' => 'url'));
$avatar = $profile->getAvatar(AVATAR_STREAM_SIZE);
$this->element('img', array('src' => ($avatar) ?
$avatar->displayUrl() :
Avatar::defaultImage(AVATAR_STREAM_SIZE),
'class' => 'photo avatar',
'width' => AVATAR_STREAM_SIZE,
'height' => AVATAR_STREAM_SIZE,
'alt' =>
($profile->fullname) ? $profile->fullname :
$profile->nickname));
$this->element('span', array('class' => 'nickname fn'),
$profile->nickname);
$this->elementEnd('a');
$this->elementEnd('span');
// FIXME: URL, image, video, audio
$this->elementStart('p', array('class' => 'entry-content'));
$this->raw($message->rendered);
$this->elementEnd('p');
$this->elementEnd('div');
$messageurl = common_local_url('showmessage',
array('message' => $message->id));
// XXX: we need to figure this out better. Is this right?
if (strcmp($message->uri, $messageurl) != 0 &&
preg_match('/^http/', $message->uri)) {
$messageurl = $message->uri;
}
$this->elementStart('div', 'entry-content');
$this->elementStart('a', array('rel' => 'bookmark',
'class' => 'timestamp',
'href' => $messageurl));
$dt = common_date_iso8601($message->created);
$this->element('abbr', array('class' => 'published',
'title' => $dt),
common_date_string($message->created));
$this->elementEnd('a');
if ($message->source) {
$this->elementStart('span', 'source');
// FIXME: bad i18n. Device should be a parameter (from %s).
$this->text(_('from'));
$this->element('span', 'device', $this->showSource($message->source));
$this->elementEnd('span');
}
$this->elementEnd('div');
$this->elementEnd('li');
}
/** /**
* Show the page notice * Show the page notice
* *
@ -300,5 +206,4 @@ class MailboxAction extends CurrentUserDesignAction
{ {
return true; return true;
} }
} }

107
lib/messagelist.php Normal file
View File

@ -0,0 +1,107 @@
<?php
/**
* StatusNet - the distributed open-source microblogging tool
* Copyright (C) 2011, StatusNet, Inc.
*
* The message list widget
*
* PHP version 5
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @category Widget
* @package StatusNet
* @author Evan Prodromou <evan@status.net>
* @copyright 2011 StatusNet, Inc.
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
* @link http://status.net/
*/
if (!defined('STATUSNET')) {
// This check helps protect against security problems;
// your code file can't be executed directly from the web.
exit(1);
}
/**
* Message list widget
*
* @category Widget
* @package StatusNet
* @author Evan Prodromou <evan@status.net>
* @copyright 2011 StatusNet, Inc.
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
* @link http://status.net/
*/
abstract class MessageList extends Widget
{
var $message;
/**
* Constructor
*
* @param HTMLOutputter $out Output context
* @param Message $message Stream of messages to show
*/
function __construct($out, $message)
{
parent::__construct($out);
$this->message = $message;
}
/**
* Show the widget
*
* Uses newItem() to create each new item.
*
* @return integer count of messages seen.
*/
function show()
{
$cnt = 0;
$this->out->elementStart('div', array('id' =>'notices_primary'));
$this->out->element('h2', null, _('Messages'));
$this->out->elementStart('ul', 'notices messages');
while ($this->message->fetch() && $cnt <= MESSAGES_PER_PAGE) {
$cnt++;
if ($cnt > MESSAGES_PER_PAGE) {
break;
}
$mli = $this->newItem($this->message);
$mli->show();
}
$this->out->elementEnd('ul');
$this->out->elementEnd('div');
}
/**
* Create a new message item for a message
*
* @param Message $message The message to show
*
* @return MessageListItem an item to show
*/
abstract function newItem($message);
}

140
lib/messagelistitem.php Normal file
View File

@ -0,0 +1,140 @@
<?php
/**
* StatusNet - the distributed open-source microblogging tool
* Copyright (C) 2011, StatusNet, Inc.
*
* A single list item for showing in a message list
*
* PHP version 5
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @category Widget
* @package StatusNet
* @author Evan Prodromou <evan@status.net>
* @copyright 2011 StatusNet, Inc.
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
* @link http://status.net/
*/
if (!defined('STATUSNET')) {
// This check helps protect against security problems;
// your code file can't be executed directly from the web.
exit(1);
}
/**
* A single item in a message list
*
* @category Widget
* @package StatusNet
* @author Evan Prodromou <evan@status.net>
* @copyright 2011 StatusNet, Inc.
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
* @link http://status.net/
*/
abstract class MessageListItem extends Widget
{
var $message;
/**
* Constructor
*
* @param HTMLOutputter $out Output context
* @param Message $message Message to show
*/
function __construct($out, $message)
{
parent::__construct($out);
$this->message = $message;
}
/**
* Show the widget
*
* @return void
*/
function show()
{
$this->out->elementStart('li', array('class' => 'hentry notice',
'id' => 'message-' . $this->message->id));
$profile = $this->getMessageProfile();
$this->out->elementStart('div', 'entry-title');
$this->out->elementStart('span', 'vcard author');
$this->out->elementStart('a', array('href' => $profile->profileurl,
'class' => 'url'));
$avatar = $profile->getAvatar(AVATAR_STREAM_SIZE);
$this->out->element('img', array('src' => ($avatar) ?
$avatar->displayUrl() :
Avatar::defaultImage(AVATAR_STREAM_SIZE),
'class' => 'photo avatar',
'width' => AVATAR_STREAM_SIZE,
'height' => AVATAR_STREAM_SIZE,
'alt' =>
($profile->fullname) ? $profile->fullname :
$profile->nickname));
$this->out->element('span', array('class' => 'nickname fn'),
$profile->nickname);
$this->out->elementEnd('a');
$this->out->elementEnd('span');
// FIXME: URL, image, video, audio
$this->out->elementStart('p', array('class' => 'entry-content'));
$this->out->raw($this->message->rendered);
$this->out->elementEnd('p');
$this->out->elementEnd('div');
$messageurl = common_local_url('showmessage',
array('message' => $this->message->id));
// XXX: we need to figure this out better. Is this right?
if (strcmp($this->message->uri, $messageurl) != 0 &&
preg_match('/^http/', $this->message->uri)) {
$messageurl = $this->message->uri;
}
$this->out->elementStart('div', 'entry-content');
$this->out->elementStart('a', array('rel' => 'bookmark',
'class' => 'timestamp',
'href' => $messageurl));
$dt = common_date_iso8601($this->message->created);
$this->out->element('abbr', array('class' => 'published',
'title' => $dt),
common_date_string($this->message->created));
$this->out->elementEnd('a');
if ($this->message->source) {
$this->out->elementStart('span', 'source');
// FIXME: bad i18n. Device should be a parameter (from %s).
$this->out->text(_('from'));
$this->out->element('span', 'device', $this->out->showSource($this->message->source));
$this->out->elementEnd('span');
}
$this->out->elementEnd('div');
$this->out->elementEnd('li');
}
/**
* Return the profile to show in the message item
*
* Overridden in sub-classes to show sender, receiver, or whatever
*
* @return Profile profile to show avatar and name of
*/
abstract function getMessageProfile();
}