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

transaction.search: add auto-generated documentation for objectType and handle unmanaged exception

Summary:
Finally we have some auto-generated documentation for the page /conduit/method/transaction.search/ about the supported values of objectType.
This is useful since we have 70+ of them, and they are totally obscure to newcomers (and us, core team, lol).

{F3942084}

The already-existing exception messages now do not suggest anymore values that exist but are not supported (e.g. XACT).

Moreover, we handle an unmanaged exception in transaction.search, when the existing `objectType` is not supported (e.g. XACT).

Closes T16054
Closes T16057

Test Plan:
Visit the page /conduit/method/transaction.search/ and enjoy the new amazing auto-generated table.

From the same page, visit the test form and set objectType = "XACT" and Call Method. You do not see anymore this confusing exception:

get_class() expects parameter 1 to be object, null given

Instead, you finally see this informative exception message (similar to the already-existing ones):

In call to "transaction.search", specified "objectType" ("XACT") is not supported because it does not implement "newObject()". Valid object types are: ABND, ADEV, AINT, ANAM, ANET, ASRV, DIFF, DREV, BOOK, DRYB, FBAK, FITV, HMBD, HMCP, HMCS, HMBB, HRUL, HWBH, HWBR, TASK, NUAI, NUAQ, NUAS, CDTL, FPRV, AUTH, CTNM, AMSG, APAS, AKEY, BDGE, CEVT, CEXP, CIMP, CONF, CONP, CDWN, DSHB, DSHP, PRTL, FORM, FILE, LEGD, MCRO, APPE, OASC, OPKG, PPAK, PPUB, PVER, PSTE, USER, BLOG, POST, PHRL, PANL, PCOL, PROJ, WTRG, CMIT, RIDT, REPO, RURI, POLL, SPCE, PSET, BULK, PVAR, MOCK, AEML, ACNT, CART, PMRC, PAYM, PHPR, PSUB, WIKI, ANSW, QUES.

Additionally, you can verify that the new documentation and the new methods in general are NOT called for normal valid API requests, so, not affecting production performance. An example of a valid request is: objectType = "TASK".

Reviewers: O1 Blessed Committers, avivey

Reviewed By: O1 Blessed Committers, avivey

Subscribers: avivey, aklapper, tobiaswiese, Matthew, Cigaryno

Maniphest Tasks: T16054, T16057

Differential Revision: https://we.phorge.it/D25988

+83 -4
+83 -4
src/applications/transactions/conduit/TransactionSearchConduitAPIMethod.php
··· 45 45 can quickly find an unknown type constant by looking at the PHID of an object 46 46 of that type.) 47 47 48 + All supported values for `objectType`: 49 + 50 + %s 51 + 48 52 Constraints 49 53 =========== 50 54 ··· 73 77 useful, reasonable fields) as we become aware of use cases for them. 74 78 75 79 EOREMARKUP 76 - ); 80 + , 81 + // Showing the supported 'objectType'(s) and their label is ideal in this 82 + // API documentation, and it's probably really cheaper than having users 83 + // randomly flooding our API to figure out these supported values. 84 + $this->getSupportedObjectTypeRemarkupDocumentation()); 77 85 78 86 $markup = $this->newRemarkupDocumentationView($markup); 79 87 ··· 366 374 throw new Exception( 367 375 pht( 368 376 'Calls to "transaction.search" must specify either an "objectType" '. 369 - 'or an "objectIdentifier"')); 377 + 'or an "objectIdentifier".')); 370 378 } else if ($has_type && $has_identifier) { 371 379 throw new Exception( 372 380 pht( ··· 378 386 $all_types = PhabricatorPHIDType::getAllTypes(); 379 387 380 388 if (!isset($all_types[$object_type])) { 381 - ksort($all_types); 382 389 throw new Exception( 383 390 pht( 384 391 'In call to "transaction.search", specified "objectType" ("%s") '. 385 392 'is unknown. Valid object types are: %s.', 386 393 $object_type, 387 - implode(', ', array_keys($all_types)))); 394 + $this->getSupportedObjectTypeKeysImploded())); 388 395 } 389 396 390 397 $object = $all_types[$object_type]->newObject(); 398 + if (!$object) { 399 + throw new Exception( 400 + pht( 401 + 'In call to "%s", specified "%s" ("%s") '. 402 + 'is not supported because it does not implement "%s". '. 403 + 'Valid object types are: %s.', 404 + 'transaction.search', 405 + 'objectType', 406 + $object_type, 407 + 'newObject()', 408 + $this->getSupportedObjectTypeKeysImploded())); 409 + } 391 410 } else { 392 411 $object = id(new PhabricatorObjectQuery()) 393 412 ->setViewer($viewer) ··· 412 431 } 413 432 414 433 return $object; 434 + } 435 + 436 + /** 437 + * Get a cute Remarkup table to document the supported 'objectType'(s). 438 + */ 439 + private function getSupportedObjectTypeRemarkupDocumentation(): string { 440 + $lines = array(); 441 + $type = pht('Object Type'); 442 + $name = pht('Name'); 443 + $lines[] = "| {$type} | {$name} |"; 444 + $lines[] = '|---------|--------|'; 445 + foreach ($this->getSupportedObjectTypesAndName() as $type => $name) { 446 + $lines[] = "| `{$type}` | {$name} |"; 447 + } 448 + return implode("\n", $lines); 449 + } 450 + 451 + /** 452 + * Get all the supported values, ordered, for the 'objectType' API parameter. 453 + * This is intended to be shown to the end-user, and not parsed. 454 + * @return string All values for 'objectType' API parameters, comma separated. 455 + */ 456 + private function getSupportedObjectTypeKeysImploded(): string { 457 + return implode(', ', $this->getSupportedObjectTypeKeys()); 458 + } 459 + 460 + /** 461 + * Get all the supported values, ordered, for the 'objectType' API parameter. 462 + * @return array<string> All values for 'objectType' API parameters. 463 + */ 464 + private function getSupportedObjectTypeKeys(): array { 465 + return array_keys($this->getSupportedObjectTypesAndName()); 466 + } 467 + 468 + /** 469 + * Get all the supported 'objectType' API parameters, ordered and with name. 470 + * @return array <string, string> Array of object type names, indexed by type. 471 + */ 472 + private function getSupportedObjectTypesAndName(): array { 473 + $all_types = PhabricatorPHIDType::getAllTypes(); 474 + ksort($all_types); 475 + 476 + $supporteds = []; 477 + foreach ($all_types as $key => $type) { 478 + if ($this->isObjectTypeSupported($type)) { 479 + $supporteds[$key] = $type->getTypeName(); 480 + } 481 + } 482 + return $supporteds; 483 + } 484 + 485 + /** 486 + * Get a new object from a 'objectType' API parameter. 487 + * @param $type PhabricatorPHIDType 488 + * @return PhabricatorApplicationTransactionInterface|null 489 + * Get the new object, or null when the type is not supported. 490 + */ 491 + private function isObjectTypeSupported($type) { 492 + $obj = $type->newObject(); 493 + return $obj && $obj instanceof PhabricatorApplicationTransactionInterface; 415 494 } 416 495 417 496 }