Add a name token table so on-demand typeaheads can match last names
Summary: See T585. We currently don't match middle/last/nth names in on-demand tokenizers. Build a table so we can match them. Test Plan: Ran upgrade script, verified table looks sensible. Searched for "priestley" in a tokenizer, got a bunch of test account hits. mysql> select * from user_nametoken; +-------------------+--------+ | token | userID | +-------------------+--------+ | evan | 1 | | priestley | 1 | | epriestley | 1 | | epriestley2 | 2 | | ducks | 4 | | epriestley3 | 4 | | asdf | 6 | | epriestley99 | 6 | ... Reviewers: bh, nh, jungejason, tuomaspelkonen, aran Reviewed By: aran CC: aran Differential Revision: 1034
This commit is contained in:
@@ -19,6 +19,7 @@
|
||||
class PhabricatorUser extends PhabricatorUserDAO {
|
||||
|
||||
const SESSION_TABLE = 'phabricator_session';
|
||||
const NAMETOKEN_TABLE = 'user_nametoken';
|
||||
|
||||
protected $phid;
|
||||
protected $userName;
|
||||
@@ -91,6 +92,7 @@ class PhabricatorUser extends PhabricatorUserDAO {
|
||||
}
|
||||
$result = parent::save();
|
||||
|
||||
$this->updateNameTokens();
|
||||
PhabricatorSearchUserIndexer::indexUser($this);
|
||||
|
||||
return $result;
|
||||
@@ -349,4 +351,53 @@ class PhabricatorUser extends PhabricatorUserDAO {
|
||||
return $preferences;
|
||||
}
|
||||
|
||||
private static function tokenizeName($name) {
|
||||
if (function_exists('mb_strtolower')) {
|
||||
$name = mb_strtolower($name, 'UTF-8');
|
||||
} else {
|
||||
$name = strtolower($name);
|
||||
}
|
||||
$name = trim($name);
|
||||
if (!strlen($name)) {
|
||||
return array();
|
||||
}
|
||||
return preg_split('/\s+/', $name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Populate the nametoken table, which used to fetch typeahead results. When
|
||||
* a user types "linc", we want to match "Abraham Lincoln" from on-demand
|
||||
* typeahead sources. To do this, we need a separate table of name fragments.
|
||||
*/
|
||||
public function updateNameTokens() {
|
||||
$tokens = array_merge(
|
||||
self::tokenizeName($this->getRealName()),
|
||||
self::tokenizeName($this->getUserName()));
|
||||
$tokens = array_unique($tokens);
|
||||
$table = self::NAMETOKEN_TABLE;
|
||||
$conn_w = $this->establishConnection('w');
|
||||
|
||||
$sql = array();
|
||||
foreach ($tokens as $token) {
|
||||
$sql[] = qsprintf(
|
||||
$conn_w,
|
||||
'(%d, %s)',
|
||||
$this->getID(),
|
||||
$token);
|
||||
}
|
||||
|
||||
queryfx(
|
||||
$conn_w,
|
||||
'DELETE FROM %T WHERE userID = %d',
|
||||
$table,
|
||||
$this->getID());
|
||||
if ($sql) {
|
||||
queryfx(
|
||||
$conn_w,
|
||||
'INSERT INTO %T (userID, token) VALUES %Q',
|
||||
$table,
|
||||
implode(', ', $sql));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ phutil_require_module('phabricator', 'applications/phid/constants');
|
||||
phutil_require_module('phabricator', 'applications/phid/storage/phid');
|
||||
phutil_require_module('phabricator', 'applications/search/index/indexer/user');
|
||||
phutil_require_module('phabricator', 'infrastructure/env');
|
||||
phutil_require_module('phabricator', 'storage/qsprintf');
|
||||
phutil_require_module('phabricator', 'storage/queryfx');
|
||||
|
||||
phutil_require_module('phutil', 'filesystem');
|
||||
|
||||
@@ -85,12 +85,21 @@ class PhabricatorTypeaheadCommonDatasourceController
|
||||
'realName',
|
||||
'phid');
|
||||
if ($query) {
|
||||
// TODO: We probably need to split last names here. Workaround until
|
||||
// we get that up and running is to not enable server-side datasources.
|
||||
$users = id(new PhabricatorUser())->loadColumnsWhere($columns,
|
||||
'(userName LIKE %> OR realName LIKE %>)',
|
||||
$query,
|
||||
$conn_r = id(new PhabricatorUser())->establishConnection('r');
|
||||
$ids = queryfx_all(
|
||||
$conn_r,
|
||||
'SELECT DISTINCT userID FROM %T WHERE token LIKE %>',
|
||||
PhabricatorUser::NAMETOKEN_TABLE,
|
||||
$query);
|
||||
$ids = ipull($ids, 'userID');
|
||||
if ($ids) {
|
||||
$users = id(new PhabricatorUser())->loadColumnsWhere(
|
||||
$columns,
|
||||
'id IN (%Ld)',
|
||||
$ids);
|
||||
} else {
|
||||
$users = array();
|
||||
}
|
||||
} else {
|
||||
$users = id(new PhabricatorUser())->loadColumns($columns);
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ phutil_require_module('phabricator', 'applications/project/storage/project');
|
||||
phutil_require_module('phabricator', 'applications/repository/storage/arcanistproject');
|
||||
phutil_require_module('phabricator', 'applications/repository/storage/repository');
|
||||
phutil_require_module('phabricator', 'applications/typeahead/controller/base');
|
||||
phutil_require_module('phabricator', 'storage/queryfx');
|
||||
|
||||
phutil_require_module('phutil', 'utils');
|
||||
|
||||
|
||||
Reference in New Issue
Block a user