From a8a36677748b304faf20742598b90f3d9634f393 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Mon, 8 Sep 2008 14:16:24 -0400 Subject: [PATCH] initial non-Ajax version of favorites darcs-hash:20080908181624-84dde-8200e1d91eb5f560ef0f296c9e1c56f93ef1b0c5.gz --- actions/disfavor.php | 74 ++++++++++++++++++++++++++ actions/favor.php | 100 +++++++++++++++++++++++++++++++++++ actions/showfavorites.php | 106 ++++++++++++++++++++++++++++++++++++++ classes/Fave.php | 11 ++++ classes/User.php | 15 ++++++ classes/stoica.ini | 1 + db/laconica.sql | 5 +- htaccess.sample | 4 ++ lib/stream.php | 14 ++++- lib/util.php | 36 ++++++++++++- 10 files changed, 362 insertions(+), 4 deletions(-) create mode 100644 actions/disfavor.php create mode 100644 actions/favor.php create mode 100644 actions/showfavorites.php diff --git a/actions/disfavor.php b/actions/disfavor.php new file mode 100644 index 0000000000..59807f5e6b --- /dev/null +++ b/actions/disfavor.php @@ -0,0 +1,74 @@ +. + */ + +if (!defined('LACONICA')) { exit(1); } + +require_once($INSTALLDIR.'/lib/mail.php'); + +class DisfavorAction extends Action { + + function handle($args) { + + parent::handle($args); + + if (!common_logged_in()) { + common_user_error(_('Not logged in.')); + return; + } + + $user = common_current_user(); + + if ($_SERVER['REQUEST_METHOD'] != 'POST') { + common_redirect(common_local_url('favorites', array('nickname' => $user->nickname))); + return; + } + + $token = $this->trimmed('token'); + + if (!$token || $token != common_session_token()) { + $this->client_error(_('There was a problem with your session token. Try again, please.')); + return; + } + + $id = $this->trimmed('notice'); + + $notice = Notice::staticGet($id); + + $fave = new Fave(); + $fave->user_id = $this->id; + $fave->notice_id = $notice->id; + if (!$fave->find(true)) { + $this->client_error(_('This notice is not a favorite!')); + return; + } + + $result = $fave->delete(); + + if (!$result) { + common_log_db_error($fave, 'DELETE', __FILE__); + $this->server_error(_('Could not delete favorite.')); + return; + } + + # XXX: ajax response + + common_redirect(common_local_url('favorites', + array('nickname' => $user->nickname))); + } +} \ No newline at end of file diff --git a/actions/favor.php b/actions/favor.php new file mode 100644 index 0000000000..f192321f90 --- /dev/null +++ b/actions/favor.php @@ -0,0 +1,100 @@ +. + */ + +if (!defined('LACONICA')) { exit(1); } + +require_once($INSTALLDIR.'/lib/mail.php'); + +class FavorAction extends Action { + + function handle($args) { + parent::handle($args); + + if (!common_logged_in()) { + common_user_error(_('Not logged in.')); + return; + } + + $user = common_current_user(); + + if ($_SERVER['REQUEST_METHOD'] != 'POST') { + common_redirect(common_local_url('showfavorites', array('nickname' => $user->nickname))); + return; + } + + # CSRF protection + + $token = $this->trimmed('token'); + if (!$token || $token != common_session_token()) { + $this->client_error(_('There was a problem with your session token. Try again, please.')); + return; + } + $id = $this->trimmed('notice'); + + $notice = Notice::staticGet($id); + + if ($user->hasFave($notice)) { + $this->client_error(_('This notice is already a favorite!')); + return; + } + + $fave = Fave::addNew($user, $notice); + + if (!$fave) { + $this->server_error(_('Could not create favorite.')); + return; + } + + $this->notify($fave, $notice, $user); + + common_redirect(common_local_url('showfavorites', + array('nickname' => $user->nickname))); + } + + function notify($fave, $notice, $user) { + $other = User::staticGet('id', $notice->profile_id); + if ($other) { + if ($other->email && $other->emailnotifyfav) { + $this->notify_mail($other, $user, $notice); + } + # XXX: notify by IM + # XXX: notify by SMS + } + } + + function notify_mail($other, $user, $notice) { + $profile = $user->getProfile(); + $bestname = $profile->getBestName(); + $subject = sprintf(_('%s added your notice as a favorite'), $bestname); + $body = sprintf(_('%1$s just added your notice from %2$s as one of their favorites.\n\n' . + 'In case you forgot, you can see the text of your notice here:\n\n' . + '%3$s\n\n' . + 'You can see the list of %1$s\'s favorites here:\n\n' . + '%4$s\n\n' . + 'Faithfully yours,\n' . + '%5$s\n'), + $bestname, + common_exact_date($notice->created), + common_local_url('shownotice', array('notice' => $notice->id)), + common_local_url('showfavorites', array('nickname' => $user->nickname)), + common_config('site', 'name')); + + mail_to_user($other, $subject, $body); + } +} \ No newline at end of file diff --git a/actions/showfavorites.php b/actions/showfavorites.php new file mode 100644 index 0000000000..f7061dc08e --- /dev/null +++ b/actions/showfavorites.php @@ -0,0 +1,106 @@ +. + */ + +if (!defined('LACONICA')) { exit(1); } + +require_once(INSTALLDIR.'/actions/showstream.php'); + +class ShowfavoritesAction extends StreamAction { + + function handle($args) { + + parent::handle($args); + + $nickname = common_canonical_nickname($this->arg('nickname')); + $user = User::staticGet('nickname', $nickname); + + if (!$user) { + $this->client_error(_('No such user.')); + return; + } + + $profile = $user->getProfile(); + + if (!$profile) { + common_server_error(_('User has no profile.')); + return; + } + + # Looks like we're good; show the header + + common_show_header(sprintf(_("%s favorite notices"), $profile->nickname), + array($this, 'show_header'), $user, + array($this, 'show_top')); + + $this->show_notices($user); + + common_show_footer(); + } + + function show_header($user) { + common_element('link', array('rel' => 'alternate', + 'href' => common_local_url('favoritesrss', array('nickname' => + $user->nickname)), + 'type' => 'application/rss+xml', + 'title' => sprintf(_('Feed for favorites of %s'), $user->nickname))); + } + + function show_top($user) { + $cur = common_current_user(); + + if ($cur && $cur->id == $user->id) { + common_notice_form('all'); + } + + $this->views_menu(); + } + + function show_notices($user) { + + $page = $this->trimmed('page'); + if (!$page) { + $page = 1; + } + + $notice = $user->favoriteNotices(($page-1)*NOTICES_PER_PAGE, NOTICES_PER_PAGE + 1); + + if (!$notice) { + $this->server_error(_('Could not retrieve favorite notices.')); + return; + } + + common_element_start('ul', array('id' => 'notices')); + + $cnt = 0; + + while ($notice->fetch() && $cnt <= NOTICES_PER_PAGE) { + $cnt++; + + if ($cnt > NOTICES_PER_PAGE) { + break; + } + + $this->show_notice($notice); + } + common_element_end('ul'); + + common_pagination($page > 1, $cnt > NOTICES_PER_PAGE, + $page, 'showfavorites', array('nickname' => $user->nickname)); + } +} diff --git a/classes/Fave.php b/classes/Fave.php index bbd72ca0b0..572dc232ea 100644 --- a/classes/Fave.php +++ b/classes/Fave.php @@ -19,4 +19,15 @@ class Fave extends DB_DataObject /* the code above is auto generated do not remove the tag below */ ###END_AUTOCODE + + static function addNew($user, $notice) { + $fave = new Fave(); + $fave->user_id = $user->id; + $fave->notice_id = $notice->id; + if (!$fave->insert()) { + common_log_db_error($fave, 'INSERT', __FILE__); + return false; + } + return $fave; + } } diff --git a/classes/User.php b/classes/User.php index 99ae40baf8..62f077739a 100644 --- a/classes/User.php +++ b/classes/User.php @@ -43,6 +43,7 @@ class User extends DB_DataObject public $email; // varchar(255) unique_key public $incomingemail; // varchar(255) unique_key public $emailnotifysub; // tinyint(1) default_1 + public $emailnotifyfav; // tinyint(1) default_1 public $emailmicroid; // tinyint(1) default_1 public $language; // varchar(50) public $timezone; // varchar(50) @@ -275,4 +276,18 @@ class User extends DB_DataObject } } } + + function hasFave($notice) { + $fave = new Fave(); + $fave->user_id = $this->id; + $fave->notice_id = $notice->id; + if ($fave->find()) { + $result = true; + } else { + $result = false; + } + $fave->free(); + unset($fave); + return $result; + } } diff --git a/classes/stoica.ini b/classes/stoica.ini index 329c5b1e76..90d83abc8a 100644 --- a/classes/stoica.ini +++ b/classes/stoica.ini @@ -252,6 +252,7 @@ password = 2 email = 2 incomingemail = 2 emailnotifysub = 17 +emailnotifyfav = 17 emailmicroid = 17 language = 2 timezone = 2 diff --git a/db/laconica.sql b/db/laconica.sql index b358e54b88..867deb7970 100644 --- a/db/laconica.sql +++ b/db/laconica.sql @@ -47,6 +47,7 @@ create table user ( email varchar(255) unique key comment 'email address for password recovery etc.', incomingemail varchar(255) unique key comment 'email address for post-by-email', emailnotifysub tinyint default 1 comment 'Notify by email of subscriptions', + emailnotifyfav tinyint default 1 comment 'Notify by email of favorites', emailmicroid tinyint default 1 comment 'whether to publish email microid', language varchar(50) comment 'preferred language', timezone varchar(50) comment 'timezone', @@ -281,10 +282,10 @@ create table foreign_link ( credentials varchar(255) comment 'authc credentials, typically a password', noticesync tinyint not null default 1 comment 'notice synchronization, bit 1 = sync outgoing, bit 2 = sync incoming', friendsync tinyint not null default 2 comment 'friend synchronization, bit 1 = sync outgoing, bit 2 = sync incoming', - profilesync tinyint not null default 1 comment 'profile synchronization, bit 1 = sync outgoing, bit 2 = sync incoming', + profilesync tinyint not null default 1 comment 'profile synchronization, bit 1 = sync outgoing, bit 2 = sync incoming', created datetime not null comment 'date this record was created', modified timestamp comment 'date this record was modified', - + constraint primary key (user_id, foreign_id, service), index foreign_user_user_id_idx (user_id) ) ENGINE=InnoDB CHARACTER SET utf8 COLLATE utf8_bin; diff --git a/htaccess.sample b/htaccess.sample index 982b605786..30f1bb5318 100644 --- a/htaccess.sample +++ b/htaccess.sample @@ -35,6 +35,9 @@ RewriteRule ^main/recoverpassword$ index.php?action=recoverpassword [L,QSA] RewriteRule ^main/recoverpassword/(.*)$ index.php?action=recoverpassword&code=$1 [L,QSA] RewriteRule ^main/invite$ index.php?action=invite [L,QSA] +RewriteRule ^main/favor$ index.php?action=favor [L,QSA] +RewriteRule ^main/disfavor$ index.php?action=disfavor [L,QSA] + RewriteRule ^settings/avatar$ index.php?action=avatar [L,QSA] RewriteRule ^settings/password$ index.php?action=password [L,QSA] RewriteRule ^settings/profile$ index.php?action=profilesettings [L,QSA] @@ -67,6 +70,7 @@ RewriteRule ^(\w+)/foaf$ index.php?action=foaf&nickname=$1 [L,QSA] RewriteRule ^(\w+)/replies$ index.php?action=replies&nickname=$1 [L,QSA] RewriteRule ^(\w+)/replies/rss$ index.php?action=repliesrss&nickname=$1 [L,QSA] RewriteRule ^(\w+)/avatar/(original|96|48|24)$ index.php?action=avatarbynickname&nickname=$1&size=$2 [L,QSA] +RewriteRule ^(\w+)/favorites$ index.php?action=showfavorites&nickname=$1 [L,QSA] RewriteRule ^(\w+)$ index.php?action=showstream&nickname=$1 [L,QSA] diff --git a/lib/stream.php b/lib/stream.php index c50167841d..62d1cd67c6 100644 --- a/lib/stream.php +++ b/lib/stream.php @@ -60,6 +60,11 @@ class StreamAction extends Action { _('Profile'), ($user_profile && $user_profile->fullname) ? $user_profile->fullname : $nickname, $action == 'showstream'); + common_menu_item(common_local_url('showfavorites', array('nickname' => + $nickname)), + _('Favorites'), + sprintf(_('%s\'s favorite notices'), ($user_profile) ? $user_profile->getBestName() : _('User')), + $action == 'showfavorites'); common_element_end('ul'); } @@ -133,10 +138,17 @@ class StreamAction extends Action { common_raw('×'); common_element_end('a'); } + if ($user) { + if ($user->hasFave($notice)) { + common_disfavor_form($notice); + } else { + common_favor_form($notice); + } + } common_element_end('p'); common_element_end('li'); } - + function source_link($source) { $source_name = _($source); switch ($source) { diff --git a/lib/util.php b/lib/util.php index eeb2d7f641..6be317701f 100644 --- a/lib/util.php +++ b/lib/util.php @@ -174,7 +174,7 @@ function common_show_header($pagetitle, $callable=NULL, $data=NULL, $headercall= # FIXME: correct language for interface $language = common_language(); - + common_element_start('html', array('xmlns' => 'http://www.w3.org/1999/xhtml', 'xml:lang' => $language, 'lang' => $language)); @@ -913,6 +913,16 @@ function common_fancy_url($action, $args=NULL) { return common_path($path . (($args) ? ('?' . http_build_query($args)) : '')); case 'tags': return common_path('tags' . (($args) ? ('?' . http_build_query($args)) : '')); + case 'favor': + return common_path('main/favor'); + case 'disfavor': + return common_path('main/disfavor'); + case 'showfavorites': + if ($args && isset($args['page'])) { + return common_path($args['nickname'].'/favorites?page=' . $args['page']); + } else { + return common_path($args['nickname'].'/favorites'); + } default: return common_simple_url($action, $args); } @@ -1537,6 +1547,30 @@ function common_session_token() { return $_SESSION['token']; } +function common_disfavor_form($notice) { + common_element_start('form', array('id' => 'disfavor-' . $notice->id, + 'method' => 'post', + 'action' => common_local_url('disfavor'))); + common_hidden('token', common_session_token()); + common_hidden('notice', $notice->id); + common_element('input', array('type' => 'button', + 'class' => 'disfavor'), + '♥'); + common_element_end('form'); +} + +function common_favor_form($notice) { + common_element_start('form', array('id' => 'favor-' . $notice->id, + 'method' => 'post', + 'action' => common_local_url('disfavor'))); + common_hidden('token', common_session_token()); + common_hidden('notice', $notice->id); + common_element('input', array('type' => 'button', + 'class' => 'disfavor'), + '♡'); + common_element_end('form'); +} + function common_cache_key($extra) { return 'laconica:' . common_keyize(common_config('site', 'name')) . ':' . $extra; }