From cb49ea88d33d51ce5a7bec3c90bbea7e0cb33890 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Tue, 1 Mar 2011 19:35:20 -0800 Subject: [PATCH] Initial go at a site directory plugin --- plugins/Directory/DirectoryPlugin.php | 159 +++++++++++++ plugins/Directory/actions/userdirectory.php | 241 ++++++++++++++++++++ plugins/Directory/lib/alphanav.php | 107 +++++++++ 3 files changed, 507 insertions(+) create mode 100644 plugins/Directory/DirectoryPlugin.php create mode 100644 plugins/Directory/actions/userdirectory.php create mode 100644 plugins/Directory/lib/alphanav.php diff --git a/plugins/Directory/DirectoryPlugin.php b/plugins/Directory/DirectoryPlugin.php new file mode 100644 index 0000000000..0ff2ea76bf --- /dev/null +++ b/plugins/Directory/DirectoryPlugin.php @@ -0,0 +1,159 @@ +. + * + * @category Plugin + * @package StatusNet + * @author Zach Copely + * @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')) { + exit(1); +} + +/** + * Directory plugin main class + * + * @category Plugin + * @package StatusNet + * @author Zach Copley + * @copyright 2011 StatusNet, Inc. + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html AGPL 3.0 + * @link http://status.net/ + */ +class DirectoryPlugin extends Plugin +{ + /** + * Initializer for this plugin + * + * @return boolean hook value; true means continue processing, + * false means stop. + */ + function initialize() + { + return true; + } + + /** + * Cleanup for this plugin. + * + * @return boolean hook value; true means continue processing, + * false means stop. + */ + function cleanup() + { + return true; + } + + /** + * Load related modules when needed + * + * @param string $cls Name of the class to be loaded + * + * @return boolean hook value; true means continue processing, + * false means stop. + */ + function onAutoload($cls) + { + $dir = dirname(__FILE__); + + // common_debug("class = $cls"); + + switch ($cls) + { + case 'UserdirectoryAction': + include_once $dir + . '/actions/' . strtolower(mb_substr($cls, 0, -6)) . '.php'; + return false; + case 'AlphaNav': + include_once $dir + . '/lib/' . strtolower($cls) . '.php'; + return false; + default: + return true; + } + } + + /** + * Map URLs to actions + * + * @param Net_URL_Mapper $m path-to-action mapper + * + * @return boolean hook value; true means continue processing, + * false means stop. + */ + function onRouterInitialized($m) + { + $m->connect( + 'main/directory', + array('action' => 'userdirectory') + ); + + return true; + } + + /** + * Modify the public local nav to add a link to the user directory + * + * @param Action $action The current action handler. Use this to + * do any output. + * + * @return boolean hook value; true means continue processing, + * false means stop. + * + * @see Action + */ + function onEndPublicGroupNav($nav) + { + // XXX: Maybe this should go under search instead? + + $actionName = $nav->action->trimmed('action'); + + $nav->out->menuItem( + common_local_url('userdirectory'), + _('Directory'), + _('User Directory'), + $actionName == 'userdirectory', + 'nav_directory' + ); + + return true; + } + + /* + * Version info + */ + function onPluginVersion(&$versions) + { + $versions[] = array( + 'name' => 'Directory', + 'version' => STATUSNET_VERSION, + 'author' => 'Zach Copley', + 'homepage' => 'http://status.net/wiki/Plugin:Directory', + 'rawdescription' => _m('Add a user directory.') + ); + + return true; + } +} diff --git a/plugins/Directory/actions/userdirectory.php b/plugins/Directory/actions/userdirectory.php new file mode 100644 index 0000000000..e4c8f673ed --- /dev/null +++ b/plugins/Directory/actions/userdirectory.php @@ -0,0 +1,241 @@ +. + * + * @category Public + * @package StatusNet + * @author Zach Copley + * @copyright 2011 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/publicgroupnav.php'; + +/** + * User directory + * + * @category Personal + * @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/ + */ +class UserdirectoryAction extends Action +{ + /* Page we're on */ + protected $page = null; + + /* What to filter the search results by */ + protected $filter = null; + + /** + * Title of the page + * + * @return string Title of the page + */ + function title() + { + // @fixme: This looks kinda gross + + if ($this->filter == 'All') { + if ($this->page != 1) { + return(sprintf(_m('All users, page %d'), $this->page)); + } + return _m('All users'); + } + + if ($this->page == 1) { + return sprintf( + _m('Users with nicknames beginning with %s'), + $this->filter + ); + } else { + return sprintf( + _m('Users with nicknames starting with %s, page %d'), + $this->filter, + $this->page + ); + } + } + + /** + * Instructions for use + * + * @return instructions for use + */ + function getInstructions() + { + return _('User directory'); + } + + /** + * Is this page read-only? + * + * @return boolean true + */ + function isReadOnly($args) + { + return true; + } + + /** + * Take arguments for running + * + * @param array $args $_REQUEST args + * + * @return boolean success flag + * + * @todo move queries from showContent() to here + */ + function prepare($args) + { + parent::prepare($args); + + $this->page = ($this->arg('page')) ? ($this->arg('page') + 0) : 1; + $this->filter = $this->arg('filter') ? $this->arg('filter') : 'All'; + common_set_returnto($this->selfUrl()); + + return true; + } + + /** + * Handle request + * + * Shows the page + * + * @param array $args $_REQUEST args; handled in prepare() + * + * @return void + */ + function handle($args) + { + parent::handle($args); + $this->showPage(); + } + + /** + * 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'); + } + + /** + * Local navigation + * + * This page is part of the public group, so show that. + * + * @return void + */ + function showLocalNav() + { + $nav = new PublicGroupNav($this); + $nav->show(); + } + + /** + * Content area + * + * Shows the list of popular notices + * + * @return void + */ + function showContent() + { + // XXX Need search bar + + $alphaNav = new AlphaNav($this, true, array('All')); + $alphaNav->show(); + + // XXX Maybe use a more specialized version of ProfileList here + + $profile = $this->getUsers(); + $cnt = 0; + + if (!empty($profile)) { + $profileList = new SubscriptionList( + $profile, + common_current_user(), + $this + ); + + $cnt = $profileList->show(); + + if (0 == $cnt) { + $this->showEmptyListMessage(); + } + } + + $this->pagination($this->page > 1, $cnt > PROFILES_PER_PAGE, + $this->page, 'userdirectory', + array('filter' => $this->filter)); + + } + + /* + * Get users filtered by the current filter and page + */ + function getUsers() + { + $offset = ($this->page-1) * PROFILES_PER_PAGE; + $limit = PROFILES_PER_PAGE + 1; + + $profile = new Profile(); + + if ($this->filter != 'All') { + $profile->whereAdd( + sprintf('LEFT(UPPER(nickname), 1) = \'%s\'', $this->filter) + ); + } + $profile->orderBy('created DESC, nickname'); + $profile->find(); + + return $profile; + } + + /** + * Show a nice message when there's no search results + */ + function showEmptyListMessage() + { + $message = sprintf(_m('No users starting with %s'), $this->filter); + + $this->elementStart('div', 'guide'); + $this->raw(common_markup_to_html($message)); + $this->elementEnd('div'); + } + +} diff --git a/plugins/Directory/lib/alphanav.php b/plugins/Directory/lib/alphanav.php new file mode 100644 index 0000000000..228237bfed --- /dev/null +++ b/plugins/Directory/lib/alphanav.php @@ -0,0 +1,107 @@ +. + * + * @category Widget + * @package StatusNet + * @author Zach Copley + * @copyright 2011 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); +} + +/** + * Outputs a fancy alphabet letter navigation menu + * + * @category Widget + * @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 HTMLOutputter + */ + +class AlphaNav extends Widget +{ + protected $action = null; + protected $filters = array(); + + /** + * Prepare the widget for use + * + * @param Action $action the current action + * @param boolean $numbers whether to output 0..9 + * @param Array $prepend array of filters to prepend + * @param Array $append array of filters to append + */ + function __construct( + $action = null, + $numbers = false, + $prepend = false, + $append = false + ) + { + parent::__construct($action); + + $this->action = $action; + + if ($prepend) { + $this->filters = array_merge($prepend, $this->filters); + } + + if ($numbers) { + $this->filters = array_merge($this->filters, range(0, 9)); + } + + if ($append) { + $this->filters = array_merge($this->filters, $append); + } + + $this->filters = array_merge($this->filters, range('A', 'Z')); + } + + /** + * Show the widget + * + * Emit the HTML for the widget, using the configured outputter. + * + * @return void + */ + + function show() + { + $actionName = $this->action->trimmed('action'); + + foreach ($this->filters as $filter) { + $href = common_local_url( + $actionName, + null, + array('filter' => $filter) + ); + $this->action->element('a', array('href' => $href), $filter); + } + } + +} -- 2.39.5