summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--actions/repeat.php122
-rw-r--r--classes/Notice.php14
-rw-r--r--classes/Profile.php11
-rw-r--r--classes/statusnet.ini2
-rw-r--r--db/08to09.sql4
-rw-r--r--db/08to09_pg.sql1
-rw-r--r--db/statusnet.sql2
-rw-r--r--db/statusnet_pg.sql4
-rw-r--r--js/util.js5
-rw-r--r--lib/noticelist.php21
-rw-r--r--lib/repeatform.php145
-rw-r--r--theme/base/css/display.css4
12 files changed, 327 insertions, 8 deletions
diff --git a/actions/repeat.php b/actions/repeat.php
new file mode 100644
index 000000000..194833fe0
--- /dev/null
+++ b/actions/repeat.php
@@ -0,0 +1,122 @@
+<?php
+
+/**
+ * Forward action.
+ *
+ * PHP version 5
+ *
+ * @category Action
+ * @package StatusNet
+ * @author Evan Prodromou <evan@status.net>
+ * @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
+ * @link http://status.net/
+ *
+ * StatusNet - the distributed open-source microblogging tool
+ * Copyright (C) 2008, 2009, StatusNet, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+if (!defined('STATUSNET')) {
+ exit(1);
+}
+
+/**
+ * Forward action
+ *
+ * @category Action
+ * @package StatusNet
+ * @author Evan Prodromou <evan@status.net>
+ * @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3
+ * @link http://status.net/
+ */
+
+class ForwardAction extends Action
+{
+ var $user = null;
+ var $notice = null;
+
+ function prepare($args)
+ {
+ parent::prepare($args);
+
+ $this->user = common_current_user();
+
+ if (empty($this->user)) {
+ $this->clientError(_("Only logged-in users can forward notices."));
+ return false;
+ }
+
+ $id = $this->trimmed('notice');
+
+ if (empty($id)) {
+ $this->clientError(_("No notice specified."));
+ return false;
+ }
+
+ $this->notice = Notice::staticGet('id', $id);
+
+ if (empty($this->notice)) {
+ $this->clientError(_("No notice specified."));
+ return false;
+ }
+
+ if ($this->user->id == $this->notice->profile_id) {
+ $this->clientError(_("You can't forward your own notice."));
+ return false;
+ }
+
+ $token = $this->trimmed('token-'.$id);
+
+ if (empty($token) || $token != common_session_token()) {
+ $this->clientError(_("There was a problem with your session token. Try again, please."));
+ return false;
+ }
+
+ $profile = $this->user->getProfile();
+
+ if ($profile->hasForwarded($id)) {
+ $this->clientError(_("You already forwarded that notice."));
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Class handler.
+ *
+ * @param array $args query arguments
+ *
+ * @return void
+ */
+
+ function handle($args)
+ {
+ $forward = Forward::saveNew($this->user->id, $this->notice->id);
+
+ if ($this->boolean('ajax')) {
+ $this->startHTML('text/xml;charset=utf-8');
+ $this->elementStart('head');
+ $this->element('title', null, _('Forwarded'));
+ $this->elementEnd('head');
+ $this->elementStart('body');
+ $this->element('p', array('id' => 'forward_response'), _('Forwarded!'));
+ $this->elementEnd('body');
+ $this->elementEnd('html');
+ } else {
+ // FIXME!
+ }
+ }
+}
diff --git a/classes/Notice.php b/classes/Notice.php
index 4422866fa..228201188 100644
--- a/classes/Notice.php
+++ b/classes/Notice.php
@@ -55,13 +55,13 @@ class Notice extends Memcached_DataObject
public $__table = 'notice'; // table name
public $id; // int(4) primary_key not_null
- public $profile_id; // int(4) not_null
+ public $profile_id; // int(4) multiple_key not_null
public $uri; // varchar(255) unique_key
- public $content; // text()
- public $rendered; // text()
+ public $content; // text
+ public $rendered; // text
public $url; // varchar(255)
- public $created; // datetime() not_null
- public $modified; // timestamp() not_null default_CURRENT_TIMESTAMP
+ public $created; // datetime multiple_key not_null default_0000-00-00%2000%3A00%3A00
+ public $modified; // timestamp not_null default_CURRENT_TIMESTAMP
public $reply_to; // int(4)
public $is_local; // tinyint(1)
public $source; // varchar(32)
@@ -70,9 +70,11 @@ class Notice extends Memcached_DataObject
public $lon; // decimal(10,7)
public $location_id; // int(4)
public $location_ns; // int(4)
+ public $repeat_of; // int(4)
/* Static get */
- function staticGet($k,$v=NULL) {
+ function staticGet($k,$v=NULL)
+ {
return Memcached_DataObject::staticGet('Notice',$k,$v);
}
diff --git a/classes/Profile.php b/classes/Profile.php
index 4b2e09006..03196447b 100644
--- a/classes/Profile.php
+++ b/classes/Profile.php
@@ -716,4 +716,15 @@ class Profile extends Memcached_DataObject
}
return $result;
}
+
+ function hasRepeated($notice_id)
+ {
+ // XXX: not really a pkey, but should work
+
+ $notice = Memcached_DataObject::pkeyGet('Notice',
+ array('profile_id' => $this->id,
+ 'repeat_of' => $notice_id));
+
+ return !empty($notice);
+ }
}
diff --git a/classes/statusnet.ini b/classes/statusnet.ini
index 835faeb0b..ff4ef2c14 100644
--- a/classes/statusnet.ini
+++ b/classes/statusnet.ini
@@ -1,3 +1,4 @@
+
[avatar]
profile_id = 129
original = 17
@@ -306,6 +307,7 @@ lat = 1
lon = 1
location_id = 1
location_ns = 1
+repeat_of = 1
[notice__keys]
id = N
diff --git a/db/08to09.sql b/db/08to09.sql
index 64640f4ce..28ec3ec16 100644
--- a/db/08to09.sql
+++ b/db/08to09.sql
@@ -4,8 +4,10 @@ alter table notice
add column lon decimal(10,7) comment 'longitude',
add column location_id integer comment 'location id if possible',
add column location_ns integer comment 'namespace for location',
+ add column repeat_of integer comment 'notice this is a repeat of' references notice (id),
drop index notice_profile_id_idx,
- add index notice_profile_id_idx (profile_id,created,id);
+ add index notice_profile_id_idx (profile_id,created,id),
+ add index notice_repeatof_idx (repeat_of);
alter table message
modify column content text comment 'message content';
diff --git a/db/08to09_pg.sql b/db/08to09_pg.sql
index 1df8c249b..0398952f6 100644
--- a/db/08to09_pg.sql
+++ b/db/08to09_pg.sql
@@ -74,6 +74,7 @@ ALTER TABLE notice ADD COLUMN lat decimal(10, 7) /* comment 'latitude'*/;
ALTER TABLE notice ADD COLUMN lon decimal(10,7) /* comment 'longitude'*/;
ALTER TABLE notice ADD COLUMN location_id integer /* comment 'location id if possible'*/ ;
ALTER TABLE notice ADD COLUMN location_ns integer /* comment 'namespace for location'*/;
+ALTER TABLE notice ADD COLUMN repeat_of integer / * comment 'notice this is a repeat of' */ references notice (id);
ALTER TABLE profile ADD COLUMN lat decimal(10,7) /*comment 'latitude'*/ ;
ALTER TABLE profile ADD COLUMN lon decimal(10,7) /*comment 'longitude'*/;
diff --git a/db/statusnet.sql b/db/statusnet.sql
index 18abcdfdb..6b3c2ca06 100644
--- a/db/statusnet.sql
+++ b/db/statusnet.sql
@@ -129,11 +129,13 @@ create table notice (
lon decimal(10,7) comment 'longitude',
location_id integer comment 'location id if possible',
location_ns integer comment 'namespace for location',
+ repeat_of integer comment 'notice this is a repeat of' references notice (id),
index notice_profile_id_idx (profile_id,created,id),
index notice_conversation_idx (conversation),
index notice_created_idx (created),
index notice_replyto_idx (reply_to),
+ index notice_repeatof_idx (repeat_of),
FULLTEXT(content)
) ENGINE=MyISAM CHARACTER SET utf8 COLLATE utf8_general_ci;
diff --git a/db/statusnet_pg.sql b/db/statusnet_pg.sql
index c37fa81de..020bfd967 100644
--- a/db/statusnet_pg.sql
+++ b/db/statusnet_pg.sql
@@ -135,7 +135,9 @@ create table notice (
lat decimal(10,7) /* comment 'latitude'*/ ,
lon decimal(10,7) /* comment 'longitude'*/ ,
location_id integer /* comment 'location id if possible'*/ ,
- location_ns integer /* comment 'namespace for location'*/
+ location_ns integer /* comment 'namespace for location'*/ ,
+ repeat_of integer /* comment 'notice this is a repeat of' */ references notice (id) ,
+
/* FULLTEXT(content) */
);
diff --git a/js/util.js b/js/util.js
index 336cd8cfe..f60b5d313 100644
--- a/js/util.js
+++ b/js/util.js
@@ -315,6 +315,10 @@ var SN = { // StatusNet
$('.form_disfavor').each(function() { SN.U.FormXHR($(this)); });
},
+ NoticeRepeat: function() {
+ $('.form_repeat').each(function() { SN.U.FormXHR($(this)); });
+ },
+
NoticeAttachments: function() {
$('.notice a.attachment').each(function() {
SN.U.NoticeWithAttachment($(this).closest('.notice'));
@@ -448,6 +452,7 @@ var SN = { // StatusNet
Notices: function() {
if ($('body.user_in').length > 0) {
SN.U.NoticeFavor();
+ SN.U.NoticeRepeat();
SN.U.NoticeReply();
}
diff --git a/lib/noticelist.php b/lib/noticelist.php
index 21cec528f..924056ece 100644
--- a/lib/noticelist.php
+++ b/lib/noticelist.php
@@ -212,6 +212,7 @@ class NoticeListItem extends Widget
$this->out->elementStart('div', 'notice-options');
$this->showFaveForm();
$this->showReplyLink();
+ $this->showRepeatForm();
$this->showDeleteLink();
$this->out->elementEnd('div');
}
@@ -552,6 +553,26 @@ class NoticeListItem extends Widget
}
/**
+ * show the form to repeat a notice
+ *
+ * @return void
+ */
+
+ function showRepeatForm()
+ {
+ $user = common_current_user();
+ if ($user && $user->id != $this->notice->profile_id) {
+ $profile = $user->getProfile();
+ if ($profile->hasRepeated($this->notice->id)) {
+ $this->out->text(_('Repeated'));
+ } else {
+ $rf = new RepeatForm($this->out, $this->notice);
+ $rf->show();
+ }
+ }
+ }
+
+ /**
* finish the notice
*
* Close the last elements in the notice list item
diff --git a/lib/repeatform.php b/lib/repeatform.php
new file mode 100644
index 000000000..50e5d6dbe
--- /dev/null
+++ b/lib/repeatform.php
@@ -0,0 +1,145 @@
+<?php
+/**
+ * StatusNet, the distributed open-source microblogging tool
+ *
+ * Form for repeating a notice
+ *
+ * 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>
+ * @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);
+}
+
+/**
+ * Form for repeating a notice
+ *
+ * @category Form
+ * @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 RepeatForm extends Form
+{
+ /**
+ * Notice to repeat
+ */
+
+ var $notice = null;
+
+ /**
+ * Constructor
+ *
+ * @param HTMLOutputter $out output channel
+ * @param Notice $notice notice to repeat
+ */
+
+ function __construct($out=null, $notice=null)
+ {
+ parent::__construct($out);
+
+ $this->notice = $notice;
+ }
+
+ /**
+ * ID of the form
+ *
+ * @return int ID of the form
+ */
+
+ function id()
+ {
+ return 'repeat-' . $this->notice->id;
+ }
+
+ /**
+ * Action of the form
+ *
+ * @return string URL of the action
+ */
+
+ function action()
+ {
+ return common_local_url('repeat');
+ }
+
+ /**
+ * Include a session token for CSRF protection
+ *
+ * @return void
+ */
+
+ function sessionToken()
+ {
+ $this->out->hidden('token-' . $this->notice->id,
+ common_session_token());
+ }
+
+ /**
+ * Legend of the Form
+ *
+ * @return void
+ */
+ function formLegend()
+ {
+ $this->out->element('legend', null, _('Repeat this notice'));
+ }
+
+ /**
+ * Data elements
+ *
+ * @return void
+ */
+
+ function formData()
+ {
+ $this->out->hidden('notice-n'.$this->notice->id,
+ $this->notice->id,
+ 'notice');
+ }
+
+ /**
+ * Action elements
+ *
+ * @return void
+ */
+
+ function formActions()
+ {
+ $this->out->submit('repeat-submit-' . $this->notice->id,
+ _('Repeat'), 'submit', null, _('Repeat this notice'));
+ }
+
+ /**
+ * Class of the form.
+ *
+ * @return string the form's class
+ */
+
+ function formClass()
+ {
+ return 'form_repeat';
+ }
+}
diff --git a/theme/base/css/display.css b/theme/base/css/display.css
index e88e1f222..7446a42cd 100644
--- a/theme/base/css/display.css
+++ b/theme/base/css/display.css
@@ -994,11 +994,13 @@ float:left;
}
.notice-options .notice_delete,
.notice-options .notice_reply,
+.notice-options .form_repeat,
.notice-options .form_favor,
.notice-options .form_disfavor {
float:left;
margin-left:20%;
}
+.notice-options .form_repeat,
.notice-options .form_favor,
.notice-options .form_disfavor {
margin-left:0;
@@ -1024,10 +1026,12 @@ border-radius:0;
-moz-border-radius:0;
-webkit-border-radius:0;
}
+.notice-options .form_repeat legend,
.notice-options .form_favor legend,
.notice-options .form_disfavor legend {
display:none;
}
+.notice-options .form_repeat fieldset,
.notice-options .form_favor fieldset,
.notice-options .form_disfavor fieldset {
border:0;