From cb49ea88d33d51ce5a7bec3c90bbea7e0cb33890 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Tue, 1 Mar 2011 19:35:20 -0800 Subject: [PATCH 01/10] 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); + } + } + +} From 3b186e1bae91ae0030c8eeb58fdfbc114dfd0b84 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Wed, 2 Mar 2011 20:21:15 -0800 Subject: [PATCH 02/10] * Fix pagination * Add some more elements for styling * Add initial CSS --- plugins/Directory/DirectoryPlugin.php | 40 +++++++++++++++++---- plugins/Directory/actions/userdirectory.php | 39 ++++++++++++++------ plugins/Directory/css/directory.css | 34 ++++++++++++++++++ plugins/Directory/lib/alphanav.php | 37 ++++++++++++++++--- 4 files changed, 129 insertions(+), 21 deletions(-) create mode 100644 plugins/Directory/css/directory.css diff --git a/plugins/Directory/DirectoryPlugin.php b/plugins/Directory/DirectoryPlugin.php index 0ff2ea76bf..aaa33a1ec1 100644 --- a/plugins/Directory/DirectoryPlugin.php +++ b/plugins/Directory/DirectoryPlugin.php @@ -44,6 +44,9 @@ if (!defined('STATUSNET')) { */ class DirectoryPlugin extends Plugin { + + private $dir = null; + /** * Initializer for this plugin * @@ -52,6 +55,7 @@ class DirectoryPlugin extends Plugin */ function initialize() { + $this->dir = dirname(__FILE__); return true; } @@ -76,18 +80,16 @@ class DirectoryPlugin extends Plugin */ function onAutoload($cls) { - $dir = dirname(__FILE__); - // common_debug("class = $cls"); switch ($cls) { case 'UserdirectoryAction': - include_once $dir + include_once $this->dir . '/actions/' . strtolower(mb_substr($cls, 0, -6)) . '.php'; return false; case 'AlphaNav': - include_once $dir + include_once $this->dir . '/lib/' . strtolower($cls) . '.php'; return false; default: @@ -106,10 +108,36 @@ class DirectoryPlugin extends Plugin function onRouterInitialized($m) { $m->connect( - 'main/directory', - array('action' => 'userdirectory') + 'directory/users/:filter', + array('action' => 'userdirectory'), + array('filter' => '[0-9a-zA-Z_]{1,64}') ); + $m->connect( + 'directory/users', + array('action' => 'userdirectory'), + array('filter' => 'all') + ); + + return true; + } + + /** + * Link in a styelsheet for the onboarding actions + * + * @param Action $action Action being shown + * + * @return boolean hook flag + */ + function onEndShowStatusNetStyles($action) + { + if (in_array( + $action->trimmed('action'), + array('userdirectory')) + ) { + $action->cssLink($this->path('css/directory.css')); + } + return true; } diff --git a/plugins/Directory/actions/userdirectory.php b/plugins/Directory/actions/userdirectory.php index e4c8f673ed..7e9f20c369 100644 --- a/plugins/Directory/actions/userdirectory.php +++ b/plugins/Directory/actions/userdirectory.php @@ -45,10 +45,14 @@ require_once INSTALLDIR . '/lib/publicgroupnav.php'; */ class UserdirectoryAction extends Action { - /* Page we're on */ + /** + * @var $page integer the page we're on + */ protected $page = null; - /* What to filter the search results by */ + /** + * @var $filter string what to filter the search results by + */ protected $filter = null; /** @@ -60,7 +64,7 @@ class UserdirectoryAction extends Action { // @fixme: This looks kinda gross - if ($this->filter == 'All') { + if ($this->filter == 'all') { if ($this->page != 1) { return(sprintf(_m('All users, page %d'), $this->page)); } @@ -115,7 +119,7 @@ class UserdirectoryAction extends Action parent::prepare($args); $this->page = ($this->arg('page')) ? ($this->arg('page') + 0) : 1; - $this->filter = $this->arg('filter') ? $this->arg('filter') : 'All'; + $this->filter = $this->arg('filter') ? $this->arg('filter') : 'all'; common_set_returnto($this->selfUrl()); return true; @@ -177,6 +181,8 @@ class UserdirectoryAction extends Action { // XXX Need search bar + $this->elementStart('div', array('id' => 'user_directory')); + $alphaNav = new AlphaNav($this, true, array('All')); $alphaNav->show(); @@ -199,9 +205,15 @@ class UserdirectoryAction extends Action } } - $this->pagination($this->page > 1, $cnt > PROFILES_PER_PAGE, - $this->page, 'userdirectory', - array('filter' => $this->filter)); + $this->pagination( + $this->page > 1, + $cnt > PROFILES_PER_PAGE, + $this->page, + 'userdirectory', + array('filter' => $this->filter) + ); + + $this->elementEnd('div'); } @@ -210,17 +222,22 @@ class UserdirectoryAction extends Action */ function getUsers() { - $offset = ($this->page-1) * PROFILES_PER_PAGE; - $limit = PROFILES_PER_PAGE + 1; + $offset = ($this->page - 1) * PROFILES_PER_PAGE; + $limit = PROFILES_PER_PAGE + 1; $profile = new Profile(); - if ($this->filter != 'All') { + // XXX Any chance of SQL injection here? + + if ($this->filter != 'all') { $profile->whereAdd( - sprintf('LEFT(UPPER(nickname), 1) = \'%s\'', $this->filter) + sprintf('LEFT(lower(nickname), 1) = \'%s\'', $this->filter) ); } + $profile->orderBy('created DESC, nickname'); + $profile->limit($limit, $offset); + $profile->find(); return $profile; diff --git a/plugins/Directory/css/directory.css b/plugins/Directory/css/directory.css new file mode 100644 index 0000000000..3778525a84 --- /dev/null +++ b/plugins/Directory/css/directory.css @@ -0,0 +1,34 @@ +/* CSS file for the Directory plugin */ + +div#user_directory div.alpha_nav { + overflow: hidden; + width: 100%; + text-align: center; +} + +/* XXX: this needs serious CSS foo */ +div#user_directory div.alpha_nav > a { + border-left: 1px solid #000; + padding-left: 2px; +} +div#user_directory div.alpha_nav > a.first { + border-left: none; +} + +div#user_directory div.alpha_nav a:link { + text-decoration: none; +} + +div#user_directory div.alpha_nav a:visited { + text-decoration: none; +} +div#user_directory div.alpha_nav a:active { + text-decoration: none; +} +div#user_directory div.alpha_nav a:hover { + text-decoration: underline; color: blue; +} + +div#user_directory div.alpha_nav a.current { + background-color:#9BB43E; +} diff --git a/plugins/Directory/lib/alphanav.php b/plugins/Directory/lib/alphanav.php index 228237bfed..6829f3d2c3 100644 --- a/plugins/Directory/lib/alphanav.php +++ b/plugins/Directory/lib/alphanav.php @@ -94,14 +94,43 @@ class AlphaNav extends Widget { $actionName = $this->action->trimmed('action'); - foreach ($this->filters as $filter) { + $this->action->elementStart('div', array('class' => 'alpha_nav')); + + for ($i = 0, $size = sizeof($this->filters); $i < $size; $i++) { + + $filter = $this->filters[$i]; + $classes = ''; + + // Add some classes for styling + if ($i == 0) { + $classes .= 'first '; // first filter in the list + } elseif ($i == $size - 1) { + $classes .= 'last '; // last filter in the list + } + $href = common_local_url( $actionName, - null, - array('filter' => $filter) + array('filter' => strtolower($filter)) ); - $this->action->element('a', array('href' => $href), $filter); + + $params = array('href' => $href); + $current = $this->action->arg('filter'); + + // Highlight the selected filter. If there is no selected + // filter, highlight the first filter in the list + if (empty($current) && $i == 0 + || $current === strtolower($filter)) { + $classes .= 'current '; + } + + if (!empty($classes)) { + $params['class'] = trim($classes); + } + + $this->action->element('a', $params, $filter); } + + $this->action->elementEnd('div'); } } From f157c523fd906f4b007d6f1b465b73832e291473 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Thu, 3 Mar 2011 21:12:24 -0800 Subject: [PATCH 03/10] * Reformat list of profiles in a table * Make table sortable --- plugins/Directory/DirectoryPlugin.php | 11 +- plugins/Directory/actions/userdirectory.php | 29 +- plugins/Directory/css/directory.css | 30 +++ .../Directory/images/control_arrow_down.gif | Bin 0 -> 110 bytes plugins/Directory/images/control_arrow_up.gif | Bin 0 -> 111 bytes plugins/Directory/lib/alphanav.php | 15 +- .../lib/sortablesubscriptionlist.php | 248 ++++++++++++++++++ 7 files changed, 326 insertions(+), 7 deletions(-) create mode 100644 plugins/Directory/images/control_arrow_down.gif create mode 100644 plugins/Directory/images/control_arrow_up.gif create mode 100644 plugins/Directory/lib/sortablesubscriptionlist.php diff --git a/plugins/Directory/DirectoryPlugin.php b/plugins/Directory/DirectoryPlugin.php index aaa33a1ec1..8fd7785ec9 100644 --- a/plugins/Directory/DirectoryPlugin.php +++ b/plugins/Directory/DirectoryPlugin.php @@ -55,7 +55,6 @@ class DirectoryPlugin extends Plugin */ function initialize() { - $this->dir = dirname(__FILE__); return true; } @@ -82,14 +81,20 @@ class DirectoryPlugin extends Plugin { // common_debug("class = $cls"); + $dir = dirname(__FILE__); + switch ($cls) { case 'UserdirectoryAction': - include_once $this->dir + include_once $dir . '/actions/' . strtolower(mb_substr($cls, 0, -6)) . '.php'; return false; case 'AlphaNav': - include_once $this->dir + include_once $dir + . '/lib/' . strtolower($cls) . '.php'; + return false; + case 'SortableSubscriptionList': + include_once $dir . '/lib/' . strtolower($cls) . '.php'; return false; default: diff --git a/plugins/Directory/actions/userdirectory.php b/plugins/Directory/actions/userdirectory.php index 7e9f20c369..7b8dbbdf60 100644 --- a/plugins/Directory/actions/userdirectory.php +++ b/plugins/Directory/actions/userdirectory.php @@ -120,6 +120,9 @@ class UserdirectoryAction extends Action $this->page = ($this->arg('page')) ? ($this->arg('page') + 0) : 1; $this->filter = $this->arg('filter') ? $this->arg('filter') : 'all'; + $this->sort = $this->arg('sort'); + $this->order = $this->boolean('asc'); // ascending or decending + common_set_returnto($this->selfUrl()); return true; @@ -192,7 +195,7 @@ class UserdirectoryAction extends Action $cnt = 0; if (!empty($profile)) { - $profileList = new SubscriptionList( + $profileList = new SortableSubscriptionList( $profile, common_current_user(), $this @@ -235,7 +238,10 @@ class UserdirectoryAction extends Action ); } - $profile->orderBy('created DESC, nickname'); + $sort = $this->getSortKey(); + $order = ($this->order) ? 'ASC' : 'DESC'; + + $profile->orderBy("$sort $order, nickname"); $profile->limit($limit, $offset); $profile->find(); @@ -243,6 +249,25 @@ class UserdirectoryAction extends Action return $profile; } + /** + * Filter the sort parameter + * + * @return string a column name for sorting + */ + function getSortKey() + { + switch ($this->sort) { + case 'nickname': + return $this->sort; + break; + case 'created': + return $this->sort; + break; + default: + return 'nickname'; + } + } + /** * Show a nice message when there's no search results */ diff --git a/plugins/Directory/css/directory.css b/plugins/Directory/css/directory.css index 3778525a84..76c9fc2583 100644 --- a/plugins/Directory/css/directory.css +++ b/plugins/Directory/css/directory.css @@ -32,3 +32,33 @@ div#user_directory div.alpha_nav a:hover { div#user_directory div.alpha_nav a.current { background-color:#9BB43E; } + +table.profile_list { + width: 100%; +} + +table.profile_list tr { + float: none; +} + +table.profile_list tr.alt { + background-color: #def; /* zebra stripe */ +} + +table.profie_list td { + width: 100%; + padding: 0; +} + + +th.current { + background-image: url(../images/control_arrow_down.gif); + background-repeat: no-repeat; + background-position: 60% 2px; +} + +th.current.asc { + background-image: url(../images/control_arrow_up.gif); + background-repeat: no-repeat; + background-position: 60% 2px; +} \ No newline at end of file diff --git a/plugins/Directory/images/control_arrow_down.gif b/plugins/Directory/images/control_arrow_down.gif new file mode 100644 index 0000000000000000000000000000000000000000..de28df6eb09f57780f20337be3df81ebfc714511 GIT binary patch literal 110 zcmZ?wbhEHb $href); + + // sort column + if (!empty($this->action->sort)) { + $params['sort'] = $this->action->sort; + } + + // sort order + if (!empty($this->action->order)) { + $params['asc'] = 'true'; + } + $current = $this->action->arg('filter'); // Highlight the selected filter. If there is no selected // filter, highlight the first filter in the list - if (empty($current) && $i == 0 + if (!isset($current) && $i == 0 || $current === strtolower($filter)) { $classes .= 'current '; } diff --git a/plugins/Directory/lib/sortablesubscriptionlist.php b/plugins/Directory/lib/sortablesubscriptionlist.php new file mode 100644 index 0000000000..2a412a628d --- /dev/null +++ b/plugins/Directory/lib/sortablesubscriptionlist.php @@ -0,0 +1,248 @@ +. + * + * @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/subscriptionlist.php'; + +/** + * Widget to show a sortable list of subscriptions + * + * @category Public + * @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 SortableSubscriptionList extends SubscriptionList +{ + /** Owner of this list */ + var $owner = null; + + function __construct($profile, $owner=null, $action=null) + { + parent::__construct($profile, $owner, $action); + + $this->owner = $owner; + } + + function startList() + { + $this->out->elementStart('table', array('class' => 'profile_list xoxo')); + $this->out->elementStart('thead'); + $this->out->elementStart('tr'); + + $tableHeaders = array( + 'nickname' => _m('Nickname'), + 'created' => _m('Created') + ); + + foreach ($tableHeaders as $id => $label) { + $attrs = array('id' => $id); + + $current = (!empty($this->action->sort) && $this->action->sort == $id); + + if ($current || empty($this->action->sort) && $id == 'nickname') { + $attrs['class'] = 'current'; + } + + if ($current && !$this->action->boolean('asc')) { + $attrs['class'] .= ' asc'; + $attrs['class'] = trim($attrs['class']); + } + + $this->out->elementStart('th', $attrs); + + $linkAttrs = array(); + $params = array('sort' => $id); + + if ($current && !$this->action->boolean('asc')) { + $params['asc'] = "true"; + } + + $args = array(); + + $filter = $this->action->arg('filter'); + + if (!empty($filter)) { + $args['filter'] = $filter; + } + + $linkAttrs['href'] = common_local_url( + $this->action->arg('action'), $args, $params + ); + + $this->out->element('a', $linkAttrs, $label); + $this->out->elementEnd('th'); + } + + $this->out->element('th', array('id' => 'subscriptions'), 'Subscriptions'); + $this->out->element('th', array('id' => 'notices'), 'Notices'); + //$this->out->element('th', array('id' => 'controls'), 'Controls'); + + $this->out->elementEnd('tr'); + $this->out->elementEnd('thead'); + + $this->out->elementStart('tbody'); + } + + function endList() + { + $this->out->elementEnd('tbody'); + $this->out->elementEnd('table'); + } + + function showProfiles() + { + $cnt = 0; + + while ($this->profile->fetch()) { + $cnt++; + if($cnt > PROFILES_PER_PAGE) { + break; + } + + $odd = ($cnt % 2 == 0); // for zebra striping + + $pli = $this->newListItem($this->profile, $odd); + $pli->show(); + } + + return $cnt; + } + + function newListItem($profile, $odd) + { + return new SortableSubscriptionListItem($profile, $this->owner, $this->action, $odd); + } +} + +class SortableSubscriptionListItem extends SubscriptionListItem +{ + /** Owner of this list */ + var $owner = null; + + function __construct($profile, $owner, $action, $alt) + { + parent::__construct($profile, $owner, $action); + + $this->alt = $alt; // is this row alternate? + $this->owner = $owner; + } + + function startItem() + { + $attr = array( + 'class' => 'profile', + 'id' => 'profile-' . $this->profile->id + ); + + if ($this->alt) { + $attr['class'] .= ' alt'; + } + + $this->out->elementStart('tr', $attr); + } + + function endItem() + { + $this->out->elementEnd('tr'); + } + + function startProfile() + { + $this->out->elementStart('td', 'entity_profile vcard entry-content'); + } + + function endProfile() + { + $this->out->elementEnd('td'); + } + + function startActions() + { + $this->out->elementStart('td', 'entity_actions'); + $this->out->elementStart('ul'); + } + + function endActions() + { + $this->out->elementEnd('ul'); + $this->out->elementEnd('td'); + } + + function show() + { + if (Event::handle('StartProfileListItem', array($this))) { + $this->startItem(); + if (Event::handle('StartProfileListItemProfile', array($this))) { + $this->showProfile(); + Event::handle('EndProfileListItemProfile', array($this)); + } + + // XXX Add events? + $this->showCreatedDate(); + $this->showSubscriberCount(); + $this->showNoticeCount(); + + if (Event::handle('StartProfileListItemActions', array($this))) { + $this->showActions(); + Event::handle('EndProfileListItemActions', array($this)); + } + $this->endItem(); + Event::handle('EndProfileListItem', array($this)); + } + } + + function showSubscriberCount() + { + $this->out->elementStart('td', 'entry_subscriber_count'); + $this->out->raw($this->profile->subscriberCount()); + $this->out->elementEnd('td'); + } + + function showCreatedDate() + { + $this->out->elementStart('td', 'entry_created'); + $this->out->raw(date('j M Y', strtotime($this->profile->created))); + $this->out->elementEnd('td'); + } + + function showNoticeCount() + { + $this->out->elementStart('td', 'entry_notice_count'); + $this->out->raw($this->profile->noticeCount()); + $this->out->elementEnd('td'); + } + +} From 52df926b8d7d1c284bc4f6dcf6ce4d8a74730087 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Fri, 4 Mar 2011 17:25:58 -0800 Subject: [PATCH 04/10] Only show profiles of local users --- plugins/Directory/actions/userdirectory.php | 29 +++++++++++-------- .../lib/sortablesubscriptionlist.php | 11 +++++++ 2 files changed, 28 insertions(+), 12 deletions(-) diff --git a/plugins/Directory/actions/userdirectory.php b/plugins/Directory/actions/userdirectory.php index 7b8dbbdf60..60ab43693b 100644 --- a/plugins/Directory/actions/userdirectory.php +++ b/plugins/Directory/actions/userdirectory.php @@ -119,7 +119,8 @@ class UserdirectoryAction extends Action parent::prepare($args); $this->page = ($this->arg('page')) ? ($this->arg('page') + 0) : 1; - $this->filter = $this->arg('filter') ? $this->arg('filter') : 'all'; + $filter = $this->arg('filter'); + $this->filter = isset($filter) ? $filter : 'all'; $this->sort = $this->arg('sort'); $this->order = $this->boolean('asc'); // ascending or decending @@ -225,26 +226,30 @@ class UserdirectoryAction extends Action */ function getUsers() { - $offset = ($this->page - 1) * PROFILES_PER_PAGE; - $limit = PROFILES_PER_PAGE + 1; $profile = new Profile(); - // XXX Any chance of SQL injection here? + $offset = ($this->page - 1) * PROFILES_PER_PAGE; + $limit = PROFILES_PER_PAGE + 1; + $sort = $this->getSortKey(); + $sql = 'SELECT profile.* FROM profile, user WHERE profile.id = user.id'; if ($this->filter != 'all') { - $profile->whereAdd( - sprintf('LEFT(lower(nickname), 1) = \'%s\'', $this->filter) + $sql .= sprintf( + ' AND LEFT(LOWER(profile.nickname), 1) = \'%s\'', + $this->filter ); } - $sort = $this->getSortKey(); - $order = ($this->order) ? 'ASC' : 'DESC'; + $sql .= sprintf( + ' ORDER BY profile.%s %s, profile.nickname DESC LIMIT %d, %d', + $sort, + ($this->order) ? 'ASC' : 'DESC', + $offset, + $limit + ); - $profile->orderBy("$sort $order, nickname"); - $profile->limit($limit, $offset); - - $profile->find(); + $profile->query($sql); return $profile; } diff --git a/plugins/Directory/lib/sortablesubscriptionlist.php b/plugins/Directory/lib/sortablesubscriptionlist.php index 2a412a628d..a22aeadb3d 100644 --- a/plugins/Directory/lib/sortablesubscriptionlist.php +++ b/plugins/Directory/lib/sortablesubscriptionlist.php @@ -245,4 +245,15 @@ class SortableSubscriptionListItem extends SubscriptionListItem $this->out->elementEnd('td'); } + /** + * Only show the tags if we're logged in + */ + function showTags() + { + if (common_logged_in()) { + parent::showTags(); + } + + } + } From 7d76b55da18df126372780e74f7943dd2e9b2323 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Fri, 4 Mar 2011 17:55:56 -0800 Subject: [PATCH 05/10] fixup comments --- plugins/Directory/actions/userdirectory.php | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/plugins/Directory/actions/userdirectory.php b/plugins/Directory/actions/userdirectory.php index 60ab43693b..f6ff0b3eec 100644 --- a/plugins/Directory/actions/userdirectory.php +++ b/plugins/Directory/actions/userdirectory.php @@ -46,12 +46,16 @@ require_once INSTALLDIR . '/lib/publicgroupnav.php'; class UserdirectoryAction extends Action { /** - * @var $page integer the page we're on + * The page we're on + * + * @var integer */ protected $page = null; /** - * @var $filter string what to filter the search results by + * what to filter the search results by + * + * @var string */ protected $filter = null; @@ -111,8 +115,6 @@ class UserdirectoryAction extends Action * @param array $args $_REQUEST args * * @return boolean success flag - * - * @todo move queries from showContent() to here */ function prepare($args) { @@ -222,7 +224,8 @@ class UserdirectoryAction extends Action } /* - * Get users filtered by the current filter and page + * Get users filtered by the current filter, sort key, + * sort order, and page */ function getUsers() { @@ -278,7 +281,7 @@ class UserdirectoryAction extends Action */ function showEmptyListMessage() { - $message = sprintf(_m('No users starting with %s'), $this->filter); + $message = sprintf(_m('No users starting with **%s**'), $this->filter); $this->elementStart('div', 'guide'); $this->raw(common_markup_to_html($message)); From 5f1a795b735e6054c7e9e7f2b32850c74ec95552 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Sat, 5 Mar 2011 01:54:47 -0800 Subject: [PATCH 06/10] Add some other ways to order searches to the base search engine class --- lib/search_engines.php | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/lib/search_engines.php b/lib/search_engines.php index 19703e03fd..7f1684a3e7 100644 --- a/lib/search_engines.php +++ b/lib/search_engines.php @@ -41,8 +41,35 @@ class SearchEngine function set_sort_mode($mode) { - if ('chron' === $mode) - return $this->target->orderBy('created desc'); + switch ($mode) { + case 'chron': + return $this->target->orderBy('created DESC'); + break; + case 'reverse_chron': + return $this->target->orderBy('created ASC'); + break; + case 'nickname_desc': + if ($this->table != 'profile') { + throw new Exception( + 'nickname_desc sort mode can only be use when searching profile.' + ); + } else { + return $this->target->orderBy('nickname DESC'); + } + break; + case 'nickname_asc': + if ($this->table != 'profile') { + throw new Exception( + 'nickname_desc sort mode can only be use when searching profile.' + ); + } else { + return $this->target->orderBy('nickname ASC'); + } + break; + default: + return $this->target->orderBy('created DESC'); + break; + } } } From 5d22f969a1ca27d2a81c27596978e7e0479310fb Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Sat, 5 Mar 2011 01:55:52 -0800 Subject: [PATCH 07/10] * Integrate search input box * Fix ordering --- plugins/Directory/DirectoryPlugin.php | 12 +- plugins/Directory/actions/userdirectory.php | 137 ++++++++++++++---- plugins/Directory/css/directory.css | 2 +- plugins/Directory/lib/alphanav.php | 4 +- .../lib/sortablesubscriptionlist.php | 16 +- 5 files changed, 128 insertions(+), 43 deletions(-) diff --git a/plugins/Directory/DirectoryPlugin.php b/plugins/Directory/DirectoryPlugin.php index 8fd7785ec9..50a0da7cf9 100644 --- a/plugins/Directory/DirectoryPlugin.php +++ b/plugins/Directory/DirectoryPlugin.php @@ -112,18 +112,18 @@ class DirectoryPlugin extends Plugin */ function onRouterInitialized($m) { - $m->connect( - 'directory/users/:filter', - array('action' => 'userdirectory'), - array('filter' => '[0-9a-zA-Z_]{1,64}') - ); - $m->connect( 'directory/users', array('action' => 'userdirectory'), array('filter' => 'all') ); + $m->connect( + 'directory/users/:filter', + array('action' => 'userdirectory'), + array('filter' => '[0-9a-zA-Z_]{1,64}') + ); + return true; } diff --git a/plugins/Directory/actions/userdirectory.php b/plugins/Directory/actions/userdirectory.php index f6ff0b3eec..005fb787d3 100644 --- a/plugins/Directory/actions/userdirectory.php +++ b/plugins/Directory/actions/userdirectory.php @@ -50,14 +50,35 @@ class UserdirectoryAction extends Action * * @var integer */ - protected $page = null; + public $page; /** - * what to filter the search results by + * What to filter the search results by * * @var string */ - protected $filter = null; + public $filter; + + /** + * Column to sort by + * + * @var string + */ + public $sort; + + /** + * How to order search results, ascending or descending + * + * @var string + */ + public $reverse; + + /** + * Query + * + * @var string + */ + public $q; /** * Title of the page @@ -120,11 +141,11 @@ class UserdirectoryAction extends Action { parent::prepare($args); - $this->page = ($this->arg('page')) ? ($this->arg('page') + 0) : 1; - $filter = $this->arg('filter'); - $this->filter = isset($filter) ? $filter : 'all'; - $this->sort = $this->arg('sort'); - $this->order = $this->boolean('asc'); // ascending or decending + $this->page = ($this->arg('page')) ? ($this->arg('page') + 0) : 1; + $this->filter = $this->arg('filter', 'all'); + $this->reverse = $this->boolean('reverse'); + $this->q = $this->trimmed('q'); + $this->sort = $this->arg('sort', 'nickname'); common_set_returnto($this->selfUrl()); @@ -185,15 +206,14 @@ class UserdirectoryAction extends Action */ function showContent() { - // XXX Need search bar + $this->showForm(); $this->elementStart('div', array('id' => 'user_directory')); $alphaNav = new AlphaNav($this, true, array('All')); $alphaNav->show(); - // XXX Maybe use a more specialized version of ProfileList here - + $profile = null; $profile = $this->getUsers(); $cnt = 0; @@ -205,55 +225,116 @@ class UserdirectoryAction extends Action ); $cnt = $profileList->show(); + $profile->free(); if (0 == $cnt) { $this->showEmptyListMessage(); } } + $args = array(); + if (isset($this->q)) { + $args['q'] = $this->q; + } else { + $args['filter'] = $this->filter; + } + $this->pagination( $this->page > 1, $cnt > PROFILES_PER_PAGE, $this->page, 'userdirectory', - array('filter' => $this->filter) + $args ); $this->elementEnd('div'); } + function showForm($error=null) + { + $this->elementStart( + 'form', + array( + 'method' => 'get', + 'id' => 'form_search', + 'class' => 'form_settings', + 'action' => common_local_url('userdirectory') + ) + ); + + $this->elementStart('fieldset'); + + $this->element('legend', null, _('Search site')); + $this->elementStart('ul', 'form_data'); + $this->elementStart('li'); + + $this->input('q', _('Keyword(s)'), $this->q); + + $this->submit('search', _m('BUTTON','Search')); + $this->elementEnd('li'); + $this->elementEnd('ul'); + $this->elementEnd('fieldset'); + $this->elementEnd('form'); + } + /* * Get users filtered by the current filter, sort key, * sort order, and page */ function getUsers() { - $profile = new Profile(); $offset = ($this->page - 1) * PROFILES_PER_PAGE; $limit = PROFILES_PER_PAGE + 1; - $sort = $this->getSortKey(); - $sql = 'SELECT profile.* FROM profile, user WHERE profile.id = user.id'; - if ($this->filter != 'all') { + if (isset($this->q)) { + // User is searching via query + $search_engine = $profile->getSearchEngine('profile'); + + $mode = 'reverse_chron'; + + if ($this->sort == 'nickname') { + if ($this->reverse) { + $mode = 'nickname_desc'; + } else { + $mode = 'nickname_asc'; + } + } else { + if ($this->reverse) { + $mode = 'chron'; + } + } + + $search_engine->set_sort_mode($mode); + $search_engine->limit($offset, $limit); + $search_engine->query($this->q); + + $profile->find(); + } else { + // User is browsing via AlphaNav + $sort = $this->getSortKey(); + $sql = 'SELECT profile.* FROM profile, user WHERE profile.id = user.id'; + + if ($this->filter != 'all') { + $sql .= sprintf( + ' AND LEFT(LOWER(profile.nickname), 1) = \'%s\'', + $this->filter + ); + } + $sql .= sprintf( - ' AND LEFT(LOWER(profile.nickname), 1) = \'%s\'', - $this->filter + ' ORDER BY profile.%s %s, profile.nickname ASC LIMIT %d, %d', + $sort, + $this->reverse ? 'DESC' : 'ASC', + $offset, + $limit ); + + $profile->query($sql); } - $sql .= sprintf( - ' ORDER BY profile.%s %s, profile.nickname DESC LIMIT %d, %d', - $sort, - ($this->order) ? 'ASC' : 'DESC', - $offset, - $limit - ); - - $profile->query($sql); - return $profile; } diff --git a/plugins/Directory/css/directory.css b/plugins/Directory/css/directory.css index 76c9fc2583..14fd2ce23b 100644 --- a/plugins/Directory/css/directory.css +++ b/plugins/Directory/css/directory.css @@ -57,7 +57,7 @@ th.current { background-position: 60% 2px; } -th.current.asc { +th.current.reverse { background-image: url(../images/control_arrow_up.gif); background-repeat: no-repeat; background-position: 60% 2px; diff --git a/plugins/Directory/lib/alphanav.php b/plugins/Directory/lib/alphanav.php index 33380b0b2b..645cdfa601 100644 --- a/plugins/Directory/lib/alphanav.php +++ b/plugins/Directory/lib/alphanav.php @@ -121,8 +121,8 @@ class AlphaNav extends Widget } // sort order - if (!empty($this->action->order)) { - $params['asc'] = 'true'; + if ($this->action->reverse) { + $params['reverse'] = 'true'; } $current = $this->action->arg('filter'); diff --git a/plugins/Directory/lib/sortablesubscriptionlist.php b/plugins/Directory/lib/sortablesubscriptionlist.php index a22aeadb3d..8f6e66d20a 100644 --- a/plugins/Directory/lib/sortablesubscriptionlist.php +++ b/plugins/Directory/lib/sortablesubscriptionlist.php @@ -68,16 +68,16 @@ class SortableSubscriptionList extends SubscriptionList ); foreach ($tableHeaders as $id => $label) { - $attrs = array('id' => $id); + $attrs = array('id' => $id); $current = (!empty($this->action->sort) && $this->action->sort == $id); if ($current || empty($this->action->sort) && $id == 'nickname') { $attrs['class'] = 'current'; } - if ($current && !$this->action->boolean('asc')) { - $attrs['class'] .= ' asc'; + if ($current && $this->action->reverse) { + $attrs['class'] .= ' reverse'; $attrs['class'] = trim($attrs['class']); } @@ -86,8 +86,12 @@ class SortableSubscriptionList extends SubscriptionList $linkAttrs = array(); $params = array('sort' => $id); - if ($current && !$this->action->boolean('asc')) { - $params['asc'] = "true"; + if (!empty($this->action->q)) { + $params['q'] = $this->action->q; + } + + if ($current && !$this->action->reverse) { + $params['reverse'] = 'true'; } $args = array(); @@ -108,7 +112,7 @@ class SortableSubscriptionList extends SubscriptionList $this->out->element('th', array('id' => 'subscriptions'), 'Subscriptions'); $this->out->element('th', array('id' => 'notices'), 'Notices'); - //$this->out->element('th', array('id' => 'controls'), 'Controls'); + $this->out->element('th', array('id' => 'controls'), null); $this->out->elementEnd('tr'); $this->out->elementEnd('thead'); From 00c14ffa88c508d1675881e6a20b70f2b1288963 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Sun, 6 Mar 2011 22:07:42 -0800 Subject: [PATCH 08/10] Better instructions, and better empty search results messages. --- plugins/Directory/actions/userdirectory.php | 50 ++++++++++++++------- 1 file changed, 35 insertions(+), 15 deletions(-) diff --git a/plugins/Directory/actions/userdirectory.php b/plugins/Directory/actions/userdirectory.php index 005fb787d3..20ec5c19e3 100644 --- a/plugins/Directory/actions/userdirectory.php +++ b/plugins/Directory/actions/userdirectory.php @@ -91,20 +91,18 @@ class UserdirectoryAction extends Action if ($this->filter == 'all') { if ($this->page != 1) { - return(sprintf(_m('All users, page %d'), $this->page)); + return(sprintf(_m('User Directory, page %d'), $this->page)); } - return _m('All users'); - } - - if ($this->page == 1) { + return _m('User directory'); + } else if ($this->page == 1) { return sprintf( - _m('Users with nicknames beginning with %s'), - $this->filter + _m('User directory - %s'), + strtoupper($this->filter) ); } else { return sprintf( - _m('Users with nicknames starting with %s, page %d'), - $this->filter, + _m('User directory - %s, page %d'), + strtoupper($this->filter), $this->page ); } @@ -117,7 +115,12 @@ class UserdirectoryAction extends Action */ function getInstructions() { - return _('User directory'); + // TRANS: %%site.name%% is the name of the StatusNet site. + return _( + 'Search for people on %%site.name%% by their name, ' + . 'location, or interests. Separate the terms by spaces; ' + . ' they must be 3 characters or more.' + ); } /** @@ -362,11 +365,28 @@ class UserdirectoryAction extends Action */ 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'); + if (!empty($this->filter) && ($this->filter != 'all')) { + $this->element( + 'p', + 'error', + sprintf( + _m('No users starting with %s'), + $this->filter + ) + ); + } else { + $this->element('p', 'error', _('No results.')); + $message = _m(<<elementStart('div', 'help instructions'); + $this->raw(common_markup_to_html($message)); + $this->elementEnd('div'); + } } } From b431a3b21686b67f2b8fc95feeb03f545e8e3ce3 Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Mon, 7 Mar 2011 14:32:14 -0800 Subject: [PATCH 09/10] Rearrange alphanav to better fit 3CL --- plugins/Directory/DirectoryPlugin.php | 2 +- plugins/Directory/actions/userdirectory.php | 13 +++++++++++-- plugins/Directory/lib/alphanav.php | 4 ++-- 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/plugins/Directory/DirectoryPlugin.php b/plugins/Directory/DirectoryPlugin.php index 50a0da7cf9..541ec556bf 100644 --- a/plugins/Directory/DirectoryPlugin.php +++ b/plugins/Directory/DirectoryPlugin.php @@ -121,7 +121,7 @@ class DirectoryPlugin extends Plugin $m->connect( 'directory/users/:filter', array('action' => 'userdirectory'), - array('filter' => '[0-9a-zA-Z_]{1,64}') + array('filter' => '([0-9a-zA-Z_]{1,64}|0-9)') ); return true; diff --git a/plugins/Directory/actions/userdirectory.php b/plugins/Directory/actions/userdirectory.php index 20ec5c19e3..24d91ad772 100644 --- a/plugins/Directory/actions/userdirectory.php +++ b/plugins/Directory/actions/userdirectory.php @@ -213,7 +213,7 @@ class UserdirectoryAction extends Action $this->elementStart('div', array('id' => 'user_directory')); - $alphaNav = new AlphaNav($this, true, array('All')); + $alphaNav = new AlphaNav($this, false, false, array('0-9', 'All')); $alphaNav->show(); $profile = null; @@ -320,7 +320,16 @@ class UserdirectoryAction extends Action $sort = $this->getSortKey(); $sql = 'SELECT profile.* FROM profile, user WHERE profile.id = user.id'; - if ($this->filter != 'all') { + switch($this->filter) + { + case 'all': + // NOOP + break; + case '0-9': + $sql .= + ' AND LEFT(profile.nickname, 1) BETWEEN \'0\' AND \'9\''; + break; + default: $sql .= sprintf( ' AND LEFT(LOWER(profile.nickname), 1) = \'%s\'', $this->filter diff --git a/plugins/Directory/lib/alphanav.php b/plugins/Directory/lib/alphanav.php index 645cdfa601..dadb589094 100644 --- a/plugins/Directory/lib/alphanav.php +++ b/plugins/Directory/lib/alphanav.php @@ -75,11 +75,11 @@ class AlphaNav extends Widget $this->filters = array_merge($this->filters, range(0, 9)); } + $this->filters = array_merge($this->filters, range('A', 'Z')); + if ($append) { $this->filters = array_merge($this->filters, $append); } - - $this->filters = array_merge($this->filters, range('A', 'Z')); } /** From 68a3246f1cb1debf45687770fdf840af778694da Mon Sep 17 00:00:00 2001 From: Zach Copley Date: Mon, 7 Mar 2011 17:18:30 -0800 Subject: [PATCH 10/10] Fixup sphinx plugin to have additional sort orders --- plugins/SphinxSearch/sphinxsearch.php | 32 ++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/plugins/SphinxSearch/sphinxsearch.php b/plugins/SphinxSearch/sphinxsearch.php index 1ce9bfd72d..46b5e3e28a 100644 --- a/plugins/SphinxSearch/sphinxsearch.php +++ b/plugins/SphinxSearch/sphinxsearch.php @@ -73,9 +73,39 @@ class SphinxSearch extends SearchEngine function set_sort_mode($mode) { - if ('chron' === $mode) { + switch ($mode) { + case 'chron': $this->sphinx->SetSortMode(SPH_SORT_ATTR_DESC, 'created_ts'); return $this->target->orderBy('id desc'); + break; + case 'reverse_chron': + $this->sphinx->SetSortMode(SPH_SORT_ATTR_ASC, 'created_ts'); + return $this->target->orderBy('id asc'); + break; + case 'nickname_desc': + if ($this->table != 'profile') { + throw new Exception( + 'nickname_desc sort mode can only be use when searching profile.' + ); + } else { + $this->sphinx->SetSortMode(SPH_SORT_ATTR_DESC, 'nickname'); + return $this->target->orderBy('id desc'); + } + break; + case 'nickname_asc': + if ($this->table != 'profile') { + throw new Exception( + 'nickname_desc sort mode can only be use when searching profile.' + ); + } else { + $this->sphinx->SetSortMode(SPH_SORT_ATTR_ASC, 'nickname'); + return $this->target->orderBy('id asc'); + } + break; + default: + $this->sphinx->SetSortMode(SPH_SORT_ATTR_DESC, 'created_ts'); + return $this->target->orderBy('id desc'); + break; } }