From daeb220b132ff5f901ab28e1ea961d08482256fe Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Tue, 28 Sep 2010 17:17:09 -0700 Subject: [PATCH] Initial plugin for allowing anonymous favoriting --- plugins/AnonymousFave/AnonymousFavePlugin.php | 198 ++++++++++++++++++ plugins/AnonymousFave/anondisfavor.php | 132 ++++++++++++ plugins/AnonymousFave/anondisfavorform.php | 74 +++++++ plugins/AnonymousFave/anonfavor.php | 125 +++++++++++ plugins/AnonymousFave/anonfavorform.php | 74 +++++++ 5 files changed, 603 insertions(+) create mode 100644 plugins/AnonymousFave/AnonymousFavePlugin.php create mode 100644 plugins/AnonymousFave/anondisfavor.php create mode 100644 plugins/AnonymousFave/anondisfavorform.php create mode 100644 plugins/AnonymousFave/anonfavor.php create mode 100644 plugins/AnonymousFave/anonfavorform.php diff --git a/plugins/AnonymousFave/AnonymousFavePlugin.php b/plugins/AnonymousFave/AnonymousFavePlugin.php new file mode 100644 index 0000000000..3dccaf538a --- /dev/null +++ b/plugins/AnonymousFave/AnonymousFavePlugin.php @@ -0,0 +1,198 @@ +. + * + * @category Plugin + * @package StatusNet + * @author Zach Copley + * @copyright 2010 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); +} + +define('ANONYMOUS_FAVE_PLUGIN_VERSION', '0.1'); + +/** + * Anonymous Fave plugin to allow anonymous (not logged in) users + * to favorite notices + * + * @category Plugin + * @package StatusNet + * @author Zach Copley + * @copyright 2010 StatusNet, Inc. + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0 + * @link http://status.net/ + */ +class AnonymousFavePlugin extends Plugin { + + function onArgsInitialize() { + // We always want a session because we're tracking anon users + common_ensure_session(); + } + + function onEndShowHTML($action) + { + if (!common_logged_in()) { + // Set a place to return to when submitting forms + common_set_returnto($action->selfUrl()); + } + } + + function onEndShowScripts($action) + { + // Setup ajax calls for favoriting. Usually this is only done when + // a user is logged in. + $action->inlineScript('SN.U.NoticeFavor();'); + } + + function onAutoload($cls) + { + $dir = dirname(__FILE__); + + switch ($cls) { + case 'AnonFavorAction': + include_once $dir . '/' . strtolower(mb_substr($cls, 0, -6)) . '.php'; + return false; + case 'AnonDisFavorAction': + include_once $dir . '/' . strtolower(mb_substr($cls, 0, -6)) . '.php'; + return false; + case 'AnonFavorForm': + include_once $dir . '/anonfavorform.php'; + return false; + case 'AnonDisFavorForm': + include_once $dir . '/anondisfavorform.php'; + return false; + default: + return true; + } + } + + function onStartInitializeRouter($m) { + + $m->connect('main/anonfavor', array('action' => 'AnonFavor')); + $m->connect('main/anondisfavor', array('action' => 'AnonDisFavor')); + + return true; + } + + function onStartShowNoticeOptions($item) { + + if (!common_logged_in()) { + $item->out->elementStart('div', 'notice-options'); + $item->showFaveForm(); + $item->out->elementEnd('div'); + } + + return true; + } + + function onStartShowFaveForm($item) { + + if (!common_logged_in()) { + + $profile = $this->getAnonProfile(); + if (!empty($profile)) { + if ($profile->hasFave($item->notice)) { + $disfavor = new AnonDisFavorForm($item->out, $item->notice); + $disfavor->show(); + } else { + $favor = new AnonFavorForm($item->out, $item->notice); + $favor->show(); + } + } + } + + return true; + } + + function createAnonProfile() { + + // Get the anon user's IP, and turn it into a nickname + list($proxy, $ip) = common_client_ip(); + // IP + time + random number should avoid collisions + $nickname = 'anonymous-' . $ip . '-' . time() . '-' . common_good_rand(5); + + $profile = new Profile(); + $profile->nickname = $nickname; + $id = $profile->insert(); + + if (!empty($id)) { + common_log( + LOG_INFO, + "AnonymousFavePlugin - created profile for anonymous user from IP: " + . $ip + . ', nickname = ' + . $nickname + ); + } + + return $profile; + } + + function getAnonProfile() { + + $anon = $_SESSION['anon_nickname']; + + $profile = null; + + if (!empty($anon)) { + $profile = Profile::staticGet('nickname', $anon); + } else { + $profile = $this->createAnonProfile(); + $_SESSION['anon_nickname'] = $profile->nickname; + } + + if (!empty($profile)) { + return $profile; + } + } + + /** + * Provide plugin version information. + * + * This data is used when showing the version page. + * + * @param array &$versions array of version data arrays; see EVENTS.txt + * + * @return boolean hook value + */ + function onPluginVersion(&$versions) + { + $url = 'http://status.net/wiki/Plugin:AnonymousFave'; + + $versions[] = array('name' => 'AnonymousFave', + 'version' => ANONYMOUS_FAVE_PLUGIN_VERSION, + 'author' => 'Zach Copley', + 'homepage' => $url, + 'rawdescription' => + _m('Allow anonymous users to favorite notices.')); + + return true; + } + +} diff --git a/plugins/AnonymousFave/anondisfavor.php b/plugins/AnonymousFave/anondisfavor.php new file mode 100644 index 0000000000..9fd56fdc32 --- /dev/null +++ b/plugins/AnonymousFave/anondisfavor.php @@ -0,0 +1,132 @@ + + * @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3 + * @link http://status.net/ + * + * StatusNet - the distributed open-source microblogging tool + * Copyright (C) 2010, 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 . + */ + +if (!defined('STATUSNET')) { + exit(1); +} + +/** + * Anonymous disfavor class + * + * @category Action + * @package StatusNet + * @author Zach Copley + * @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3 + * @link http://status.net/ + */ +class AnonDisfavorAction extends RedirectingAction +{ + /** + * Class handler. + * + * @param array $args query arguments + * + * @return void + */ + function handle($args) + { + parent::handle($args); + + $anon = $_SESSION['anon_nickname']; + + $profile = Profile::staticGet('nickname', $anon); + + if (empty($profile)) { + common_debug( + "AnonDisFavorAction - Anon user tried to disfave a notice but doesn't have a profile." + ); + } + + if (empty($profile) || $_SERVER['REQUEST_METHOD'] != 'POST') { + $this->clientError( + _m('Could not disfavor notice! Please make sure your browser has cookies enabled.') + ); + return; + } + + $id = $this->trimmed('notice'); + $notice = Notice::staticGet($id); + $token = $this->trimmed('token-' . $notice->id); + + if (!$token || $token != common_session_token()) { + $this->clientError(_m('There was a problem with your session token. Try again, please.')); + return; + } + + $fave = new Fave(); + $fave->user_id = $profile->id; + $fave->notice_id = $notice->id; + + if (!$fave->find(true)) { + $this->clientError(_m('This notice is not a favorite!')); + return; + } + + $result = $fave->delete(); + + if (!$result) { + common_log_db_error($fave, 'DELETE', __FILE__); + $this->serverError(_m('Could not delete favorite.')); + return; + } + + $profile->blowFavesCache(); + + if ($this->boolean('ajax')) { + $this->startHTML('text/xml;charset=utf-8'); + $this->elementStart('head'); + $this->element('title', null, _m('Add to favorites')); + $this->elementEnd('head'); + $this->elementStart('body'); + $favor = new AnonFavorForm($this, $notice); + $favor->show(); + $this->elementEnd('body'); + $this->elementEnd('html'); + } else { + $this->returnToPrevious(); + } + } + + /** + * If returnto not set, return to the public stream. + * + * @return string URL + */ + function defaultReturnTo() + { + $returnto = common_get_returnto(); + if (empty($returnto)) { + return common_local_url('public'); + } else { + return $returnto; + } + } +} + diff --git a/plugins/AnonymousFave/anondisfavorform.php b/plugins/AnonymousFave/anondisfavorform.php new file mode 100644 index 0000000000..c347ed7b43 --- /dev/null +++ b/plugins/AnonymousFave/anondisfavorform.php @@ -0,0 +1,74 @@ +. + * + * @category Form + * @package StatusNet + * @author Zach Copley + * @copyright 2010 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); +} + +require_once INSTALLDIR.'/lib/form.php'; + +/** + * Form for disfavoring a notice anonymously + * + * @category Form + * @package StatusNet + * @author Zach Copley + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://status.net/ + * + * @see DisFavorForm + */ + +class AnonDisfavorForm extends DisFavorForm +{ + + /** + * Constructor + * + * @param HTMLOutputter $out output channel + * @param Notice $notice notice to disfavor + */ + + function __construct($out=null, $notice=null) + { + parent::__construct($out, $notice); + } + + /** + * Action of the form + * + * @return string URL of the action + */ + + function action() + { + return common_local_url('AnonDisFavor'); + } + +} diff --git a/plugins/AnonymousFave/anonfavor.php b/plugins/AnonymousFave/anonfavor.php new file mode 100644 index 0000000000..c972f202e4 --- /dev/null +++ b/plugins/AnonymousFave/anonfavor.php @@ -0,0 +1,125 @@ + + * @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3 + * @link http://status.net/ + * + * StatusNet - the distributed open-source microblogging tool + * Copyright (C) 2010, 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 . + */ + +if (!defined('STATUSNET')) { + exit(1); +} + +/** + * Anonymous favor class + * + * @category Action + * @package StatusNet + * @author Zach Copley + * @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3 + * @link http://status.net/ + */ +class AnonFavorAction extends RedirectingAction +{ + /** + * Class handler. + * + * @param array $args query arguments + * + * @return void + */ + function handle($args) + { + parent::handle($args); + + $anon = $_SESSION['anon_nickname']; + $profile = Profile::staticGet('nickname', $anon); + + if (empty($profile)) { + common_debug( + "AnonFavorAction - Anon user tried to fave a notice but doesn't have a profile." + ); + } + + if (empty($profile) || $_SERVER['REQUEST_METHOD'] != 'POST') { + $this->clientError( + _m('Could not favor notice! Please make sure your browser has cookies enabled.') + ); + return; + } + + $id = $this->trimmed('notice'); + $notice = Notice::staticGet($id); + $token = $this->trimmed('token-' . $notice->id); + + if (empty($token) || $token != common_session_token()) { + $this->clientError(_m('There was a problem with your session token. Try again, please.')); + return; + } + + + if ($profile->hasFave($notice)) { + $this->clientError(_m('This notice is already a favorite!')); + return; + } + $fave = Fave::addNew($profile, $notice); + + if (!$fave) { + $this->serverError(_m('Could not create favorite.')); + return; + } + + $profile->blowFavesCache(); + + if ($this->boolean('ajax')) { + $this->startHTML('text/xml;charset=utf-8'); + $this->elementStart('head'); + $this->element('title', null, _m('Disfavor favorite')); + $this->elementEnd('head'); + $this->elementStart('body'); + $disfavor = new AnonDisFavorForm($this, $notice); + $disfavor->show(); + $this->elementEnd('body'); + $this->elementEnd('html'); + } else { + $this->returnToPrevious(); + } + } + + /** + * If returnto not set, return to the public stream. + * + * @return string URL + */ + function defaultReturnTo() + { + $returnto = common_get_returnto(); + if (empty($returnto)) { + return common_local_url('public'); + } else { + return $returnto; + } + } +} diff --git a/plugins/AnonymousFave/anonfavorform.php b/plugins/AnonymousFave/anonfavorform.php new file mode 100644 index 0000000000..d73c2831d0 --- /dev/null +++ b/plugins/AnonymousFave/anonfavorform.php @@ -0,0 +1,74 @@ +. + * + * @category Form + * @package StatusNet + * @author Zach Copley + * @copyright 20010 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); +} + +require_once INSTALLDIR.'/lib/form.php'; + +/** + * Form for favoring a notice anonymously + * + * @category Form + * @package StatusNet + * @author Zach Copley + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://status.net/ + * + * @see AnonDisfavorForm + */ + +class AnonFavorForm extends FavorForm +{ + + /** + * Constructor + * + * @param HTMLOutputter $out output channel + * @param Notice $notice notice to favor + */ + + function __construct($out=null, $notice=null) + { + parent::__construct($out, $notice); + } + + /** + * Action of the form + * + * @return string URL of the action + */ + + function action() + { + return common_local_url('AnonFavor'); + } + +}