We still have to move some API calls into the new plugin.
+++ /dev/null
-<?php
-/**
- * StatusNet, the distributed open-source microblogging tool
- *
- * Show a the direct messages from or to a user
- *
- * PHP version 5
- *
- * LICENCE: 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 API
- * @package StatusNet
- * @author Adrian Lang <mail@adrianlang.de>
- * @author Evan Prodromou <evan@status.net>
- * @author Robin Millette <robin@millette.info>
- * @author Zach Copley <zach@status.net>
- * @copyright 2009 StatusNet, Inc.
- * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
- * @link http://status.net/
- */
-
-if (!defined('STATUSNET')) {
- exit(1);
-}
-
-/**
- * Show a list of direct messages from or to the authenticating user
- *
- * @category API
- * @package StatusNet
- * @author Adrian Lang <mail@adrianlang.de>
- * @author Evan Prodromou <evan@status.net>
- * @author Robin Millette <robin@millette.info>
- * @author Zach Copley <zach@status.net>
- * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
- * @link http://status.net/
- */
-class ApiDirectMessageAction extends ApiAuthAction
-{
- var $messages = null;
- var $title = null;
- var $subtitle = null;
- var $link = null;
- var $selfuri_base = null;
- var $id = null;
-
- /**
- * Take arguments for running
- *
- * @param array $args $_REQUEST args
- *
- * @return boolean success flag
- */
- function prepare($args)
- {
- parent::prepare($args);
-
- $this->user = $this->auth_user;
-
- if (empty($this->user)) {
- // TRANS: Client error given when a user was not found (404).
- $this->clientError(_('No such user.'), 404);
- }
-
- $server = common_root_url();
- $taguribase = TagURI::base();
-
- if ($this->arg('sent')) {
-
- // Action was called by /api/direct_messages/sent.format
-
- $this->title = sprintf(
- // TRANS: Title. %s is a user nickname.
- _("Direct messages from %s"),
- $this->user->nickname
- );
- $this->subtitle = sprintf(
- // TRANS: Subtitle. %s is a user nickname.
- _("All the direct messages sent from %s"),
- $this->user->nickname
- );
- $this->link = $server . $this->user->nickname . '/outbox';
- $this->selfuri_base = common_root_url() . 'api/direct_messages/sent';
- $this->id = "tag:$taguribase:SentDirectMessages:" . $this->user->id;
- } else {
- $this->title = sprintf(
- // TRANS: Title. %s is a user nickname.
- _("Direct messages to %s"),
- $this->user->nickname
- );
- $this->subtitle = sprintf(
- // TRANS: Subtitle. %s is a user nickname.
- _("All the direct messages sent to %s"),
- $this->user->nickname
- );
- $this->link = $server . $this->user->nickname . '/inbox';
- $this->selfuri_base = common_root_url() . 'api/direct_messages';
- $this->id = "tag:$taguribase:DirectMessages:" . $this->user->id;
- }
-
- $this->messages = $this->getMessages();
-
- return true;
- }
-
- /**
- * Handle the request
- *
- * Show the messages
- *
- * @param array $args $_REQUEST data (unused)
- *
- * @return void
- */
- function handle($args)
- {
- parent::handle($args);
- $this->showMessages();
- }
-
- /**
- * Show the messages
- *
- * @return void
- */
- function showMessages()
- {
- switch($this->format) {
- case 'xml':
- $this->showXmlDirectMessages();
- break;
- case 'rss':
- $this->showRssDirectMessages();
- break;
- case 'atom':
- $this->showAtomDirectMessages();
- break;
- case 'json':
- $this->showJsonDirectMessages();
- break;
- default:
- // TRANS: Client error displayed when coming across a non-supported API method.
- $this->clientError(_('API method not found.'), $code = 404);
- break;
- }
- }
-
- /**
- * Get notices
- *
- * @return array notices
- */
- function getMessages()
- {
- $message = new Message();
-
- if ($this->arg('sent')) {
- $message->from_profile = $this->user->id;
- } else {
- $message->to_profile = $this->user->id;
- }
-
- if (!empty($this->max_id)) {
- $message->whereAdd('id <= ' . $this->max_id);
- }
-
- if (!empty($this->since_id)) {
- $message->whereAdd('id > ' . $this->since_id);
- }
-
- $message->orderBy('created DESC, id DESC');
- $message->limit((($this->page - 1) * $this->count), $this->count);
- $message->find();
-
- $messages = array();
-
- while ($message->fetch()) {
- $messages[] = clone($message);
- }
-
- return $messages;
- }
-
- /**
- * Is this action read only?
- *
- * @param array $args other arguments
- *
- * @return boolean true
- */
- function isReadOnly($args)
- {
- return true;
- }
-
- /**
- * When was this notice last modified?
- *
- * @return string datestamp of the latest notice in the stream
- */
- function lastModified()
- {
- if (!empty($this->messages)) {
- return strtotime($this->messages[0]->created);
- }
-
- return null;
- }
-
- /**
- * Shows a list of direct messages as Twitter-style XML array
- *
- * @return void
- */
- function showXmlDirectMessages()
- {
- $this->initDocument('xml');
- $this->elementStart('direct-messages', array('type' => 'array',
- 'xmlns:statusnet' => 'http://status.net/schema/api/1/'));
-
- foreach ($this->messages as $m) {
- $dm_array = $this->directMessageArray($m);
- $this->showXmlDirectMessage($dm_array);
- }
-
- $this->elementEnd('direct-messages');
- $this->endDocument('xml');
- }
-
- /**
- * Shows a list of direct messages as a JSON encoded array
- *
- * @return void
- */
- function showJsonDirectMessages()
- {
- $this->initDocument('json');
-
- $dmsgs = array();
-
- foreach ($this->messages as $m) {
- $dm_array = $this->directMessageArray($m);
- array_push($dmsgs, $dm_array);
- }
-
- $this->showJsonObjects($dmsgs);
- $this->endDocument('json');
- }
-
- /**
- * Shows a list of direct messages as RSS items
- *
- * @return void
- */
- function showRssDirectMessages()
- {
- $this->initDocument('rss');
-
- $this->element('title', null, $this->title);
-
- $this->element('link', null, $this->link);
- $this->element('description', null, $this->subtitle);
- $this->element('language', null, 'en-us');
-
- $this->element(
- 'atom:link',
- array(
- 'type' => 'application/rss+xml',
- 'href' => $this->selfuri_base . '.rss',
- 'rel' => self
- ),
- null
- );
- $this->element('ttl', null, '40');
-
- foreach ($this->messages as $m) {
- $entry = $this->rssDirectMessageArray($m);
- $this->showTwitterRssItem($entry);
- }
-
- $this->endTwitterRss();
- }
-
- /**
- * Shows a list of direct messages as Atom entries
- *
- * @return void
- */
- function showAtomDirectMessages()
- {
- $this->initDocument('atom');
-
- $this->element('title', null, $this->title);
- $this->element('id', null, $this->id);
-
- $selfuri = common_root_url() . 'api/direct_messages.atom';
-
- $this->element(
- 'link', array(
- 'href' => $this->link,
- 'rel' => 'alternate',
- 'type' => 'text/html'),
- null
- );
- $this->element(
- 'link', array(
- 'href' => $this->selfuri_base . '.atom', 'rel' => 'self',
- 'type' => 'application/atom+xml'),
- null
- );
- $this->element('updated', null, common_date_iso8601('now'));
- $this->element('subtitle', null, $this->subtitle);
-
- foreach ($this->messages as $m) {
- $entry = $this->rssDirectMessageArray($m);
- $this->showTwitterAtomEntry($entry);
- }
-
- $this->endDocument('atom');
- }
-
- /**
- * An entity tag for this notice
- *
- * Returns an Etag based on the action name, language, and
- * timestamps of the notice
- *
- * @return string etag
- */
- function etag()
- {
- if (!empty($this->messages)) {
-
- $last = count($this->messages) - 1;
-
- return '"' . implode(
- ':',
- array($this->arg('action'),
- common_user_cache_hash($this->auth_user),
- common_language(),
- strtotime($this->messages[0]->created),
- strtotime($this->messages[$last]->created)
- )
- )
- . '"';
- }
-
- return null;
- }
-}
+++ /dev/null
-<?php
-/**
- * StatusNet, the distributed open-source microblogging tool
- *
- * Send a direct message via the API
- *
- * PHP version 5
- *
- * LICENCE: 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 API
- * @package StatusNet
- * @author Adrian Lang <mail@adrianlang.de>
- * @author Evan Prodromou <evan@status.net>
- * @author Robin Millette <robin@millette.info>
- * @author Zach Copley <zach@status.net>
- * @copyright 2009 StatusNet, Inc.
- * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
- * @link http://status.net/
- */
-
-if (!defined('STATUSNET')) {
- exit(1);
-}
-
-/**
- * Creates a new direct message from the authenticating user to
- * the user specified by id.
- *
- * @category API
- * @package StatusNet
- * @author Adrian Lang <mail@adrianlang.de>
- * @author Evan Prodromou <evan@status.net>
- * @author Robin Millette <robin@millette.info>
- * @author Zach Copley <zach@status.net>
- * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
- * @link http://status.net/
- */
-class ApiDirectMessageNewAction extends ApiAuthAction
-{
- protected $needPost = true;
-
- var $other = null; // Profile we're sending to
- var $content = null;
-
- /**
- * Take arguments for running
- *
- * @param array $args $_REQUEST args
- *
- * @return boolean success flag
- */
- protected function prepare(array $args=array())
- {
- parent::prepare($args);
-
- if (empty($this->user)) {
- // TRANS: Client error when user not found for an API direct message action.
- $this->clientError(_('No such user.'), 404);
- }
-
- $this->content = $this->trimmed('text');
-
- $user_param = $this->trimmed('user');
- $user_id = $this->arg('user_id');
- $screen_name = $this->trimmed('screen_name');
-
- if (isset($user_param) || isset($user_id) || isset($screen_name)) {
- $this->other = $this->getTargetProfile($user_param);
- }
-
- return true;
- }
-
- /**
- * Handle the request
- *
- * Save the new message
- *
- * @return void
- */
- protected function handle()
- {
- parent::handle();
-
- if (empty($this->content)) {
- // TRANS: Client error displayed when no message text was submitted (406).
- $this->clientError(_('No message text!'), 406);
- } else {
- $content_shortened = $this->auth_user->shortenLinks($this->content);
- if (Message::contentTooLong($content_shortened)) {
- // TRANS: Client error displayed when message content is too long.
- // TRANS: %d is the maximum number of characters for a message.
- $this->clientError(
- 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()),
- 406);
- }
- }
-
- if (!$this->other instanceof Profile) {
- // TRANS: Client error displayed if a recipient user could not be found (403).
- $this->clientError(_('Recipient user not found.'), 403);
- } else if (!$this->user->mutuallySubscribed($this->other)) {
- // TRANS: Client error displayed trying to direct message another user who's not a friend (403).
- $this->clientError(_('Cannot send direct messages to users who aren\'t your friend.'), 403);
- } else if ($this->user->id == $this->other->id) {
-
- // Note: sending msgs to yourself is allowed by Twitter
-
- // TRANS: Client error displayed trying to direct message self (403).
- $this->clientError(_('Do not send a message to yourself; just say it to yourself quietly instead.'), 403);
- }
-
- $message = Message::saveNew(
- $this->user->id,
- $this->other->id,
- html_entity_decode($this->content, ENT_NOQUOTES, 'UTF-8'),
- $this->source
- );
-
- $message->notify();
-
- if ($this->format == 'xml') {
- $this->showSingleXmlDirectMessage($message);
- } elseif ($this->format == 'json') {
- $this->showSingleJsondirectMessage($message);
- }
- }
-}
+++ /dev/null
-<?php
-/**
- * StatusNet, the distributed open-source microblogging tool
- *
- * action handler for message inbox
- *
- * PHP version 5
- *
- * LICENCE: 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 Message
- * @package StatusNet
- * @author Evan Prodromou <evan@status.net>
- * @copyright 2008 StatusNet, Inc.
- * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
- * @link http://status.net/
- */
-
-if (!defined('STATUSNET') && !defined('LACONICA')) {
- exit(1);
-}
-
-require_once INSTALLDIR.'/lib/mailbox.php';
-
-/**
- * action handler for message inbox
- *
- * @category Message
- * @package StatusNet
- * @author Evan Prodromou <evan@status.net>
- * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
- * @link http://status.net/
- * @see MailboxAction
- */
-class InboxAction extends MailboxAction
-{
-
- /**
- * Title of the page
- *
- * @return string page title
- */
- function title()
- {
- if ($this->page > 1) {
- // TRANS: Title for all but the first page of the inbox page.
- // TRANS: %1$s is the user's nickname, %2$s is the page number.
- return sprintf(_('Inbox for %1$s - page %2$d'), $this->user->nickname,
- $this->page);
- } else {
- // TRANS: Title for the first page of the inbox page.
- // TRANS: %s is the user's nickname.
- return sprintf(_('Inbox for %s'), $this->user->nickname);
- }
- }
-
- /**
- * Retrieve the messages for this user and this page
- *
- * Does a query for the right messages
- *
- * @return Message data object with stream for messages
- *
- * @see MailboxAction::getMessages()
- */
- function getMessages()
- {
- $message = new Message();
-
- $message->to_profile = $this->user->id;
- $message->orderBy('created DESC, id DESC');
- $message->limit((($this->page - 1) * MESSAGES_PER_PAGE),
- MESSAGES_PER_PAGE + 1);
-
- if ($message->find()) {
- return $message;
- } else {
- return null;
- }
- }
-
- function getMessageList($message)
- {
- return new InboxMessageList($this, $message);
- }
-
- /**
- * Instructions for using this page
- *
- * @return string localised instructions for using the page
- */
- function getInstructions()
- {
- // TRANS: Instructions for user inbox page.
- 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();
- }
-}
+++ /dev/null
-<?php
-/**
- * StatusNet, the distributed open-source microblogging tool
- *
- * Handler for posting new messages
- *
- * PHP version 5
- *
- * LICENCE: 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 Personal
- * @package StatusNet
- * @author Evan Prodromou <evan@status.net>
- * @author Zach Copley <zach@status.net>
- * @author Sarven Capadisli <csarven@status.net>
- * @copyright 2008-2009 StatusNet, Inc.
- * @copyright 2013 Free Software Foundation, Inc.
- * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
- * @link http://status.net/
- */
-
-if (!defined('STATUSNET')) {
- exit(1);
-}
-
-/**
- * Action for posting new direct messages
- *
- * @category Personal
- * @package StatusNet
- * @author Evan Prodromou <evan@status.net>
- * @author Zach Copley <zach@status.net>
- * @author Sarven Capadisli <csarven@status.net>
- * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
- * @link http://status.net/
- */
-
-class NewmessageAction extends FormAction
-{
- var $content = null;
- var $to = null;
- var $other = null;
-
- /**
- * Title of the page
- *
- * Note that this usually doesn't get called unless something went wrong
- *
- * @return string page title
- */
-
- function title()
- {
- // TRANS: Page title for new direct message page.
- return _('New message');
- }
-
- /**
- * Handle input, produce output
- *
- * @param array $args $_REQUEST contents
- *
- * @return void
- */
-
- protected function prepare(array $args=array())
- {
- parent::prepare($args);
-
- $this->content = $this->trimmed('content');
- $this->to = $this->trimmed('to');
-
- if ($this->to) {
-
- $this->other = Profile::getKV('id', $this->to);
-
- if (!$this->other instanceof Profile) {
- // TRANS: Client error displayed trying to send a direct message to a non-existing user.
- $this->clientError(_('No such user.'), 404);
- }
-
- if (!$this->other->isLocal()) {
- // TRANS: Explains that current federation does not support direct, private messages yet.
- $this->clientError(_('You cannot send direct messages to federated users yet.'));
- }
-
- if (!$this->scoped->mutuallySubscribed($this->other)) {
- // TRANS: Client error displayed trying to send a direct message to a user while sender and
- // TRANS: receiver are not subscribed to each other.
- $this->clientError(_('You cannot send a message to this user.'), 404);
- }
- }
-
- return true;
- }
-
- protected function handlePost()
- {
- parent::handlePost();
-
- assert($this->scoped instanceof Profile); // XXX: maybe an error instead...
-
- if (!$this->content) {
- // TRANS: Form validator error displayed trying to send a direct message without content.
- $this->clientError(_('No content!'));
- } else {
- $content_shortened = $this->scoped->shortenLinks($this->content);
-
- if (Message::contentTooLong($content_shortened)) {
- // TRANS: Form validation error displayed when message content is too long.
- // TRANS: %d is the maximum number of characters for a message.
- $this->clientError(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()));
- }
- }
-
- if (!$this->other) {
- // TRANS: Form validation error displayed trying to send a direct message without specifying a recipient.
- $this->clientError(_('No recipient specified.'));
- } else if (!$this->scoped->mutuallySubscribed($this->other)) {
- // TRANS: Client error displayed trying to send a direct message to a user while sender and
- // TRANS: receiver are not subscribed to each other.
- $this->clientError(_('You cannot send a message to this user.'), 404);
- } else if ($this->scoped->id == $this->other->id) {
- // TRANS: Client error displayed trying to send a direct message to self.
- $this->clientError(_('Do not send a message to yourself; ' .
- 'just say it to yourself quietly instead.'), 403);
- }
-
- $message = Message::saveNew($this->scoped->id, $this->other->id, $this->content, 'web');
- $message->notify();
-
- if ($this->boolean('ajax')) {
- $this->startHTML('text/xml;charset=utf-8');
- $this->elementStart('head');
- // TRANS: Page title after sending a direct message.
- $this->element('title', null, _('Message sent'));
- $this->elementEnd('head');
- $this->elementStart('body');
- $this->element('p', array('id' => 'command_result'),
- // TRANS: Confirmation text after sending a direct message.
- // TRANS: %s is the direct message recipient.
- sprintf(_('Direct message to %s sent.'),
- $this->other->nickname));
- $this->elementEnd('body');
- $this->endHTML();
- } else {
- $url = common_local_url('outbox',
- array('nickname' => $this->scoped->nickname));
- common_redirect($url, 303);
- }
- }
-
- /**
- * Show an Ajax-y error message
- *
- * Goes back to the browser, where it's shown in a popup.
- *
- * @param string $msg Message to show
- *
- * @return void
- */
-
- function ajaxErrorMsg($msg)
- {
- $this->startHTML('text/xml;charset=utf-8', true);
- $this->elementStart('head');
- // TRANS: Page title after an AJAX error occurred on the "send direct message" page.
- $this->element('title', null, _('Ajax Error'));
- $this->elementEnd('head');
- $this->elementStart('body');
- $this->element('p', array('id' => 'error'), $msg);
- $this->elementEnd('body');
- $this->endHTML();
- }
-
- function showForm($msg = null)
- {
- if ($msg && $this->boolean('ajax')) {
- $this->ajaxErrorMsg($msg);
- return;
- }
-
- $this->msg = $msg;
- if ($this->trimmed('ajax')) {
- $this->startHTML('text/xml;charset=utf-8');
- $this->elementStart('head');
- // TRANS: Page title on page for sending a direct message.
- $this->element('title', null, _('New message'));
- $this->elementEnd('head');
- $this->elementStart('body');
- $this->showNoticeForm();
- $this->elementEnd('body');
- $this->endHTML();
- }
- else {
- $this->showPage();
- }
- }
-
- function showPageNotice()
- {
- if ($this->msg) {
- $this->element('p', 'error', $this->msg);
- }
- }
-
- // Do nothing (override)
-
- function showNoticeForm()
- {
- $message_form = new MessageForm($this, $this->other, $this->content);
- $message_form->show();
- }
-}
+++ /dev/null
-<?php
-/**
- * StatusNet, the distributed open-source microblogging tool
- *
- * action handler for message inbox
- *
- * PHP version 5
- *
- * LICENCE: 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 Message
- * @package StatusNet
- * @author Evan Prodromou <evan@status.net>
- * @copyright 2008 StatusNet, Inc.
- * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
- * @link http://status.net/
- */
-if (!defined('STATUSNET') && !defined('LACONICA')) {
- exit(1);
-}
-
-require_once INSTALLDIR.'/lib/mailbox.php';
-
-/**
- * action handler for message outbox
- *
- * @category Message
- * @package StatusNet
- * @author Evan Prodromou <evan@status.net>
- * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
- * @link http://status.net/
- * @see MailboxAction
- */
-class OutboxAction extends MailboxAction
-{
- /**
- * Title of the page
- *
- * @return string page title
- */
- function title()
- {
- if ($this->page > 1) {
- // TRANS: Title for outbox for any but the fist page.
- // TRANS: %1$s is the user nickname, %2$d is the page number.
- return sprintf(_('Outbox for %1$s - page %2$d'),
- $this->user->nickname, $page);
- } else {
- // TRANS: Title for first page of outbox.
- return sprintf(_('Outbox for %s'), $this->user->nickname);
- }
- }
-
- /**
- * retrieve the messages for this user and this page
- *
- * Does a query for the right messages
- *
- * @return Message data object with stream for messages
- *
- * @see MailboxAction::getMessages()
- */
- function getMessages()
- {
- $message = new Message();
-
- $message->from_profile = $this->user->id;
- $message->orderBy('created DESC, id DESC');
- $message->limit((($this->page - 1) * MESSAGES_PER_PAGE),
- MESSAGES_PER_PAGE + 1);
-
- if ($message->find()) {
- return $message;
- } else {
- return null;
- }
- }
-
- function getMessageList($message)
- {
- return new OutboxMessageList($this, $message);
- }
-
- /**
- * instructions for using this page
- *
- * @return string localised instructions for using the page
- */
- function getInstructions()
- {
- // TRANS: Instructions for outbox.
- 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();
- }
-}
+++ /dev/null
-<?php
-/**
- * StatusNet, the distributed open-source microblogging tool
- *
- * Show a single message
- *
- * PHP version 5
- *
- * LICENCE: 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 Personal
- * @package StatusNet
- * @author Evan Prodromou <evan@status.net>
- * @copyright 2008-2009 StatusNet, Inc.
- * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
- * @link http://status.net/
- */
-if (!defined('STATUSNET') && !defined('LACONICA')) {
- exit(1);
-}
-
-/**
- * Show a single message
- *
- * @category Personal
- * @package StatusNet
- * @author Evan Prodromou <evan@status.net>
- * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
- * @link http://status.net/
- */
-
-class ShowmessageAction extends Action
-{
- /**
- * Message object to show
- */
- var $message = null;
-
- /**
- * The current user
- */
-
- var $user = null;
-
- /**
- * Load attributes based on database arguments
- *
- * Loads all the DB stuff
- *
- * @param array $args $_REQUEST array
- *
- * @return success flag
- */
- function prepare($args)
- {
- parent::prepare($args);
-
- $this->page = 1;
-
- $id = $this->trimmed('message');
- $this->message = Message::getKV('id', $id);
-
- if (!$this->message) {
- // TRANS: Client error displayed requesting a single message that does not exist.
- $this->clientError(_('No such message.'), 404);
- }
-
- $this->user = common_current_user();
-
- if (empty($this->user) ||
- ($this->user->id != $this->message->from_profile &&
- $this->user->id != $this->message->to_profile)) {
- // TRANS: Client error displayed requesting a single direct message the requesting user was not a party in.
- throw new ClientException(_('Only the sender and recipient ' .
- 'may read this message.'), 403);
- }
-
- return true;
- }
-
- function handle($args)
- {
- $this->showPage();
- }
-
- function title()
- {
- if ($this->user->id == $this->message->from_profile) {
- $to = $this->message->getTo();
- // @todo FIXME: Might be nice if the timestamp could be localised.
- // TRANS: Page title for single direct message display when viewing user is the sender.
- // TRANS: %1$s is the addressed user's nickname, $2$s is a timestamp.
- return sprintf(_('Message to %1$s on %2$s'),
- $to->nickname,
- common_exact_date($this->message->created));
- } else if ($this->user->id == $this->message->to_profile) {
- $from = $this->message->getFrom();
- // @todo FIXME: Might be nice if the timestamp could be localised.
- // TRANS: Page title for single message display.
- // TRANS: %1$s is the sending user's nickname, $2$s is a timestamp.
- return sprintf(_('Message from %1$s on %2$s'),
- $from->nickname,
- common_exact_date($this->message->created));
- }
- }
-
-
- function showContent()
- {
- $this->elementStart('ul', 'notices messages');
- $ml = new ShowMessageListItem($this, $this->message, $this->user);
- $ml->show();
- $this->elementEnd('ul');
- }
-
- function isReadOnly($args)
- {
- return true;
- }
-
- /**
- * Don't show aside
- *
- * @return void
- */
-
- function showAside() {
- }
-}
-
-class ShowMessageListItem extends MessageListItem
-{
- var $user;
-
- function __construct($out, $message, $user)
- {
- parent::__construct($out, $message);
- $this->user = $user;
- }
-
- function getMessageProfile()
- {
- if ($this->user->id == $this->message->from_profile) {
- return $this->message->getTo();
- } else if ($this->user->id == $this->message->to_profile) {
- return $this->message->getFrom();
- } else {
- // This shouldn't happen
- return null;
- }
- }
-}
+++ /dev/null
-<?php
-/**
- * Table Definition for message
- */
-require_once INSTALLDIR.'/classes/Memcached_DataObject.php';
-
-class Message extends Managed_DataObject
-{
- ###START_AUTOCODE
- /* the code below is auto generated do not remove the above tag */
-
- public $__table = 'message'; // table name
- public $id; // int(4) primary_key not_null
- public $uri; // varchar(255) unique_key
- public $from_profile; // int(4) not_null
- public $to_profile; // int(4) not_null
- public $content; // text()
- public $rendered; // text()
- public $url; // varchar(255)
- public $created; // datetime() not_null
- public $modified; // timestamp() not_null default_CURRENT_TIMESTAMP
- public $source; // varchar(32)
-
- /* the code above is auto generated do not remove the tag below */
- ###END_AUTOCODE
-
- public static function schemaDef()
- {
- return array(
- 'fields' => array(
- 'id' => array('type' => 'serial', 'not null' => true, 'description' => 'unique identifier'),
- 'uri' => array('type' => 'varchar', 'length' => 255, 'description' => 'universally unique identifier'),
- 'from_profile' => array('type' => 'int', 'not null' => true, 'description' => 'who the message is from'),
- 'to_profile' => array('type' => 'int', 'not null' => true, 'description' => 'who the message is to'),
- 'content' => array('type' => 'text', 'description' => 'message content'),
- 'rendered' => array('type' => 'text', 'description' => 'HTML version of the content'),
- 'url' => array('type' => 'varchar', 'length' => 255, 'description' => 'URL of any attachment (image, video, bookmark, whatever)'),
- 'created' => array('type' => 'datetime', 'not null' => true, 'description' => 'date this record was created'),
- 'modified' => array('type' => 'timestamp', 'not null' => true, 'description' => 'date this record was modified'),
- 'source' => array('type' => 'varchar', 'length' => 32, 'description' => 'source of comment, like "web", "im", or "clientname"'),
- ),
- 'primary key' => array('id'),
- 'unique keys' => array(
- 'message_uri_key' => array('uri'),
- ),
- 'foreign keys' => array(
- 'message_from_profile_fkey' => array('profile', array('from_profile' => 'id')),
- 'message_to_profile_fkey' => array('profile', array('to_profile' => 'id')),
- ),
- 'indexes' => array(
- // @fixme these are really terrible indexes, since you can only sort on one of them at a time.
- // looks like we really need a (to_profile, created) for inbox and a (from_profile, created) for outbox
- 'message_from_idx' => array('from_profile'),
- 'message_to_idx' => array('to_profile'),
- 'message_created_idx' => array('created'),
- ),
- );
- }
-
- function getFrom()
- {
- return Profile::getKV('id', $this->from_profile);
- }
-
- function getTo()
- {
- return Profile::getKV('id', $this->to_profile);
- }
-
- static function saveNew($from, $to, $content, $source) {
- $sender = Profile::getKV('id', $from);
-
- if (!$sender->hasRight(Right::NEWMESSAGE)) {
- // TRANS: Client exception thrown when a user tries to send a direct message while being banned from sending them.
- throw new ClientException(_('You are banned from sending direct messages.'));
- }
-
- $user = User::getKV('id', $sender->id);
-
- $msg = new Message();
-
- $msg->from_profile = $from;
- $msg->to_profile = $to;
- if ($user) {
- // Use the sender's URL shortening options.
- $msg->content = $user->shortenLinks($content);
- } else {
- $msg->content = common_shorten_links($content);
- }
- $msg->rendered = common_render_text($msg->content);
- $msg->created = common_sql_now();
- $msg->source = $source;
-
- $result = $msg->insert();
-
- if (!$result) {
- common_log_db_error($msg, 'INSERT', __FILE__);
- // TRANS: Message given when a message could not be stored on the server.
- throw new ServerException(_('Could not insert message.'));
- }
-
- $orig = clone($msg);
- $msg->uri = common_local_url('showmessage', array('message' => $msg->id));
-
- $result = $msg->update($orig);
-
- if (!$result) {
- common_log_db_error($msg, 'UPDATE', __FILE__);
- // TRANS: Message given when a message could not be updated on the server.
- throw new ServerException(_('Could not update message with new URI.'));
- }
-
- return $msg;
- }
-
- static function maxContent()
- {
- $desclimit = common_config('message', 'contentlimit');
- // null => use global limit (distinct from 0!)
- if (is_null($desclimit)) {
- $desclimit = common_config('site', 'textlimit');
- }
- return $desclimit;
- }
-
- static function contentTooLong($content)
- {
- $contentlimit = self::maxContent();
- return ($contentlimit > 0 && !empty($content) && (mb_strlen($content) > $contentlimit));
- }
-
- function notify()
- {
- $from = User::getKV('id', $this->from_profile);
- $to = User::getKV('id', $this->to_profile);
-
- mail_notify_message($this, $from, $to);
- }
-
- function getSource()
- {
- if (empty($this->source)) {
- return false;
- }
-
- $ns = new Notice_source();
- switch ($this->source) {
- case 'web':
- case 'xmpp':
- case 'mail':
- case 'omb':
- case 'system':
- case 'api':
- $ns->code = $this->source;
- break;
- default:
- $ns = Notice_source::getKV($this->source);
- if (!$ns instanceof Notice_source) {
- $ns = new Notice_source();
- $ns->code = $this->source;
- $app = Oauth_application::getKV('name', $this->source);
- if ($app) {
- $ns->name = $app->name;
- $ns->url = $app->source_url;
- }
- }
- break;
- }
- return $ns;
- }
-
- function asActivity()
- {
- $act = new Activity();
-
- if (Event::handle('StartMessageAsActivity', array($this, &$act))) {
-
- $act->id = TagURI::mint(sprintf('activity:message:%d', $this->id));
- $act->time = strtotime($this->created);
- $act->link = $this->url;
-
- $profile = Profile::getKV('id', $this->from_profile);
-
- if (empty($profile)) {
- throw new Exception(sprintf("Sender profile not found: %d", $this->from_profile));
- }
-
- $act->actor = $profile->asActivityObject();
- $act->actor->extra[] = $profile->profileInfo();
-
- $act->verb = ActivityVerb::POST;
-
- $act->objects[] = ActivityObject::fromMessage($this);
-
- $ctx = new ActivityContext();
-
- $rprofile = Profile::getKV('id', $this->to_profile);
-
- if (empty($rprofile)) {
- throw new Exception(sprintf("Receiver profile not found: %d", $this->to_profile));
- }
-
- $ctx->attention[$rprofile->getUri()] = ActivityObject::PERSON;
-
- $act->context = $ctx;
-
- $source = $this->getSource();
-
- if ($source instanceof Notice_source) {
- $act->generator = ActivityObject::fromNoticeSource($source);
- }
-
- Event::handle('EndMessageAsActivity', array($this, &$act));
- }
-
- return $act;
- }
-}
{
$this->_deleteNotices();
$this->_deleteSubscriptions();
- $this->_deleteMessages();
$this->_deleteTags();
$this->_deleteBlocks();
$this->_deleteAttentions();
$self->delete();
}
- function _deleteMessages()
- {
- $msg = new Message();
- $msg->from_profile = $this->id;
- $msg->delete();
-
- $msg = new Message();
- $msg->to_profile = $this->id;
- $msg->delete();
- }
-
function _deleteTags()
{
$tag = new Profile_tag();
'Foreign_link',
'Foreign_subscription',
'Invitation',
- 'Message',
'Profile_prefs',
'Profile_tag',
'Profile_list',
$this->out->elementEnd('li');
if ($this->profile->isLocal() && $cur->mutuallySubscribed($this->profile)) {
-
- // message
-
- $this->out->elementStart('li', 'entity_send-a-message');
- $this->out->element('a', array('href' => common_local_url('newmessage', array('to' => $this->user->id)),
- // TRANS: Link title for link on user profile.
- 'title' => _('Send a direct message to this user.')),
- // TRANS: Link text for link on user profile.
- _m('BUTTON','Message'));
- $this->out->elementEnd('li');
-
// nudge
if ($this->user->email && $this->user->emailnotifynudge) {
+++ /dev/null
-<?php
-/**
- * StatusNet, the distributed open-source microblogging tool
- *
- * common superclass for direct messages inbox and outbox
- *
- * PHP version 5
- *
- * LICENCE: 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 Message
- * @package StatusNet
- * @author Evan Prodromou <evan@status.net>
- * @copyright 2008 StatusNet, Inc.
- * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
- * @link http://status.net/
- */
-
-if (!defined('STATUSNET') && !defined('LACONICA')) {
- exit(1);
-}
-
-/**
- * common superclass for direct messages inbox and outbox
- *
- * @category Message
- * @package StatusNet
- * @author Evan Prodromou <evan@status.net>
- * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
- * @link http://status.net/
- * @see InboxAction
- * @see OutboxAction
- */
-class MailboxAction extends Action
-{
- var $page = null;
-
- function prepare($args)
- {
- parent::prepare($args);
-
- $nickname = common_canonical_nickname($this->arg('nickname'));
- $this->user = User::getKV('nickname', $nickname);
- $this->page = $this->trimmed('page');
-
- if (!$this->page) {
- $this->page = 1;
- }
-
- common_set_returnto($this->selfUrl());
-
- return true;
- }
-
- /**
- * output page based on arguments
- *
- * @param array $args HTTP arguments (from $_REQUEST)
- *
- * @return void
- */
- function handle($args)
- {
- parent::handle($args);
-
- if (!$this->user) {
- // TRANS: Client error displayed when trying to access a mailbox without providing a user.
- $this->clientError(_('No such user.'), 404);
- }
-
- $cur = common_current_user();
-
- if (!$cur || $cur->id != $this->user->id) {
- // TRANS: Client error displayed when trying to access a mailbox that is not of the logged in user.
- $this->clientError(_('Only the user can read their own mailboxes.'), 403);
- }
-
- $this->showPage();
- }
-
- function showNoticeForm()
- {
- $message_form = new MessageForm($this);
- $message_form->show();
- }
-
- function showContent()
- {
- $message = $this->getMessages();
-
- if ($message) {
-
- $ml = $this->getMessageList($message);
-
- $cnt = $ml->show();
-
- $this->pagination($this->page > 1,
- $cnt > MESSAGES_PER_PAGE,
- $this->page,
- $this->trimmed('action'),
- array('nickname' => $this->user->nickname));
- } else {
- $this->element('p',
- 'guide',
- // TRANS: Message displayed when there are no private messages in the inbox of a user.
- _('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.'));
- }
- }
-
- function getMessages()
- {
- return null;
- }
-
- function getMessageList($message)
- {
- return null;
- }
-
- /**
- * Show the page notice
- *
- * Shows instructions for the page
- *
- * @return void
- */
- function showPageNotice()
- {
- $instr = $this->getInstructions();
- $output = common_markup_to_html($instr);
-
- $this->elementStart('div', 'instructions');
- $this->raw($output);
- $this->elementEnd('div');
- }
-
- /**
- * Mailbox actions are read only
- *
- * @param array $args other arguments
- *
- * @return boolean
- */
- function isReadOnly($args)
- {
- return true;
- }
-
- function showObjectNav()
- {
- $mm = new MailboxMenu($this);
- $mm->show();
- }
-}
+++ /dev/null
-<?php
-/**
- * StatusNet - the distributed open-source microblogging tool
- * Copyright (C) 2011, StatusNet, Inc.
- *
- * Private mailboxes menu
- *
- * PHP version 5
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- * @category Cache
- * @package StatusNet
- * @author Evan Prodromou <evan@status.net>
- * @copyright 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);
-}
-
-/**
- * Menu of existing mailboxes
- *
- * @category General
- * @package StatusNet
- * @author Evan Prodromou <evan@status.net>
- * @copyright 2011 StatusNet, Inc.
- * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
- * @link http://status.net/
- */
-class MailboxMenu extends Menu
-{
- function show()
- {
- $cur = common_current_user();
- $nickname = $cur->nickname;
-
- $this->out->elementStart('ul', array('class' => 'nav'));
-
- $this->item('inbox',
- array('nickname' => $nickname),
- // TRANS: Menu item in mailbox menu. Leads to incoming private messages.
- _m('MENU','Inbox'),
- // TRANS: Menu item title in mailbox menu. Leads to incoming private messages.
- _('Your incoming messages.'));
-
- $this->item('outbox',
- array('nickname' => $nickname),
- // TRANS: Menu item in mailbox menu. Leads to outgoing private messages.
- _m('MENU','Outbox'),
- // TRANS: Menu item title in mailbox menu. Leads to outgoing private messages.
- _('Your sent messages.'));
-
- $this->out->elementEnd('ul');
- }
-}
+++ /dev/null
-<?php
-/**
- * StatusNet, the distributed open-source microblogging tool
- *
- * Form for posting a direct message
- *
- * PHP version 5
- *
- * LICENCE: 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 Form
- * @package StatusNet
- * @author Evan Prodromou <evan@status.net>
- * @author Sarven Capadisli <csarven@status.net>
- * @copyright 2009 StatusNet, Inc.
- * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
- * @link http://status.net/
- */
-
-if (!defined('STATUSNET') && !defined('LACONICA')) {
- exit(1);
-}
-
-require_once INSTALLDIR.'/lib/form.php';
-
-/**
- * Form for posting a direct message
- *
- * @category Form
- * @package StatusNet
- * @author Evan Prodromou <evan@status.net>
- * @author Sarven Capadisli <csarven@status.net>
- * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
- * @link http://status.net/
- *
- * @see HTMLOutputter
- */
-class MessageForm extends Form
-{
- /**
- * User to send a direct message to
- */
- var $to = null;
-
- /**
- * Pre-filled content of the form
- */
- var $content = null;
-
- /**
- * Constructor
- *
- * @param HTMLOutputter $out output channel
- * @param User $to user to send a message to
- * @param string $content content to pre-fill
- */
- function __construct($out=null, $to=null, $content=null)
- {
- parent::__construct($out);
-
- $this->to = $to;
- $this->content = $content;
- }
-
- /**
- * ID of the form
- *
- * @return string ID of the form
- */
- function id()
- {
- return 'form_notice-direct';
- }
-
- /**
- * Class of the form
- *
- * @return string class of the form
- */
- function formClass()
- {
- return 'form_notice ajax-notice';
- }
-
- /**
- * Action of the form
- *
- * @return string URL of the action
- */
- function action()
- {
- return common_local_url('newmessage');
- }
-
- /**
- * Legend of the Form
- *
- * @return void
- */
- function formLegend()
- {
- // TRANS: Form legend for direct notice.
- $this->out->element('legend', null, _('Send a direct notice'));
- }
-
- /**
- * Data elements
- *
- * @return void
- */
- function formData()
- {
- $user = common_current_user();
-
- $mutual_users = $user->mutuallySubscribedUsers();
-
- $mutual = array();
- // TRANS: Label entry in drop-down selection box in direct-message inbox/outbox.
- // TRANS: This is the default entry in the drop-down box, doubling as instructions
- // TRANS: and a brake against accidental submissions with the first user in the list.
- $mutual[0] = _('Select recipient:');
-
- while ($mutual_users->fetch()) {
- if ($mutual_users->id != $user->id) {
- $mutual[$mutual_users->id] = $mutual_users->nickname;
- }
- }
-
- $mutual_users->free();
- unset($mutual_users);
-
- if (count($mutual) == 1) {
- // TRANS: Entry in drop-down selection box in direct-message inbox/outbox when no one is available to message.
- $mutual[0] = _('No mutual subscribers.');
- }
-
- // TRANS: Dropdown label in direct notice form.
- $this->out->dropdown('to', _('To'), $mutual, null, false,
- ($this->to) ? $this->to->id : null);
-
- $this->out->element('textarea', array('class' => 'notice_data-text',
- 'cols' => 35,
- 'rows' => 4,
- 'name' => 'content'),
- ($this->content) ? $this->content : '');
-
- $contentLimit = Message::maxContent();
-
- if ($contentLimit > 0) {
- $this->out->element('span',
- array('class' => 'count'),
- $contentLimit);
- }
- }
-
- /**
- * Action elements
- *
- * @return void
- */
- function formActions()
- {
- $this->out->element('input', array('id' => 'notice_action-submit',
- 'class' => 'submit',
- 'name' => 'message_send',
- 'type' => 'submit',
- // TRANS: Button text for sending a direct notice.
- 'value' => _m('Send button for sending notice', 'Send')));
- }
-
-
- /**
- * Show the form
- *
- * Uses a recipe to output the form.
- *
- * @return void
- * @see Widget::show()
- */
-
- function show()
- {
- $this->elementStart('div', 'input_forms');
- $this->elementStart(
- 'div',
- array(
- 'id' => 'input_form_direct',
- 'class' => 'input_form current nonav'
- )
- );
-
- parent::show();
-
- $this->elementEnd('div');
- $this->elementEnd('div');
-
- }
-}
+++ /dev/null
-<?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'));
-
- // TRANS: Header in message list.
- $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);
-}
+++ /dev/null
-<?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' => 'h-entry notice',
- 'id' => 'message-' . $this->message->id));
-
- $profile = $this->getMessageProfile();
-
- $this->out->elementStart('a', array('href' => $profile->profileurl,
- 'class' => 'p-author'));
- $avatarUrl = $profile->avatarUrl(AVATAR_STREAM_SIZE);
- $this->out->element('img', array('src' => $avatarUrl,
- 'class' => 'avatar u-photo',
- 'width' => AVATAR_STREAM_SIZE,
- 'height' => AVATAR_STREAM_SIZE,
- 'alt' => $profile->getBestName()));
- $this->out->element('span', array('class' => 'nickname fn'), $profile->getNickname());
- $this->out->elementEnd('a');
-
- // FIXME: URL, image, video, audio
- $this->out->elementStart('div', array('class' => 'e-content'));
- $this->out->raw($this->message->rendered);
- $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-metadata');
- $this->out->elementStart('a', array('rel' => 'bookmark',
- 'class' => 'timestamp',
- 'href' => $messageurl));
- $dt = common_date_iso8601($this->message->created);
- $this->out->element('time', array('class' => 'dt-published',
- 'datetime' => common_date_iso8601($this->message->created),
- // TRANS: Timestamp title (tooltip text) for NoticeListItem
- 'title' => common_exact_date($this->message->created)),
- 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).
- // TRANS: Followed by notice source (usually the client used to send the notice).
- $this->out->text(_('from'));
- $this->showSource($this->message->source);
- $this->out->elementEnd('span');
- }
- $this->out->elementEnd('div');
-
- $this->out->elementEnd('li');
- }
-
- /**
- * Dummy method. Serves no other purpose than to make strings available used
- * in self::showSource() through xgettext.
- *
- * @return void
- */
- function messageListItemDummyMessages()
- {
- // A dummy array with messages. These will get extracted by xgettext and
- // are used in self::showSource().
- $dummy_messages = array(
- // TRANS: A possible notice source (web interface).
- _m('SOURCE','web'),
- // TRANS: A possible notice source (XMPP).
- _m('SOURCE','xmpp'),
- // TRANS: A possible notice source (e-mail).
- _m('SOURCE','mail'),
- // TRANS: A possible notice source (OpenMicroBlogging).
- _m('SOURCE','omb'),
- // TRANS: A possible notice source (Application Programming Interface).
- _m('SOURCE','api'),
- );
- }
-
- /**
- * Show the source of the message
- *
- * Returns either the name (and link) of the API client that posted the notice,
- * or one of other other channels.
- *
- * @param string $source the source of the message
- *
- * @return void
- */
- function showSource($source)
- {
- $source_name = _m('SOURCE',$source);
- switch ($source) {
- case 'web':
- case 'xmpp':
- case 'mail':
- case 'omb':
- case 'api':
- $this->out->element('span', 'device', $source_name);
- break;
- default:
- $ns = Notice_source::getKV($source);
- if ($ns) {
- $this->out->elementStart('span', 'device');
- $this->out->element('a', array('href' => $ns->url,
- 'rel' => 'external'),
- $ns->name);
- $this->out->elementEnd('span');
- } else {
- $this->out->element('span', 'device', $source_name);
- }
- break;
- }
- return;
- }
-
- /**
- * 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();
-}
sprintf(_('Replies to %s'), $name),
$mine && $action =='replies', 'nav_timeline_replies');
-
- if ($scoped instanceof Profile && $scoped->id == $target->id &&
- !common_config('singleuser', 'enabled')) {
-
- $this->out->menuItem(common_local_url('inbox', array('nickname' =>
- $nickname)),
- // TRANS: Menu item in personal group navigation menu.
- _m('MENU','Messages'),
- // TRANS: Menu item title in personal group navigation menu.
- _('Your incoming messages'),
- $mine && $action =='inbox');
- }
-
Event::handle('EndPersonalGroupNav', array($this, $target, $scoped));
}
$this->out->elementEnd('ul');
array('action' => 'conversation'),
array('id' => '[0-9]+'));
- $m->connect('message/new', array('action' => 'newmessage'));
- $m->connect('message/new?to=:to', array('action' => 'newmessage'), array('to' => Nickname::DISPLAY_FMT));
- $m->connect('message/:message',
- array('action' => 'showmessage'),
- array('message' => '[0-9]+'));
-
$m->connect('user/:id',
array('action' => 'userbyid'),
array('id' => '[0-9]+'));
'screen_name' => Nickname::DISPLAY_FMT,
'format' => '(xml|json)'));
- // direct messages
-
- $m->connect('api/direct_messages.:format',
- array('action' => 'ApiDirectMessage',
- 'format' => '(xml|json|rss|atom)'));
-
- $m->connect('api/direct_messages/sent.:format',
- array('action' => 'ApiDirectMessage',
- 'format' => '(xml|json|rss|atom)',
- 'sent' => true));
-
- $m->connect('api/direct_messages/new.:format',
- array('action' => 'ApiDirectMessageNew',
- 'format' => '(xml|json)'));
-
// friendships
$m->connect('api/friendships/show.:format',
--- /dev/null
+<?php
+/*
+ * GNU Social - a federating social network
+ * Copyright (C) 2014, Free Software Foundation, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+if (!defined('GNUSOCIAL')) { exit(1); }
+
+/**
+ * @maintainer Mikael Nordfeldth <mmn@hethane.se>
+ */
+class DirectMessagePlugin extends Plugin
+{
+ public function onCheckSchema()
+ {
+ $schema = Schema::get();
+ $schema->ensureTable('message', Message::schemaDef());
+ return true;
+ }
+
+ public function onRouterInitialized(URLMapper $m)
+ {
+ // web front-end actions
+ $m->connect('message/new', array('action' => 'newmessage'));
+ $m->connect('message/new?to=:to', array('action' => 'newmessage'), array('to' => Nickname::DISPLAY_FMT));
+ $m->connect('message/:message',
+ array('action' => 'showmessage'),
+ array('message' => '[0-9]+'));
+
+ // direct messages
+ $m->connect('api/direct_messages.:format',
+ array('action' => 'ApiDirectMessage',
+ 'format' => '(xml|json|rss|atom)'));
+ $m->connect('api/direct_messages/sent.:format',
+ array('action' => 'ApiDirectMessage',
+ 'format' => '(xml|json|rss|atom)',
+ 'sent' => true));
+ $m->connect('api/direct_messages/new.:format',
+ array('action' => 'ApiDirectMessageNew',
+ 'format' => '(xml|json)'));
+
+ return true;
+ }
+
+ public function onEndPersonalGroupNav(Menu $menu, Profile $target, Profile $scoped=null)
+ {
+ if ($scoped instanceof Profile && $scoped->id == $target->id
+ && !common_config('singleuser', 'enabled')) {
+
+ $menu->out->menuItem(common_local_url('inbox', array('nickname' =>
+ $target->getNickname())),
+ // TRANS: Menu item in personal group navigation menu.
+ _m('MENU','Messages'),
+ // TRANS: Menu item title in personal group navigation menu.
+ _('Your incoming messages'),
+ $scoped->id === $target->id && $menu->actionName =='inbox');
+ }
+ }
+
+ public function onEndProfilePageActionsElements(HTMLOutputter $out, Profile $profile)
+ {
+ $scoped = Profile::current();
+ if (!$scoped instanceof Profile) {
+ return true;
+ }
+
+ if ($profile->isLocal() && $scoped->mutuallySubscribed($profile)) {
+ $out->elementStart('li', 'entity_send-a-message');
+ $out->element('a', array('href' => common_local_url('newmessage', array('to' => $profile->id)),
+ // TRANS: Link title for link on user profile.
+ 'title' => _('Send a direct message to this user.')),
+ // TRANS: Link text for link on user profile.
+ _m('BUTTON','Message'));
+ $out->elementEnd('li');
+ }
+ return true;
+ }
+
+ public function onProfileDeleteRelated(Profile $profile, &$related)
+ {
+ $msg = new Message();
+ $msg->from_profile = $profile->id;
+ $msg->delete();
+
+ $msg = new Message();
+ $msg->to_profile = $profile->id;
+ $msg->delete();
+ return true;
+ }
+
+ public function onPluginVersion(array &$versions)
+ {
+ $versions[] = array('name' => 'Direct Message',
+ 'version' => GNUSOCIAL_VERSION,
+ 'author' => 'Mikael Nordfeldth',
+ 'homepage' => 'http://gnu.io/',
+ 'rawdescription' =>
+ // TRANS: Plugin description.
+ _m('Direct Message to other local users (broken out of core).'));
+
+ return true;
+ }
+}
--- /dev/null
+<?php
+/**
+ * StatusNet, the distributed open-source microblogging tool
+ *
+ * Show a the direct messages from or to a user
+ *
+ * PHP version 5
+ *
+ * LICENCE: 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 API
+ * @package StatusNet
+ * @author Adrian Lang <mail@adrianlang.de>
+ * @author Evan Prodromou <evan@status.net>
+ * @author Robin Millette <robin@millette.info>
+ * @author Zach Copley <zach@status.net>
+ * @copyright 2009 StatusNet, Inc.
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://status.net/
+ */
+
+if (!defined('STATUSNET')) {
+ exit(1);
+}
+
+/**
+ * Show a list of direct messages from or to the authenticating user
+ *
+ * @category API
+ * @package StatusNet
+ * @author Adrian Lang <mail@adrianlang.de>
+ * @author Evan Prodromou <evan@status.net>
+ * @author Robin Millette <robin@millette.info>
+ * @author Zach Copley <zach@status.net>
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://status.net/
+ */
+class ApiDirectMessageAction extends ApiAuthAction
+{
+ var $messages = null;
+ var $title = null;
+ var $subtitle = null;
+ var $link = null;
+ var $selfuri_base = null;
+ var $id = null;
+
+ /**
+ * Take arguments for running
+ *
+ * @param array $args $_REQUEST args
+ *
+ * @return boolean success flag
+ */
+ function prepare($args)
+ {
+ parent::prepare($args);
+
+ $this->user = $this->auth_user;
+
+ if (empty($this->user)) {
+ // TRANS: Client error given when a user was not found (404).
+ $this->clientError(_('No such user.'), 404);
+ }
+
+ $server = common_root_url();
+ $taguribase = TagURI::base();
+
+ if ($this->arg('sent')) {
+
+ // Action was called by /api/direct_messages/sent.format
+
+ $this->title = sprintf(
+ // TRANS: Title. %s is a user nickname.
+ _("Direct messages from %s"),
+ $this->user->nickname
+ );
+ $this->subtitle = sprintf(
+ // TRANS: Subtitle. %s is a user nickname.
+ _("All the direct messages sent from %s"),
+ $this->user->nickname
+ );
+ $this->link = $server . $this->user->nickname . '/outbox';
+ $this->selfuri_base = common_root_url() . 'api/direct_messages/sent';
+ $this->id = "tag:$taguribase:SentDirectMessages:" . $this->user->id;
+ } else {
+ $this->title = sprintf(
+ // TRANS: Title. %s is a user nickname.
+ _("Direct messages to %s"),
+ $this->user->nickname
+ );
+ $this->subtitle = sprintf(
+ // TRANS: Subtitle. %s is a user nickname.
+ _("All the direct messages sent to %s"),
+ $this->user->nickname
+ );
+ $this->link = $server . $this->user->nickname . '/inbox';
+ $this->selfuri_base = common_root_url() . 'api/direct_messages';
+ $this->id = "tag:$taguribase:DirectMessages:" . $this->user->id;
+ }
+
+ $this->messages = $this->getMessages();
+
+ return true;
+ }
+
+ /**
+ * Handle the request
+ *
+ * Show the messages
+ *
+ * @param array $args $_REQUEST data (unused)
+ *
+ * @return void
+ */
+ function handle($args)
+ {
+ parent::handle($args);
+ $this->showMessages();
+ }
+
+ /**
+ * Show the messages
+ *
+ * @return void
+ */
+ function showMessages()
+ {
+ switch($this->format) {
+ case 'xml':
+ $this->showXmlDirectMessages();
+ break;
+ case 'rss':
+ $this->showRssDirectMessages();
+ break;
+ case 'atom':
+ $this->showAtomDirectMessages();
+ break;
+ case 'json':
+ $this->showJsonDirectMessages();
+ break;
+ default:
+ // TRANS: Client error displayed when coming across a non-supported API method.
+ $this->clientError(_('API method not found.'), $code = 404);
+ break;
+ }
+ }
+
+ /**
+ * Get notices
+ *
+ * @return array notices
+ */
+ function getMessages()
+ {
+ $message = new Message();
+
+ if ($this->arg('sent')) {
+ $message->from_profile = $this->user->id;
+ } else {
+ $message->to_profile = $this->user->id;
+ }
+
+ if (!empty($this->max_id)) {
+ $message->whereAdd('id <= ' . $this->max_id);
+ }
+
+ if (!empty($this->since_id)) {
+ $message->whereAdd('id > ' . $this->since_id);
+ }
+
+ $message->orderBy('created DESC, id DESC');
+ $message->limit((($this->page - 1) * $this->count), $this->count);
+ $message->find();
+
+ $messages = array();
+
+ while ($message->fetch()) {
+ $messages[] = clone($message);
+ }
+
+ return $messages;
+ }
+
+ /**
+ * Is this action read only?
+ *
+ * @param array $args other arguments
+ *
+ * @return boolean true
+ */
+ function isReadOnly($args)
+ {
+ return true;
+ }
+
+ /**
+ * When was this notice last modified?
+ *
+ * @return string datestamp of the latest notice in the stream
+ */
+ function lastModified()
+ {
+ if (!empty($this->messages)) {
+ return strtotime($this->messages[0]->created);
+ }
+
+ return null;
+ }
+
+ /**
+ * Shows a list of direct messages as Twitter-style XML array
+ *
+ * @return void
+ */
+ function showXmlDirectMessages()
+ {
+ $this->initDocument('xml');
+ $this->elementStart('direct-messages', array('type' => 'array',
+ 'xmlns:statusnet' => 'http://status.net/schema/api/1/'));
+
+ foreach ($this->messages as $m) {
+ $dm_array = $this->directMessageArray($m);
+ $this->showXmlDirectMessage($dm_array);
+ }
+
+ $this->elementEnd('direct-messages');
+ $this->endDocument('xml');
+ }
+
+ /**
+ * Shows a list of direct messages as a JSON encoded array
+ *
+ * @return void
+ */
+ function showJsonDirectMessages()
+ {
+ $this->initDocument('json');
+
+ $dmsgs = array();
+
+ foreach ($this->messages as $m) {
+ $dm_array = $this->directMessageArray($m);
+ array_push($dmsgs, $dm_array);
+ }
+
+ $this->showJsonObjects($dmsgs);
+ $this->endDocument('json');
+ }
+
+ /**
+ * Shows a list of direct messages as RSS items
+ *
+ * @return void
+ */
+ function showRssDirectMessages()
+ {
+ $this->initDocument('rss');
+
+ $this->element('title', null, $this->title);
+
+ $this->element('link', null, $this->link);
+ $this->element('description', null, $this->subtitle);
+ $this->element('language', null, 'en-us');
+
+ $this->element(
+ 'atom:link',
+ array(
+ 'type' => 'application/rss+xml',
+ 'href' => $this->selfuri_base . '.rss',
+ 'rel' => self
+ ),
+ null
+ );
+ $this->element('ttl', null, '40');
+
+ foreach ($this->messages as $m) {
+ $entry = $this->rssDirectMessageArray($m);
+ $this->showTwitterRssItem($entry);
+ }
+
+ $this->endTwitterRss();
+ }
+
+ /**
+ * Shows a list of direct messages as Atom entries
+ *
+ * @return void
+ */
+ function showAtomDirectMessages()
+ {
+ $this->initDocument('atom');
+
+ $this->element('title', null, $this->title);
+ $this->element('id', null, $this->id);
+
+ $selfuri = common_root_url() . 'api/direct_messages.atom';
+
+ $this->element(
+ 'link', array(
+ 'href' => $this->link,
+ 'rel' => 'alternate',
+ 'type' => 'text/html'),
+ null
+ );
+ $this->element(
+ 'link', array(
+ 'href' => $this->selfuri_base . '.atom', 'rel' => 'self',
+ 'type' => 'application/atom+xml'),
+ null
+ );
+ $this->element('updated', null, common_date_iso8601('now'));
+ $this->element('subtitle', null, $this->subtitle);
+
+ foreach ($this->messages as $m) {
+ $entry = $this->rssDirectMessageArray($m);
+ $this->showTwitterAtomEntry($entry);
+ }
+
+ $this->endDocument('atom');
+ }
+
+ /**
+ * An entity tag for this notice
+ *
+ * Returns an Etag based on the action name, language, and
+ * timestamps of the notice
+ *
+ * @return string etag
+ */
+ function etag()
+ {
+ if (!empty($this->messages)) {
+
+ $last = count($this->messages) - 1;
+
+ return '"' . implode(
+ ':',
+ array($this->arg('action'),
+ common_user_cache_hash($this->auth_user),
+ common_language(),
+ strtotime($this->messages[0]->created),
+ strtotime($this->messages[$last]->created)
+ )
+ )
+ . '"';
+ }
+
+ return null;
+ }
+}
--- /dev/null
+<?php
+/**
+ * StatusNet, the distributed open-source microblogging tool
+ *
+ * Send a direct message via the API
+ *
+ * PHP version 5
+ *
+ * LICENCE: 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 API
+ * @package StatusNet
+ * @author Adrian Lang <mail@adrianlang.de>
+ * @author Evan Prodromou <evan@status.net>
+ * @author Robin Millette <robin@millette.info>
+ * @author Zach Copley <zach@status.net>
+ * @copyright 2009 StatusNet, Inc.
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://status.net/
+ */
+
+if (!defined('STATUSNET')) {
+ exit(1);
+}
+
+/**
+ * Creates a new direct message from the authenticating user to
+ * the user specified by id.
+ *
+ * @category API
+ * @package StatusNet
+ * @author Adrian Lang <mail@adrianlang.de>
+ * @author Evan Prodromou <evan@status.net>
+ * @author Robin Millette <robin@millette.info>
+ * @author Zach Copley <zach@status.net>
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://status.net/
+ */
+class ApiDirectMessageNewAction extends ApiAuthAction
+{
+ protected $needPost = true;
+
+ var $other = null; // Profile we're sending to
+ var $content = null;
+
+ /**
+ * Take arguments for running
+ *
+ * @param array $args $_REQUEST args
+ *
+ * @return boolean success flag
+ */
+ protected function prepare(array $args=array())
+ {
+ parent::prepare($args);
+
+ if (empty($this->user)) {
+ // TRANS: Client error when user not found for an API direct message action.
+ $this->clientError(_('No such user.'), 404);
+ }
+
+ $this->content = $this->trimmed('text');
+
+ $user_param = $this->trimmed('user');
+ $user_id = $this->arg('user_id');
+ $screen_name = $this->trimmed('screen_name');
+
+ if (isset($user_param) || isset($user_id) || isset($screen_name)) {
+ $this->other = $this->getTargetProfile($user_param);
+ }
+
+ return true;
+ }
+
+ /**
+ * Handle the request
+ *
+ * Save the new message
+ *
+ * @return void
+ */
+ protected function handle()
+ {
+ parent::handle();
+
+ if (empty($this->content)) {
+ // TRANS: Client error displayed when no message text was submitted (406).
+ $this->clientError(_('No message text!'), 406);
+ } else {
+ $content_shortened = $this->auth_user->shortenLinks($this->content);
+ if (Message::contentTooLong($content_shortened)) {
+ // TRANS: Client error displayed when message content is too long.
+ // TRANS: %d is the maximum number of characters for a message.
+ $this->clientError(
+ 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()),
+ 406);
+ }
+ }
+
+ if (!$this->other instanceof Profile) {
+ // TRANS: Client error displayed if a recipient user could not be found (403).
+ $this->clientError(_('Recipient user not found.'), 403);
+ } else if (!$this->user->mutuallySubscribed($this->other)) {
+ // TRANS: Client error displayed trying to direct message another user who's not a friend (403).
+ $this->clientError(_('Cannot send direct messages to users who aren\'t your friend.'), 403);
+ } else if ($this->user->id == $this->other->id) {
+
+ // Note: sending msgs to yourself is allowed by Twitter
+
+ // TRANS: Client error displayed trying to direct message self (403).
+ $this->clientError(_('Do not send a message to yourself; just say it to yourself quietly instead.'), 403);
+ }
+
+ $message = Message::saveNew(
+ $this->user->id,
+ $this->other->id,
+ html_entity_decode($this->content, ENT_NOQUOTES, 'UTF-8'),
+ $this->source
+ );
+
+ $message->notify();
+
+ if ($this->format == 'xml') {
+ $this->showSingleXmlDirectMessage($message);
+ } elseif ($this->format == 'json') {
+ $this->showSingleJsondirectMessage($message);
+ }
+ }
+}
--- /dev/null
+<?php
+/**
+ * StatusNet, the distributed open-source microblogging tool
+ *
+ * action handler for message inbox
+ *
+ * PHP version 5
+ *
+ * LICENCE: 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 Message
+ * @package StatusNet
+ * @author Evan Prodromou <evan@status.net>
+ * @copyright 2008 StatusNet, Inc.
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://status.net/
+ */
+
+if (!defined('STATUSNET') && !defined('LACONICA')) {
+ exit(1);
+}
+
+require_once INSTALLDIR.'/lib/mailbox.php';
+
+/**
+ * action handler for message inbox
+ *
+ * @category Message
+ * @package StatusNet
+ * @author Evan Prodromou <evan@status.net>
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://status.net/
+ * @see MailboxAction
+ */
+class InboxAction extends MailboxAction
+{
+
+ /**
+ * Title of the page
+ *
+ * @return string page title
+ */
+ function title()
+ {
+ if ($this->page > 1) {
+ // TRANS: Title for all but the first page of the inbox page.
+ // TRANS: %1$s is the user's nickname, %2$s is the page number.
+ return sprintf(_('Inbox for %1$s - page %2$d'), $this->user->nickname,
+ $this->page);
+ } else {
+ // TRANS: Title for the first page of the inbox page.
+ // TRANS: %s is the user's nickname.
+ return sprintf(_('Inbox for %s'), $this->user->nickname);
+ }
+ }
+
+ /**
+ * Retrieve the messages for this user and this page
+ *
+ * Does a query for the right messages
+ *
+ * @return Message data object with stream for messages
+ *
+ * @see MailboxAction::getMessages()
+ */
+ function getMessages()
+ {
+ $message = new Message();
+
+ $message->to_profile = $this->user->id;
+ $message->orderBy('created DESC, id DESC');
+ $message->limit((($this->page - 1) * MESSAGES_PER_PAGE),
+ MESSAGES_PER_PAGE + 1);
+
+ if ($message->find()) {
+ return $message;
+ } else {
+ return null;
+ }
+ }
+
+ function getMessageList($message)
+ {
+ return new InboxMessageList($this, $message);
+ }
+
+ /**
+ * Instructions for using this page
+ *
+ * @return string localised instructions for using the page
+ */
+ function getInstructions()
+ {
+ // TRANS: Instructions for user inbox page.
+ 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();
+ }
+}
--- /dev/null
+<?php
+/**
+ * StatusNet, the distributed open-source microblogging tool
+ *
+ * Handler for posting new messages
+ *
+ * PHP version 5
+ *
+ * LICENCE: 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 Personal
+ * @package StatusNet
+ * @author Evan Prodromou <evan@status.net>
+ * @author Zach Copley <zach@status.net>
+ * @author Sarven Capadisli <csarven@status.net>
+ * @copyright 2008-2009 StatusNet, Inc.
+ * @copyright 2013 Free Software Foundation, Inc.
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://status.net/
+ */
+
+if (!defined('STATUSNET')) {
+ exit(1);
+}
+
+/**
+ * Action for posting new direct messages
+ *
+ * @category Personal
+ * @package StatusNet
+ * @author Evan Prodromou <evan@status.net>
+ * @author Zach Copley <zach@status.net>
+ * @author Sarven Capadisli <csarven@status.net>
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://status.net/
+ */
+
+class NewmessageAction extends FormAction
+{
+ var $content = null;
+ var $to = null;
+ var $other = null;
+
+ /**
+ * Title of the page
+ *
+ * Note that this usually doesn't get called unless something went wrong
+ *
+ * @return string page title
+ */
+
+ function title()
+ {
+ // TRANS: Page title for new direct message page.
+ return _('New message');
+ }
+
+ /**
+ * Handle input, produce output
+ *
+ * @param array $args $_REQUEST contents
+ *
+ * @return void
+ */
+
+ protected function prepare(array $args=array())
+ {
+ parent::prepare($args);
+
+ $this->content = $this->trimmed('content');
+ $this->to = $this->trimmed('to');
+
+ if ($this->to) {
+
+ $this->other = Profile::getKV('id', $this->to);
+
+ if (!$this->other instanceof Profile) {
+ // TRANS: Client error displayed trying to send a direct message to a non-existing user.
+ $this->clientError(_('No such user.'), 404);
+ }
+
+ if (!$this->other->isLocal()) {
+ // TRANS: Explains that current federation does not support direct, private messages yet.
+ $this->clientError(_('You cannot send direct messages to federated users yet.'));
+ }
+
+ if (!$this->scoped->mutuallySubscribed($this->other)) {
+ // TRANS: Client error displayed trying to send a direct message to a user while sender and
+ // TRANS: receiver are not subscribed to each other.
+ $this->clientError(_('You cannot send a message to this user.'), 404);
+ }
+ }
+
+ return true;
+ }
+
+ protected function handlePost()
+ {
+ parent::handlePost();
+
+ assert($this->scoped instanceof Profile); // XXX: maybe an error instead...
+
+ if (!$this->content) {
+ // TRANS: Form validator error displayed trying to send a direct message without content.
+ $this->clientError(_('No content!'));
+ } else {
+ $content_shortened = $this->scoped->shortenLinks($this->content);
+
+ if (Message::contentTooLong($content_shortened)) {
+ // TRANS: Form validation error displayed when message content is too long.
+ // TRANS: %d is the maximum number of characters for a message.
+ $this->clientError(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()));
+ }
+ }
+
+ if (!$this->other) {
+ // TRANS: Form validation error displayed trying to send a direct message without specifying a recipient.
+ $this->clientError(_('No recipient specified.'));
+ } else if (!$this->scoped->mutuallySubscribed($this->other)) {
+ // TRANS: Client error displayed trying to send a direct message to a user while sender and
+ // TRANS: receiver are not subscribed to each other.
+ $this->clientError(_('You cannot send a message to this user.'), 404);
+ } else if ($this->scoped->id == $this->other->id) {
+ // TRANS: Client error displayed trying to send a direct message to self.
+ $this->clientError(_('Do not send a message to yourself; ' .
+ 'just say it to yourself quietly instead.'), 403);
+ }
+
+ $message = Message::saveNew($this->scoped->id, $this->other->id, $this->content, 'web');
+ $message->notify();
+
+ if ($this->boolean('ajax')) {
+ $this->startHTML('text/xml;charset=utf-8');
+ $this->elementStart('head');
+ // TRANS: Page title after sending a direct message.
+ $this->element('title', null, _('Message sent'));
+ $this->elementEnd('head');
+ $this->elementStart('body');
+ $this->element('p', array('id' => 'command_result'),
+ // TRANS: Confirmation text after sending a direct message.
+ // TRANS: %s is the direct message recipient.
+ sprintf(_('Direct message to %s sent.'),
+ $this->other->nickname));
+ $this->elementEnd('body');
+ $this->endHTML();
+ } else {
+ $url = common_local_url('outbox',
+ array('nickname' => $this->scoped->nickname));
+ common_redirect($url, 303);
+ }
+ }
+
+ /**
+ * Show an Ajax-y error message
+ *
+ * Goes back to the browser, where it's shown in a popup.
+ *
+ * @param string $msg Message to show
+ *
+ * @return void
+ */
+
+ function ajaxErrorMsg($msg)
+ {
+ $this->startHTML('text/xml;charset=utf-8', true);
+ $this->elementStart('head');
+ // TRANS: Page title after an AJAX error occurred on the "send direct message" page.
+ $this->element('title', null, _('Ajax Error'));
+ $this->elementEnd('head');
+ $this->elementStart('body');
+ $this->element('p', array('id' => 'error'), $msg);
+ $this->elementEnd('body');
+ $this->endHTML();
+ }
+
+ function showForm($msg = null)
+ {
+ if ($msg && $this->boolean('ajax')) {
+ $this->ajaxErrorMsg($msg);
+ return;
+ }
+
+ $this->msg = $msg;
+ if ($this->trimmed('ajax')) {
+ $this->startHTML('text/xml;charset=utf-8');
+ $this->elementStart('head');
+ // TRANS: Page title on page for sending a direct message.
+ $this->element('title', null, _('New message'));
+ $this->elementEnd('head');
+ $this->elementStart('body');
+ $this->showNoticeForm();
+ $this->elementEnd('body');
+ $this->endHTML();
+ }
+ else {
+ $this->showPage();
+ }
+ }
+
+ function showPageNotice()
+ {
+ if ($this->msg) {
+ $this->element('p', 'error', $this->msg);
+ }
+ }
+
+ // Do nothing (override)
+
+ function showNoticeForm()
+ {
+ $message_form = new MessageForm($this, $this->other, $this->content);
+ $message_form->show();
+ }
+}
--- /dev/null
+<?php
+/**
+ * StatusNet, the distributed open-source microblogging tool
+ *
+ * action handler for message inbox
+ *
+ * PHP version 5
+ *
+ * LICENCE: 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 Message
+ * @package StatusNet
+ * @author Evan Prodromou <evan@status.net>
+ * @copyright 2008 StatusNet, Inc.
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://status.net/
+ */
+if (!defined('STATUSNET') && !defined('LACONICA')) {
+ exit(1);
+}
+
+require_once INSTALLDIR.'/lib/mailbox.php';
+
+/**
+ * action handler for message outbox
+ *
+ * @category Message
+ * @package StatusNet
+ * @author Evan Prodromou <evan@status.net>
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://status.net/
+ * @see MailboxAction
+ */
+class OutboxAction extends MailboxAction
+{
+ /**
+ * Title of the page
+ *
+ * @return string page title
+ */
+ function title()
+ {
+ if ($this->page > 1) {
+ // TRANS: Title for outbox for any but the fist page.
+ // TRANS: %1$s is the user nickname, %2$d is the page number.
+ return sprintf(_('Outbox for %1$s - page %2$d'),
+ $this->user->nickname, $page);
+ } else {
+ // TRANS: Title for first page of outbox.
+ return sprintf(_('Outbox for %s'), $this->user->nickname);
+ }
+ }
+
+ /**
+ * retrieve the messages for this user and this page
+ *
+ * Does a query for the right messages
+ *
+ * @return Message data object with stream for messages
+ *
+ * @see MailboxAction::getMessages()
+ */
+ function getMessages()
+ {
+ $message = new Message();
+
+ $message->from_profile = $this->user->id;
+ $message->orderBy('created DESC, id DESC');
+ $message->limit((($this->page - 1) * MESSAGES_PER_PAGE),
+ MESSAGES_PER_PAGE + 1);
+
+ if ($message->find()) {
+ return $message;
+ } else {
+ return null;
+ }
+ }
+
+ function getMessageList($message)
+ {
+ return new OutboxMessageList($this, $message);
+ }
+
+ /**
+ * instructions for using this page
+ *
+ * @return string localised instructions for using the page
+ */
+ function getInstructions()
+ {
+ // TRANS: Instructions for outbox.
+ 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();
+ }
+}
--- /dev/null
+<?php
+/**
+ * StatusNet, the distributed open-source microblogging tool
+ *
+ * Show a single message
+ *
+ * PHP version 5
+ *
+ * LICENCE: 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 Personal
+ * @package StatusNet
+ * @author Evan Prodromou <evan@status.net>
+ * @copyright 2008-2009 StatusNet, Inc.
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://status.net/
+ */
+if (!defined('STATUSNET') && !defined('LACONICA')) {
+ exit(1);
+}
+
+/**
+ * Show a single message
+ *
+ * @category Personal
+ * @package StatusNet
+ * @author Evan Prodromou <evan@status.net>
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://status.net/
+ */
+
+class ShowmessageAction extends Action
+{
+ /**
+ * Message object to show
+ */
+ var $message = null;
+
+ /**
+ * The current user
+ */
+
+ var $user = null;
+
+ /**
+ * Load attributes based on database arguments
+ *
+ * Loads all the DB stuff
+ *
+ * @param array $args $_REQUEST array
+ *
+ * @return success flag
+ */
+ function prepare($args)
+ {
+ parent::prepare($args);
+
+ $this->page = 1;
+
+ $id = $this->trimmed('message');
+ $this->message = Message::getKV('id', $id);
+
+ if (!$this->message) {
+ // TRANS: Client error displayed requesting a single message that does not exist.
+ $this->clientError(_('No such message.'), 404);
+ }
+
+ $this->user = common_current_user();
+
+ if (empty($this->user) ||
+ ($this->user->id != $this->message->from_profile &&
+ $this->user->id != $this->message->to_profile)) {
+ // TRANS: Client error displayed requesting a single direct message the requesting user was not a party in.
+ throw new ClientException(_('Only the sender and recipient ' .
+ 'may read this message.'), 403);
+ }
+
+ return true;
+ }
+
+ function handle($args)
+ {
+ $this->showPage();
+ }
+
+ function title()
+ {
+ if ($this->user->id == $this->message->from_profile) {
+ $to = $this->message->getTo();
+ // @todo FIXME: Might be nice if the timestamp could be localised.
+ // TRANS: Page title for single direct message display when viewing user is the sender.
+ // TRANS: %1$s is the addressed user's nickname, $2$s is a timestamp.
+ return sprintf(_('Message to %1$s on %2$s'),
+ $to->nickname,
+ common_exact_date($this->message->created));
+ } else if ($this->user->id == $this->message->to_profile) {
+ $from = $this->message->getFrom();
+ // @todo FIXME: Might be nice if the timestamp could be localised.
+ // TRANS: Page title for single message display.
+ // TRANS: %1$s is the sending user's nickname, $2$s is a timestamp.
+ return sprintf(_('Message from %1$s on %2$s'),
+ $from->nickname,
+ common_exact_date($this->message->created));
+ }
+ }
+
+
+ function showContent()
+ {
+ $this->elementStart('ul', 'notices messages');
+ $ml = new ShowMessageListItem($this, $this->message, $this->user);
+ $ml->show();
+ $this->elementEnd('ul');
+ }
+
+ function isReadOnly($args)
+ {
+ return true;
+ }
+
+ /**
+ * Don't show aside
+ *
+ * @return void
+ */
+
+ function showAside() {
+ }
+}
+
+class ShowMessageListItem extends MessageListItem
+{
+ var $user;
+
+ function __construct($out, $message, $user)
+ {
+ parent::__construct($out, $message);
+ $this->user = $user;
+ }
+
+ function getMessageProfile()
+ {
+ if ($this->user->id == $this->message->from_profile) {
+ return $this->message->getTo();
+ } else if ($this->user->id == $this->message->to_profile) {
+ return $this->message->getFrom();
+ } else {
+ // This shouldn't happen
+ return null;
+ }
+ }
+}
--- /dev/null
+<?php
+/**
+ * Table Definition for message
+ */
+require_once INSTALLDIR.'/classes/Memcached_DataObject.php';
+
+class Message extends Managed_DataObject
+{
+ ###START_AUTOCODE
+ /* the code below is auto generated do not remove the above tag */
+
+ public $__table = 'message'; // table name
+ public $id; // int(4) primary_key not_null
+ public $uri; // varchar(255) unique_key
+ public $from_profile; // int(4) not_null
+ public $to_profile; // int(4) not_null
+ public $content; // text()
+ public $rendered; // text()
+ public $url; // varchar(255)
+ public $created; // datetime() not_null
+ public $modified; // timestamp() not_null default_CURRENT_TIMESTAMP
+ public $source; // varchar(32)
+
+ /* the code above is auto generated do not remove the tag below */
+ ###END_AUTOCODE
+
+ public static function schemaDef()
+ {
+ return array(
+ 'fields' => array(
+ 'id' => array('type' => 'serial', 'not null' => true, 'description' => 'unique identifier'),
+ 'uri' => array('type' => 'varchar', 'length' => 255, 'description' => 'universally unique identifier'),
+ 'from_profile' => array('type' => 'int', 'not null' => true, 'description' => 'who the message is from'),
+ 'to_profile' => array('type' => 'int', 'not null' => true, 'description' => 'who the message is to'),
+ 'content' => array('type' => 'text', 'description' => 'message content'),
+ 'rendered' => array('type' => 'text', 'description' => 'HTML version of the content'),
+ 'url' => array('type' => 'varchar', 'length' => 255, 'description' => 'URL of any attachment (image, video, bookmark, whatever)'),
+ 'created' => array('type' => 'datetime', 'not null' => true, 'description' => 'date this record was created'),
+ 'modified' => array('type' => 'timestamp', 'not null' => true, 'description' => 'date this record was modified'),
+ 'source' => array('type' => 'varchar', 'length' => 32, 'description' => 'source of comment, like "web", "im", or "clientname"'),
+ ),
+ 'primary key' => array('id'),
+ 'unique keys' => array(
+ 'message_uri_key' => array('uri'),
+ ),
+ 'foreign keys' => array(
+ 'message_from_profile_fkey' => array('profile', array('from_profile' => 'id')),
+ 'message_to_profile_fkey' => array('profile', array('to_profile' => 'id')),
+ ),
+ 'indexes' => array(
+ // @fixme these are really terrible indexes, since you can only sort on one of them at a time.
+ // looks like we really need a (to_profile, created) for inbox and a (from_profile, created) for outbox
+ 'message_from_idx' => array('from_profile'),
+ 'message_to_idx' => array('to_profile'),
+ 'message_created_idx' => array('created'),
+ ),
+ );
+ }
+
+ function getFrom()
+ {
+ return Profile::getKV('id', $this->from_profile);
+ }
+
+ function getTo()
+ {
+ return Profile::getKV('id', $this->to_profile);
+ }
+
+ static function saveNew($from, $to, $content, $source) {
+ $sender = Profile::getKV('id', $from);
+
+ if (!$sender->hasRight(Right::NEWMESSAGE)) {
+ // TRANS: Client exception thrown when a user tries to send a direct message while being banned from sending them.
+ throw new ClientException(_('You are banned from sending direct messages.'));
+ }
+
+ $user = User::getKV('id', $sender->id);
+
+ $msg = new Message();
+
+ $msg->from_profile = $from;
+ $msg->to_profile = $to;
+ if ($user) {
+ // Use the sender's URL shortening options.
+ $msg->content = $user->shortenLinks($content);
+ } else {
+ $msg->content = common_shorten_links($content);
+ }
+ $msg->rendered = common_render_text($msg->content);
+ $msg->created = common_sql_now();
+ $msg->source = $source;
+
+ $result = $msg->insert();
+
+ if (!$result) {
+ common_log_db_error($msg, 'INSERT', __FILE__);
+ // TRANS: Message given when a message could not be stored on the server.
+ throw new ServerException(_('Could not insert message.'));
+ }
+
+ $orig = clone($msg);
+ $msg->uri = common_local_url('showmessage', array('message' => $msg->id));
+
+ $result = $msg->update($orig);
+
+ if (!$result) {
+ common_log_db_error($msg, 'UPDATE', __FILE__);
+ // TRANS: Message given when a message could not be updated on the server.
+ throw new ServerException(_('Could not update message with new URI.'));
+ }
+
+ return $msg;
+ }
+
+ static function maxContent()
+ {
+ $desclimit = common_config('message', 'contentlimit');
+ // null => use global limit (distinct from 0!)
+ if (is_null($desclimit)) {
+ $desclimit = common_config('site', 'textlimit');
+ }
+ return $desclimit;
+ }
+
+ static function contentTooLong($content)
+ {
+ $contentlimit = self::maxContent();
+ return ($contentlimit > 0 && !empty($content) && (mb_strlen($content) > $contentlimit));
+ }
+
+ function notify()
+ {
+ $from = User::getKV('id', $this->from_profile);
+ $to = User::getKV('id', $this->to_profile);
+
+ mail_notify_message($this, $from, $to);
+ }
+
+ function getSource()
+ {
+ if (empty($this->source)) {
+ return false;
+ }
+
+ $ns = new Notice_source();
+ switch ($this->source) {
+ case 'web':
+ case 'xmpp':
+ case 'mail':
+ case 'omb':
+ case 'system':
+ case 'api':
+ $ns->code = $this->source;
+ break;
+ default:
+ $ns = Notice_source::getKV($this->source);
+ if (!$ns instanceof Notice_source) {
+ $ns = new Notice_source();
+ $ns->code = $this->source;
+ $app = Oauth_application::getKV('name', $this->source);
+ if ($app) {
+ $ns->name = $app->name;
+ $ns->url = $app->source_url;
+ }
+ }
+ break;
+ }
+ return $ns;
+ }
+
+ function asActivity()
+ {
+ $act = new Activity();
+
+ if (Event::handle('StartMessageAsActivity', array($this, &$act))) {
+
+ $act->id = TagURI::mint(sprintf('activity:message:%d', $this->id));
+ $act->time = strtotime($this->created);
+ $act->link = $this->url;
+
+ $profile = Profile::getKV('id', $this->from_profile);
+
+ if (empty($profile)) {
+ throw new Exception(sprintf("Sender profile not found: %d", $this->from_profile));
+ }
+
+ $act->actor = $profile->asActivityObject();
+ $act->actor->extra[] = $profile->profileInfo();
+
+ $act->verb = ActivityVerb::POST;
+
+ $act->objects[] = ActivityObject::fromMessage($this);
+
+ $ctx = new ActivityContext();
+
+ $rprofile = Profile::getKV('id', $this->to_profile);
+
+ if (empty($rprofile)) {
+ throw new Exception(sprintf("Receiver profile not found: %d", $this->to_profile));
+ }
+
+ $ctx->attention[$rprofile->getUri()] = ActivityObject::PERSON;
+
+ $act->context = $ctx;
+
+ $source = $this->getSource();
+
+ if ($source instanceof Notice_source) {
+ $act->generator = ActivityObject::fromNoticeSource($source);
+ }
+
+ Event::handle('EndMessageAsActivity', array($this, &$act));
+ }
+
+ return $act;
+ }
+}
--- /dev/null
+<?php
+/**
+ * StatusNet, the distributed open-source microblogging tool
+ *
+ * common superclass for direct messages inbox and outbox
+ *
+ * PHP version 5
+ *
+ * LICENCE: 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 Message
+ * @package StatusNet
+ * @author Evan Prodromou <evan@status.net>
+ * @copyright 2008 StatusNet, Inc.
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://status.net/
+ */
+
+if (!defined('STATUSNET') && !defined('LACONICA')) {
+ exit(1);
+}
+
+/**
+ * common superclass for direct messages inbox and outbox
+ *
+ * @category Message
+ * @package StatusNet
+ * @author Evan Prodromou <evan@status.net>
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://status.net/
+ * @see InboxAction
+ * @see OutboxAction
+ */
+class MailboxAction extends Action
+{
+ var $page = null;
+
+ function prepare($args)
+ {
+ parent::prepare($args);
+
+ $nickname = common_canonical_nickname($this->arg('nickname'));
+ $this->user = User::getKV('nickname', $nickname);
+ $this->page = $this->trimmed('page');
+
+ if (!$this->page) {
+ $this->page = 1;
+ }
+
+ common_set_returnto($this->selfUrl());
+
+ return true;
+ }
+
+ /**
+ * output page based on arguments
+ *
+ * @param array $args HTTP arguments (from $_REQUEST)
+ *
+ * @return void
+ */
+ function handle($args)
+ {
+ parent::handle($args);
+
+ if (!$this->user) {
+ // TRANS: Client error displayed when trying to access a mailbox without providing a user.
+ $this->clientError(_('No such user.'), 404);
+ }
+
+ $cur = common_current_user();
+
+ if (!$cur || $cur->id != $this->user->id) {
+ // TRANS: Client error displayed when trying to access a mailbox that is not of the logged in user.
+ $this->clientError(_('Only the user can read their own mailboxes.'), 403);
+ }
+
+ $this->showPage();
+ }
+
+ function showNoticeForm()
+ {
+ $message_form = new MessageForm($this);
+ $message_form->show();
+ }
+
+ function showContent()
+ {
+ $message = $this->getMessages();
+
+ if ($message) {
+
+ $ml = $this->getMessageList($message);
+
+ $cnt = $ml->show();
+
+ $this->pagination($this->page > 1,
+ $cnt > MESSAGES_PER_PAGE,
+ $this->page,
+ $this->trimmed('action'),
+ array('nickname' => $this->user->nickname));
+ } else {
+ $this->element('p',
+ 'guide',
+ // TRANS: Message displayed when there are no private messages in the inbox of a user.
+ _('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.'));
+ }
+ }
+
+ function getMessages()
+ {
+ return null;
+ }
+
+ function getMessageList($message)
+ {
+ return null;
+ }
+
+ /**
+ * Show the page notice
+ *
+ * Shows instructions for the page
+ *
+ * @return void
+ */
+ function showPageNotice()
+ {
+ $instr = $this->getInstructions();
+ $output = common_markup_to_html($instr);
+
+ $this->elementStart('div', 'instructions');
+ $this->raw($output);
+ $this->elementEnd('div');
+ }
+
+ /**
+ * Mailbox actions are read only
+ *
+ * @param array $args other arguments
+ *
+ * @return boolean
+ */
+ function isReadOnly($args)
+ {
+ return true;
+ }
+
+ function showObjectNav()
+ {
+ $mm = new MailboxMenu($this);
+ $mm->show();
+ }
+}
--- /dev/null
+<?php
+/**
+ * StatusNet - the distributed open-source microblogging tool
+ * Copyright (C) 2011, StatusNet, Inc.
+ *
+ * Private mailboxes menu
+ *
+ * PHP version 5
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @category Cache
+ * @package StatusNet
+ * @author Evan Prodromou <evan@status.net>
+ * @copyright 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);
+}
+
+/**
+ * Menu of existing mailboxes
+ *
+ * @category General
+ * @package StatusNet
+ * @author Evan Prodromou <evan@status.net>
+ * @copyright 2011 StatusNet, Inc.
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
+ * @link http://status.net/
+ */
+class MailboxMenu extends Menu
+{
+ function show()
+ {
+ $cur = common_current_user();
+ $nickname = $cur->nickname;
+
+ $this->out->elementStart('ul', array('class' => 'nav'));
+
+ $this->item('inbox',
+ array('nickname' => $nickname),
+ // TRANS: Menu item in mailbox menu. Leads to incoming private messages.
+ _m('MENU','Inbox'),
+ // TRANS: Menu item title in mailbox menu. Leads to incoming private messages.
+ _('Your incoming messages.'));
+
+ $this->item('outbox',
+ array('nickname' => $nickname),
+ // TRANS: Menu item in mailbox menu. Leads to outgoing private messages.
+ _m('MENU','Outbox'),
+ // TRANS: Menu item title in mailbox menu. Leads to outgoing private messages.
+ _('Your sent messages.'));
+
+ $this->out->elementEnd('ul');
+ }
+}
--- /dev/null
+<?php
+/**
+ * StatusNet, the distributed open-source microblogging tool
+ *
+ * Form for posting a direct message
+ *
+ * PHP version 5
+ *
+ * LICENCE: 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 Form
+ * @package StatusNet
+ * @author Evan Prodromou <evan@status.net>
+ * @author Sarven Capadisli <csarven@status.net>
+ * @copyright 2009 StatusNet, Inc.
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://status.net/
+ */
+
+if (!defined('STATUSNET') && !defined('LACONICA')) {
+ exit(1);
+}
+
+require_once INSTALLDIR.'/lib/form.php';
+
+/**
+ * Form for posting a direct message
+ *
+ * @category Form
+ * @package StatusNet
+ * @author Evan Prodromou <evan@status.net>
+ * @author Sarven Capadisli <csarven@status.net>
+ * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
+ * @link http://status.net/
+ *
+ * @see HTMLOutputter
+ */
+class MessageForm extends Form
+{
+ /**
+ * User to send a direct message to
+ */
+ var $to = null;
+
+ /**
+ * Pre-filled content of the form
+ */
+ var $content = null;
+
+ /**
+ * Constructor
+ *
+ * @param HTMLOutputter $out output channel
+ * @param User $to user to send a message to
+ * @param string $content content to pre-fill
+ */
+ function __construct($out=null, $to=null, $content=null)
+ {
+ parent::__construct($out);
+
+ $this->to = $to;
+ $this->content = $content;
+ }
+
+ /**
+ * ID of the form
+ *
+ * @return string ID of the form
+ */
+ function id()
+ {
+ return 'form_notice-direct';
+ }
+
+ /**
+ * Class of the form
+ *
+ * @return string class of the form
+ */
+ function formClass()
+ {
+ return 'form_notice ajax-notice';
+ }
+
+ /**
+ * Action of the form
+ *
+ * @return string URL of the action
+ */
+ function action()
+ {
+ return common_local_url('newmessage');
+ }
+
+ /**
+ * Legend of the Form
+ *
+ * @return void
+ */
+ function formLegend()
+ {
+ // TRANS: Form legend for direct notice.
+ $this->out->element('legend', null, _('Send a direct notice'));
+ }
+
+ /**
+ * Data elements
+ *
+ * @return void
+ */
+ function formData()
+ {
+ $user = common_current_user();
+
+ $mutual_users = $user->mutuallySubscribedUsers();
+
+ $mutual = array();
+ // TRANS: Label entry in drop-down selection box in direct-message inbox/outbox.
+ // TRANS: This is the default entry in the drop-down box, doubling as instructions
+ // TRANS: and a brake against accidental submissions with the first user in the list.
+ $mutual[0] = _('Select recipient:');
+
+ while ($mutual_users->fetch()) {
+ if ($mutual_users->id != $user->id) {
+ $mutual[$mutual_users->id] = $mutual_users->nickname;
+ }
+ }
+
+ $mutual_users->free();
+ unset($mutual_users);
+
+ if (count($mutual) == 1) {
+ // TRANS: Entry in drop-down selection box in direct-message inbox/outbox when no one is available to message.
+ $mutual[0] = _('No mutual subscribers.');
+ }
+
+ // TRANS: Dropdown label in direct notice form.
+ $this->out->dropdown('to', _('To'), $mutual, null, false,
+ ($this->to) ? $this->to->id : null);
+
+ $this->out->element('textarea', array('class' => 'notice_data-text',
+ 'cols' => 35,
+ 'rows' => 4,
+ 'name' => 'content'),
+ ($this->content) ? $this->content : '');
+
+ $contentLimit = Message::maxContent();
+
+ if ($contentLimit > 0) {
+ $this->out->element('span',
+ array('class' => 'count'),
+ $contentLimit);
+ }
+ }
+
+ /**
+ * Action elements
+ *
+ * @return void
+ */
+ function formActions()
+ {
+ $this->out->element('input', array('id' => 'notice_action-submit',
+ 'class' => 'submit',
+ 'name' => 'message_send',
+ 'type' => 'submit',
+ // TRANS: Button text for sending a direct notice.
+ 'value' => _m('Send button for sending notice', 'Send')));
+ }
+
+
+ /**
+ * Show the form
+ *
+ * Uses a recipe to output the form.
+ *
+ * @return void
+ * @see Widget::show()
+ */
+
+ function show()
+ {
+ $this->elementStart('div', 'input_forms');
+ $this->elementStart(
+ 'div',
+ array(
+ 'id' => 'input_form_direct',
+ 'class' => 'input_form current nonav'
+ )
+ );
+
+ parent::show();
+
+ $this->elementEnd('div');
+ $this->elementEnd('div');
+
+ }
+}
--- /dev/null
+<?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'));
+
+ // TRANS: Header in message list.
+ $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);
+}
--- /dev/null
+<?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' => 'h-entry notice',
+ 'id' => 'message-' . $this->message->id));
+
+ $profile = $this->getMessageProfile();
+
+ $this->out->elementStart('a', array('href' => $profile->profileurl,
+ 'class' => 'p-author'));
+ $avatarUrl = $profile->avatarUrl(AVATAR_STREAM_SIZE);
+ $this->out->element('img', array('src' => $avatarUrl,
+ 'class' => 'avatar u-photo',
+ 'width' => AVATAR_STREAM_SIZE,
+ 'height' => AVATAR_STREAM_SIZE,
+ 'alt' => $profile->getBestName()));
+ $this->out->element('span', array('class' => 'nickname fn'), $profile->getNickname());
+ $this->out->elementEnd('a');
+
+ // FIXME: URL, image, video, audio
+ $this->out->elementStart('div', array('class' => 'e-content'));
+ $this->out->raw($this->message->rendered);
+ $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-metadata');
+ $this->out->elementStart('a', array('rel' => 'bookmark',
+ 'class' => 'timestamp',
+ 'href' => $messageurl));
+ $dt = common_date_iso8601($this->message->created);
+ $this->out->element('time', array('class' => 'dt-published',
+ 'datetime' => common_date_iso8601($this->message->created),
+ // TRANS: Timestamp title (tooltip text) for NoticeListItem
+ 'title' => common_exact_date($this->message->created)),
+ 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).
+ // TRANS: Followed by notice source (usually the client used to send the notice).
+ $this->out->text(_('from'));
+ $this->showSource($this->message->source);
+ $this->out->elementEnd('span');
+ }
+ $this->out->elementEnd('div');
+
+ $this->out->elementEnd('li');
+ }
+
+ /**
+ * Dummy method. Serves no other purpose than to make strings available used
+ * in self::showSource() through xgettext.
+ *
+ * @return void
+ */
+ function messageListItemDummyMessages()
+ {
+ // A dummy array with messages. These will get extracted by xgettext and
+ // are used in self::showSource().
+ $dummy_messages = array(
+ // TRANS: A possible notice source (web interface).
+ _m('SOURCE','web'),
+ // TRANS: A possible notice source (XMPP).
+ _m('SOURCE','xmpp'),
+ // TRANS: A possible notice source (e-mail).
+ _m('SOURCE','mail'),
+ // TRANS: A possible notice source (OpenMicroBlogging).
+ _m('SOURCE','omb'),
+ // TRANS: A possible notice source (Application Programming Interface).
+ _m('SOURCE','api'),
+ );
+ }
+
+ /**
+ * Show the source of the message
+ *
+ * Returns either the name (and link) of the API client that posted the notice,
+ * or one of other other channels.
+ *
+ * @param string $source the source of the message
+ *
+ * @return void
+ */
+ function showSource($source)
+ {
+ $source_name = _m('SOURCE',$source);
+ switch ($source) {
+ case 'web':
+ case 'xmpp':
+ case 'mail':
+ case 'omb':
+ case 'api':
+ $this->out->element('span', 'device', $source_name);
+ break;
+ default:
+ $ns = Notice_source::getKV($source);
+ if ($ns) {
+ $this->out->elementStart('span', 'device');
+ $this->out->element('a', array('href' => $ns->url,
+ 'rel' => 'external'),
+ $ns->name);
+ $this->out->elementEnd('span');
+ } else {
+ $this->out->element('span', 'device', $source_name);
+ }
+ break;
+ }
+ return;
+ }
+
+ /**
+ * 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();
+}