From 5d6b6bfd3494a7829c8fdccfdf85278811db83c8 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Sun, 27 Dec 2009 11:04:53 -0800 Subject: admin page checks for right to review flags --- plugins/UserFlag/UserFlagPlugin.php | 12 +++++++++- plugins/UserFlag/adminprofileflag.php | 43 +++++++++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+), 1 deletion(-) (limited to 'plugins') diff --git a/plugins/UserFlag/UserFlagPlugin.php b/plugins/UserFlag/UserFlagPlugin.php index 75dcca4fc..b4f9bd783 100644 --- a/plugins/UserFlag/UserFlagPlugin.php +++ b/plugins/UserFlag/UserFlagPlugin.php @@ -43,6 +43,8 @@ if (!defined('STATUSNET') && !defined('LACONICA')) { class UserFlagPlugin extends Plugin { + const REVIEWFLAGS = 'UserFlagPlugin::reviewflags'; + function onCheckSchema() { $schema = Schema::get(); @@ -138,7 +140,7 @@ class UserFlagPlugin extends Plugin function onEndShowStatusNetStyles($action) { - $action->cssLink(common_path('plugins/UserFlag/userflag.css'), + $action->cssLink(common_path('plugins/UserFlag/userflag.css'), null, 'screen, projection, tv'); return true; } @@ -148,4 +150,12 @@ class UserFlagPlugin extends Plugin $action->inlineScript('if ($(".form_entity_flag").length > 0) { SN.U.FormXHR($(".form_entity_flag")); }'); return true; } + + function onUserRightsCheck($user, $right, &$result) { + if ($right == self::REVIEWFLAGS) { + $result = $user->hasRole('moderator'); + return false; // done processing! + } + return true; // unchanged! + } } diff --git a/plugins/UserFlag/adminprofileflag.php b/plugins/UserFlag/adminprofileflag.php index 20b808637..5d6acf086 100644 --- a/plugins/UserFlag/adminprofileflag.php +++ b/plugins/UserFlag/adminprofileflag.php @@ -43,6 +43,8 @@ if (!defined('STATUSNET')) { class AdminprofileflagAction extends Action { + var $page = null; + /** * Take arguments for running * @@ -55,6 +57,47 @@ class AdminprofileflagAction extends Action { parent::prepare($args); + $user = common_current_user(); + + // User must be logged in. + + if (!common_logged_in()) { + $this->clientError(_('Not logged in.')); + return; + } + + $user = common_current_user(); + + // ...because they're logged in + + assert(!empty($user)); + + // It must be a "real" login, not saved cookie login + + if (!common_is_real_login()) { + // Cookie theft is too easy; we require automatic + // logins to re-authenticate before admining the site + common_set_returnto($this->selfUrl()); + if (Event::handle('RedirectToLogin', array($this, $user))) { + common_redirect(common_local_url('login'), 303); + } + } + + // User must have the right to review flags + + if (!$user->hasRight(UserFlagPlugin::REVIEWFLAGS)) { + $this->clientError(_('You cannot review profile flags.')); + return false; + } + + $page = $this->int('page'); + + if (empty($page)) { + $this->page = 1; + } else { + $this->page = $page; + } + return true; } -- cgit v1.2.3-54-g00ecf From 4b7835caa570a27f372935fdda799dd065ae8ea4 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Sun, 27 Dec 2009 11:47:54 -0800 Subject: pagination works for flagged profiles --- plugins/UserFlag/adminprofileflag.php | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) (limited to 'plugins') diff --git a/plugins/UserFlag/adminprofileflag.php b/plugins/UserFlag/adminprofileflag.php index 5d6acf086..b0888a31d 100644 --- a/plugins/UserFlag/adminprofileflag.php +++ b/plugins/UserFlag/adminprofileflag.php @@ -43,7 +43,8 @@ if (!defined('STATUSNET')) { class AdminprofileflagAction extends Action { - var $page = null; + var $page = null; + var $profiles = null; /** * Take arguments for running @@ -90,14 +91,14 @@ class AdminprofileflagAction extends Action return false; } - $page = $this->int('page'); + $this->page = $this->trimmed('page'); - if (empty($page)) { + if (empty($this->page)) { $this->page = 1; - } else { - $this->page = $page; } + $this->profiles = $this->getProfiles(); + return true; } @@ -128,11 +129,12 @@ class AdminprofileflagAction extends Action function showContent() { - $profile = $this->getProfiles(); + $pl = new FlaggedProfileList($this->profiles, $this); - $pl = new FlaggedProfileList($profile, $this); + $cnt = $pl->show(); - $pl->show(); + $this->pagination($this->page > 1, $cnt > PROFILES_PER_PAGE, + $this->page, 'adminprofileflag'); } function getProfiles() @@ -146,7 +148,12 @@ class AdminprofileflagAction extends Action $ufp->whereAdd('cleared is NULL'); $ufp->groupBy('profile_id'); - $ufp->orderBy('flag_count DESC'); + $ufp->orderBy('flag_count DESC, profile_id DESC'); + + $offset = ($this->page-1) * PROFILES_PER_PAGE; + $limit = PROFILES_PER_PAGE + 1; + + $ufp->limit($offset, $limit); $profiles = array(); -- cgit v1.2.3-54-g00ecf From 75fbec2fa336ac9b749fa273ac5a44c2fb211623 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Mon, 28 Dec 2009 07:58:33 -0800 Subject: Add tools to clear flags Added a form to clear all flags for a profile, when showed on adminprofileflags list. Add an action to handle the form, and a right for the action. --- plugins/UserFlag/clearflag.php | 129 +++++++++++++++++++++++++++++++++++++ plugins/UserFlag/clearflagform.php | 92 ++++++++++++++++++++++++++ 2 files changed, 221 insertions(+) create mode 100644 plugins/UserFlag/clearflag.php create mode 100644 plugins/UserFlag/clearflagform.php (limited to 'plugins') diff --git a/plugins/UserFlag/clearflag.php b/plugins/UserFlag/clearflag.php new file mode 100644 index 000000000..58151d33c --- /dev/null +++ b/plugins/UserFlag/clearflag.php @@ -0,0 +1,129 @@ + + * @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3 + * @link http://status.net/ + * + * StatusNet - the distributed open-source microblogging tool + * Copyright (C) 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 . + */ + +if (!defined('STATUSNET')) { + exit(1); +} + +/** + * Action to clear flags for a profile + * + * @category Action + * @package StatusNet + * @author Evan Prodromou + * @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3 + * @link http://status.net/ + */ + +class ClearflagAction extends ProfileFormAction +{ + /** + * Take arguments for running + * + * @param array $args $_REQUEST args + * + * @return boolean success flag + */ + + function prepare($args) + { + if (!parent::prepare($args)) { + return false; + } + + $user = common_current_user(); + + assert(!empty($user)); // checked above + assert(!empty($this->profile)); // checked above + + return true; + } + + /** + * Handle request + * + * Overriding the base Action's handle() here to deal check + * for Ajax and return an HXR response if necessary + * + * @param array $args $_REQUEST args; handled in prepare() + * + * @return void + */ + + function handle($args) + { + if ($_SERVER['REQUEST_METHOD'] == 'POST') { + $this->handlePost(); + if (!$this->boolean('ajax')) { + $this->returnToArgs(); + } + } + } + + /** + * Handle POST + * + * @return void + */ + + function handlePost() + { + $ufp = new User_flag_profile(); + + $result = $ufp->query('UPDATE user_flag_profile ' . + 'SET cleared = now() ' . + 'WHERE cleared is null ' . + 'AND profile_id = ' . $this->profile->id); + + if ($result == false) { + throw new ServerException(sprintf(_("Couldn't clear flags for profile '%s'."), + $this->profile->nickname)); + } + + $ufp->free(); + + if ($this->boolean('ajax')) { + $this->ajaxResults(); + } + } + + function ajaxResults() { + header('Content-Type: text/xml;charset=utf-8'); + $this->xw->startDocument('1.0', 'UTF-8'); + $this->elementStart('html'); + $this->elementStart('head'); + $this->element('title', null, _('Flags cleared')); + $this->elementEnd('head'); + $this->elementStart('body'); + $this->element('p', 'cleared', _('Cleared')); + $this->elementEnd('body'); + $this->elementEnd('html'); + } +} + diff --git a/plugins/UserFlag/clearflagform.php b/plugins/UserFlag/clearflagform.php new file mode 100644 index 000000000..5ad6055d3 --- /dev/null +++ b/plugins/UserFlag/clearflagform.php @@ -0,0 +1,92 @@ +. + * + * @category Form + * @package StatusNet + * @author Evan Prodromou + * @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); +} + +require_once INSTALLDIR.'/lib/form.php'; + +/** + * Form for clearing profile flags + * + * @category Form + * @package StatusNet + * @author Evan Prodromou + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://status.net/ + */ + +class ClearFlagForm extends ProfileActionForm +{ + /** + * class of the form + * Action this form provides + * + * @return string class of the form + */ + + function formClass() + { + return 'form_entity_clearflag'; + } + + /** + * Action this form provides + * + * @return string Name of the action, lowercased. + */ + + function target() + { + return 'clearflag'; + } + + /** + * Title of the form + * + * @return string Title of the form, internationalized + */ + + function title() + { + return _('Clear'); + } + + /** + * Description of the form + * + * @return string description of the form, internationalized + */ + + function description() + { + return _('Clear all flags'); + } +} -- cgit v1.2.3-54-g00ecf From 2c2a82fda0b78422802a9d0b23afc765c2f5f52b Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Mon, 28 Dec 2009 08:19:22 -0800 Subject: add stuff for clearing flags to UserFlagPlugin --- plugins/UserFlag/UserFlagPlugin.php | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'plugins') diff --git a/plugins/UserFlag/UserFlagPlugin.php b/plugins/UserFlag/UserFlagPlugin.php index b4f9bd783..78979ace2 100644 --- a/plugins/UserFlag/UserFlagPlugin.php +++ b/plugins/UserFlag/UserFlagPlugin.php @@ -44,6 +44,7 @@ if (!defined('STATUSNET') && !defined('LACONICA')) { class UserFlagPlugin extends Plugin { const REVIEWFLAGS = 'UserFlagPlugin::reviewflags'; + const CLEARFLAGS = 'UserFlagPlugin::clearflags'; function onCheckSchema() { @@ -72,6 +73,7 @@ class UserFlagPlugin extends Plugin function onRouterInitialized($m) { $m->connect('main/flag/profile', array('action' => 'flagprofile')); + $m->connect('main/flag/clear', array('action' => 'clearflag')); $m->connect('admin/profile/flag', array('action' => 'adminprofileflag')); return true; } @@ -82,9 +84,11 @@ class UserFlagPlugin extends Plugin { case 'FlagprofileAction': case 'AdminprofileflagAction': + case 'ClearflagAction': require_once(INSTALLDIR.'/plugins/UserFlag/' . strtolower(mb_substr($cls, 0, -6)) . '.php'); return false; case 'FlagProfileForm': + case 'ClearFlagForm': require_once(INSTALLDIR.'/plugins/UserFlag/' . strtolower($cls . '.php')); return false; case 'User_flag_profile': @@ -152,10 +156,13 @@ class UserFlagPlugin extends Plugin } function onUserRightsCheck($user, $right, &$result) { - if ($right == self::REVIEWFLAGS) { + switch ($right) { + case self::REVIEWFLAGS: + case self::CLEARFLAGS: $result = $user->hasRole('moderator'); return false; // done processing! } + return true; // unchanged! } } -- cgit v1.2.3-54-g00ecf From 85b8b35f53258a95989a8679455e0b2fd72bc5f5 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Mon, 28 Dec 2009 08:19:56 -0800 Subject: clear flags and show flaggers in adminflagprofile --- plugins/UserFlag/adminprofileflag.php | 67 +++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) (limited to 'plugins') diff --git a/plugins/UserFlag/adminprofileflag.php b/plugins/UserFlag/adminprofileflag.php index b0888a31d..ab1a86ac4 100644 --- a/plugins/UserFlag/adminprofileflag.php +++ b/plugins/UserFlag/adminprofileflag.php @@ -182,6 +182,8 @@ class FlaggedProfileList extends ProfileList { class FlaggedProfileListItem extends ProfileListItem { + const MAX_FLAGGERS = 5; + var $user = null; var $r2args = null; @@ -252,5 +254,70 @@ class FlaggedProfileListItem extends ProfileListItem function showClearButton() { + if ($this->user->hasRight(UserFlagPlugin::CLEARFLAGS)) { + $this->out->elementStart('li', 'entity_clear'); + $cf = new ClearFlagForm($this->out, $this->profile, $this->r2args); + $cf->show(); + $this->out->elementEnd('li'); + } + } + + function endProfile() + { + $this->showFlaggersList(); + parent::endProfile(); + } + + function showFlaggersList() + { + $flaggers = array(); + + $ufp = new User_flag_profile(); + + $ufp->selectAdd(); + $ufp->selectAdd('user_id'); + $ufp->profile_id = $this->profile->id; + $ufp->orderBy('created'); + + if ($ufp->find()) { // XXX: this should always happen + while ($ufp->fetch()) { + $user = User::staticGet('id', $ufp->user_id); + if (!empty($user)) { // XXX: this would also be unusual + $flaggers[] = clone($user); + } + } + } + + $cnt = count($flaggers); + $others = 0; + + if ($cnt > self::MAX_FLAGGERS) { + $flaggers = array_slice($flaggers, 0, self::MAX_FLAGGERS); + $others = $cnt - self::MAX_FLAGGERS; + } + + $lnks = array(); + + foreach ($flaggers as $flagger) { + + $url = common_local_url('showstream', + array('nickname' => $flagger->nickname)); + + $lnks[] = XMLStringer::estring('a', array('href' => $url, + 'class' => 'flagger'), + $flagger->nickname); + } + + if ($cnt > 0) { + $text = _('Flagged by '); + $text .= implode(', ', $lnks); + if ($others > 0) { + $text .= sprintf(_(' and %d others'), $others); + } + + $this->out->elementStart('p', array('class' => 'flaggers')); + $this->out->raw($text); + $this->out->elementEnd('p'); + } } } -- cgit v1.2.3-54-g00ecf From ea23111a5611a3634faf3828f3f5c67867a460e3 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Mon, 28 Dec 2009 08:37:30 -0800 Subject: PHPCS-clean UserFlagPlugin --- plugins/UserFlag/UserFlagPlugin.php | 100 ++++++++++++++++++++++++++++++------ 1 file changed, 85 insertions(+), 15 deletions(-) (limited to 'plugins') diff --git a/plugins/UserFlag/UserFlagPlugin.php b/plugins/UserFlag/UserFlagPlugin.php index 78979ace2..21af506a9 100644 --- a/plugins/UserFlag/UserFlagPlugin.php +++ b/plugins/UserFlag/UserFlagPlugin.php @@ -27,7 +27,7 @@ * @link http://status.net/ */ -if (!defined('STATUSNET') && !defined('LACONICA')) { +if (!defined('STATUSNET')) { exit(1); } @@ -46,6 +46,15 @@ class UserFlagPlugin extends Plugin const REVIEWFLAGS = 'UserFlagPlugin::reviewflags'; const CLEARFLAGS = 'UserFlagPlugin::clearflags'; + /** + * Hook for ensuring our tables are created + * + * Ensures that the user_flag_profile table exists + * and has the right columns. + * + * @return boolean hook return + */ + function onCheckSchema() { $schema = Schema::get(); @@ -65,40 +74,61 @@ class UserFlagPlugin extends Plugin return true; } - function onInitializePlugin() - { - // XXX: do something here? - return true; - } + /** + * Add our actions to the URL router + * + * @param Net_URL_Mapper $m URL mapper for this hit + * + * @return boolean hook return + */ - function onRouterInitialized($m) { + function onRouterInitialized($m) + { $m->connect('main/flag/profile', array('action' => 'flagprofile')); $m->connect('main/flag/clear', array('action' => 'clearflag')); $m->connect('admin/profile/flag', array('action' => 'adminprofileflag')); return true; } - function onAutoload($cls) + /** + * Auto-load our classes if called + * + * @param string $cls Class to load + * + * @return boolean hook return + */ + + function onAutoload($cls) { switch ($cls) { case 'FlagprofileAction': case 'AdminprofileflagAction': case 'ClearflagAction': - require_once(INSTALLDIR.'/plugins/UserFlag/' . strtolower(mb_substr($cls, 0, -6)) . '.php'); + include_once INSTALLDIR.'/plugins/UserFlag/' . + strtolower(mb_substr($cls, 0, -6)) . '.php'; return false; case 'FlagProfileForm': case 'ClearFlagForm': - require_once(INSTALLDIR.'/plugins/UserFlag/' . strtolower($cls . '.php')); + include_once INSTALLDIR.'/plugins/UserFlag/' . strtolower($cls . '.php'); return false; case 'User_flag_profile': - require_once(INSTALLDIR.'/plugins/UserFlag/'.$cls.'.php'); + include_once INSTALLDIR.'/plugins/UserFlag/'.$cls.'.php'; return false; default: return true; } } + /** + * Add a 'flag' button to profile page + * + * @param Action &$action The action being called + * @param Profile $profile Profile being shown + * + * @return boolean hook result + */ + function onEndProfilePageActionsElements(&$action, $profile) { $user = common_current_user(); @@ -111,8 +141,8 @@ class UserFlagPlugin extends Plugin $action->element('p', 'flagged', _('Flagged')); } else { $form = new FlagProfileForm($action, $profile, - array('action' => 'showstream', - 'nickname' => $profile->nickname)); + array('action' => 'showstream', + 'nickname' => $profile->nickname)); $form->show(); } @@ -122,6 +152,14 @@ class UserFlagPlugin extends Plugin return true; } + /** + * Add a 'flag' button to profiles in a list + * + * @param ProfileListItem $item item being shown + * + * @return boolean hook result + */ + function onEndProfileListItemActionElements($item) { $user = common_current_user(); @@ -142,6 +180,14 @@ class UserFlagPlugin extends Plugin return true; } + /** + * Add our plugin's CSS to page output + * + * @param Action $action action being shown + * + * @return boolean hook result + */ + function onEndShowStatusNetStyles($action) { $action->cssLink(common_path('plugins/UserFlag/userflag.css'), @@ -149,13 +195,37 @@ class UserFlagPlugin extends Plugin return true; } + /** + * Initialize any flagging buttons on the page + * + * @param Action $action action being shown + * + * @return boolean hook result + */ + function onEndShowScripts($action) { - $action->inlineScript('if ($(".form_entity_flag").length > 0) { SN.U.FormXHR($(".form_entity_flag")); }'); + $action->inlineScript('if ($(".form_entity_flag").length > 0) { '. + 'SN.U.FormXHR($(".form_entity_flag")); '. + '}'); return true; } - function onUserRightsCheck($user, $right, &$result) { + /** + * Check whether a user has one of our defined rights + * + * We define extra rights; this function checks to see if a + * user has one of them. + * + * @param User $user User being checked + * @param string $right Right we're checking + * @param boolean &$result out, result of the check + * + * @return boolean hook result + */ + + function onUserRightsCheck($user, $right, &$result) + { switch ($right) { case self::REVIEWFLAGS: case self::CLEARFLAGS: -- cgit v1.2.3-54-g00ecf From c8fd5403e5bfc3b9110042eb1573904625f607e1 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Mon, 28 Dec 2009 08:45:21 -0800 Subject: PHPCS-clean adminprofileflags.php --- plugins/UserFlag/adminprofileflag.php | 99 ++++++++++++++++++++++++++++++++--- 1 file changed, 93 insertions(+), 6 deletions(-) (limited to 'plugins') diff --git a/plugins/UserFlag/adminprofileflag.php b/plugins/UserFlag/adminprofileflag.php index ab1a86ac4..17374927b 100644 --- a/plugins/UserFlag/adminprofileflag.php +++ b/plugins/UserFlag/adminprofileflag.php @@ -117,7 +117,14 @@ class AdminprofileflagAction extends Action $this->showPage(); } - function title() { + /** + * Title of this page + * + * @return string Title of the page + */ + + function title() + { return _('Flagged profiles'); } @@ -137,6 +144,12 @@ class AdminprofileflagAction extends Action $this->page, 'adminprofileflag'); } + /** + * Retrieve this action's profiles + * + * @return Profile $profile Profile query results + */ + function getProfiles() { $ufp = new User_flag_profile(); @@ -151,7 +164,7 @@ class AdminprofileflagAction extends Action $ufp->orderBy('flag_count DESC, profile_id DESC'); $offset = ($this->page-1) * PROFILES_PER_PAGE; - $limit = PROFILES_PER_PAGE + 1; + $limit = PROFILES_PER_PAGE + 1; $ufp->limit($offset, $limit); @@ -172,7 +185,27 @@ class AdminprofileflagAction extends Action } } -class FlaggedProfileList extends ProfileList { +/** + * Specialization of ProfileList to show flagging information + * + * Most of the hard part is done in FlaggedProfileListItem. + * + * @category Widget + * @package StatusNet + * @author Evan Prodromou + * @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3 + * @link http://status.net/ + */ + +class FlaggedProfileList extends ProfileList +{ + /** + * Factory method for creating new list items + * + * @param Profile $profile Profile to create an item for + * + * @return ProfileListItem newly-created item + */ function newListItem($profile) { @@ -180,13 +213,29 @@ class FlaggedProfileList extends ProfileList { } } +/** + * Specialization of ProfileListItem to show flagging information + * + * @category Widget + * @package StatusNet + * @author Evan Prodromou + * @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3 + * @link http://status.net/ + */ + class FlaggedProfileListItem extends ProfileListItem { const MAX_FLAGGERS = 5; - var $user = null; + var $user = null; var $r2args = null; + /** + * Overload parent's action list with our own moderation-oriented buttons + * + * @return void + */ + function showActions() { $this->user = common_current_user(); @@ -211,6 +260,12 @@ class FlaggedProfileListItem extends ProfileListItem $this->endActions(); } + /** + * Show a button to sandbox the profile + * + * @return void + */ + function showSandboxButton() { if ($this->user->hasRight(Right::SANDBOXUSER)) { @@ -226,6 +281,12 @@ class FlaggedProfileListItem extends ProfileListItem } } + /** + * Show a button to silence the profile + * + * @return void + */ + function showSilenceButton() { if ($this->user->hasRight(Right::SILENCEUSER)) { @@ -241,6 +302,12 @@ class FlaggedProfileListItem extends ProfileListItem } } + /** + * Show a button to delete user and profile + * + * @return void + */ + function showDeleteButton() { @@ -252,6 +319,12 @@ class FlaggedProfileListItem extends ProfileListItem } } + /** + * Show a button to clear flags + * + * @return void + */ + function showClearButton() { if ($this->user->hasRight(UserFlagPlugin::CLEARFLAGS)) { @@ -262,12 +335,24 @@ class FlaggedProfileListItem extends ProfileListItem } } + /** + * Overload parent function to add flaggers list + * + * @return void + */ + function endProfile() { $this->showFlaggersList(); parent::endProfile(); } + /** + * Show a list of people who've flagged this profile + * + * @return void + */ + function showFlaggersList() { $flaggers = array(); @@ -288,12 +373,12 @@ class FlaggedProfileListItem extends ProfileListItem } } - $cnt = count($flaggers); + $cnt = count($flaggers); $others = 0; if ($cnt > self::MAX_FLAGGERS) { $flaggers = array_slice($flaggers, 0, self::MAX_FLAGGERS); - $others = $cnt - self::MAX_FLAGGERS; + $others = $cnt - self::MAX_FLAGGERS; } $lnks = array(); @@ -310,7 +395,9 @@ class FlaggedProfileListItem extends ProfileListItem if ($cnt > 0) { $text = _('Flagged by '); + $text .= implode(', ', $lnks); + if ($others > 0) { $text .= sprintf(_(' and %d others'), $others); } -- cgit v1.2.3-54-g00ecf From df98ddff0c6daa6a94c71be11b7db683f6181482 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Mon, 28 Dec 2009 09:06:38 -0800 Subject: phpcs-clean clearflag.php --- plugins/UserFlag/clearflag.php | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) (limited to 'plugins') diff --git a/plugins/UserFlag/clearflag.php b/plugins/UserFlag/clearflag.php index 58151d33c..bd6732e2d 100644 --- a/plugins/UserFlag/clearflag.php +++ b/plugins/UserFlag/clearflag.php @@ -89,6 +89,8 @@ class ClearflagAction extends ProfileFormAction /** * Handle POST * + * Executes the actions; deletes all flags + * * @return void */ @@ -102,8 +104,9 @@ class ClearflagAction extends ProfileFormAction 'AND profile_id = ' . $this->profile->id); if ($result == false) { - throw new ServerException(sprintf(_("Couldn't clear flags for profile '%s'."), - $this->profile->nickname)); + $msg = sprintf(_("Couldn't clear flags for profile '%s'."), + $this->profile->nickname); + throw new ServerException($msg); } $ufp->free(); @@ -113,7 +116,14 @@ class ClearflagAction extends ProfileFormAction } } - function ajaxResults() { + /** + * Return results in ajax form + * + * @return void + */ + + function ajaxResults() + { header('Content-Type: text/xml;charset=utf-8'); $this->xw->startDocument('1.0', 'UTF-8'); $this->elementStart('html'); @@ -126,4 +136,3 @@ class ClearflagAction extends ProfileFormAction $this->elementEnd('html'); } } - -- cgit v1.2.3-54-g00ecf From 4a5bac43c33ef0006b85eb39eda10de55985d52d Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Mon, 28 Dec 2009 09:08:28 -0800 Subject: phpcs-clean flagprofile.php --- plugins/UserFlag/flagprofile.php | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) (limited to 'plugins') diff --git a/plugins/UserFlag/flagprofile.php b/plugins/UserFlag/flagprofile.php index 9bce7865b..55753f4e8 100644 --- a/plugins/UserFlag/flagprofile.php +++ b/plugins/UserFlag/flagprofile.php @@ -63,8 +63,7 @@ class FlagprofileAction extends ProfileFormAction assert(!empty($this->profile)); // checked above if (User_flag_profile::exists($this->profile->id, - $user->id)) - { + $user->id)) { $this->clientError(_('Flag already exists.')); return false; } @@ -72,7 +71,6 @@ class FlagprofileAction extends ProfileFormAction return true; } - /** * Handle request * @@ -114,8 +112,9 @@ class FlagprofileAction extends ProfileFormAction $ufp->created = common_sql_now(); if (!$ufp->insert()) { - throw new ServerException(sprintf(_("Couldn't flag profile '%s' for review."), - $this->profile->nickname)); + $msg = sprintf(_("Couldn't flag profile '%s' for review."), + $this->profile->nickname); + throw new ServerException($msg); } $ufp->free(); @@ -125,7 +124,14 @@ class FlagprofileAction extends ProfileFormAction } } - function ajaxResults() { + /** + * Return results as AJAX message + * + * @return void + */ + + function ajaxResults() + { header('Content-Type: text/xml;charset=utf-8'); $this->xw->startDocument('1.0', 'UTF-8'); $this->elementStart('html'); -- cgit v1.2.3-54-g00ecf From a80fa178726da3ff6d06272bd06f35afbfe2f757 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Mon, 28 Dec 2009 09:15:07 -0800 Subject: phpcs-clean User_flag_profile as best as possible --- plugins/UserFlag/User_flag_profile.php | 59 ++++++++++++++++++++++++++++++++-- 1 file changed, 56 insertions(+), 3 deletions(-) (limited to 'plugins') diff --git a/plugins/UserFlag/User_flag_profile.php b/plugins/UserFlag/User_flag_profile.php index 30bd4ae68..b8f3f3fe1 100644 --- a/plugins/UserFlag/User_flag_profile.php +++ b/plugins/UserFlag/User_flag_profile.php @@ -1,5 +1,15 @@ + * @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3 + * @link http://status.net/ + * * StatusNet - the distributed open-source microblogging tool * Copyright (C) 2009, StatusNet, Inc. * @@ -23,6 +33,18 @@ if (!defined('STATUSNET')) { require_once INSTALLDIR . '/classes/Memcached_DataObject.php'; +/** + * Data class for profile flags + * + * A class representing a user flagging another profile for review. + * + * @category Action + * @package StatusNet + * @author Evan Prodromou + * @license http://www.fsf.org/licensing/licenses/agpl.html AGPLv3 + * @link http://status.net/ + */ + class User_flag_profile extends Memcached_DataObject { ###START_AUTOCODE @@ -40,7 +62,14 @@ class User_flag_profile extends Memcached_DataObject /* the code above is auto generated do not remove the tag below */ ###END_AUTOCODE - function table() { + /** + * return table definition for DB_DataObject + * + * @return array array of column definitions + */ + + function table() + { return array( 'profile_id' => DB_DATAOBJECT_INT + DB_DATAOBJECT_NOTNULL, 'user_id' => DB_DATAOBJECT_INT + DB_DATAOBJECT_NOTNULL, @@ -49,15 +78,39 @@ class User_flag_profile extends Memcached_DataObject ); } - function keys() { + /** + * return key definitions for DB_DataObject + * + * @return array key definitions + */ + + function keys() + { return array('profile_id' => 'N', 'user_id' => 'N'); } + /** + * Get a single object with multiple keys + * + * @param array $kv Map of key-value pairs + * + * @return User_flag_profile found object or null + */ + function &pkeyGet($kv) { return Memcached_DataObject::pkeyGet('User_flag_profile', $kv); } + /** + * Check if a flag exists for given profile and user + * + * @param integer $profile_id Profile to check for + * @param integer $user_id User to check for + * + * @return boolean true if exists, else false + */ + static function exists($profile_id, $user_id) { $ufp = User_flag_profile::pkeyGet(array('profile_id' => $profile_id, -- cgit v1.2.3-54-g00ecf From 6d3e6b42849ad14b15cb4c41c4f8baac45e58df0 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Mon, 28 Dec 2009 10:58:49 -0800 Subject: move flag creation to a method of data object --- plugins/UserFlag/User_flag_profile.php | 19 +++++++++++++++++++ plugins/UserFlag/flagprofile.php | 14 ++------------ 2 files changed, 21 insertions(+), 12 deletions(-) (limited to 'plugins') diff --git a/plugins/UserFlag/User_flag_profile.php b/plugins/UserFlag/User_flag_profile.php index b8f3f3fe1..658259452 100644 --- a/plugins/UserFlag/User_flag_profile.php +++ b/plugins/UserFlag/User_flag_profile.php @@ -118,4 +118,23 @@ class User_flag_profile extends Memcached_DataObject return !empty($ufp); } + + static function create($user_id, $profile_id) + { + $ufp = new User_flag_profile(); + + $ufp->profile_id = $profile_id; + $ufp->user_id = $user_id; + $ufp->created = common_sql_now(); + + if (!$ufp->insert()) { + $msg = sprintf(_("Couldn't flag profile '%d' for review."), + $profile_id); + throw new ServerException($msg); + } + + $ufp->free(); + + return true; + } } diff --git a/plugins/UserFlag/flagprofile.php b/plugins/UserFlag/flagprofile.php index 55753f4e8..2d0f0abb9 100644 --- a/plugins/UserFlag/flagprofile.php +++ b/plugins/UserFlag/flagprofile.php @@ -105,19 +105,9 @@ class FlagprofileAction extends ProfileFormAction assert(!empty($user)); assert(!empty($this->profile)); - $ufp = new User_flag_profile(); + // throws an exception on error - $ufp->profile_id = $this->profile->id; - $ufp->user_id = $user->id; - $ufp->created = common_sql_now(); - - if (!$ufp->insert()) { - $msg = sprintf(_("Couldn't flag profile '%s' for review."), - $this->profile->nickname); - throw new ServerException($msg); - } - - $ufp->free(); + User_flag_profile::create($user->id, $this->profile->id); if ($this->boolean('ajax')) { $this->ajaxResults(); -- cgit v1.2.3-54-g00ecf From d9efeb6ac3810ef2ed7da6a274c3fc5ef1cfd5d7 Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Mon, 28 Dec 2009 11:02:44 -0800 Subject: optionally flag a profile for review when blocked --- plugins/UserFlag/UserFlagPlugin.php | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) (limited to 'plugins') diff --git a/plugins/UserFlag/UserFlagPlugin.php b/plugins/UserFlag/UserFlagPlugin.php index 21af506a9..0fca5f9cf 100644 --- a/plugins/UserFlag/UserFlagPlugin.php +++ b/plugins/UserFlag/UserFlagPlugin.php @@ -46,6 +46,8 @@ class UserFlagPlugin extends Plugin const REVIEWFLAGS = 'UserFlagPlugin::reviewflags'; const CLEARFLAGS = 'UserFlagPlugin::clearflags'; + public $flagOnBlock = true; + /** * Hook for ensuring our tables are created * @@ -235,4 +237,23 @@ class UserFlagPlugin extends Plugin return true; // unchanged! } + + /** + * Optionally flag profile when a block happens + * + * We optionally add a flag when a profile has been blocked + * + * @param User $user User doing the block + * @param Profile $profile Profile being blocked + * + * @return boolean hook result + */ + + function onEndBlockProfile($user, $profile) + { + if ($this->flagOnBlock) { + User_flag_profile::create($user->id, $profile->id); + } + return true; + } } -- cgit v1.2.3-54-g00ecf From dd0aaac70ec092edd38b53285ac74a4ad36e7c1e Mon Sep 17 00:00:00 2001 From: Evan Prodromou Date: Mon, 28 Dec 2009 12:42:22 -0800 Subject: First version of blacklist plugin First version of blacklist plugin. Replaces custom code in identi.ca's config.php, which was getting scary and long. Also correctly handles changed nicknames or URLs in profile settings and using 'forbidden' URLs in notice text. --- plugins/Blacklist/BlacklistPlugin.php | 203 ++++++++++++++++++++++++++++++++++ 1 file changed, 203 insertions(+) create mode 100644 plugins/Blacklist/BlacklistPlugin.php (limited to 'plugins') diff --git a/plugins/Blacklist/BlacklistPlugin.php b/plugins/Blacklist/BlacklistPlugin.php new file mode 100644 index 000000000..655b0926b --- /dev/null +++ b/plugins/Blacklist/BlacklistPlugin.php @@ -0,0 +1,203 @@ +. + * + * @category Action + * @package StatusNet + * @author Evan Prodromou + * @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); +} + +/** + * Plugin to prevent use of nicknames or URLs on a blacklist + * + * @category Plugin + * @package StatusNet + * @author Evan Prodromou + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link http://status.net/ + */ + +class BlacklistPlugin extends Plugin +{ + public $nicknames = array(); + public $urls = array(); + + /** + * Hook registration to prevent blacklisted homepages or nicknames + * + * Throws an exception if there's a blacklisted homepage or nickname. + * + * @param Action $action Action being called (usually register) + * + * @return boolean hook value + */ + + function onStartRegistrationTry($action) + { + $homepage = strtolower($action->trimmed('homepage')); + + if (!empty($homepage)) { + if (!$this->_checkUrl($homepage)) { + $msg = sprintf(_m("You may not register with homepage '%s'"), + $homepage); + throw new ClientException($msg); + } + } + + $nickname = strtolower($action->trimmed('nickname')); + + if (!empty($nickname)) { + if (!$this->_checkNickname($nickname)) { + $msg = sprintf(_m("You may not register with nickname '%s'"), + $nickname); + throw new ClientException($msg); + } + } + + return true; + } + + /** + * Hook profile update to prevent blacklisted homepages or nicknames + * + * Throws an exception if there's a blacklisted homepage or nickname. + * + * @param Action $action Action being called (usually register) + * + * @return boolean hook value + */ + + function onStartProfileSaveForm($action) + { + $homepage = strtolower($action->trimmed('homepage')); + + if (!empty($homepage)) { + if (!$this->_checkUrl($homepage)) { + $msg = sprintf(_m("You may not use homepage '%s'"), + $homepage); + throw new ClientException($msg); + } + } + + $nickname = strtolower($action->trimmed('nickname')); + + if (!empty($nickname)) { + if (!$this->_checkNickname($nickname)) { + $msg = sprintf(_m("You may not use nickname '%s'"), + $nickname); + throw new ClientException($msg); + } + } + + return true; + } + + /** + * Hook notice save to prevent blacklisted urls + * + * Throws an exception if there's a blacklisted url in the content. + * + * @param Notice &$notice Notice being saved + * + * @return boolean hook value + */ + + function onStartNoticeSave(&$notice) + { + common_replace_urls_callback($notice->content, + array($this, 'checkNoticeUrl')); + return true; + } + + /** + * Helper callback for notice save + * + * Throws an exception if there's a blacklisted url in the content. + * + * @param string $url URL in the notice content + * + * @return boolean hook value + */ + + function checkNoticeUrl($url) + { + // It comes in special'd, so we unspecial it + // before comparing against patterns + + $url = htmlspecialchars_decode($url); + + if (!$this->_checkUrl($url)) { + $msg = sprintf(_m("You may not use url '%s' in notices"), + $url); + throw new ClientException($msg); + } + + return $url; + } + + /** + * Helper for checking URLs + * + * Checks an URL against our patterns for a match. + * + * @param string $url URL to check + * + * @return boolean true means it's OK, false means it's bad + */ + + private function _checkUrl($url) + { + foreach ($this->urls as $pattern) { + if (preg_match("/$pattern/", $url)) { + return false; + } + } + + return true; + } + + /** + * Helper for checking nicknames + * + * Checks a nickname against our patterns for a match. + * + * @param string $nickname nickname to check + * + * @return boolean true means it's OK, false means it's bad + */ + + private function _checkNickname($nickname) + { + foreach ($this->nicknames as $pattern) { + if (preg_match("/$pattern/", $nickname)) { + return false; + } + } + + return true; + } +} -- cgit v1.2.3-54-g00ecf