]> git.mxchange.org Git - quix0rs-gnu-social.git/commitdiff
DirectMessage moved into a plugin, not done yet
authorMikael Nordfeldth <mmn@hethane.se>
Fri, 7 Nov 2014 14:47:10 +0000 (15:47 +0100)
committerMikael Nordfeldth <mmn@hethane.se>
Fri, 7 Nov 2014 14:53:35 +0000 (15:53 +0100)
We still have to move some API calls into the new plugin.

30 files changed:
actions/apidirectmessage.php [deleted file]
actions/apidirectmessagenew.php [deleted file]
actions/inbox.php [deleted file]
actions/newmessage.php [deleted file]
actions/outbox.php [deleted file]
actions/showmessage.php [deleted file]
classes/Message.php [deleted file]
classes/Profile.php
db/core.php
lib/accountprofileblock.php
lib/mailbox.php [deleted file]
lib/mailboxmenu.php [deleted file]
lib/messageform.php [deleted file]
lib/messagelist.php [deleted file]
lib/messagelistitem.php [deleted file]
lib/personalgroupnav.php
lib/router.php
plugins/DirectMessage/DirectMessagePlugin.php [new file with mode: 0644]
plugins/DirectMessage/actions/apidirectmessage.php [new file with mode: 0644]
plugins/DirectMessage/actions/apidirectmessagenew.php [new file with mode: 0644]
plugins/DirectMessage/actions/inbox.php [new file with mode: 0644]
plugins/DirectMessage/actions/newmessage.php [new file with mode: 0644]
plugins/DirectMessage/actions/outbox.php [new file with mode: 0644]
plugins/DirectMessage/actions/showmessage.php [new file with mode: 0644]
plugins/DirectMessage/classes/Message.php [new file with mode: 0644]
plugins/DirectMessage/lib/mailbox.php [new file with mode: 0644]
plugins/DirectMessage/lib/mailboxmenu.php [new file with mode: 0644]
plugins/DirectMessage/lib/messageform.php [new file with mode: 0644]
plugins/DirectMessage/lib/messagelist.php [new file with mode: 0644]
plugins/DirectMessage/lib/messagelistitem.php [new file with mode: 0644]

diff --git a/actions/apidirectmessage.php b/actions/apidirectmessage.php
deleted file mode 100644 (file)
index e971a7d..0000000
+++ /dev/null
@@ -1,361 +0,0 @@
-<?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;
-    }
-}
diff --git a/actions/apidirectmessagenew.php b/actions/apidirectmessagenew.php
deleted file mode 100644 (file)
index 653fa3a..0000000
+++ /dev/null
@@ -1,140 +0,0 @@
-<?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);
-        }
-    }
-}
diff --git a/actions/inbox.php b/actions/inbox.php
deleted file mode 100644 (file)
index e9aa343..0000000
+++ /dev/null
@@ -1,129 +0,0 @@
-<?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();
-    }
-}
diff --git a/actions/newmessage.php b/actions/newmessage.php
deleted file mode 100644 (file)
index 428a557..0000000
+++ /dev/null
@@ -1,228 +0,0 @@
-<?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();
-    }
-}
diff --git a/actions/outbox.php b/actions/outbox.php
deleted file mode 100644 (file)
index 6d10c81..0000000
+++ /dev/null
@@ -1,126 +0,0 @@
-<?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();
-    }
-}
diff --git a/actions/showmessage.php b/actions/showmessage.php
deleted file mode 100644 (file)
index 86fbee8..0000000
+++ /dev/null
@@ -1,163 +0,0 @@
-<?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;
-        }
-    }
-}
diff --git a/classes/Message.php b/classes/Message.php
deleted file mode 100644 (file)
index 9c79862..0000000
+++ /dev/null
@@ -1,218 +0,0 @@
-<?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;
-    }
-}
index a03f53cc7d69cbdce92d38deff48caa8789cb932..00a457a5c9c2062aa9163373fddb4bc170fe65e3 100644 (file)
@@ -861,7 +861,6 @@ class Profile extends Managed_DataObject
     {
         $this->_deleteNotices();
         $this->_deleteSubscriptions();
-        $this->_deleteMessages();
         $this->_deleteTags();
         $this->_deleteBlocks();
         $this->_deleteAttentions();
@@ -937,17 +936,6 @@ class Profile extends Managed_DataObject
         $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();
index c0aed1d3db835dd4c643deef9fb0134d8d21ab80..ec3fe7f736c55830358762cfb3edb753c799e8db 100644 (file)
@@ -55,7 +55,6 @@ $classes = array('Schema_version',
                  'Foreign_link',
                  'Foreign_subscription',
                  'Invitation',
-                 'Message',
                  'Profile_prefs',
                  'Profile_tag',
                  'Profile_list',
index 76e2edb7cec4cde00fd0956e28ac068c26f63266..fe11a0fc1571c3658fa38253c4073a18aa543127 100644 (file)
@@ -171,17 +171,6 @@ class AccountProfileBlock extends ProfileBlock
                         $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) {
diff --git a/lib/mailbox.php b/lib/mailbox.php
deleted file mode 100644 (file)
index 3c7281e..0000000
+++ /dev/null
@@ -1,167 +0,0 @@
-<?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();
-    }
-}
diff --git a/lib/mailboxmenu.php b/lib/mailboxmenu.php
deleted file mode 100644 (file)
index 49e7dce..0000000
+++ /dev/null
@@ -1,72 +0,0 @@
-<?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');
-    }
-}
diff --git a/lib/messageform.php b/lib/messageform.php
deleted file mode 100644 (file)
index acd30e3..0000000
+++ /dev/null
@@ -1,209 +0,0 @@
-<?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');
-
-    }
-}
diff --git a/lib/messagelist.php b/lib/messagelist.php
deleted file mode 100644 (file)
index 0185977..0000000
+++ /dev/null
@@ -1,107 +0,0 @@
-<?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);
-}
diff --git a/lib/messagelistitem.php b/lib/messagelistitem.php
deleted file mode 100644 (file)
index c9f4c60..0000000
+++ /dev/null
@@ -1,194 +0,0 @@
-<?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();
-}
index 8c413c6ab951e9c2943aa1796f17f687707c79ee..06bd2474bb928292dd043496bc4ae436adc448f4 100644 (file)
@@ -96,19 +96,6 @@ class PersonalGroupNav extends Menu
                                  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');
index 54683e986e67977aff5a3e72fed935df4e122571..8260cb3e2e8cffa99b0290f3d346548f40a23c6a 100644 (file)
@@ -249,12 +249,6 @@ class Router
                         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]+'));
@@ -507,21 +501,6 @@ class Router
                               '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',
diff --git a/plugins/DirectMessage/DirectMessagePlugin.php b/plugins/DirectMessage/DirectMessagePlugin.php
new file mode 100644 (file)
index 0000000..1e71783
--- /dev/null
@@ -0,0 +1,116 @@
+<?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;
+    }
+}
diff --git a/plugins/DirectMessage/actions/apidirectmessage.php b/plugins/DirectMessage/actions/apidirectmessage.php
new file mode 100644 (file)
index 0000000..e971a7d
--- /dev/null
@@ -0,0 +1,361 @@
+<?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;
+    }
+}
diff --git a/plugins/DirectMessage/actions/apidirectmessagenew.php b/plugins/DirectMessage/actions/apidirectmessagenew.php
new file mode 100644 (file)
index 0000000..653fa3a
--- /dev/null
@@ -0,0 +1,140 @@
+<?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);
+        }
+    }
+}
diff --git a/plugins/DirectMessage/actions/inbox.php b/plugins/DirectMessage/actions/inbox.php
new file mode 100644 (file)
index 0000000..e9aa343
--- /dev/null
@@ -0,0 +1,129 @@
+<?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();
+    }
+}
diff --git a/plugins/DirectMessage/actions/newmessage.php b/plugins/DirectMessage/actions/newmessage.php
new file mode 100644 (file)
index 0000000..428a557
--- /dev/null
@@ -0,0 +1,228 @@
+<?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();
+    }
+}
diff --git a/plugins/DirectMessage/actions/outbox.php b/plugins/DirectMessage/actions/outbox.php
new file mode 100644 (file)
index 0000000..6d10c81
--- /dev/null
@@ -0,0 +1,126 @@
+<?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();
+    }
+}
diff --git a/plugins/DirectMessage/actions/showmessage.php b/plugins/DirectMessage/actions/showmessage.php
new file mode 100644 (file)
index 0000000..86fbee8
--- /dev/null
@@ -0,0 +1,163 @@
+<?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;
+        }
+    }
+}
diff --git a/plugins/DirectMessage/classes/Message.php b/plugins/DirectMessage/classes/Message.php
new file mode 100644 (file)
index 0000000..9c79862
--- /dev/null
@@ -0,0 +1,218 @@
+<?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;
+    }
+}
diff --git a/plugins/DirectMessage/lib/mailbox.php b/plugins/DirectMessage/lib/mailbox.php
new file mode 100644 (file)
index 0000000..3c7281e
--- /dev/null
@@ -0,0 +1,167 @@
+<?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();
+    }
+}
diff --git a/plugins/DirectMessage/lib/mailboxmenu.php b/plugins/DirectMessage/lib/mailboxmenu.php
new file mode 100644 (file)
index 0000000..49e7dce
--- /dev/null
@@ -0,0 +1,72 @@
+<?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');
+    }
+}
diff --git a/plugins/DirectMessage/lib/messageform.php b/plugins/DirectMessage/lib/messageform.php
new file mode 100644 (file)
index 0000000..acd30e3
--- /dev/null
@@ -0,0 +1,209 @@
+<?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');
+
+    }
+}
diff --git a/plugins/DirectMessage/lib/messagelist.php b/plugins/DirectMessage/lib/messagelist.php
new file mode 100644 (file)
index 0000000..0185977
--- /dev/null
@@ -0,0 +1,107 @@
+<?php
+/**
+ * StatusNet - the distributed open-source microblogging tool
+ * Copyright (C) 2011, StatusNet, Inc.
+ *
+ * The message list widget
+ *
+ * PHP version 5
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @category  Widget
+ * @package   StatusNet
+ * @author    Evan Prodromou <evan@status.net>
+ * @copyright 2011 StatusNet, Inc.
+ * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
+ * @link      http://status.net/
+ */
+
+if (!defined('STATUSNET')) {
+    // This check helps protect against security problems;
+    // your code file can't be executed directly from the web.
+    exit(1);
+}
+
+/**
+ * Message list widget
+ *
+ * @category  Widget
+ * @package   StatusNet
+ * @author    Evan Prodromou <evan@status.net>
+ * @copyright 2011 StatusNet, Inc.
+ * @license   http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0
+ * @link      http://status.net/
+ */
+abstract class MessageList extends Widget
+{
+    var $message;
+
+    /**
+     * Constructor
+     *
+     * @param HTMLOutputter $out     Output context
+     * @param Message       $message Stream of messages to show
+     */
+    function __construct($out, $message)
+    {
+        parent::__construct($out);
+        $this->message = $message;
+    }
+
+    /**
+     * Show the widget
+     *
+     * Uses newItem() to create each new item.
+     *
+     * @return integer count of messages seen.
+     */
+    function show()
+    {
+            $cnt = 0;
+
+            $this->out->elementStart('div', array('id' =>'notices_primary'));
+
+            // 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);
+}
diff --git a/plugins/DirectMessage/lib/messagelistitem.php b/plugins/DirectMessage/lib/messagelistitem.php
new file mode 100644 (file)
index 0000000..c9f4c60
--- /dev/null
@@ -0,0 +1,194 @@
+<?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();
+}