From 57cc30d0c4aafc3510f3f4bcaa0a0a7761d14190 Mon Sep 17 00:00:00 2001 From: epriestley Date: Wed, 16 Dec 2015 06:19:47 -0800 Subject: [PATCH] Continue hammering new *.search / *.edit documentation into shape Summary: Ref T9964. Create some docuemntation for this stuff, and clean up the *.edit endpoints a bit. Test Plan: Read documentation. Reviewers: chad Reviewed By: chad Maniphest Tasks: T9964 Differential Revision: https://secure.phabricator.com/D14798 --- .../PhabricatorConduitApplication.php | 4 +- .../PhabricatorSearchEngineAPIMethod.php | 4 +- .../PhabricatorEditEngineAPIMethod.php | 255 ++++++++---------- src/docs/book/user.book | 3 + src/docs/tech/conduit.diviner | 28 -- src/docs/user/field/conduit_changes.diviner | 8 + src/docs/user/userguide/conduit.diviner | 68 +++++ src/docs/user/userguide/conduit_edit.diviner | 115 ++++++++ .../user/userguide/conduit_search.diviner | 74 +++++ 9 files changed, 380 insertions(+), 179 deletions(-) delete mode 100644 src/docs/tech/conduit.diviner create mode 100644 src/docs/user/userguide/conduit.diviner create mode 100644 src/docs/user/userguide/conduit_edit.diviner create mode 100644 src/docs/user/userguide/conduit_search.diviner diff --git a/src/applications/conduit/application/PhabricatorConduitApplication.php b/src/applications/conduit/application/PhabricatorConduitApplication.php index 2632648109..7a0ca0e4b9 100644 --- a/src/applications/conduit/application/PhabricatorConduitApplication.php +++ b/src/applications/conduit/application/PhabricatorConduitApplication.php @@ -17,8 +17,8 @@ final class PhabricatorConduitApplication extends PhabricatorApplication { public function getHelpDocumentationArticles(PhabricatorUser $viewer) { return array( array( - 'name' => pht('Conduit Technical Documentation'), - 'href' => PhabricatorEnv::getDoclink('Conduit Technical Documentation'), + 'name' => pht('Conduit API Overview'), + 'href' => PhabricatorEnv::getDoclink('Conduit API Overview'), ), ); } diff --git a/src/applications/search/engine/PhabricatorSearchEngineAPIMethod.php b/src/applications/search/engine/PhabricatorSearchEngineAPIMethod.php index effe57e47d..a299d90018 100644 --- a/src/applications/search/engine/PhabricatorSearchEngineAPIMethod.php +++ b/src/applications/search/engine/PhabricatorSearchEngineAPIMethod.php @@ -42,7 +42,9 @@ abstract class PhabricatorSearchEngineAPIMethod final public function getMethodDescription() { return pht( 'This is a standard **ApplicationSearch** method which will let you '. - 'list, query, or search for objects.'); + 'list, query, or search for objects. For documentation on these '. + 'endpoints, see **[[ %s | Conduit API: Using Search Endpoints ]]**.', + PhabricatorEnv::getDoclink('Conduit API: Using Edit Endpoints')); } final public function getMethodDocumentation() { diff --git a/src/applications/transactions/editengine/PhabricatorEditEngineAPIMethod.php b/src/applications/transactions/editengine/PhabricatorEditEngineAPIMethod.php index d29ec1c4ac..3cf04aeca8 100644 --- a/src/applications/transactions/editengine/PhabricatorEditEngineAPIMethod.php +++ b/src/applications/transactions/editengine/PhabricatorEditEngineAPIMethod.php @@ -38,6 +38,15 @@ abstract class PhabricatorEditEngineAPIMethod } final public function getMethodDescription() { + return pht( + 'This is a standard **ApplicationEditor** method which allows you to '. + 'create and modify objects by applying transactions. For documentation '. + 'on these endpoints, see '. + '**[[ %s | Conduit API: Using Edit Endpoints ]]**.', + PhabricatorEnv::getDoclink('Conduit API: Using Edit Endpoints')); + } + + final public function getMethodDocumentation() { $viewer = $this->getViewer(); $engine = $this->newEditEngine() @@ -47,156 +56,106 @@ abstract class PhabricatorEditEngineAPIMethod $out = array(); - $out[] = pht(<<buildEditTypesBoxes($engine, $types); -Each transaction applies one change to the object. For example, to create an -object with a specific title or change the title of an existing object you might -start by building a transaction like this: - -```lang=json, name=Example Single Transaction -{ - "type": "title", - "value": "New Object Title" -} -``` - -By passing a list of transactions in the `transactions` parameter, you can -apply a sequence of edits. For example, you'll often pass a value like this to -create an object with several field values or apply changes to multiple fields: - -```lang=json, name=Example Transaction List -[ - { - "type": "title", - "value": "New Object Title" - }, - { - "type": "body", - "value": "New body text for the object." - }, - { - "type": "projects.add", - "value": ["PHID-PROJ-1111", "PHID-PROJ-2222"] - } -] -``` - -Exactly which types of edits are available depends on the object you're editing. - - -Creating Objects ----------------- - -To create an object, pass a list of `transactions` but leave `objectIdentifier` -empty. This will create a new object with the initial field values you -specify. - - -Editing Objects ---------------- - -To edit an object, pass a list of `transactions` and specify an object to -apply them to with `objectIdentifier`. This will apply the changes to the -object. - -You may pass an ID (like `123`), PHID (like `PHID-WXYZ-abcdef...`), or -monogram (like `T123`, for objects which have monograms). - - -Return Type ------------ - -WARNING: The structure of the return value from these methods is likely to -change as ApplicationEditor evolves. - -Return values look something like this for now: - -```lang=json, name=Example Return Value -{ - "object": { - "phid": "PHID-XXXX-1111" - }, - "transactions": [ - { - "phid": "PHID-YYYY-1111", - }, - { - "phid": "PHID-YYYY-2222", - } - ] -} -``` - -The `object` key contains information about the object which was created or -edited. - -The `transactions` key contains information about the transactions which were -actually applied. For many reasons, the transactions which actually apply may -be greater or fewer in number than the transactions you provided, or may differ -in their nature in other ways. - - -Edit Types -========== - -This API method supports these edit types: -EOTEXT - ); - - $key = pht('Key'); - $description = pht('Description'); - $head_type = pht('Type'); - - $table = array(); - $table[] = "| {$key} | {$description} |"; - $table[] = '|--------|----------------|'; - foreach ($types as $type) { - $edit_type = $type->getEditType(); - $edit_description = $type->getConduitDescription(); - $table[] = "| `{$edit_type}` | {$edit_description} |"; - } - - $out[] = implode("\n", $table); - - foreach ($types as $type) { - $section = array(); - $section[] = pht('Edit Type: %s', $type->getEditType()); - $section[] = '---------'; - $section[] = null; - $section[] = $type->getConduitDescription(); - $section[] = null; - $section[] = pht( - 'This edit generates transactions of type `%s` internally.', - $type->getTransactionType()); - $section[] = null; - - $type_documentation = $type->getConduitDocumentation(); - if ($type_documentation) { - $section[] = $type_documentation; - $section[] = null; - } - - $type_description = pht( - 'Use `%s` to select this edit type.', - $type->getEditType()); - - $value_type = $type->getConduitType(); - $value_description = $type->getConduitTypeDescription(); - - $table = array(); - $table[] = "| {$key} | {$head_type} | {$description} |"; - $table[] = '|--------|--------------|----------------|'; - $table[] = "| `type` | `const` | {$type_description} |"; - $table[] = "| `value` | `{$value_type}` | {$value_description} |"; - $section[] = implode("\n", $table); - - $out[] = implode("\n", $section); - } - - $out = implode("\n\n", $out); return $out; } + private function buildEditTypesBoxes( + PhabricatorEditEngine $engine, + array $types) { + + $boxes = array(); + + $summary_info = pht( + 'This endpoint supports these types of transactions. See below for '. + 'detailed information about each transaction type.'); + + $rows = array(); + foreach ($types as $type) { + $rows[] = array( + $type->getEditType(), + $type->getConduitDescription(), + ); + } + + $summary_table = id(new AphrontTableView($rows)) + ->setHeaders( + array( + pht('Key'), + pht('Description'), + )) + ->setColumnClasses( + array( + 'prewrap', + 'wide', + )); + + $boxes[] = id(new PHUIObjectBoxView()) + ->setHeaderText(pht('Transaction Types')) + ->setCollapsed(true) + ->appendChild($this->buildRemarkup($summary_info)) + ->appendChild($summary_table); + + foreach ($types as $type) { + $section = array(); + + $section[] = $type->getConduitDescription(); + + $type_documentation = $type->getConduitDocumentation(); + if (strlen($type_documentation)) { + $section[] = $type_documentation; + } + + $section = implode("\n\n", $section); + + $rows = array(); + + $rows[] = array( + 'type', + 'const', + $type->getEditType(), + ); + + $rows[] = array( + 'value', + $type->getConduitType(), + $type->getConduitTypeDescription(), + ); + + $type_table = id(new AphrontTableView($rows)) + ->setHeaders( + array( + pht('Key'), + pht('Type'), + pht('Description'), + )) + ->setColumnClasses( + array( + 'prewrap', + 'prewrap', + 'wide', + )); + + $boxes[] = id(new PHUIObjectBoxView()) + ->setHeaderText(pht('Transaction Type: %s', $type->getEditType())) + ->setCollapsed(true) + ->appendChild($this->buildRemarkup($section)) + ->appendChild($type_table); + } + + return $boxes; + } + + + private function buildRemarkup($remarkup) { + $viewer = $this->getViewer(); + + $view = new PHUIRemarkupView($viewer, $remarkup); + + return id(new PHUIBoxView()) + ->appendChild($view) + ->addPadding(PHUI::PADDING_LARGE); + } + } diff --git a/src/docs/book/user.book b/src/docs/book/user.book index 2312bf65cd..20a72698be 100644 --- a/src/docs/book/user.book +++ b/src/docs/book/user.book @@ -29,6 +29,9 @@ "userguide": { "name": "Application User Guides" }, + "conduit": { + "name": "API Documentation" + }, "fieldmanual": { "name": "Field Manuals" }, diff --git a/src/docs/tech/conduit.diviner b/src/docs/tech/conduit.diviner deleted file mode 100644 index c31473b684..0000000000 --- a/src/docs/tech/conduit.diviner +++ /dev/null @@ -1,28 +0,0 @@ -@title Conduit Technical Documentation -@group conduit - -Technical overview of the Conduit API. - -Overview -======== - -Conduit is the HTTP API for Phabricator. It is roughly JSON-RPC: you usually -pass a JSON blob, and usually get a JSON blob back, although both call and -result formats are flexible in some cases. - -The easiest way to begin exploring Conduit is by visiting {nav Conduit} in the -web UI. The application provides an API console which you can use to explore -available methods, make calls, read documentation, and see examples. - -The API console has details about how to construct calls and generate API -tokens for authentication. - -The three primary ways to make Conduit calls are: - - - `arc call-conduit`: You can use this `arc` command to execute low-level - Conduit calls. - - `curl`: You can format a call with basic HTTP parameters and cURL. - - `ConduitClient`: - -There are also clients available in other languages. The Arcanist CLI client -for Phabricator is implemented over Conduit. diff --git a/src/docs/user/field/conduit_changes.diviner b/src/docs/user/field/conduit_changes.diviner index 3b78490546..e77a582251 100644 --- a/src/docs/user/field/conduit_changes.diviner +++ b/src/docs/user/field/conduit_changes.diviner @@ -49,3 +49,11 @@ When the changelogs mention a method deprecation, you can use the call logs to identify callers and notify them to upgrade or switch away. When the changelogs mention a method removal, you can use the call logs to verify that you will not be impacted. + + +Next Steps +========== + +Continue by: + + - returning to @{article:Conduit API Overview}. diff --git a/src/docs/user/userguide/conduit.diviner b/src/docs/user/userguide/conduit.diviner new file mode 100644 index 0000000000..5292736f30 --- /dev/null +++ b/src/docs/user/userguide/conduit.diviner @@ -0,0 +1,68 @@ +@title Conduit API Overview +@group conduit + +Overview of the Conduit API. + +Overview +======== + +Conduit is the HTTP API for Phabricator. It is roughly JSON-RPC: you usually +pass a JSON blob, and usually get a JSON blob back, although both call and +result formats are flexible in some cases. + +API Clients +=========== + +The primary ways to make Conduit calls are: + +**Web Console**: The {nav Conduit} application provides a web UI for exploring +the API and making calls. This is the best starting point for learning about +the API. See the next section for details. + +`ConduitClient`: This is the official client available in `libphutil`, and +the one used by `arc`. + +`arc call-conduit`: You can use this `arc` command to execute low-level +Conduit calls by piping JSON in to stdin. This can provide a simple way +to explore the API, or a quick way to get API access from a script written +in another language without needing a real client. + +`curl`: You can format a call with basic HTTP parameters and cURL. The console +includes examples which show how to format calls. + +**Other Clients**: There are also clients available in other languages. You +can check the [[ https://secure.phabricator.com/w/community_resources/ | +Community Resources ]] page for links. + +API Console +=========== + +The easiest way to begin exploring Conduit is by visiting {nav Conduit} in the +web UI. The application provides an API console which you can use to explore +available methods, make calls, read documentation, and see examples. + +The API console has details about how to construct calls and generate API +tokens for authentication. + + +Querying and Reading Objects +============================ + +For information on searching for objects and reading their properties and +information, see @{article:Conduit API: Using Search Endpoints}. + + +Creating and Editing Objects +============================ + +For information on creating, editing and updating objects, see +@{article:Conduit API: Using Search Endpoints}. + + +Next Steps +========== + +Continue by: + + - reading recommendations on responding to API changes in + @{article:Managing Conduit Changes}. diff --git a/src/docs/user/userguide/conduit_edit.diviner b/src/docs/user/userguide/conduit_edit.diviner new file mode 100644 index 0000000000..01d15873a8 --- /dev/null +++ b/src/docs/user/userguide/conduit_edit.diviner @@ -0,0 +1,115 @@ +@title Conduit API: Using Edit Endpoints +@group conduit + +Describes how to use edit endpoints to create and update objects. + +Overview +======== + +Many applications provide `edit` endpoints, which are the primary way to +create and update objects (like tasks) using the API. + +To create or edit an object, you'll build a list of //transactions// and pass +them to the endpoint. Each transaction applies a change to a field or property +on the object. + +For example, a transaction might change the title of an object or add +subscribers. + +When creating an object, transactions will be applied to an empty object. When +editing an object, transactions will be applied to an existing object. + +The best reference for a particular `edit` endpoint is the Conduit API console. +For example, you can find the console page for `maniphest.edit` by navigating +to {nav Conduit > maniphest.edit} in the web UI. This page contains detailed +information about the endpoint and how it can be used. + +Creating Objects +================ + +To create objects, pass a list of transactions but leave `objectIdentfier` +blank. This tells the endpoint that you want to create a new, empty object and +then apply the transactions to it. + + +Editing Objects +=============== + +To edit objects, pass a list of transactions and use `objectIdentifier` to +specify which object to apply them to. You can normally pass an ID or PHID, +and many applicaitons also allow you to pass a monogram (for example, you can +edit a task by passing `T123`). + + +Building Transactions +===================== + +When creating or editing objects, you'll build a list of transactions to +apply. This transaction list will look something like this: + +```lang=json, name="Example Transaction List" +[ + { + "type": "title", + "value": "Assemble in the barnyard" + }, + { + "type": "description", + "value": "All animals should assemble in the barnyard promptly." + }, + { + "type": "subscribers.add", + "value": ["dog", "cat", "mouse"] + } +] +``` + +Applied to an empty object (say, a task), these transactions would create a new +task with the specified title, description and subscribers. + +Applied to an existing object, they would retitle the task, change its +description, and add new subscribers. + +The particular transactions available on each object are documented on the +Conduit API console page for that object. + + +Return Type +=========== + +WARNING: The structure of the return value from these methods is likely to +change as ApplicationEditor evolves. + +Return values look something like this for now: + +```lang=json, name=Example Return Value +{ + "object": { + "phid": "PHID-XXXX-1111" + }, + "transactions": [ + { + "phid": "PHID-YYYY-1111", + }, + { + "phid": "PHID-YYYY-2222", + } + ] +} +``` + +The `object` key contains information about the object which was created or +edited. + +The `transactions` key contains information about the transactions which were +actually applied. For many reasons, the transactions which actually apply may +be greater or fewer in number than the transactions you provided, or may differ +in their nature in other ways. + + +Next Steps +========== + +Continue by: + + - returning to the @{article:Conduit API Overview}. diff --git a/src/docs/user/userguide/conduit_search.diviner b/src/docs/user/userguide/conduit_search.diviner new file mode 100644 index 0000000000..2253831c65 --- /dev/null +++ b/src/docs/user/userguide/conduit_search.diviner @@ -0,0 +1,74 @@ +@title Conduit API: Using Search Endpoints +@group conduit + +Describes how to use search endpoints to find objects and read information. + +Overview +======== + +Many applications provide `search` endpoints, which are the primary way to +get information about objects (like tasks) using the API. + +To read information about objects, you'll specify a //query// which describes +which objects you want to retrieve. You can query for specific objects by +ID, or for a list of objects satisfying certain constraints (for example, open +tasks in a particular project). + +The best reference for a particular `search` endpoint is the Conduit API +console. For example, you can find the console page for `maniphest.search` by +navigating to {nav Conduit > maniphest.search} in the web UI. This page +contains detailed information about the endpoint and how it can be used. + + +Specifying a Query +================== + +The simplest query you can use is no query at all: just make a request with +no parameters. This will return the first page of visible objects. Most +applications sort objects by creation date by default, so usually this is +the 100 most recent objects. + +The easiest way to constrain results is to use a builtin query or a custom +query that you build using the web UI. To do this, first issue the query in +the web UI (for example, by clicking the builtin link on the left nav of the +list view, or by submitting the query form). + +The results page will include a //query key// in the URL. For builtin queries, +this is usually a human-readable term like `all` or `active`. For custom +queries, it is a hash value which looks something like `MT0Rh0fB2x4I`. + +You can submit this key in the `queryKey` parameter to issue the exact same +query via the Conduit API. This provides a simple way to build complex queries: +just build the via the web UI, then reuse the same query in the API. + +If you need more control or want to build dynamic queries, use the +`constraints` parameter to set constraints for individual query fields. + +For more details, consult the Conduit API console documentation for the +method you're using. It includes documentation on all available constraints +and lists builtin and saved query keys. + + +Attachments +=========== + +By default, queries return basic information about objects. If you want more +detailed information, most applications offer //attachments// which can let +you retrieve more information. + +For example, subscribers and projects are not returned by default, but you +can use subscribers to query them if you need this data. + +Asking for more data means a slower query and a larger result, so usually you +should only ask for data you need. + +The Conduit API console page for each query method has detailed information +on which attachments it supports. + + +Next Steps +========== + +Continue by: + + - returning to the @{article:Conduit API Overview}.