2015-11-03 05:38:06 -08:00
|
|
|
<?php
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Renders the "HTTP Parameters" help page for edit engines.
|
|
|
|
*
|
|
|
|
* This page has a ton of text and specialized rendering on it, this class
|
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 12:52:52 -08:00
|
|
|
* just pulls it out of the main @{class:PhabricatorEditEngine}.
|
2015-11-03 05:38:06 -08:00
|
|
|
*/
|
|
|
|
final class PhabricatorApplicationEditHTTPParameterHelpView
|
|
|
|
extends AphrontView {
|
|
|
|
|
|
|
|
private $object;
|
|
|
|
private $fields;
|
|
|
|
|
|
|
|
public function setObject($object) {
|
|
|
|
$this->object = $object;
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getObject() {
|
|
|
|
return $this->object;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function setFields(array $fields) {
|
|
|
|
$this->fields = $fields;
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getFields() {
|
|
|
|
return $this->fields;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function render() {
|
|
|
|
$object = $this->getObject();
|
|
|
|
$fields = $this->getFields();
|
|
|
|
|
|
|
|
$uri = 'https://your.install.com/application/edit/';
|
|
|
|
|
|
|
|
// Remove fields which do not expose an HTTP parameter type.
|
|
|
|
$types = array();
|
|
|
|
foreach ($fields as $key => $field) {
|
2015-12-18 10:51:10 -08:00
|
|
|
if (!$field->shouldGenerateTransactionsFromSubmit()) {
|
|
|
|
unset($fields[$key]);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2015-11-03 05:38:06 -08:00
|
|
|
$type = $field->getHTTPParameterType();
|
|
|
|
if ($type === null) {
|
|
|
|
unset($fields[$key]);
|
2015-11-18 14:11:21 -08:00
|
|
|
continue;
|
2015-11-03 05:38:06 -08:00
|
|
|
}
|
2015-12-18 10:51:10 -08:00
|
|
|
|
2015-11-04 05:05:10 -08:00
|
|
|
$types[$type->getTypeName()] = $type;
|
2015-11-03 05:38:06 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
$intro = pht(<<<EOTEXT
|
|
|
|
When creating objects in the web interface, you can use HTTP parameters to
|
|
|
|
prefill fields in the form. This allows you to quickly create a link to a
|
|
|
|
form with some of the fields already filled in with default values.
|
|
|
|
|
|
|
|
To prefill a form, start by finding the URI for the form you want to prefill.
|
|
|
|
Do this by navigating to the relevant application, clicking the "Create" button
|
|
|
|
for the type of object you want to create, and then copying the URI out of your
|
|
|
|
browser's address bar. It will usually look something like this:
|
|
|
|
|
|
|
|
```
|
|
|
|
%s
|
|
|
|
```
|
|
|
|
|
|
|
|
However, `your.install.com` will be the domain where your copy of Phabricator
|
|
|
|
is installed, and `application/` will be the URI for an application. Some
|
|
|
|
applications have multiple forms for creating objects or URIs that look a little
|
|
|
|
different than this example, so the URI may not look exactly like this.
|
|
|
|
|
|
|
|
To prefill the form, add properly encoded HTTP parameters to the URI. You
|
|
|
|
should end up with something like this:
|
|
|
|
|
|
|
|
```
|
|
|
|
%s?title=Platyplus&body=Ornithopter
|
|
|
|
```
|
|
|
|
|
|
|
|
If the form has `title` and `body` fields of the correct types, visiting this
|
|
|
|
link will prefill those fields with the values "Platypus" and "Ornithopter"
|
|
|
|
respectively.
|
|
|
|
|
|
|
|
The rest of this document shows which parameters you can add to this form and
|
|
|
|
how to format them.
|
|
|
|
|
|
|
|
|
|
|
|
Supported Fields
|
|
|
|
----------------
|
|
|
|
|
|
|
|
This form supports these fields:
|
|
|
|
|
|
|
|
EOTEXT
|
|
|
|
,
|
|
|
|
$uri,
|
|
|
|
$uri);
|
|
|
|
|
|
|
|
$rows = array();
|
|
|
|
foreach ($fields as $field) {
|
|
|
|
$rows[] = array(
|
|
|
|
$field->getLabel(),
|
2015-12-02 05:55:31 -08:00
|
|
|
head($field->getAllReadValueFromRequestKeys()),
|
2015-11-04 05:05:10 -08:00
|
|
|
$field->getHTTPParameterType()->getTypeName(),
|
2015-11-03 05:38:06 -08:00
|
|
|
$field->getDescription(),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
$main_table = id(new AphrontTableView($rows))
|
|
|
|
->setHeaders(
|
|
|
|
array(
|
|
|
|
pht('Label'),
|
|
|
|
pht('Key'),
|
|
|
|
pht('Type'),
|
|
|
|
pht('Description'),
|
|
|
|
))
|
|
|
|
->setColumnClasses(
|
|
|
|
array(
|
|
|
|
'pri',
|
|
|
|
null,
|
|
|
|
null,
|
|
|
|
'wide',
|
|
|
|
));
|
|
|
|
|
|
|
|
$aliases_text = pht(<<<EOTEXT
|
|
|
|
Aliases
|
|
|
|
-------
|
|
|
|
|
|
|
|
Aliases are alternate recognized keys for a field. For example, a field with
|
|
|
|
a complex key like `examplePHIDs` might be have a simple version of that key
|
|
|
|
as an alias, like `example`.
|
|
|
|
|
|
|
|
Aliases work just like the primary key when prefilling forms. They make it
|
|
|
|
easier to remember and use HTTP parameters by providing more natural ways to do
|
|
|
|
some prefilling.
|
|
|
|
|
|
|
|
For example, if a field has `examplePHIDs` as a key but has aliases `example`
|
|
|
|
and `examples`, these three URIs will all do the same thing:
|
|
|
|
|
|
|
|
```
|
|
|
|
%s?examplePHIDs=...
|
|
|
|
%s?examples=...
|
|
|
|
%s?example=...
|
|
|
|
```
|
|
|
|
|
|
|
|
If a URI specifies multiple default values for a field, the value using the
|
|
|
|
primary key has precedence. Generally, you can not mix different aliases in
|
|
|
|
a single URI.
|
|
|
|
|
|
|
|
EOTEXT
|
|
|
|
,
|
|
|
|
$uri,
|
|
|
|
$uri,
|
|
|
|
$uri);
|
|
|
|
|
|
|
|
$rows = array();
|
|
|
|
foreach ($fields as $field) {
|
2015-12-02 05:55:31 -08:00
|
|
|
$aliases = array_slice($field->getAllReadValueFromRequestKeys(), 1);
|
2015-11-03 05:38:06 -08:00
|
|
|
if (!$aliases) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
$rows[] = array(
|
|
|
|
$field->getLabel(),
|
|
|
|
$field->getKey(),
|
|
|
|
implode(', ', $aliases),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
$alias_table = id(new AphrontTableView($rows))
|
|
|
|
->setNoDataString(pht('This object has no fields with aliases.'))
|
|
|
|
->setHeaders(
|
|
|
|
array(
|
|
|
|
pht('Label'),
|
|
|
|
pht('Key'),
|
|
|
|
pht('Aliases'),
|
|
|
|
))
|
|
|
|
->setColumnClasses(
|
|
|
|
array(
|
|
|
|
'pri',
|
|
|
|
null,
|
|
|
|
'wide',
|
|
|
|
));
|
|
|
|
|
2015-12-07 11:37:51 -08:00
|
|
|
$template_text = pht(<<<EOTEXT
|
|
|
|
Template Objects
|
|
|
|
----------------
|
|
|
|
|
|
|
|
Instead of specifying each field value individually, you can specify another
|
|
|
|
object to use as a template. Some of the initial fields will be copied from the
|
|
|
|
template object.
|
|
|
|
|
|
|
|
Specify a template object with the `template` parameter. You can use an ID,
|
|
|
|
PHID, or monogram (for objects which have monograms). For example, you might
|
|
|
|
use URIs like these:
|
|
|
|
|
|
|
|
```
|
|
|
|
%s?template=123
|
|
|
|
%s?template=PHID-WXYZ-abcdef...
|
|
|
|
%s?template=T123
|
|
|
|
```
|
|
|
|
|
|
|
|
You can combine the `template` parameter with HTTP parameters: the template
|
|
|
|
object will be copied first, then any HTTP parameters will be read.
|
|
|
|
|
|
|
|
When using `template`, these fields will be copied:
|
|
|
|
EOTEXT
|
|
|
|
,
|
|
|
|
$uri,
|
|
|
|
$uri,
|
|
|
|
$uri);
|
|
|
|
|
2016-01-27 20:38:01 -08:00
|
|
|
$yes = id(new PHUIIconView())->setIcon('fa-check-circle green');
|
|
|
|
$no = id(new PHUIIconView())->setIcon('fa-times grey');
|
2015-12-07 11:37:51 -08:00
|
|
|
|
|
|
|
$rows = array();
|
|
|
|
foreach ($fields as $field) {
|
|
|
|
$rows[] = array(
|
|
|
|
$field->getLabel(),
|
|
|
|
$field->getIsCopyable() ? $yes : $no,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
$template_table = id(new AphrontTableView($rows))
|
|
|
|
->setNoDataString(
|
|
|
|
pht('None of the fields on this object support templating.'))
|
|
|
|
->setHeaders(
|
|
|
|
array(
|
|
|
|
pht('Field'),
|
|
|
|
pht('Will Copy'),
|
|
|
|
))
|
|
|
|
->setColumnClasses(
|
|
|
|
array(
|
|
|
|
'pri',
|
|
|
|
'wide',
|
|
|
|
));
|
|
|
|
|
2015-11-03 05:38:06 -08:00
|
|
|
$select_text = pht(<<<EOTEXT
|
|
|
|
Select Fields
|
|
|
|
-------------
|
|
|
|
|
|
|
|
Some fields support selection from a specific set of values. When prefilling
|
|
|
|
these fields, use the value in the **Value** column to select the appropriate
|
|
|
|
setting.
|
|
|
|
|
|
|
|
EOTEXT
|
|
|
|
);
|
|
|
|
|
|
|
|
$rows = array();
|
|
|
|
foreach ($fields as $field) {
|
|
|
|
if (!($field instanceof PhabricatorSelectEditField)) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
$options = $field->getOptions();
|
|
|
|
$label = $field->getLabel();
|
|
|
|
foreach ($options as $option_key => $option_value) {
|
|
|
|
if (strlen($option_key)) {
|
|
|
|
$option_display = $option_key;
|
|
|
|
} else {
|
|
|
|
$option_display = phutil_tag('em', array(), pht('<empty>'));
|
|
|
|
}
|
|
|
|
|
|
|
|
$rows[] = array(
|
|
|
|
$label,
|
|
|
|
$option_display,
|
|
|
|
$option_value,
|
|
|
|
);
|
|
|
|
$label = null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
$select_table = id(new AphrontTableView($rows))
|
|
|
|
->setNoDataString(pht('This object has no select fields.'))
|
|
|
|
->setHeaders(
|
|
|
|
array(
|
|
|
|
pht('Field'),
|
|
|
|
pht('Value'),
|
|
|
|
pht('Label'),
|
|
|
|
))
|
|
|
|
->setColumnClasses(
|
|
|
|
array(
|
|
|
|
'pri',
|
|
|
|
null,
|
|
|
|
'wide',
|
|
|
|
));
|
|
|
|
|
|
|
|
$types_text = pht(<<<EOTEXT
|
|
|
|
Field Types
|
|
|
|
-----------
|
|
|
|
|
|
|
|
Fields in this form have the types described in the table below. This table
|
|
|
|
shows how to format values for each field type.
|
|
|
|
EOTEXT
|
|
|
|
);
|
|
|
|
|
2015-11-04 05:05:10 -08:00
|
|
|
$types_table = id(new PhabricatorHTTPParameterTypeTableView())
|
|
|
|
->setHTTPParameterTypes($types);
|
2015-11-03 05:38:06 -08:00
|
|
|
|
|
|
|
return array(
|
|
|
|
$this->renderInstructions($intro),
|
2015-11-03 13:41:20 -08:00
|
|
|
$main_table,
|
2015-11-03 05:38:06 -08:00
|
|
|
$this->renderInstructions($aliases_text),
|
2015-11-03 13:41:20 -08:00
|
|
|
$alias_table,
|
2015-12-07 11:37:51 -08:00
|
|
|
$this->renderInstructions($template_text),
|
|
|
|
$template_table,
|
2015-11-03 05:38:06 -08:00
|
|
|
$this->renderInstructions($select_text),
|
2015-11-03 13:41:20 -08:00
|
|
|
$select_table,
|
2015-11-03 05:38:06 -08:00
|
|
|
$this->renderInstructions($types_text),
|
2015-11-03 13:41:20 -08:00
|
|
|
$types_table,
|
2015-11-03 05:38:06 -08:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
protected function renderInstructions($corpus) {
|
|
|
|
$viewer = $this->getUser();
|
2016-05-22 09:54:41 -07:00
|
|
|
$view = new PHUIRemarkupView($viewer, $corpus);
|
|
|
|
|
|
|
|
$view->setRemarkupOptions(
|
|
|
|
array(
|
|
|
|
PHUIRemarkupView::OPTION_PRESERVE_LINEBREAKS => false,
|
|
|
|
));
|
|
|
|
|
|
|
|
return $view;
|
2015-11-03 05:38:06 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|