mirror of
https://we.phorge.it/source/phorge.git
synced 2025-01-22 20:51:10 +01:00
Support "phriction.document.search" queries by "parentPaths" or "ancestorPaths"
Summary: Ref T13090. Ref T13077. This adds `parentPaths` and `ancestorPaths` constraints to `phriction.document.query`. These should be a little more usable than the internal `slugPrefix` / `depth` stuff -- that's technically more powerful, but requires callers to know more slug normalization rules. We could perhaps expose `minDepth` / `maxDepth` in the future. Test Plan: Ran valid and invalid `parentPaths` and `ancestorPaths` queries for `/`, `aaa/`, `AAA/`, etc. Got sensible-seeming results. Maniphest Tasks: T13090, T13077 Differential Revision: https://secure.phabricator.com/D19125
This commit is contained in:
parent
ffcfc04652
commit
4cb62ca0d6
2 changed files with 118 additions and 1 deletions
|
@ -10,6 +10,9 @@ final class PhrictionDocumentQuery
|
|||
private $slugPrefix;
|
||||
private $statuses;
|
||||
|
||||
private $parentPaths;
|
||||
private $ancestorPaths;
|
||||
|
||||
private $needContent;
|
||||
|
||||
const ORDER_HIERARCHY = 'hierarchy';
|
||||
|
@ -34,7 +37,7 @@ final class PhrictionDocumentQuery
|
|||
return $this;
|
||||
}
|
||||
|
||||
public function withSlugPrefix($slug_prefix) {
|
||||
public function withSlugPrefix($slug_prefix) {
|
||||
$this->slugPrefix = $slug_prefix;
|
||||
return $this;
|
||||
}
|
||||
|
@ -44,6 +47,16 @@ final class PhrictionDocumentQuery
|
|||
return $this;
|
||||
}
|
||||
|
||||
public function withParentPaths(array $paths) {
|
||||
$this->parentPaths = $paths;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function withAncestorPaths(array $paths) {
|
||||
$this->ancestorPaths = $paths;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function needContent($need_content) {
|
||||
$this->needContent = $need_content;
|
||||
return $this;
|
||||
|
@ -214,6 +227,94 @@ final class PhrictionDocumentQuery
|
|||
$this->depths);
|
||||
}
|
||||
|
||||
if ($this->parentPaths !== null || $this->ancestorPaths !== null) {
|
||||
$sets = array(
|
||||
array(
|
||||
'paths' => $this->parentPaths,
|
||||
'parents' => true,
|
||||
),
|
||||
array(
|
||||
'paths' => $this->ancestorPaths,
|
||||
'parents' => false,
|
||||
),
|
||||
);
|
||||
|
||||
$paths = array();
|
||||
foreach ($sets as $set) {
|
||||
$set_paths = $set['paths'];
|
||||
if ($set_paths === null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!$set_paths) {
|
||||
throw new PhabricatorEmptyQueryException(
|
||||
pht('No parent/ancestor paths specified.'));
|
||||
}
|
||||
|
||||
$is_parents = $set['parents'];
|
||||
foreach ($set_paths as $path) {
|
||||
$path_normal = PhabricatorSlug::normalize($path);
|
||||
if ($path !== $path_normal) {
|
||||
throw new Exception(
|
||||
pht(
|
||||
'Document path "%s" is not a valid path. The normalized '.
|
||||
'form of this path is "%s".',
|
||||
$path,
|
||||
$path_normal));
|
||||
}
|
||||
|
||||
$depth = PhabricatorSlug::getDepth($path_normal);
|
||||
if ($is_parents) {
|
||||
$min_depth = $depth + 1;
|
||||
$max_depth = $depth + 1;
|
||||
} else {
|
||||
$min_depth = $depth + 1;
|
||||
$max_depth = null;
|
||||
}
|
||||
|
||||
$paths[] = array(
|
||||
$path_normal,
|
||||
$min_depth,
|
||||
$max_depth,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
$path_clauses = array();
|
||||
foreach ($paths as $path) {
|
||||
$parts = array();
|
||||
list($prefix, $min, $max) = $path;
|
||||
|
||||
// If we're getting children or ancestors of the root document, they
|
||||
// aren't actually stored with the leading "/" in the database, so
|
||||
// just skip this part of the clause.
|
||||
if ($prefix !== '/') {
|
||||
$parts[] = qsprintf(
|
||||
$conn,
|
||||
'd.slug LIKE %>',
|
||||
$prefix);
|
||||
}
|
||||
|
||||
if ($min !== null) {
|
||||
$parts[] = qsprintf(
|
||||
$conn,
|
||||
'd.depth >= %d',
|
||||
$min);
|
||||
}
|
||||
|
||||
if ($max !== null) {
|
||||
$parts[] = qsprintf(
|
||||
$conn,
|
||||
'd.depth <= %d',
|
||||
$max);
|
||||
}
|
||||
|
||||
$path_clauses[] = '('.implode(') AND (', $parts).')';
|
||||
}
|
||||
|
||||
$where[] = '('.implode(') OR (', $path_clauses).')';
|
||||
}
|
||||
|
||||
return $where;
|
||||
}
|
||||
|
||||
|
|
|
@ -27,6 +27,14 @@ final class PhrictionDocumentSearchEngine
|
|||
$query->withSlugs($map['paths']);
|
||||
}
|
||||
|
||||
if ($map['parentPaths']) {
|
||||
$query->withParentPaths($map['parentPaths']);
|
||||
}
|
||||
|
||||
if ($map['ancestorPaths']) {
|
||||
$query->withAncestorPaths($map['ancestorPaths']);
|
||||
}
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
|
@ -40,6 +48,14 @@ final class PhrictionDocumentSearchEngine
|
|||
->setKey('paths')
|
||||
->setIsHidden(true)
|
||||
->setLabel(pht('Paths')),
|
||||
id(new PhabricatorSearchStringListField())
|
||||
->setKey('parentPaths')
|
||||
->setIsHidden(true)
|
||||
->setLabel(pht('Parent Paths')),
|
||||
id(new PhabricatorSearchStringListField())
|
||||
->setKey('ancestorPaths')
|
||||
->setIsHidden(true)
|
||||
->setLabel(pht('Ancestor Paths')),
|
||||
);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue