Index: resources/sql/autopatches/20140305.diviner.1.slugcol.sql =================================================================== --- /dev/null +++ resources/sql/autopatches/20140305.diviner.1.slugcol.sql @@ -0,0 +1,2 @@ +ALTER TABLE {$NAMESPACE}_diviner.diviner_livesymbol + ADD titleSlugHash CHAR(12) COLLATE latin1_bin AFTER title; Index: resources/sql/autopatches/20140305.diviner.2.slugkey.sql =================================================================== --- /dev/null +++ resources/sql/autopatches/20140305.diviner.2.slugkey.sql @@ -0,0 +1,2 @@ +ALTER TABLE {$NAMESPACE}_diviner.diviner_livesymbol + ADD KEY `key_slug` (titleSlugHash); Index: src/applications/diviner/atom/DivinerAtom.php =================================================================== --- src/applications/diviner/atom/DivinerAtom.php +++ src/applications/diviner/atom/DivinerAtom.php @@ -197,6 +197,7 @@ } $parts = array( + $this->getBook(), $this->getType(), $this->getName(), $this->getFile(), Index: src/applications/diviner/atom/DivinerAtomRef.php =================================================================== --- src/applications/diviner/atom/DivinerAtomRef.php +++ src/applications/diviner/atom/DivinerAtomRef.php @@ -109,6 +109,10 @@ return $this->title; } + public function getTitleSlug() { + return self::normalizeTitleString($this->getTitle()); + } + public function toDictionary() { return array( 'book' => $this->getBook(), @@ -144,6 +148,7 @@ $obj->index = idx($dict, 'index'); $obj->summary = idx($dict, 'summary'); $obj->title = idx($dict, 'title'); + return $obj; } @@ -193,4 +198,9 @@ return idx($alternates, $str, $str); } + public static function normalizeTitleString($str) { + $str = self::normalizeString($str); + return phutil_utf8_strtolower($str); + } + } Index: src/applications/diviner/controller/DivinerFindController.php =================================================================== --- src/applications/diviner/controller/DivinerFindController.php +++ src/applications/diviner/controller/DivinerFindController.php @@ -24,14 +24,7 @@ } $query = id(new DivinerAtomQuery()) - ->setViewer($viewer) - ->withNames( - array( - $request->getStr('name'), - // TODO: This could probably be more smartly normalized in the DB, - // but just fake it for now. - phutil_utf8_strtolower($request->getStr('name')), - )); + ->setViewer($viewer); if ($book) { $query->withBookPHIDs(array($book->getPHID())); @@ -47,7 +40,23 @@ $query->withTypes(array($type)); } - $atoms = $query->execute(); + $name_query = clone $query; + + $name_query->withNames( + array( + $request->getStr('name'), + // TODO: This could probably be more smartly normalized in the DB, + // but just fake it for now. + phutil_utf8_strtolower($request->getStr('name')), + )); + + $atoms = $name_query->execute(); + + if (!$atoms) { + $title_query = clone $query; + $title_query->withTitles(array($request->getStr('name'))); + $atoms = $title_query->execute(); + } if (!$atoms) { return new Aphront404Response(); Index: src/applications/diviner/query/DivinerAtomQuery.php =================================================================== --- src/applications/diviner/query/DivinerAtomQuery.php +++ src/applications/diviner/query/DivinerAtomQuery.php @@ -13,6 +13,7 @@ private $includeUndocumentable; private $includeGhosts; private $nodeHashes; + private $titles; private $needAtoms; private $needExtends; @@ -58,6 +59,11 @@ return $this; } + public function withTitles($titles) { + $this->titles = $titles; + return $this; + } + public function needAtoms($need) { $this->needAtoms = $need; return $this; @@ -287,6 +293,20 @@ $this->names); } + if ($this->titles) { + $hashes = array(); + foreach ($this->titles as $title) { + $slug = DivinerAtomRef::normalizeTitleString($title); + $hash = PhabricatorHash::digestForIndex($slug); + $hashes[] = $hash; + } + + $where[] = qsprintf( + $conn_r, + 'titleSlugHash in (%Ls)', + $hashes); + } + if ($this->contexts) { $with_null = false; $contexts = $this->contexts; Index: src/applications/diviner/storage/DivinerLiveSymbol.php =================================================================== --- src/applications/diviner/storage/DivinerLiveSymbol.php +++ src/applications/diviner/storage/DivinerLiveSymbol.php @@ -13,6 +13,7 @@ protected $nodeHash; protected $title; + protected $titleSlugHash; protected $groupName; protected $summary; protected $isDocumentable = 0; @@ -105,6 +106,18 @@ return $title; } + public function setTitle($value) { + $this->writeField('title', $value); + if (strlen($value)) { + $slug = DivinerAtomRef::normalizeTitleString($value); + $hash = PhabricatorHash::digestForIndex($slug); + $this->titleSlugHash = $hash; + } else { + $this->titleSlugHash = null; + } + return $this; + } + public function attachExtends(array $extends) { assert_instances_of($extends, 'DivinerLiveSymbol'); $this->extends = $extends;