@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.

Allow "transaction.search" to be called on an object type

Summary:
Ref T13631. This supports a more robust version of "poll for updates by using dateModified window queries" that uses transactions as a logical clock.

This is particularly relevant for commits, since they don't have a "dateModified" at time of writing.

Test Plan:
- Queried for transactions by type and object.
- Issued various invalid transaction queries, got appropriate errors.

Maniphest Tasks: T13631

Differential Revision: https://secure.phabricator.com/D21601

+92 -32
+92 -32
src/applications/transactions/conduit/TransactionSearchConduitAPIMethod.php
··· 8 8 } 9 9 10 10 public function getMethodDescription() { 11 - return pht('Read transactions and comments for an object.'); 11 + return pht( 12 + 'Read transactions and comments for a particular object '. 13 + 'or an entire object type.'); 12 14 } 13 15 14 16 public function getMethodDocumentation() { ··· 23 25 just received a notification that an object has changed. See the Webhooks 24 26 documentation for more detailed discussion of this use case. 25 27 28 + One Object Type at a Time 29 + ========================= 30 + 31 + This API method can query transactions for any type of object which supports 32 + transactions, but only one type of object can be queried per call. For example: 33 + you can retrieve transactions affecting Tasks, or you can retrieve transactions 34 + affecting Revisions, but a single call can not retrieve both. 35 + 36 + This is a technical limitation arising because (among other reasons) there is 37 + no global ordering on transactions. 38 + 39 + To find transactions for a specific object (like a particular task), pass the 40 + object PHID or an appropriate object identifier (like `T123`) as an 41 + `objectIdentifier`. 42 + 43 + To find all transactions for an object type, pass the object type constant as 44 + an `objectType`. For example, the correct identifier for tasks is `TASK`. (You 45 + can quickly find an unknown type constant by looking at the PHID of an object 46 + of that type.) 47 + 26 48 Constraints 27 49 =========== 28 50 ··· 64 86 65 87 protected function defineParamTypes() { 66 88 return array( 67 - 'objectIdentifier' => 'phid|string', 68 - 'constraints' => 'map<string, wild>', 89 + 'objectIdentifier' => 'optional phid|string', 90 + 'objectType' => 'optional string', 91 + 'constraints' => 'optional map<string, wild>', 69 92 ) + $this->getPagerParamTypes(); 70 93 } 71 94 ··· 81 104 $viewer = $request->getUser(); 82 105 $pager = $this->newPager($request); 83 106 84 - $object_name = $request->getValue('objectIdentifier', null); 85 - if (!strlen($object_name)) { 86 - throw new Exception( 87 - pht( 88 - 'When calling "transaction.search", you must provide an object to '. 89 - 'retrieve transactions for.')); 90 - } 91 - 92 - $object = id(new PhabricatorObjectQuery()) 93 - ->setViewer($viewer) 94 - ->withNames(array($object_name)) 95 - ->executeOne(); 96 - if (!$object) { 97 - throw new Exception( 98 - pht( 99 - 'No object "%s" exists.', 100 - $object_name)); 101 - } 102 - 103 - if (!($object instanceof PhabricatorApplicationTransactionInterface)) { 104 - throw new Exception( 105 - pht( 106 - 'Object "%s" (of type "%s") does not implement "%s", so '. 107 - 'transactions can not be loaded for it.', 108 - $object_name, 109 - get_class($object), 110 - 'PhabricatorApplicationTransactionInterface')); 111 - } 107 + $object = $this->loadTemplateObject($request); 112 108 113 109 $xaction_query = PhabricatorApplicationTransactionQuery::newQueryForObject( 114 110 $object); 115 111 116 112 $xaction_query 117 113 ->needHandles(false) 118 - ->withObjectPHIDs(array($object->getPHID())) 119 114 ->setViewer($viewer); 115 + 116 + if ($object->getPHID()) { 117 + $xaction_query->withObjectPHIDs(array($object->getPHID())); 118 + } 120 119 121 120 $constraints = $request->getValue('constraints', array()); 122 121 ··· 353 352 return array( 354 353 'operations' => $operations, 355 354 ); 355 + } 356 + 357 + private function loadTemplateObject(ConduitAPIRequest $request) { 358 + $viewer = $request->getUser(); 359 + 360 + $object_identifier = $request->getValue('objectIdentifier'); 361 + $object_type = $request->getValue('objectType'); 362 + 363 + $has_identifier = ($object_identifier !== null); 364 + $has_type = ($object_type !== null); 365 + 366 + if (!$has_type && !$has_identifier) { 367 + throw new Exception( 368 + pht( 369 + 'Calls to "transaction.search" must specify either an "objectType" '. 370 + 'or an "objectIdentifier"')); 371 + } else if ($has_type && $has_identifier) { 372 + throw new Exception( 373 + pht( 374 + 'Calls to "transaction.search" must not specify both an '. 375 + '"objectType" and an "objectIdentifier".')); 376 + } 377 + 378 + if ($has_type) { 379 + $all_types = PhabricatorPHIDType::getAllTypes(); 380 + 381 + if (!isset($all_types[$object_type])) { 382 + ksort($all_types); 383 + throw new Exception( 384 + pht( 385 + 'In call to "transaction.search", specified "objectType" ("%s") '. 386 + 'is unknown. Valid object types are: %s.', 387 + $object_type, 388 + implode(', ', array_keys($all_types)))); 389 + } 390 + 391 + $object = $all_types[$object_type]->newObject(); 392 + } else { 393 + $object = id(new PhabricatorObjectQuery()) 394 + ->setViewer($viewer) 395 + ->withNames(array($object_identifier)) 396 + ->executeOne(); 397 + if (!$object) { 398 + throw new Exception( 399 + pht( 400 + 'In call to "transaction.search", specified "objectIdentifier" '. 401 + '("%s") does not exist.', 402 + $object_identifier)); 403 + } 404 + } 405 + 406 + if (!($object instanceof PhabricatorApplicationTransactionInterface)) { 407 + throw new Exception( 408 + pht( 409 + 'In call to "transaction.search", selected object (of type "%s") '. 410 + 'does not implement "%s", so transactions can not be loaded for it.', 411 + get_class($object), 412 + 'PhabricatorApplicationTransactionInterface')); 413 + } 414 + 415 + return $object; 356 416 } 357 417 358 418 }