mirror of
https://we.phorge.it/source/phorge.git
synced 2024-12-22 21:40:55 +01:00
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
This commit is contained in:
parent
404b55ce57
commit
afdef332fb
1 changed files with 92 additions and 32 deletions
|
@ -8,7 +8,9 @@ final class TransactionSearchConduitAPIMethod
|
|||
}
|
||||
|
||||
public function getMethodDescription() {
|
||||
return pht('Read transactions and comments for an object.');
|
||||
return pht(
|
||||
'Read transactions and comments for a particular object '.
|
||||
'or an entire object type.');
|
||||
}
|
||||
|
||||
public function getMethodDocumentation() {
|
||||
|
@ -23,6 +25,26 @@ One common reason to call this method is that you're implmenting a webhook and
|
|||
just received a notification that an object has changed. See the Webhooks
|
||||
documentation for more detailed discussion of this use case.
|
||||
|
||||
One Object Type at a Time
|
||||
=========================
|
||||
|
||||
This API method can query transactions for any type of object which supports
|
||||
transactions, but only one type of object can be queried per call. For example:
|
||||
you can retrieve transactions affecting Tasks, or you can retrieve transactions
|
||||
affecting Revisions, but a single call can not retrieve both.
|
||||
|
||||
This is a technical limitation arising because (among other reasons) there is
|
||||
no global ordering on transactions.
|
||||
|
||||
To find transactions for a specific object (like a particular task), pass the
|
||||
object PHID or an appropriate object identifier (like `T123`) as an
|
||||
`objectIdentifier`.
|
||||
|
||||
To find all transactions for an object type, pass the object type constant as
|
||||
an `objectType`. For example, the correct identifier for tasks is `TASK`. (You
|
||||
can quickly find an unknown type constant by looking at the PHID of an object
|
||||
of that type.)
|
||||
|
||||
Constraints
|
||||
===========
|
||||
|
||||
|
@ -64,8 +86,9 @@ EOREMARKUP
|
|||
|
||||
protected function defineParamTypes() {
|
||||
return array(
|
||||
'objectIdentifier' => 'phid|string',
|
||||
'constraints' => 'map<string, wild>',
|
||||
'objectIdentifier' => 'optional phid|string',
|
||||
'objectType' => 'optional string',
|
||||
'constraints' => 'optional map<string, wild>',
|
||||
) + $this->getPagerParamTypes();
|
||||
}
|
||||
|
||||
|
@ -81,43 +104,19 @@ EOREMARKUP
|
|||
$viewer = $request->getUser();
|
||||
$pager = $this->newPager($request);
|
||||
|
||||
$object_name = $request->getValue('objectIdentifier', null);
|
||||
if (!strlen($object_name)) {
|
||||
throw new Exception(
|
||||
pht(
|
||||
'When calling "transaction.search", you must provide an object to '.
|
||||
'retrieve transactions for.'));
|
||||
}
|
||||
|
||||
$object = id(new PhabricatorObjectQuery())
|
||||
->setViewer($viewer)
|
||||
->withNames(array($object_name))
|
||||
->executeOne();
|
||||
if (!$object) {
|
||||
throw new Exception(
|
||||
pht(
|
||||
'No object "%s" exists.',
|
||||
$object_name));
|
||||
}
|
||||
|
||||
if (!($object instanceof PhabricatorApplicationTransactionInterface)) {
|
||||
throw new Exception(
|
||||
pht(
|
||||
'Object "%s" (of type "%s") does not implement "%s", so '.
|
||||
'transactions can not be loaded for it.',
|
||||
$object_name,
|
||||
get_class($object),
|
||||
'PhabricatorApplicationTransactionInterface'));
|
||||
}
|
||||
$object = $this->loadTemplateObject($request);
|
||||
|
||||
$xaction_query = PhabricatorApplicationTransactionQuery::newQueryForObject(
|
||||
$object);
|
||||
|
||||
$xaction_query
|
||||
->needHandles(false)
|
||||
->withObjectPHIDs(array($object->getPHID()))
|
||||
->setViewer($viewer);
|
||||
|
||||
if ($object->getPHID()) {
|
||||
$xaction_query->withObjectPHIDs(array($object->getPHID()));
|
||||
}
|
||||
|
||||
$constraints = $request->getValue('constraints', array());
|
||||
|
||||
$xaction_query = $this->applyConstraints($constraints, $xaction_query);
|
||||
|
@ -355,4 +354,65 @@ EOREMARKUP
|
|||
);
|
||||
}
|
||||
|
||||
private function loadTemplateObject(ConduitAPIRequest $request) {
|
||||
$viewer = $request->getUser();
|
||||
|
||||
$object_identifier = $request->getValue('objectIdentifier');
|
||||
$object_type = $request->getValue('objectType');
|
||||
|
||||
$has_identifier = ($object_identifier !== null);
|
||||
$has_type = ($object_type !== null);
|
||||
|
||||
if (!$has_type && !$has_identifier) {
|
||||
throw new Exception(
|
||||
pht(
|
||||
'Calls to "transaction.search" must specify either an "objectType" '.
|
||||
'or an "objectIdentifier"'));
|
||||
} else if ($has_type && $has_identifier) {
|
||||
throw new Exception(
|
||||
pht(
|
||||
'Calls to "transaction.search" must not specify both an '.
|
||||
'"objectType" and an "objectIdentifier".'));
|
||||
}
|
||||
|
||||
if ($has_type) {
|
||||
$all_types = PhabricatorPHIDType::getAllTypes();
|
||||
|
||||
if (!isset($all_types[$object_type])) {
|
||||
ksort($all_types);
|
||||
throw new Exception(
|
||||
pht(
|
||||
'In call to "transaction.search", specified "objectType" ("%s") '.
|
||||
'is unknown. Valid object types are: %s.',
|
||||
$object_type,
|
||||
implode(', ', array_keys($all_types))));
|
||||
}
|
||||
|
||||
$object = $all_types[$object_type]->newObject();
|
||||
} else {
|
||||
$object = id(new PhabricatorObjectQuery())
|
||||
->setViewer($viewer)
|
||||
->withNames(array($object_identifier))
|
||||
->executeOne();
|
||||
if (!$object) {
|
||||
throw new Exception(
|
||||
pht(
|
||||
'In call to "transaction.search", specified "objectIdentifier" '.
|
||||
'("%s") does not exist.',
|
||||
$object_identifier));
|
||||
}
|
||||
}
|
||||
|
||||
if (!($object instanceof PhabricatorApplicationTransactionInterface)) {
|
||||
throw new Exception(
|
||||
pht(
|
||||
'In call to "transaction.search", selected object (of type "%s") '.
|
||||
'does not implement "%s", so transactions can not be loaded for it.',
|
||||
get_class($object),
|
||||
'PhabricatorApplicationTransactionInterface'));
|
||||
}
|
||||
|
||||
return $object;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue