2015-11-03 17:45:00 +01:00
|
|
|
<?php
|
|
|
|
|
Allow ApplicationEditor forms to be reconfigured
Summary:
Ref T9132. This diff doesn't do anything interesting, it just lays the groundwork for more interesting future diffs.
Broadly, the idea here is to let you create multiple views of each edit form. For example, we might create several different "Create Task" forms, like:
- "New Bug Report"
- "New Feature Request"
These would be views of the "Create Task" form, but with various adjustments:
- A form might have additional instructions ("how to file a good bug report").
- A form might have prefilled values for some fields (like particular projects, subscribers, or policies).
- A form might have some fields locked (so they can not be edited) or hidden.
- A form might have a different field order.
- A form might have a limited visibility policy, so only some users can access it.
This diff adds a new storage object (`EditEngineConfiguration`) to keep track of all those customizations and represent "a form which has been configured to look and work a certain way".
This doesn't let these configurations do anything useful/interesting, and you can't access them directly yet, it's just all the boring plumbing to enable more interesting behavior in the future.
Test Plan:
ApplicationEditor forms now let you manage available forms and edit the current form:
{F959025}
There's a new (bare bones) list of all available engines:
{F959030}
And if you jump into an engine, you can see all the forms for it:
{F959038}
The actual form configurations have standard detail/edit pages. The edit pages are themselves driven by ApplicationEditor, of course, so you can edit the form for editing forms.
Reviewers: chad
Reviewed By: chad
Maniphest Tasks: T9132
Differential Revision: https://secure.phabricator.com/D14453
2015-11-04 21:52:52 +01:00
|
|
|
abstract class PhabricatorEditEngineAPIMethod
|
2015-11-03 17:45:00 +01:00
|
|
|
extends ConduitAPIMethod {
|
|
|
|
|
|
|
|
abstract public function newEditEngine();
|
|
|
|
|
2015-11-16 18:24:50 +01:00
|
|
|
public function getApplication() {
|
|
|
|
$engine = $this->newEditEngine();
|
|
|
|
$class = $engine->getEngineApplicationClass();
|
|
|
|
return PhabricatorApplication::getByClass($class);
|
|
|
|
}
|
|
|
|
|
2015-11-03 17:45:00 +01:00
|
|
|
public function getMethodStatus() {
|
|
|
|
return self::METHOD_STATUS_UNSTABLE;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getMethodStatusDescription() {
|
|
|
|
return pht('ApplicationEditor methods are highly unstable.');
|
|
|
|
}
|
|
|
|
|
|
|
|
final protected function defineParamTypes() {
|
|
|
|
return array(
|
|
|
|
'transactions' => 'list<map<string, wild>>',
|
2015-11-29 20:28:27 +01:00
|
|
|
'objectIdentifier' => 'optional id|phid|string',
|
2015-11-03 17:45:00 +01:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
final protected function defineReturnType() {
|
|
|
|
return 'map<string, wild>';
|
|
|
|
}
|
|
|
|
|
|
|
|
final protected function execute(ConduitAPIRequest $request) {
|
|
|
|
$engine = $this->newEditEngine()
|
|
|
|
->setViewer($request->getUser());
|
|
|
|
|
|
|
|
return $engine->buildConduitResponse($request);
|
|
|
|
}
|
|
|
|
|
|
|
|
final public function getMethodDescription() {
|
|
|
|
// TODO: We don't currently have a real viewer in this method.
|
2015-11-17 18:33:06 +01:00
|
|
|
$viewer = PhabricatorUser::getOmnipotentUser();
|
2015-11-03 17:45:00 +01:00
|
|
|
|
|
|
|
$engine = $this->newEditEngine()
|
|
|
|
->setViewer($viewer);
|
|
|
|
|
2015-11-30 16:58:35 +01:00
|
|
|
$types = $engine->getConduitEditTypes();
|
2015-11-03 17:45:00 +01:00
|
|
|
|
|
|
|
$out = array();
|
|
|
|
|
|
|
|
$out[] = pht(<<<EOTEXT
|
|
|
|
This is a standard **ApplicationEditor** method which allows you to create and
|
|
|
|
modify objects by applying transactions.
|
|
|
|
|
|
|
|
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
|
|
|
|
----------------
|
|
|
|
|
2015-11-29 20:28:27 +01:00
|
|
|
To create an object, pass a list of `transactions` but leave `objectIdentifier`
|
2015-11-03 17:45:00 +01:00
|
|
|
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
|
2015-11-29 20:28:27 +01:00
|
|
|
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).
|
2015-11-03 17:45:00 +01:00
|
|
|
|
|
|
|
|
|
|
|
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');
|
|
|
|
$summary = pht('Summary');
|
|
|
|
$description = pht('Description');
|
|
|
|
$head_type = pht('Type');
|
|
|
|
|
|
|
|
$table = array();
|
|
|
|
$table[] = "| {$key} | {$summary} |";
|
|
|
|
$table[] = '|--------|----------------|';
|
|
|
|
foreach ($types as $type) {
|
|
|
|
$edit_type = $type->getEditType();
|
|
|
|
$edit_summary = $type->getSummary();
|
|
|
|
$table[] = "| `{$edit_type}` | {$edit_summary} |";
|
|
|
|
}
|
|
|
|
|
|
|
|
$out[] = implode("\n", $table);
|
|
|
|
|
|
|
|
foreach ($types as $type) {
|
|
|
|
$section = array();
|
|
|
|
$section[] = pht('Edit Type: %s', $type->getEditType());
|
|
|
|
$section[] = '---------';
|
|
|
|
$section[] = null;
|
|
|
|
$section[] = $type->getDescription();
|
|
|
|
$section[] = null;
|
|
|
|
$section[] = pht(
|
|
|
|
'This edit generates transactions of type `%s` internally.',
|
|
|
|
$type->getTransactionType());
|
|
|
|
$section[] = null;
|
|
|
|
|
|
|
|
$type_description = pht(
|
|
|
|
'Use `%s` to select this edit type.',
|
|
|
|
$type->getEditType());
|
|
|
|
|
|
|
|
$value_type = $type->getValueType();
|
2015-12-02 15:16:45 +01:00
|
|
|
if (!strlen($value_type)) {
|
|
|
|
$value_type = '?';
|
|
|
|
}
|
|
|
|
|
2015-11-03 17:45:00 +01:00
|
|
|
$value_description = $type->getValueDescription();
|
|
|
|
|
|
|
|
$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;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|