@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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

+118 -1
+102 -1
src/applications/phriction/query/PhrictionDocumentQuery.php
··· 10 10 private $slugPrefix; 11 11 private $statuses; 12 12 13 + private $parentPaths; 14 + private $ancestorPaths; 15 + 13 16 private $needContent; 14 17 15 18 const ORDER_HIERARCHY = 'hierarchy'; ··· 34 37 return $this; 35 38 } 36 39 37 - public function withSlugPrefix($slug_prefix) { 40 + public function withSlugPrefix($slug_prefix) { 38 41 $this->slugPrefix = $slug_prefix; 39 42 return $this; 40 43 } 41 44 42 45 public function withStatuses(array $statuses) { 43 46 $this->statuses = $statuses; 47 + return $this; 48 + } 49 + 50 + public function withParentPaths(array $paths) { 51 + $this->parentPaths = $paths; 52 + return $this; 53 + } 54 + 55 + public function withAncestorPaths(array $paths) { 56 + $this->ancestorPaths = $paths; 44 57 return $this; 45 58 } 46 59 ··· 212 225 $conn, 213 226 'd.depth IN (%Ld)', 214 227 $this->depths); 228 + } 229 + 230 + if ($this->parentPaths !== null || $this->ancestorPaths !== null) { 231 + $sets = array( 232 + array( 233 + 'paths' => $this->parentPaths, 234 + 'parents' => true, 235 + ), 236 + array( 237 + 'paths' => $this->ancestorPaths, 238 + 'parents' => false, 239 + ), 240 + ); 241 + 242 + $paths = array(); 243 + foreach ($sets as $set) { 244 + $set_paths = $set['paths']; 245 + if ($set_paths === null) { 246 + continue; 247 + } 248 + 249 + if (!$set_paths) { 250 + throw new PhabricatorEmptyQueryException( 251 + pht('No parent/ancestor paths specified.')); 252 + } 253 + 254 + $is_parents = $set['parents']; 255 + foreach ($set_paths as $path) { 256 + $path_normal = PhabricatorSlug::normalize($path); 257 + if ($path !== $path_normal) { 258 + throw new Exception( 259 + pht( 260 + 'Document path "%s" is not a valid path. The normalized '. 261 + 'form of this path is "%s".', 262 + $path, 263 + $path_normal)); 264 + } 265 + 266 + $depth = PhabricatorSlug::getDepth($path_normal); 267 + if ($is_parents) { 268 + $min_depth = $depth + 1; 269 + $max_depth = $depth + 1; 270 + } else { 271 + $min_depth = $depth + 1; 272 + $max_depth = null; 273 + } 274 + 275 + $paths[] = array( 276 + $path_normal, 277 + $min_depth, 278 + $max_depth, 279 + ); 280 + } 281 + } 282 + 283 + $path_clauses = array(); 284 + foreach ($paths as $path) { 285 + $parts = array(); 286 + list($prefix, $min, $max) = $path; 287 + 288 + // If we're getting children or ancestors of the root document, they 289 + // aren't actually stored with the leading "/" in the database, so 290 + // just skip this part of the clause. 291 + if ($prefix !== '/') { 292 + $parts[] = qsprintf( 293 + $conn, 294 + 'd.slug LIKE %>', 295 + $prefix); 296 + } 297 + 298 + if ($min !== null) { 299 + $parts[] = qsprintf( 300 + $conn, 301 + 'd.depth >= %d', 302 + $min); 303 + } 304 + 305 + if ($max !== null) { 306 + $parts[] = qsprintf( 307 + $conn, 308 + 'd.depth <= %d', 309 + $max); 310 + } 311 + 312 + $path_clauses[] = '('.implode(') AND (', $parts).')'; 313 + } 314 + 315 + $where[] = '('.implode(') OR (', $path_clauses).')'; 215 316 } 216 317 217 318 return $where;
+16
src/applications/phriction/query/PhrictionDocumentSearchEngine.php
··· 27 27 $query->withSlugs($map['paths']); 28 28 } 29 29 30 + if ($map['parentPaths']) { 31 + $query->withParentPaths($map['parentPaths']); 32 + } 33 + 34 + if ($map['ancestorPaths']) { 35 + $query->withAncestorPaths($map['ancestorPaths']); 36 + } 37 + 30 38 return $query; 31 39 } 32 40 ··· 40 48 ->setKey('paths') 41 49 ->setIsHidden(true) 42 50 ->setLabel(pht('Paths')), 51 + id(new PhabricatorSearchStringListField()) 52 + ->setKey('parentPaths') 53 + ->setIsHidden(true) 54 + ->setLabel(pht('Parent Paths')), 55 + id(new PhabricatorSearchStringListField()) 56 + ->setKey('ancestorPaths') 57 + ->setIsHidden(true) 58 + ->setLabel(pht('Ancestor Paths')), 43 59 ); 44 60 } 45 61