Implement a basic version of ApplicationEditor in Paste
Summary:
Ref T9132. Ref T4768. This is a rough v0 of ApplicationEditor, which replaces the edit workflow in Paste.
This mostly looks and works like ApplicationSearch, and is heavily modeled on it.
Roughly, we define a set of editable fields and the ApplicationEditor stuff builds everything else.
This has no functional changes, except:
- I removed "Fork Paste" since I don't think it's particularly useful now that pastes are editable. We could restore it if users miss it.
- Subscribers are now editable.
- Form field order is a little goofy (this will be fixed in a future diff).
- Subscribers and projects are now race-resistant.
The race-resistance works like this: instead of submitting just the new value ("subscribers=apple, dog") and doing a set operation ("set subscribers = apple, dog"), we submit the old and new values ("original=apple" + "new=apple, dog") then apply the user's changes as an add + remove ("add=dog", "remove=<none>"). This means that two users who do "Edit Paste" at around the same time and each add or remove a couple of subscribers won't overwrite each other, unless they actually add or remove the exact same subscribers (in which case their edits legitimately conflict). Previously, the last user to save would win, and whatever was in their field would overwrite the prior state, potentially losing the first user's edits.
Test Plan:
- Created pastes.
- Created pastes via API.
- Edited pastes.
- Edited every field.
- Opened a paste in two windows and did project/subscriber edits in each, saved in arbitrary order, had edits respected.
Reviewers: chad
Reviewed By: chad
Maniphest Tasks: T4768, T9132
Differential Revision: https://secure.phabricator.com/D14390
2015-11-02 18:58:32 -08:00
|
|
|
<?php
|
|
|
|
|
2015-11-03 08:45:00 -08:00
|
|
|
|
|
|
|
/**
|
2015-11-03 15:59:23 -08:00
|
|
|
* @task fields Managing Fields
|
|
|
|
* @task text Display Text
|
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
|
|
|
* @task config Edit Engine Configuration
|
2015-11-03 15:59:23 -08:00
|
|
|
* @task uri Managing URIs
|
|
|
|
* @task load Creating and Loading Objects
|
2015-11-03 08:45:00 -08:00
|
|
|
* @task web Responding to Web Requests
|
2015-11-03 15:59:23 -08:00
|
|
|
* @task edit Responding to Edit Requests
|
|
|
|
* @task http Responding to HTTP Parameter Requests
|
2015-11-03 08:45:00 -08:00
|
|
|
* @task conduit Responding to Conduit Requests
|
|
|
|
*/
|
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
|
|
|
abstract class PhabricatorEditEngine
|
|
|
|
extends Phobject
|
|
|
|
implements PhabricatorPolicyInterface {
|
|
|
|
|
|
|
|
const EDITENGINECONFIG_DEFAULT = 'default';
|
Implement a basic version of ApplicationEditor in Paste
Summary:
Ref T9132. Ref T4768. This is a rough v0 of ApplicationEditor, which replaces the edit workflow in Paste.
This mostly looks and works like ApplicationSearch, and is heavily modeled on it.
Roughly, we define a set of editable fields and the ApplicationEditor stuff builds everything else.
This has no functional changes, except:
- I removed "Fork Paste" since I don't think it's particularly useful now that pastes are editable. We could restore it if users miss it.
- Subscribers are now editable.
- Form field order is a little goofy (this will be fixed in a future diff).
- Subscribers and projects are now race-resistant.
The race-resistance works like this: instead of submitting just the new value ("subscribers=apple, dog") and doing a set operation ("set subscribers = apple, dog"), we submit the old and new values ("original=apple" + "new=apple, dog") then apply the user's changes as an add + remove ("add=dog", "remove=<none>"). This means that two users who do "Edit Paste" at around the same time and each add or remove a couple of subscribers won't overwrite each other, unless they actually add or remove the exact same subscribers (in which case their edits legitimately conflict). Previously, the last user to save would win, and whatever was in their field would overwrite the prior state, potentially losing the first user's edits.
Test Plan:
- Created pastes.
- Created pastes via API.
- Edited pastes.
- Edited every field.
- Opened a paste in two windows and did project/subscriber edits in each, saved in arbitrary order, had edits respected.
Reviewers: chad
Reviewed By: chad
Maniphest Tasks: T4768, T9132
Differential Revision: https://secure.phabricator.com/D14390
2015-11-02 18:58:32 -08:00
|
|
|
|
|
|
|
private $viewer;
|
|
|
|
private $controller;
|
2015-11-03 05:38:06 -08:00
|
|
|
private $isCreate;
|
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
|
|
|
private $editEngineConfiguration;
|
Implement a basic version of ApplicationEditor in Paste
Summary:
Ref T9132. Ref T4768. This is a rough v0 of ApplicationEditor, which replaces the edit workflow in Paste.
This mostly looks and works like ApplicationSearch, and is heavily modeled on it.
Roughly, we define a set of editable fields and the ApplicationEditor stuff builds everything else.
This has no functional changes, except:
- I removed "Fork Paste" since I don't think it's particularly useful now that pastes are editable. We could restore it if users miss it.
- Subscribers are now editable.
- Form field order is a little goofy (this will be fixed in a future diff).
- Subscribers and projects are now race-resistant.
The race-resistance works like this: instead of submitting just the new value ("subscribers=apple, dog") and doing a set operation ("set subscribers = apple, dog"), we submit the old and new values ("original=apple" + "new=apple, dog") then apply the user's changes as an add + remove ("add=dog", "remove=<none>"). This means that two users who do "Edit Paste" at around the same time and each add or remove a couple of subscribers won't overwrite each other, unless they actually add or remove the exact same subscribers (in which case their edits legitimately conflict). Previously, the last user to save would win, and whatever was in their field would overwrite the prior state, potentially losing the first user's edits.
Test Plan:
- Created pastes.
- Created pastes via API.
- Edited pastes.
- Edited every field.
- Opened a paste in two windows and did project/subscriber edits in each, saved in arbitrary order, had edits respected.
Reviewers: chad
Reviewed By: chad
Maniphest Tasks: T4768, T9132
Differential Revision: https://secure.phabricator.com/D14390
2015-11-02 18:58:32 -08:00
|
|
|
|
|
|
|
final public function setViewer(PhabricatorUser $viewer) {
|
|
|
|
$this->viewer = $viewer;
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
|
|
|
final public function getViewer() {
|
|
|
|
return $this->viewer;
|
|
|
|
}
|
|
|
|
|
|
|
|
final public function setController(PhabricatorController $controller) {
|
|
|
|
$this->controller = $controller;
|
|
|
|
$this->setViewer($controller->getViewer());
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
|
|
|
final public function getController() {
|
|
|
|
return $this->controller;
|
|
|
|
}
|
|
|
|
|
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
|
|
|
final public function getEngineKey() {
|
|
|
|
return $this->getPhobjectClassConstant('ENGINECONST', 64);
|
|
|
|
}
|
|
|
|
|
2015-11-17 09:33:06 -08:00
|
|
|
final public function getApplication() {
|
|
|
|
$app_class = $this->getEngineApplicationClass();
|
|
|
|
return PhabricatorApplication::getByClass($app_class);
|
|
|
|
}
|
|
|
|
|
2015-11-03 15:59:23 -08:00
|
|
|
|
|
|
|
/* -( Managing Fields )---------------------------------------------------- */
|
|
|
|
|
|
|
|
|
2015-11-16 09:24:50 -08:00
|
|
|
abstract public function getEngineApplicationClass();
|
2015-11-03 15:59:23 -08:00
|
|
|
abstract protected function buildCustomEditFields($object);
|
|
|
|
|
2015-11-17 09:33:06 -08:00
|
|
|
public function getFieldsForConfig(
|
|
|
|
PhabricatorEditEngineConfiguration $config) {
|
|
|
|
|
|
|
|
$object = $this->newEditableObject();
|
2015-11-18 10:38:12 -08:00
|
|
|
|
2015-11-17 09:33:06 -08:00
|
|
|
$this->editEngineConfiguration = $config;
|
|
|
|
|
2015-11-18 10:38:12 -08:00
|
|
|
// This is mostly making sure that we fill in default values.
|
|
|
|
$this->setIsCreate(true);
|
|
|
|
|
2015-11-17 09:33:06 -08:00
|
|
|
return $this->buildEditFields($object);
|
|
|
|
}
|
|
|
|
|
Implement a basic version of ApplicationEditor in Paste
Summary:
Ref T9132. Ref T4768. This is a rough v0 of ApplicationEditor, which replaces the edit workflow in Paste.
This mostly looks and works like ApplicationSearch, and is heavily modeled on it.
Roughly, we define a set of editable fields and the ApplicationEditor stuff builds everything else.
This has no functional changes, except:
- I removed "Fork Paste" since I don't think it's particularly useful now that pastes are editable. We could restore it if users miss it.
- Subscribers are now editable.
- Form field order is a little goofy (this will be fixed in a future diff).
- Subscribers and projects are now race-resistant.
The race-resistance works like this: instead of submitting just the new value ("subscribers=apple, dog") and doing a set operation ("set subscribers = apple, dog"), we submit the old and new values ("original=apple" + "new=apple, dog") then apply the user's changes as an add + remove ("add=dog", "remove=<none>"). This means that two users who do "Edit Paste" at around the same time and each add or remove a couple of subscribers won't overwrite each other, unless they actually add or remove the exact same subscribers (in which case their edits legitimately conflict). Previously, the last user to save would win, and whatever was in their field would overwrite the prior state, potentially losing the first user's edits.
Test Plan:
- Created pastes.
- Created pastes via API.
- Edited pastes.
- Edited every field.
- Opened a paste in two windows and did project/subscriber edits in each, saved in arbitrary order, had edits respected.
Reviewers: chad
Reviewed By: chad
Maniphest Tasks: T4768, T9132
Differential Revision: https://secure.phabricator.com/D14390
2015-11-02 18:58:32 -08:00
|
|
|
final protected function buildEditFields($object) {
|
|
|
|
$viewer = $this->getViewer();
|
|
|
|
$editor = $object->getApplicationTransactionEditor();
|
|
|
|
|
|
|
|
$types = $editor->getTransactionTypesForObject($object);
|
|
|
|
$types = array_fuse($types);
|
|
|
|
|
|
|
|
$fields = $this->buildCustomEditFields($object);
|
|
|
|
|
|
|
|
if ($object instanceof PhabricatorPolicyInterface) {
|
|
|
|
$policies = id(new PhabricatorPolicyQuery())
|
|
|
|
->setViewer($viewer)
|
|
|
|
->setObject($object)
|
|
|
|
->execute();
|
|
|
|
|
|
|
|
$map = array(
|
|
|
|
PhabricatorTransactions::TYPE_VIEW_POLICY => array(
|
|
|
|
'key' => 'policy.view',
|
|
|
|
'aliases' => array('view'),
|
|
|
|
'capability' => PhabricatorPolicyCapability::CAN_VIEW,
|
2015-11-03 05:38:06 -08:00
|
|
|
'label' => pht('View Policy'),
|
|
|
|
'description' => pht('Controls who can view the object.'),
|
2015-11-03 08:45:00 -08:00
|
|
|
'edit' => 'view',
|
Implement a basic version of ApplicationEditor in Paste
Summary:
Ref T9132. Ref T4768. This is a rough v0 of ApplicationEditor, which replaces the edit workflow in Paste.
This mostly looks and works like ApplicationSearch, and is heavily modeled on it.
Roughly, we define a set of editable fields and the ApplicationEditor stuff builds everything else.
This has no functional changes, except:
- I removed "Fork Paste" since I don't think it's particularly useful now that pastes are editable. We could restore it if users miss it.
- Subscribers are now editable.
- Form field order is a little goofy (this will be fixed in a future diff).
- Subscribers and projects are now race-resistant.
The race-resistance works like this: instead of submitting just the new value ("subscribers=apple, dog") and doing a set operation ("set subscribers = apple, dog"), we submit the old and new values ("original=apple" + "new=apple, dog") then apply the user's changes as an add + remove ("add=dog", "remove=<none>"). This means that two users who do "Edit Paste" at around the same time and each add or remove a couple of subscribers won't overwrite each other, unless they actually add or remove the exact same subscribers (in which case their edits legitimately conflict). Previously, the last user to save would win, and whatever was in their field would overwrite the prior state, potentially losing the first user's edits.
Test Plan:
- Created pastes.
- Created pastes via API.
- Edited pastes.
- Edited every field.
- Opened a paste in two windows and did project/subscriber edits in each, saved in arbitrary order, had edits respected.
Reviewers: chad
Reviewed By: chad
Maniphest Tasks: T4768, T9132
Differential Revision: https://secure.phabricator.com/D14390
2015-11-02 18:58:32 -08:00
|
|
|
),
|
|
|
|
PhabricatorTransactions::TYPE_EDIT_POLICY => array(
|
|
|
|
'key' => 'policy.edit',
|
|
|
|
'aliases' => array('edit'),
|
|
|
|
'capability' => PhabricatorPolicyCapability::CAN_EDIT,
|
2015-11-03 05:38:06 -08:00
|
|
|
'label' => pht('Edit Policy'),
|
|
|
|
'description' => pht('Controls who can edit the object.'),
|
2015-11-03 08:45:00 -08:00
|
|
|
'edit' => 'edit',
|
Implement a basic version of ApplicationEditor in Paste
Summary:
Ref T9132. Ref T4768. This is a rough v0 of ApplicationEditor, which replaces the edit workflow in Paste.
This mostly looks and works like ApplicationSearch, and is heavily modeled on it.
Roughly, we define a set of editable fields and the ApplicationEditor stuff builds everything else.
This has no functional changes, except:
- I removed "Fork Paste" since I don't think it's particularly useful now that pastes are editable. We could restore it if users miss it.
- Subscribers are now editable.
- Form field order is a little goofy (this will be fixed in a future diff).
- Subscribers and projects are now race-resistant.
The race-resistance works like this: instead of submitting just the new value ("subscribers=apple, dog") and doing a set operation ("set subscribers = apple, dog"), we submit the old and new values ("original=apple" + "new=apple, dog") then apply the user's changes as an add + remove ("add=dog", "remove=<none>"). This means that two users who do "Edit Paste" at around the same time and each add or remove a couple of subscribers won't overwrite each other, unless they actually add or remove the exact same subscribers (in which case their edits legitimately conflict). Previously, the last user to save would win, and whatever was in their field would overwrite the prior state, potentially losing the first user's edits.
Test Plan:
- Created pastes.
- Created pastes via API.
- Edited pastes.
- Edited every field.
- Opened a paste in two windows and did project/subscriber edits in each, saved in arbitrary order, had edits respected.
Reviewers: chad
Reviewed By: chad
Maniphest Tasks: T4768, T9132
Differential Revision: https://secure.phabricator.com/D14390
2015-11-02 18:58:32 -08:00
|
|
|
),
|
|
|
|
PhabricatorTransactions::TYPE_JOIN_POLICY => array(
|
|
|
|
'key' => 'policy.join',
|
|
|
|
'aliases' => array('join'),
|
|
|
|
'capability' => PhabricatorPolicyCapability::CAN_JOIN,
|
2015-11-03 05:38:06 -08:00
|
|
|
'label' => pht('Join Policy'),
|
|
|
|
'description' => pht('Controls who can join the object.'),
|
2015-11-03 08:45:00 -08:00
|
|
|
'edit' => 'join',
|
Implement a basic version of ApplicationEditor in Paste
Summary:
Ref T9132. Ref T4768. This is a rough v0 of ApplicationEditor, which replaces the edit workflow in Paste.
This mostly looks and works like ApplicationSearch, and is heavily modeled on it.
Roughly, we define a set of editable fields and the ApplicationEditor stuff builds everything else.
This has no functional changes, except:
- I removed "Fork Paste" since I don't think it's particularly useful now that pastes are editable. We could restore it if users miss it.
- Subscribers are now editable.
- Form field order is a little goofy (this will be fixed in a future diff).
- Subscribers and projects are now race-resistant.
The race-resistance works like this: instead of submitting just the new value ("subscribers=apple, dog") and doing a set operation ("set subscribers = apple, dog"), we submit the old and new values ("original=apple" + "new=apple, dog") then apply the user's changes as an add + remove ("add=dog", "remove=<none>"). This means that two users who do "Edit Paste" at around the same time and each add or remove a couple of subscribers won't overwrite each other, unless they actually add or remove the exact same subscribers (in which case their edits legitimately conflict). Previously, the last user to save would win, and whatever was in their field would overwrite the prior state, potentially losing the first user's edits.
Test Plan:
- Created pastes.
- Created pastes via API.
- Edited pastes.
- Edited every field.
- Opened a paste in two windows and did project/subscriber edits in each, saved in arbitrary order, had edits respected.
Reviewers: chad
Reviewed By: chad
Maniphest Tasks: T4768, T9132
Differential Revision: https://secure.phabricator.com/D14390
2015-11-02 18:58:32 -08:00
|
|
|
),
|
|
|
|
);
|
|
|
|
|
|
|
|
foreach ($map as $type => $spec) {
|
|
|
|
if (empty($types[$type])) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
$capability = $spec['capability'];
|
|
|
|
$key = $spec['key'];
|
|
|
|
$aliases = $spec['aliases'];
|
2015-11-03 05:38:06 -08:00
|
|
|
$label = $spec['label'];
|
|
|
|
$description = $spec['description'];
|
2015-11-03 08:45:00 -08:00
|
|
|
$edit = $spec['edit'];
|
Implement a basic version of ApplicationEditor in Paste
Summary:
Ref T9132. Ref T4768. This is a rough v0 of ApplicationEditor, which replaces the edit workflow in Paste.
This mostly looks and works like ApplicationSearch, and is heavily modeled on it.
Roughly, we define a set of editable fields and the ApplicationEditor stuff builds everything else.
This has no functional changes, except:
- I removed "Fork Paste" since I don't think it's particularly useful now that pastes are editable. We could restore it if users miss it.
- Subscribers are now editable.
- Form field order is a little goofy (this will be fixed in a future diff).
- Subscribers and projects are now race-resistant.
The race-resistance works like this: instead of submitting just the new value ("subscribers=apple, dog") and doing a set operation ("set subscribers = apple, dog"), we submit the old and new values ("original=apple" + "new=apple, dog") then apply the user's changes as an add + remove ("add=dog", "remove=<none>"). This means that two users who do "Edit Paste" at around the same time and each add or remove a couple of subscribers won't overwrite each other, unless they actually add or remove the exact same subscribers (in which case their edits legitimately conflict). Previously, the last user to save would win, and whatever was in their field would overwrite the prior state, potentially losing the first user's edits.
Test Plan:
- Created pastes.
- Created pastes via API.
- Edited pastes.
- Edited every field.
- Opened a paste in two windows and did project/subscriber edits in each, saved in arbitrary order, had edits respected.
Reviewers: chad
Reviewed By: chad
Maniphest Tasks: T4768, T9132
Differential Revision: https://secure.phabricator.com/D14390
2015-11-02 18:58:32 -08:00
|
|
|
|
|
|
|
$policy_field = id(new PhabricatorPolicyEditField())
|
|
|
|
->setKey($key)
|
2015-11-03 05:38:06 -08:00
|
|
|
->setLabel($label)
|
|
|
|
->setDescription($description)
|
Implement a basic version of ApplicationEditor in Paste
Summary:
Ref T9132. Ref T4768. This is a rough v0 of ApplicationEditor, which replaces the edit workflow in Paste.
This mostly looks and works like ApplicationSearch, and is heavily modeled on it.
Roughly, we define a set of editable fields and the ApplicationEditor stuff builds everything else.
This has no functional changes, except:
- I removed "Fork Paste" since I don't think it's particularly useful now that pastes are editable. We could restore it if users miss it.
- Subscribers are now editable.
- Form field order is a little goofy (this will be fixed in a future diff).
- Subscribers and projects are now race-resistant.
The race-resistance works like this: instead of submitting just the new value ("subscribers=apple, dog") and doing a set operation ("set subscribers = apple, dog"), we submit the old and new values ("original=apple" + "new=apple, dog") then apply the user's changes as an add + remove ("add=dog", "remove=<none>"). This means that two users who do "Edit Paste" at around the same time and each add or remove a couple of subscribers won't overwrite each other, unless they actually add or remove the exact same subscribers (in which case their edits legitimately conflict). Previously, the last user to save would win, and whatever was in their field would overwrite the prior state, potentially losing the first user's edits.
Test Plan:
- Created pastes.
- Created pastes via API.
- Edited pastes.
- Edited every field.
- Opened a paste in two windows and did project/subscriber edits in each, saved in arbitrary order, had edits respected.
Reviewers: chad
Reviewed By: chad
Maniphest Tasks: T4768, T9132
Differential Revision: https://secure.phabricator.com/D14390
2015-11-02 18:58:32 -08:00
|
|
|
->setAliases($aliases)
|
|
|
|
->setCapability($capability)
|
|
|
|
->setPolicies($policies)
|
|
|
|
->setTransactionType($type)
|
2015-11-03 08:45:00 -08:00
|
|
|
->setEditTypeKey($edit)
|
Implement a basic version of ApplicationEditor in Paste
Summary:
Ref T9132. Ref T4768. This is a rough v0 of ApplicationEditor, which replaces the edit workflow in Paste.
This mostly looks and works like ApplicationSearch, and is heavily modeled on it.
Roughly, we define a set of editable fields and the ApplicationEditor stuff builds everything else.
This has no functional changes, except:
- I removed "Fork Paste" since I don't think it's particularly useful now that pastes are editable. We could restore it if users miss it.
- Subscribers are now editable.
- Form field order is a little goofy (this will be fixed in a future diff).
- Subscribers and projects are now race-resistant.
The race-resistance works like this: instead of submitting just the new value ("subscribers=apple, dog") and doing a set operation ("set subscribers = apple, dog"), we submit the old and new values ("original=apple" + "new=apple, dog") then apply the user's changes as an add + remove ("add=dog", "remove=<none>"). This means that two users who do "Edit Paste" at around the same time and each add or remove a couple of subscribers won't overwrite each other, unless they actually add or remove the exact same subscribers (in which case their edits legitimately conflict). Previously, the last user to save would win, and whatever was in their field would overwrite the prior state, potentially losing the first user's edits.
Test Plan:
- Created pastes.
- Created pastes via API.
- Edited pastes.
- Edited every field.
- Opened a paste in two windows and did project/subscriber edits in each, saved in arbitrary order, had edits respected.
Reviewers: chad
Reviewed By: chad
Maniphest Tasks: T4768, T9132
Differential Revision: https://secure.phabricator.com/D14390
2015-11-02 18:58:32 -08:00
|
|
|
->setValue($object->getPolicy($capability));
|
|
|
|
$fields[] = $policy_field;
|
|
|
|
|
|
|
|
if ($object instanceof PhabricatorSpacesInterface) {
|
|
|
|
if ($capability == PhabricatorPolicyCapability::CAN_VIEW) {
|
|
|
|
$type_space = PhabricatorTransactions::TYPE_SPACE;
|
|
|
|
if (isset($types[$type_space])) {
|
|
|
|
$space_field = id(new PhabricatorSpaceEditField())
|
|
|
|
->setKey('spacePHID')
|
2015-11-03 05:38:06 -08:00
|
|
|
->setLabel(pht('Space'))
|
2015-11-03 08:45:00 -08:00
|
|
|
->setEditTypeKey('space')
|
2015-11-03 05:38:06 -08:00
|
|
|
->setDescription(
|
|
|
|
pht('Shifts the object in the Spaces application.'))
|
2015-11-17 09:33:06 -08:00
|
|
|
->setIsReorderable(false)
|
Implement a basic version of ApplicationEditor in Paste
Summary:
Ref T9132. Ref T4768. This is a rough v0 of ApplicationEditor, which replaces the edit workflow in Paste.
This mostly looks and works like ApplicationSearch, and is heavily modeled on it.
Roughly, we define a set of editable fields and the ApplicationEditor stuff builds everything else.
This has no functional changes, except:
- I removed "Fork Paste" since I don't think it's particularly useful now that pastes are editable. We could restore it if users miss it.
- Subscribers are now editable.
- Form field order is a little goofy (this will be fixed in a future diff).
- Subscribers and projects are now race-resistant.
The race-resistance works like this: instead of submitting just the new value ("subscribers=apple, dog") and doing a set operation ("set subscribers = apple, dog"), we submit the old and new values ("original=apple" + "new=apple, dog") then apply the user's changes as an add + remove ("add=dog", "remove=<none>"). This means that two users who do "Edit Paste" at around the same time and each add or remove a couple of subscribers won't overwrite each other, unless they actually add or remove the exact same subscribers (in which case their edits legitimately conflict). Previously, the last user to save would win, and whatever was in their field would overwrite the prior state, potentially losing the first user's edits.
Test Plan:
- Created pastes.
- Created pastes via API.
- Edited pastes.
- Edited every field.
- Opened a paste in two windows and did project/subscriber edits in each, saved in arbitrary order, had edits respected.
Reviewers: chad
Reviewed By: chad
Maniphest Tasks: T4768, T9132
Differential Revision: https://secure.phabricator.com/D14390
2015-11-02 18:58:32 -08:00
|
|
|
->setAliases(array('space', 'policy.space'))
|
|
|
|
->setTransactionType($type_space)
|
|
|
|
->setValue($object->getSpacePHID());
|
|
|
|
$fields[] = $space_field;
|
|
|
|
|
|
|
|
$policy_field->setSpaceField($space_field);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
$edge_type = PhabricatorTransactions::TYPE_EDGE;
|
|
|
|
$object_phid = $object->getPHID();
|
|
|
|
|
|
|
|
$project_edge_type = PhabricatorProjectObjectHasProjectEdgeType::EDGECONST;
|
|
|
|
|
|
|
|
if ($object instanceof PhabricatorProjectInterface) {
|
|
|
|
if (isset($types[$edge_type])) {
|
|
|
|
if ($object_phid) {
|
|
|
|
$project_phids = PhabricatorEdgeQuery::loadDestinationPHIDs(
|
|
|
|
$object_phid,
|
|
|
|
$project_edge_type);
|
|
|
|
$project_phids = array_reverse($project_phids);
|
|
|
|
} else {
|
|
|
|
$project_phids = array();
|
|
|
|
}
|
|
|
|
|
2015-11-04 10:20:38 -08:00
|
|
|
$edge_field = id(new PhabricatorProjectsEditField())
|
Implement a basic version of ApplicationEditor in Paste
Summary:
Ref T9132. Ref T4768. This is a rough v0 of ApplicationEditor, which replaces the edit workflow in Paste.
This mostly looks and works like ApplicationSearch, and is heavily modeled on it.
Roughly, we define a set of editable fields and the ApplicationEditor stuff builds everything else.
This has no functional changes, except:
- I removed "Fork Paste" since I don't think it's particularly useful now that pastes are editable. We could restore it if users miss it.
- Subscribers are now editable.
- Form field order is a little goofy (this will be fixed in a future diff).
- Subscribers and projects are now race-resistant.
The race-resistance works like this: instead of submitting just the new value ("subscribers=apple, dog") and doing a set operation ("set subscribers = apple, dog"), we submit the old and new values ("original=apple" + "new=apple, dog") then apply the user's changes as an add + remove ("add=dog", "remove=<none>"). This means that two users who do "Edit Paste" at around the same time and each add or remove a couple of subscribers won't overwrite each other, unless they actually add or remove the exact same subscribers (in which case their edits legitimately conflict). Previously, the last user to save would win, and whatever was in their field would overwrite the prior state, potentially losing the first user's edits.
Test Plan:
- Created pastes.
- Created pastes via API.
- Edited pastes.
- Edited every field.
- Opened a paste in two windows and did project/subscriber edits in each, saved in arbitrary order, had edits respected.
Reviewers: chad
Reviewed By: chad
Maniphest Tasks: T4768, T9132
Differential Revision: https://secure.phabricator.com/D14390
2015-11-02 18:58:32 -08:00
|
|
|
->setKey('projectPHIDs')
|
|
|
|
->setLabel(pht('Projects'))
|
2015-11-03 08:45:00 -08:00
|
|
|
->setEditTypeKey('projects')
|
2015-11-04 10:20:38 -08:00
|
|
|
->setDescription(pht('Add or remove associated projects.'))
|
Implement a basic version of ApplicationEditor in Paste
Summary:
Ref T9132. Ref T4768. This is a rough v0 of ApplicationEditor, which replaces the edit workflow in Paste.
This mostly looks and works like ApplicationSearch, and is heavily modeled on it.
Roughly, we define a set of editable fields and the ApplicationEditor stuff builds everything else.
This has no functional changes, except:
- I removed "Fork Paste" since I don't think it's particularly useful now that pastes are editable. We could restore it if users miss it.
- Subscribers are now editable.
- Form field order is a little goofy (this will be fixed in a future diff).
- Subscribers and projects are now race-resistant.
The race-resistance works like this: instead of submitting just the new value ("subscribers=apple, dog") and doing a set operation ("set subscribers = apple, dog"), we submit the old and new values ("original=apple" + "new=apple, dog") then apply the user's changes as an add + remove ("add=dog", "remove=<none>"). This means that two users who do "Edit Paste" at around the same time and each add or remove a couple of subscribers won't overwrite each other, unless they actually add or remove the exact same subscribers (in which case their edits legitimately conflict). Previously, the last user to save would win, and whatever was in their field would overwrite the prior state, potentially losing the first user's edits.
Test Plan:
- Created pastes.
- Created pastes via API.
- Edited pastes.
- Edited every field.
- Opened a paste in two windows and did project/subscriber edits in each, saved in arbitrary order, had edits respected.
Reviewers: chad
Reviewed By: chad
Maniphest Tasks: T4768, T9132
Differential Revision: https://secure.phabricator.com/D14390
2015-11-02 18:58:32 -08:00
|
|
|
->setAliases(array('project', 'projects'))
|
|
|
|
->setTransactionType($edge_type)
|
|
|
|
->setMetadataValue('edge:type', $project_edge_type)
|
|
|
|
->setValue($project_phids);
|
|
|
|
$fields[] = $edge_field;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
$subscribers_type = PhabricatorTransactions::TYPE_SUBSCRIBERS;
|
|
|
|
|
|
|
|
if ($object instanceof PhabricatorSubscribableInterface) {
|
|
|
|
if (isset($types[$subscribers_type])) {
|
|
|
|
if ($object_phid) {
|
|
|
|
$sub_phids = PhabricatorSubscribersQuery::loadSubscribersForPHID(
|
|
|
|
$object_phid);
|
|
|
|
} else {
|
|
|
|
// TODO: Allow applications to provide default subscribers; Maniphest
|
|
|
|
// does this at a minimum.
|
|
|
|
$sub_phids = array();
|
|
|
|
}
|
|
|
|
|
2015-11-04 10:20:38 -08:00
|
|
|
$subscribers_field = id(new PhabricatorSubscribersEditField())
|
Implement a basic version of ApplicationEditor in Paste
Summary:
Ref T9132. Ref T4768. This is a rough v0 of ApplicationEditor, which replaces the edit workflow in Paste.
This mostly looks and works like ApplicationSearch, and is heavily modeled on it.
Roughly, we define a set of editable fields and the ApplicationEditor stuff builds everything else.
This has no functional changes, except:
- I removed "Fork Paste" since I don't think it's particularly useful now that pastes are editable. We could restore it if users miss it.
- Subscribers are now editable.
- Form field order is a little goofy (this will be fixed in a future diff).
- Subscribers and projects are now race-resistant.
The race-resistance works like this: instead of submitting just the new value ("subscribers=apple, dog") and doing a set operation ("set subscribers = apple, dog"), we submit the old and new values ("original=apple" + "new=apple, dog") then apply the user's changes as an add + remove ("add=dog", "remove=<none>"). This means that two users who do "Edit Paste" at around the same time and each add or remove a couple of subscribers won't overwrite each other, unless they actually add or remove the exact same subscribers (in which case their edits legitimately conflict). Previously, the last user to save would win, and whatever was in their field would overwrite the prior state, potentially losing the first user's edits.
Test Plan:
- Created pastes.
- Created pastes via API.
- Edited pastes.
- Edited every field.
- Opened a paste in two windows and did project/subscriber edits in each, saved in arbitrary order, had edits respected.
Reviewers: chad
Reviewed By: chad
Maniphest Tasks: T4768, T9132
Differential Revision: https://secure.phabricator.com/D14390
2015-11-02 18:58:32 -08:00
|
|
|
->setKey('subscriberPHIDs')
|
|
|
|
->setLabel(pht('Subscribers'))
|
2015-11-03 08:45:00 -08:00
|
|
|
->setEditTypeKey('subscribers')
|
2015-11-03 05:38:06 -08:00
|
|
|
->setDescription(pht('Manage subscribers.'))
|
Implement a basic version of ApplicationEditor in Paste
Summary:
Ref T9132. Ref T4768. This is a rough v0 of ApplicationEditor, which replaces the edit workflow in Paste.
This mostly looks and works like ApplicationSearch, and is heavily modeled on it.
Roughly, we define a set of editable fields and the ApplicationEditor stuff builds everything else.
This has no functional changes, except:
- I removed "Fork Paste" since I don't think it's particularly useful now that pastes are editable. We could restore it if users miss it.
- Subscribers are now editable.
- Form field order is a little goofy (this will be fixed in a future diff).
- Subscribers and projects are now race-resistant.
The race-resistance works like this: instead of submitting just the new value ("subscribers=apple, dog") and doing a set operation ("set subscribers = apple, dog"), we submit the old and new values ("original=apple" + "new=apple, dog") then apply the user's changes as an add + remove ("add=dog", "remove=<none>"). This means that two users who do "Edit Paste" at around the same time and each add or remove a couple of subscribers won't overwrite each other, unless they actually add or remove the exact same subscribers (in which case their edits legitimately conflict). Previously, the last user to save would win, and whatever was in their field would overwrite the prior state, potentially losing the first user's edits.
Test Plan:
- Created pastes.
- Created pastes via API.
- Edited pastes.
- Edited every field.
- Opened a paste in two windows and did project/subscriber edits in each, saved in arbitrary order, had edits respected.
Reviewers: chad
Reviewed By: chad
Maniphest Tasks: T4768, T9132
Differential Revision: https://secure.phabricator.com/D14390
2015-11-02 18:58:32 -08:00
|
|
|
->setAliases(array('subscriber', 'subscribers'))
|
|
|
|
->setTransactionType($subscribers_type)
|
|
|
|
->setValue($sub_phids);
|
|
|
|
$fields[] = $subscribers_field;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-11-18 14:11:21 -08:00
|
|
|
$xaction = $object->getApplicationTransactionTemplate();
|
|
|
|
$comment = $xaction->getApplicationTransactionCommentObject();
|
|
|
|
if ($comment) {
|
|
|
|
$comment_type = PhabricatorTransactions::TYPE_COMMENT;
|
|
|
|
|
|
|
|
$comment_field = id(new PhabricatorCommentEditField())
|
|
|
|
->setKey('comment')
|
|
|
|
->setLabel(pht('Comments'))
|
|
|
|
->setDescription(pht('Add comments.'))
|
|
|
|
->setAliases(array('comments'))
|
|
|
|
->setIsHidden(true)
|
|
|
|
->setTransactionType($comment_type)
|
|
|
|
->setValue(null);
|
|
|
|
$fields[] = $comment_field;
|
|
|
|
}
|
|
|
|
|
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
|
|
|
$config = $this->getEditEngineConfiguration();
|
|
|
|
$fields = $config->applyConfigurationToFields($this, $fields);
|
|
|
|
|
2015-11-03 15:59:23 -08:00
|
|
|
foreach ($fields as $field) {
|
|
|
|
$field
|
|
|
|
->setViewer($viewer)
|
|
|
|
->setObject($object);
|
|
|
|
}
|
|
|
|
|
Implement a basic version of ApplicationEditor in Paste
Summary:
Ref T9132. Ref T4768. This is a rough v0 of ApplicationEditor, which replaces the edit workflow in Paste.
This mostly looks and works like ApplicationSearch, and is heavily modeled on it.
Roughly, we define a set of editable fields and the ApplicationEditor stuff builds everything else.
This has no functional changes, except:
- I removed "Fork Paste" since I don't think it's particularly useful now that pastes are editable. We could restore it if users miss it.
- Subscribers are now editable.
- Form field order is a little goofy (this will be fixed in a future diff).
- Subscribers and projects are now race-resistant.
The race-resistance works like this: instead of submitting just the new value ("subscribers=apple, dog") and doing a set operation ("set subscribers = apple, dog"), we submit the old and new values ("original=apple" + "new=apple, dog") then apply the user's changes as an add + remove ("add=dog", "remove=<none>"). This means that two users who do "Edit Paste" at around the same time and each add or remove a couple of subscribers won't overwrite each other, unless they actually add or remove the exact same subscribers (in which case their edits legitimately conflict). Previously, the last user to save would win, and whatever was in their field would overwrite the prior state, potentially losing the first user's edits.
Test Plan:
- Created pastes.
- Created pastes via API.
- Edited pastes.
- Edited every field.
- Opened a paste in two windows and did project/subscriber edits in each, saved in arbitrary order, had edits respected.
Reviewers: chad
Reviewed By: chad
Maniphest Tasks: T4768, T9132
Differential Revision: https://secure.phabricator.com/D14390
2015-11-02 18:58:32 -08:00
|
|
|
return $fields;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-11-03 15:59:23 -08:00
|
|
|
/* -( Display Text )------------------------------------------------------- */
|
|
|
|
|
|
|
|
|
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
|
|
|
/**
|
|
|
|
* @task text
|
|
|
|
*/
|
|
|
|
abstract public function getEngineName();
|
|
|
|
|
|
|
|
|
2015-11-03 15:59:23 -08:00
|
|
|
/**
|
|
|
|
* @task text
|
|
|
|
*/
|
Implement a basic version of ApplicationEditor in Paste
Summary:
Ref T9132. Ref T4768. This is a rough v0 of ApplicationEditor, which replaces the edit workflow in Paste.
This mostly looks and works like ApplicationSearch, and is heavily modeled on it.
Roughly, we define a set of editable fields and the ApplicationEditor stuff builds everything else.
This has no functional changes, except:
- I removed "Fork Paste" since I don't think it's particularly useful now that pastes are editable. We could restore it if users miss it.
- Subscribers are now editable.
- Form field order is a little goofy (this will be fixed in a future diff).
- Subscribers and projects are now race-resistant.
The race-resistance works like this: instead of submitting just the new value ("subscribers=apple, dog") and doing a set operation ("set subscribers = apple, dog"), we submit the old and new values ("original=apple" + "new=apple, dog") then apply the user's changes as an add + remove ("add=dog", "remove=<none>"). This means that two users who do "Edit Paste" at around the same time and each add or remove a couple of subscribers won't overwrite each other, unless they actually add or remove the exact same subscribers (in which case their edits legitimately conflict). Previously, the last user to save would win, and whatever was in their field would overwrite the prior state, potentially losing the first user's edits.
Test Plan:
- Created pastes.
- Created pastes via API.
- Edited pastes.
- Edited every field.
- Opened a paste in two windows and did project/subscriber edits in each, saved in arbitrary order, had edits respected.
Reviewers: chad
Reviewed By: chad
Maniphest Tasks: T4768, T9132
Differential Revision: https://secure.phabricator.com/D14390
2015-11-02 18:58:32 -08:00
|
|
|
abstract protected function getObjectCreateTitleText($object);
|
2015-11-03 15:59:23 -08:00
|
|
|
|
2015-11-17 09:33:06 -08:00
|
|
|
/**
|
|
|
|
* @task text
|
|
|
|
*/
|
|
|
|
protected function getFormHeaderText($object) {
|
|
|
|
$config = $this->getEditEngineConfiguration();
|
|
|
|
return $config->getName();
|
|
|
|
}
|
2015-11-03 15:59:23 -08:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @task text
|
|
|
|
*/
|
Implement a basic version of ApplicationEditor in Paste
Summary:
Ref T9132. Ref T4768. This is a rough v0 of ApplicationEditor, which replaces the edit workflow in Paste.
This mostly looks and works like ApplicationSearch, and is heavily modeled on it.
Roughly, we define a set of editable fields and the ApplicationEditor stuff builds everything else.
This has no functional changes, except:
- I removed "Fork Paste" since I don't think it's particularly useful now that pastes are editable. We could restore it if users miss it.
- Subscribers are now editable.
- Form field order is a little goofy (this will be fixed in a future diff).
- Subscribers and projects are now race-resistant.
The race-resistance works like this: instead of submitting just the new value ("subscribers=apple, dog") and doing a set operation ("set subscribers = apple, dog"), we submit the old and new values ("original=apple" + "new=apple, dog") then apply the user's changes as an add + remove ("add=dog", "remove=<none>"). This means that two users who do "Edit Paste" at around the same time and each add or remove a couple of subscribers won't overwrite each other, unless they actually add or remove the exact same subscribers (in which case their edits legitimately conflict). Previously, the last user to save would win, and whatever was in their field would overwrite the prior state, potentially losing the first user's edits.
Test Plan:
- Created pastes.
- Created pastes via API.
- Edited pastes.
- Edited every field.
- Opened a paste in two windows and did project/subscriber edits in each, saved in arbitrary order, had edits respected.
Reviewers: chad
Reviewed By: chad
Maniphest Tasks: T4768, T9132
Differential Revision: https://secure.phabricator.com/D14390
2015-11-02 18:58:32 -08:00
|
|
|
abstract protected function getObjectEditTitleText($object);
|
2015-11-03 15:59:23 -08:00
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @task text
|
|
|
|
*/
|
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
|
|
|
abstract protected function getObjectCreateShortText();
|
2015-11-03 15:59:23 -08:00
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @task text
|
|
|
|
*/
|
Implement a basic version of ApplicationEditor in Paste
Summary:
Ref T9132. Ref T4768. This is a rough v0 of ApplicationEditor, which replaces the edit workflow in Paste.
This mostly looks and works like ApplicationSearch, and is heavily modeled on it.
Roughly, we define a set of editable fields and the ApplicationEditor stuff builds everything else.
This has no functional changes, except:
- I removed "Fork Paste" since I don't think it's particularly useful now that pastes are editable. We could restore it if users miss it.
- Subscribers are now editable.
- Form field order is a little goofy (this will be fixed in a future diff).
- Subscribers and projects are now race-resistant.
The race-resistance works like this: instead of submitting just the new value ("subscribers=apple, dog") and doing a set operation ("set subscribers = apple, dog"), we submit the old and new values ("original=apple" + "new=apple, dog") then apply the user's changes as an add + remove ("add=dog", "remove=<none>"). This means that two users who do "Edit Paste" at around the same time and each add or remove a couple of subscribers won't overwrite each other, unless they actually add or remove the exact same subscribers (in which case their edits legitimately conflict). Previously, the last user to save would win, and whatever was in their field would overwrite the prior state, potentially losing the first user's edits.
Test Plan:
- Created pastes.
- Created pastes via API.
- Edited pastes.
- Edited every field.
- Opened a paste in two windows and did project/subscriber edits in each, saved in arbitrary order, had edits respected.
Reviewers: chad
Reviewed By: chad
Maniphest Tasks: T4768, T9132
Differential Revision: https://secure.phabricator.com/D14390
2015-11-02 18:58:32 -08:00
|
|
|
abstract protected function getObjectEditShortText($object);
|
2015-11-03 15:59:23 -08:00
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @task text
|
|
|
|
*/
|
|
|
|
protected function getObjectCreateButtonText($object) {
|
|
|
|
return $this->getObjectCreateTitleText($object);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @task text
|
|
|
|
*/
|
|
|
|
protected function getObjectEditButtonText($object) {
|
|
|
|
return pht('Save Changes');
|
|
|
|
}
|
|
|
|
|
|
|
|
|
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
|
|
|
/* -( Edit Engine Configuration )------------------------------------------ */
|
|
|
|
|
|
|
|
|
|
|
|
protected function supportsEditEngineConfiguration() {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
final protected function getEditEngineConfiguration() {
|
|
|
|
return $this->editEngineConfiguration;
|
|
|
|
}
|
|
|
|
|
|
|
|
private function loadEditEngineConfiguration($key) {
|
|
|
|
if ($key === null) {
|
|
|
|
$key = self::EDITENGINECONFIG_DEFAULT;
|
|
|
|
}
|
|
|
|
|
|
|
|
$config = id(new PhabricatorEditEngineConfigurationQuery())
|
|
|
|
->setViewer($this->getViewer())
|
|
|
|
->withEngineKeys(array($this->getEngineKey()))
|
|
|
|
->withIdentifiers(array($key))
|
|
|
|
->executeOne();
|
|
|
|
if (!$config) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
$this->editEngineConfiguration = $config;
|
|
|
|
|
|
|
|
return $config;
|
|
|
|
}
|
|
|
|
|
|
|
|
final public function getBuiltinEngineConfigurations() {
|
|
|
|
$configurations = $this->newBuiltinEngineConfigurations();
|
|
|
|
|
|
|
|
if (!$configurations) {
|
|
|
|
throw new Exception(
|
|
|
|
pht(
|
|
|
|
'EditEngine ("%s") returned no builtin engine configurations, but '.
|
|
|
|
'an edit engine must have at least one configuration.',
|
|
|
|
get_class($this)));
|
|
|
|
}
|
|
|
|
|
|
|
|
assert_instances_of($configurations, 'PhabricatorEditEngineConfiguration');
|
|
|
|
|
|
|
|
$has_default = false;
|
|
|
|
foreach ($configurations as $config) {
|
|
|
|
if ($config->getBuiltinKey() == self::EDITENGINECONFIG_DEFAULT) {
|
|
|
|
$has_default = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!$has_default) {
|
|
|
|
$first = head($configurations);
|
|
|
|
if (!$first->getBuiltinKey()) {
|
|
|
|
$first->setBuiltinKey(self::EDITENGINECONFIG_DEFAULT);
|
|
|
|
|
|
|
|
if (!strlen($first->getName())) {
|
|
|
|
$first->setName($this->getObjectCreateShortText());
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
throw new Exception(
|
|
|
|
pht(
|
|
|
|
'EditEngine ("%s") returned builtin engine configurations, '.
|
|
|
|
'but none are marked as default and the first configuration has '.
|
|
|
|
'a different builtin key already. Mark a builtin as default or '.
|
|
|
|
'omit the key from the first configuration',
|
|
|
|
get_class($this)));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
$builtins = array();
|
|
|
|
foreach ($configurations as $key => $config) {
|
|
|
|
$builtin_key = $config->getBuiltinKey();
|
|
|
|
|
|
|
|
if ($builtin_key === null) {
|
|
|
|
throw new Exception(
|
|
|
|
pht(
|
|
|
|
'EditEngine ("%s") returned builtin engine configurations, '.
|
|
|
|
'but one (with key "%s") is missing a builtin key. Provide a '.
|
|
|
|
'builtin key for each configuration (you can omit it from the '.
|
|
|
|
'first configuration in the list to automatically assign the '.
|
|
|
|
'default key).',
|
|
|
|
get_class($this),
|
|
|
|
$key));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (isset($builtins[$builtin_key])) {
|
|
|
|
throw new Exception(
|
|
|
|
pht(
|
|
|
|
'EditEngine ("%s") returned builtin engine configurations, '.
|
|
|
|
'but at least two specify the same builtin key ("%s"). Engines '.
|
|
|
|
'must have unique builtin keys.',
|
|
|
|
get_class($this),
|
|
|
|
$builtin_key));
|
|
|
|
}
|
|
|
|
|
|
|
|
$builtins[$builtin_key] = $config;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return $builtins;
|
|
|
|
}
|
|
|
|
|
|
|
|
protected function newBuiltinEngineConfigurations() {
|
|
|
|
return array(
|
|
|
|
$this->newConfiguration(),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
final protected function newConfiguration() {
|
|
|
|
return PhabricatorEditEngineConfiguration::initializeNewConfiguration(
|
|
|
|
$this->getViewer(),
|
|
|
|
$this);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-11-03 15:59:23 -08:00
|
|
|
/* -( Managing URIs )------------------------------------------------------ */
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @task uri
|
|
|
|
*/
|
Implement a basic version of ApplicationEditor in Paste
Summary:
Ref T9132. Ref T4768. This is a rough v0 of ApplicationEditor, which replaces the edit workflow in Paste.
This mostly looks and works like ApplicationSearch, and is heavily modeled on it.
Roughly, we define a set of editable fields and the ApplicationEditor stuff builds everything else.
This has no functional changes, except:
- I removed "Fork Paste" since I don't think it's particularly useful now that pastes are editable. We could restore it if users miss it.
- Subscribers are now editable.
- Form field order is a little goofy (this will be fixed in a future diff).
- Subscribers and projects are now race-resistant.
The race-resistance works like this: instead of submitting just the new value ("subscribers=apple, dog") and doing a set operation ("set subscribers = apple, dog"), we submit the old and new values ("original=apple" + "new=apple, dog") then apply the user's changes as an add + remove ("add=dog", "remove=<none>"). This means that two users who do "Edit Paste" at around the same time and each add or remove a couple of subscribers won't overwrite each other, unless they actually add or remove the exact same subscribers (in which case their edits legitimately conflict). Previously, the last user to save would win, and whatever was in their field would overwrite the prior state, potentially losing the first user's edits.
Test Plan:
- Created pastes.
- Created pastes via API.
- Edited pastes.
- Edited every field.
- Opened a paste in two windows and did project/subscriber edits in each, saved in arbitrary order, had edits respected.
Reviewers: chad
Reviewed By: chad
Maniphest Tasks: T4768, T9132
Differential Revision: https://secure.phabricator.com/D14390
2015-11-02 18:58:32 -08:00
|
|
|
abstract protected function getObjectViewURI($object);
|
|
|
|
|
2015-11-03 15:59:23 -08:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @task uri
|
|
|
|
*/
|
2015-11-17 09:33:06 -08:00
|
|
|
protected function getObjectCreateCancelURI($object) {
|
|
|
|
return $this->getApplication()->getApplicationURI();
|
2015-11-03 05:38:06 -08:00
|
|
|
}
|
|
|
|
|
2015-11-03 15:59:23 -08:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @task uri
|
|
|
|
*/
|
2015-11-17 09:33:06 -08:00
|
|
|
protected function getEditorURI() {
|
|
|
|
return $this->getApplication()->getApplicationURI('edit/');
|
Implement a basic version of ApplicationEditor in Paste
Summary:
Ref T9132. Ref T4768. This is a rough v0 of ApplicationEditor, which replaces the edit workflow in Paste.
This mostly looks and works like ApplicationSearch, and is heavily modeled on it.
Roughly, we define a set of editable fields and the ApplicationEditor stuff builds everything else.
This has no functional changes, except:
- I removed "Fork Paste" since I don't think it's particularly useful now that pastes are editable. We could restore it if users miss it.
- Subscribers are now editable.
- Form field order is a little goofy (this will be fixed in a future diff).
- Subscribers and projects are now race-resistant.
The race-resistance works like this: instead of submitting just the new value ("subscribers=apple, dog") and doing a set operation ("set subscribers = apple, dog"), we submit the old and new values ("original=apple" + "new=apple, dog") then apply the user's changes as an add + remove ("add=dog", "remove=<none>"). This means that two users who do "Edit Paste" at around the same time and each add or remove a couple of subscribers won't overwrite each other, unless they actually add or remove the exact same subscribers (in which case their edits legitimately conflict). Previously, the last user to save would win, and whatever was in their field would overwrite the prior state, potentially losing the first user's edits.
Test Plan:
- Created pastes.
- Created pastes via API.
- Edited pastes.
- Edited every field.
- Opened a paste in two windows and did project/subscriber edits in each, saved in arbitrary order, had edits respected.
Reviewers: chad
Reviewed By: chad
Maniphest Tasks: T4768, T9132
Differential Revision: https://secure.phabricator.com/D14390
2015-11-02 18:58:32 -08:00
|
|
|
}
|
|
|
|
|
2015-11-03 15:59:23 -08:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @task uri
|
|
|
|
*/
|
Implement a basic version of ApplicationEditor in Paste
Summary:
Ref T9132. Ref T4768. This is a rough v0 of ApplicationEditor, which replaces the edit workflow in Paste.
This mostly looks and works like ApplicationSearch, and is heavily modeled on it.
Roughly, we define a set of editable fields and the ApplicationEditor stuff builds everything else.
This has no functional changes, except:
- I removed "Fork Paste" since I don't think it's particularly useful now that pastes are editable. We could restore it if users miss it.
- Subscribers are now editable.
- Form field order is a little goofy (this will be fixed in a future diff).
- Subscribers and projects are now race-resistant.
The race-resistance works like this: instead of submitting just the new value ("subscribers=apple, dog") and doing a set operation ("set subscribers = apple, dog"), we submit the old and new values ("original=apple" + "new=apple, dog") then apply the user's changes as an add + remove ("add=dog", "remove=<none>"). This means that two users who do "Edit Paste" at around the same time and each add or remove a couple of subscribers won't overwrite each other, unless they actually add or remove the exact same subscribers (in which case their edits legitimately conflict). Previously, the last user to save would win, and whatever was in their field would overwrite the prior state, potentially losing the first user's edits.
Test Plan:
- Created pastes.
- Created pastes via API.
- Edited pastes.
- Edited every field.
- Opened a paste in two windows and did project/subscriber edits in each, saved in arbitrary order, had edits respected.
Reviewers: chad
Reviewed By: chad
Maniphest Tasks: T4768, T9132
Differential Revision: https://secure.phabricator.com/D14390
2015-11-02 18:58:32 -08:00
|
|
|
protected function getObjectEditCancelURI($object) {
|
|
|
|
return $this->getObjectViewURI($object);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-11-03 15:59:23 -08:00
|
|
|
/**
|
|
|
|
* @task uri
|
|
|
|
*/
|
2015-11-17 09:33:06 -08:00
|
|
|
public function getEditURI($object = null, $path = null) {
|
|
|
|
$parts = array();
|
|
|
|
|
|
|
|
$parts[] = $this->getEditorURI();
|
2015-11-03 05:38:06 -08:00
|
|
|
|
2015-11-17 09:33:06 -08:00
|
|
|
if ($object && $object->getID()) {
|
2015-11-03 05:38:06 -08:00
|
|
|
$parts[] = $object->getID().'/';
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($path !== null) {
|
|
|
|
$parts[] = $path;
|
|
|
|
}
|
|
|
|
|
|
|
|
return implode('', $parts);
|
|
|
|
}
|
|
|
|
|
2015-11-03 15:59:23 -08:00
|
|
|
|
|
|
|
/* -( Creating and Loading Objects )--------------------------------------- */
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Initialize a new object for creation.
|
|
|
|
*
|
|
|
|
* @return object Newly initialized object.
|
|
|
|
* @task load
|
|
|
|
*/
|
|
|
|
abstract protected function newEditableObject();
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Build an empty query for objects.
|
|
|
|
*
|
|
|
|
* @return PhabricatorPolicyAwareQuery Query.
|
|
|
|
* @task load
|
|
|
|
*/
|
|
|
|
abstract protected function newObjectQuery();
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Test if this workflow is creating a new object or editing an existing one.
|
|
|
|
*
|
|
|
|
* @return bool True if a new object is being created.
|
|
|
|
* @task load
|
|
|
|
*/
|
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
|
|
|
final public function getIsCreate() {
|
2015-11-03 15:59:23 -08:00
|
|
|
return $this->isCreate;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Flag this workflow as a create or edit.
|
|
|
|
*
|
|
|
|
* @param bool True if this is a create workflow.
|
|
|
|
* @return this
|
|
|
|
* @task load
|
|
|
|
*/
|
|
|
|
private function setIsCreate($is_create) {
|
2015-11-03 05:38:06 -08:00
|
|
|
$this->isCreate = $is_create;
|
|
|
|
return $this;
|
|
|
|
}
|
|
|
|
|
2015-11-03 15:59:23 -08:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Load an object by ID.
|
|
|
|
*
|
|
|
|
* @param int Object ID.
|
|
|
|
* @return object|null Object, or null if no such object exists.
|
|
|
|
* @task load
|
|
|
|
*/
|
|
|
|
private function newObjectFromID($id) {
|
|
|
|
$query = $this->newObjectQuery()
|
|
|
|
->withIDs(array($id));
|
|
|
|
|
|
|
|
return $this->newObjectFromQuery($query);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Load an object by PHID.
|
|
|
|
*
|
|
|
|
* @param phid Object PHID.
|
|
|
|
* @return object|null Object, or null if no such object exists.
|
|
|
|
* @task load
|
|
|
|
*/
|
|
|
|
private function newObjectFromPHID($phid) {
|
|
|
|
$query = $this->newObjectQuery()
|
|
|
|
->withPHIDs(array($phid));
|
|
|
|
|
|
|
|
return $this->newObjectFromQuery($query);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Load an object given a configured query.
|
|
|
|
*
|
|
|
|
* @param PhabricatorPolicyAwareQuery Configured query.
|
|
|
|
* @return object|null Object, or null if no such object exists.
|
|
|
|
* @task load
|
|
|
|
*/
|
|
|
|
private function newObjectFromQuery(PhabricatorPolicyAwareQuery $query) {
|
|
|
|
$viewer = $this->getViewer();
|
|
|
|
|
|
|
|
$object = $query
|
|
|
|
->setViewer($viewer)
|
|
|
|
->requireCapabilities(
|
|
|
|
array(
|
|
|
|
PhabricatorPolicyCapability::CAN_VIEW,
|
|
|
|
PhabricatorPolicyCapability::CAN_EDIT,
|
|
|
|
))
|
|
|
|
->executeOne();
|
|
|
|
if (!$object) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
return $object;
|
2015-11-03 05:38:06 -08:00
|
|
|
}
|
|
|
|
|
2015-11-03 15:59:23 -08:00
|
|
|
|
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
|
|
|
/**
|
|
|
|
* Verify that an object is appropriate for editing.
|
|
|
|
*
|
|
|
|
* @param wild Loaded value.
|
|
|
|
* @return void
|
|
|
|
* @task load
|
|
|
|
*/
|
|
|
|
private function validateObject($object) {
|
|
|
|
if (!$object || !is_object($object)) {
|
|
|
|
throw new Exception(
|
|
|
|
pht(
|
|
|
|
'EditEngine "%s" created or loaded an invalid object: object must '.
|
|
|
|
'actually be an object, but is of some other type ("%s").',
|
|
|
|
get_class($this),
|
|
|
|
gettype($object)));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!($object instanceof PhabricatorApplicationTransactionInterface)) {
|
|
|
|
throw new Exception(
|
|
|
|
pht(
|
|
|
|
'EditEngine "%s" created or loaded an invalid object: object (of '.
|
|
|
|
'class "%s") must implement "%s", but does not.',
|
|
|
|
get_class($this),
|
|
|
|
get_class($object),
|
|
|
|
'PhabricatorApplicationTransactionInterface'));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-11-03 15:59:23 -08:00
|
|
|
/* -( Responding to Web Requests )----------------------------------------- */
|
|
|
|
|
|
|
|
|
Implement a basic version of ApplicationEditor in Paste
Summary:
Ref T9132. Ref T4768. This is a rough v0 of ApplicationEditor, which replaces the edit workflow in Paste.
This mostly looks and works like ApplicationSearch, and is heavily modeled on it.
Roughly, we define a set of editable fields and the ApplicationEditor stuff builds everything else.
This has no functional changes, except:
- I removed "Fork Paste" since I don't think it's particularly useful now that pastes are editable. We could restore it if users miss it.
- Subscribers are now editable.
- Form field order is a little goofy (this will be fixed in a future diff).
- Subscribers and projects are now race-resistant.
The race-resistance works like this: instead of submitting just the new value ("subscribers=apple, dog") and doing a set operation ("set subscribers = apple, dog"), we submit the old and new values ("original=apple" + "new=apple, dog") then apply the user's changes as an add + remove ("add=dog", "remove=<none>"). This means that two users who do "Edit Paste" at around the same time and each add or remove a couple of subscribers won't overwrite each other, unless they actually add or remove the exact same subscribers (in which case their edits legitimately conflict). Previously, the last user to save would win, and whatever was in their field would overwrite the prior state, potentially losing the first user's edits.
Test Plan:
- Created pastes.
- Created pastes via API.
- Edited pastes.
- Edited every field.
- Opened a paste in two windows and did project/subscriber edits in each, saved in arbitrary order, had edits respected.
Reviewers: chad
Reviewed By: chad
Maniphest Tasks: T4768, T9132
Differential Revision: https://secure.phabricator.com/D14390
2015-11-02 18:58:32 -08:00
|
|
|
final public function buildResponse() {
|
|
|
|
$viewer = $this->getViewer();
|
2015-11-03 15:59:23 -08:00
|
|
|
$controller = $this->getController();
|
Implement a basic version of ApplicationEditor in Paste
Summary:
Ref T9132. Ref T4768. This is a rough v0 of ApplicationEditor, which replaces the edit workflow in Paste.
This mostly looks and works like ApplicationSearch, and is heavily modeled on it.
Roughly, we define a set of editable fields and the ApplicationEditor stuff builds everything else.
This has no functional changes, except:
- I removed "Fork Paste" since I don't think it's particularly useful now that pastes are editable. We could restore it if users miss it.
- Subscribers are now editable.
- Form field order is a little goofy (this will be fixed in a future diff).
- Subscribers and projects are now race-resistant.
The race-resistance works like this: instead of submitting just the new value ("subscribers=apple, dog") and doing a set operation ("set subscribers = apple, dog"), we submit the old and new values ("original=apple" + "new=apple, dog") then apply the user's changes as an add + remove ("add=dog", "remove=<none>"). This means that two users who do "Edit Paste" at around the same time and each add or remove a couple of subscribers won't overwrite each other, unless they actually add or remove the exact same subscribers (in which case their edits legitimately conflict). Previously, the last user to save would win, and whatever was in their field would overwrite the prior state, potentially losing the first user's edits.
Test Plan:
- Created pastes.
- Created pastes via API.
- Edited pastes.
- Edited every field.
- Opened a paste in two windows and did project/subscriber edits in each, saved in arbitrary order, had edits respected.
Reviewers: chad
Reviewed By: chad
Maniphest Tasks: T4768, T9132
Differential Revision: https://secure.phabricator.com/D14390
2015-11-02 18:58:32 -08:00
|
|
|
$request = $controller->getRequest();
|
|
|
|
|
2015-11-17 09:33:06 -08:00
|
|
|
$form_key = $request->getURIData('formKey');
|
|
|
|
$config = $this->loadEditEngineConfiguration($form_key);
|
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
|
|
|
if (!$config) {
|
|
|
|
return new Aphront404Response();
|
|
|
|
}
|
|
|
|
|
Implement a basic version of ApplicationEditor in Paste
Summary:
Ref T9132. Ref T4768. This is a rough v0 of ApplicationEditor, which replaces the edit workflow in Paste.
This mostly looks and works like ApplicationSearch, and is heavily modeled on it.
Roughly, we define a set of editable fields and the ApplicationEditor stuff builds everything else.
This has no functional changes, except:
- I removed "Fork Paste" since I don't think it's particularly useful now that pastes are editable. We could restore it if users miss it.
- Subscribers are now editable.
- Form field order is a little goofy (this will be fixed in a future diff).
- Subscribers and projects are now race-resistant.
The race-resistance works like this: instead of submitting just the new value ("subscribers=apple, dog") and doing a set operation ("set subscribers = apple, dog"), we submit the old and new values ("original=apple" + "new=apple, dog") then apply the user's changes as an add + remove ("add=dog", "remove=<none>"). This means that two users who do "Edit Paste" at around the same time and each add or remove a couple of subscribers won't overwrite each other, unless they actually add or remove the exact same subscribers (in which case their edits legitimately conflict). Previously, the last user to save would win, and whatever was in their field would overwrite the prior state, potentially losing the first user's edits.
Test Plan:
- Created pastes.
- Created pastes via API.
- Edited pastes.
- Edited every field.
- Opened a paste in two windows and did project/subscriber edits in each, saved in arbitrary order, had edits respected.
Reviewers: chad
Reviewed By: chad
Maniphest Tasks: T4768, T9132
Differential Revision: https://secure.phabricator.com/D14390
2015-11-02 18:58:32 -08:00
|
|
|
$id = $request->getURIData('id');
|
|
|
|
if ($id) {
|
2015-11-03 15:59:23 -08:00
|
|
|
$this->setIsCreate(false);
|
|
|
|
$object = $this->newObjectFromID($id);
|
Implement a basic version of ApplicationEditor in Paste
Summary:
Ref T9132. Ref T4768. This is a rough v0 of ApplicationEditor, which replaces the edit workflow in Paste.
This mostly looks and works like ApplicationSearch, and is heavily modeled on it.
Roughly, we define a set of editable fields and the ApplicationEditor stuff builds everything else.
This has no functional changes, except:
- I removed "Fork Paste" since I don't think it's particularly useful now that pastes are editable. We could restore it if users miss it.
- Subscribers are now editable.
- Form field order is a little goofy (this will be fixed in a future diff).
- Subscribers and projects are now race-resistant.
The race-resistance works like this: instead of submitting just the new value ("subscribers=apple, dog") and doing a set operation ("set subscribers = apple, dog"), we submit the old and new values ("original=apple" + "new=apple, dog") then apply the user's changes as an add + remove ("add=dog", "remove=<none>"). This means that two users who do "Edit Paste" at around the same time and each add or remove a couple of subscribers won't overwrite each other, unless they actually add or remove the exact same subscribers (in which case their edits legitimately conflict). Previously, the last user to save would win, and whatever was in their field would overwrite the prior state, potentially losing the first user's edits.
Test Plan:
- Created pastes.
- Created pastes via API.
- Edited pastes.
- Edited every field.
- Opened a paste in two windows and did project/subscriber edits in each, saved in arbitrary order, had edits respected.
Reviewers: chad
Reviewed By: chad
Maniphest Tasks: T4768, T9132
Differential Revision: https://secure.phabricator.com/D14390
2015-11-02 18:58:32 -08:00
|
|
|
if (!$object) {
|
|
|
|
return new Aphront404Response();
|
|
|
|
}
|
|
|
|
} else {
|
2015-11-03 05:38:06 -08:00
|
|
|
$this->setIsCreate(true);
|
2015-11-03 15:59:23 -08:00
|
|
|
$object = $this->newEditableObject();
|
Implement a basic version of ApplicationEditor in Paste
Summary:
Ref T9132. Ref T4768. This is a rough v0 of ApplicationEditor, which replaces the edit workflow in Paste.
This mostly looks and works like ApplicationSearch, and is heavily modeled on it.
Roughly, we define a set of editable fields and the ApplicationEditor stuff builds everything else.
This has no functional changes, except:
- I removed "Fork Paste" since I don't think it's particularly useful now that pastes are editable. We could restore it if users miss it.
- Subscribers are now editable.
- Form field order is a little goofy (this will be fixed in a future diff).
- Subscribers and projects are now race-resistant.
The race-resistance works like this: instead of submitting just the new value ("subscribers=apple, dog") and doing a set operation ("set subscribers = apple, dog"), we submit the old and new values ("original=apple" + "new=apple, dog") then apply the user's changes as an add + remove ("add=dog", "remove=<none>"). This means that two users who do "Edit Paste" at around the same time and each add or remove a couple of subscribers won't overwrite each other, unless they actually add or remove the exact same subscribers (in which case their edits legitimately conflict). Previously, the last user to save would win, and whatever was in their field would overwrite the prior state, potentially losing the first user's edits.
Test Plan:
- Created pastes.
- Created pastes via API.
- Edited pastes.
- Edited every field.
- Opened a paste in two windows and did project/subscriber edits in each, saved in arbitrary order, had edits respected.
Reviewers: chad
Reviewed By: chad
Maniphest Tasks: T4768, T9132
Differential Revision: https://secure.phabricator.com/D14390
2015-11-02 18:58:32 -08:00
|
|
|
}
|
|
|
|
|
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
|
|
|
$this->validateObject($object);
|
|
|
|
|
2015-11-03 05:38:06 -08:00
|
|
|
$action = $request->getURIData('editAction');
|
|
|
|
switch ($action) {
|
|
|
|
case 'parameters':
|
2015-11-03 15:59:23 -08:00
|
|
|
return $this->buildParametersResponse($object);
|
|
|
|
default:
|
|
|
|
return $this->buildEditResponse($object);
|
2015-11-03 05:38:06 -08:00
|
|
|
}
|
2015-11-03 15:59:23 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
private function buildCrumbs($object, $final = false) {
|
|
|
|
$controller = $this->getcontroller();
|
|
|
|
|
|
|
|
$crumbs = $controller->buildApplicationCrumbsForEditEngine();
|
|
|
|
if ($this->getIsCreate()) {
|
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
|
|
|
$create_text = $this->getObjectCreateShortText();
|
2015-11-03 15:59:23 -08:00
|
|
|
if ($final) {
|
|
|
|
$crumbs->addTextCrumb($create_text);
|
|
|
|
} else {
|
|
|
|
$edit_uri = $this->getEditURI($object);
|
|
|
|
$crumbs->addTextCrumb($create_text, $edit_uri);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
$crumbs->addTextCrumb(
|
|
|
|
$this->getObjectEditShortText($object),
|
|
|
|
$this->getObjectViewURI($object));
|
|
|
|
|
|
|
|
$edit_text = pht('Edit');
|
|
|
|
if ($final) {
|
|
|
|
$crumbs->addTextCrumb($edit_text);
|
|
|
|
} else {
|
|
|
|
$edit_uri = $this->getEditURI($object);
|
|
|
|
$crumbs->addTextCrumb($edit_text, $edit_uri);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return $crumbs;
|
|
|
|
}
|
|
|
|
|
|
|
|
private function buildEditResponse($object) {
|
|
|
|
$viewer = $this->getViewer();
|
|
|
|
$controller = $this->getController();
|
|
|
|
$request = $controller->getRequest();
|
|
|
|
|
|
|
|
$fields = $this->buildEditFields($object);
|
|
|
|
$template = $object->getApplicationTransactionTemplate();
|
2015-11-03 05:38:06 -08:00
|
|
|
|
Implement a basic version of ApplicationEditor in Paste
Summary:
Ref T9132. Ref T4768. This is a rough v0 of ApplicationEditor, which replaces the edit workflow in Paste.
This mostly looks and works like ApplicationSearch, and is heavily modeled on it.
Roughly, we define a set of editable fields and the ApplicationEditor stuff builds everything else.
This has no functional changes, except:
- I removed "Fork Paste" since I don't think it's particularly useful now that pastes are editable. We could restore it if users miss it.
- Subscribers are now editable.
- Form field order is a little goofy (this will be fixed in a future diff).
- Subscribers and projects are now race-resistant.
The race-resistance works like this: instead of submitting just the new value ("subscribers=apple, dog") and doing a set operation ("set subscribers = apple, dog"), we submit the old and new values ("original=apple" + "new=apple, dog") then apply the user's changes as an add + remove ("add=dog", "remove=<none>"). This means that two users who do "Edit Paste" at around the same time and each add or remove a couple of subscribers won't overwrite each other, unless they actually add or remove the exact same subscribers (in which case their edits legitimately conflict). Previously, the last user to save would win, and whatever was in their field would overwrite the prior state, potentially losing the first user's edits.
Test Plan:
- Created pastes.
- Created pastes via API.
- Edited pastes.
- Edited every field.
- Opened a paste in two windows and did project/subscriber edits in each, saved in arbitrary order, had edits respected.
Reviewers: chad
Reviewed By: chad
Maniphest Tasks: T4768, T9132
Differential Revision: https://secure.phabricator.com/D14390
2015-11-02 18:58:32 -08:00
|
|
|
$validation_exception = null;
|
|
|
|
if ($request->isFormPost()) {
|
|
|
|
foreach ($fields as $field) {
|
2015-11-18 10:50:09 -08:00
|
|
|
if ($field->getIsLocked() || $field->getIsHidden()) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
Implement a basic version of ApplicationEditor in Paste
Summary:
Ref T9132. Ref T4768. This is a rough v0 of ApplicationEditor, which replaces the edit workflow in Paste.
This mostly looks and works like ApplicationSearch, and is heavily modeled on it.
Roughly, we define a set of editable fields and the ApplicationEditor stuff builds everything else.
This has no functional changes, except:
- I removed "Fork Paste" since I don't think it's particularly useful now that pastes are editable. We could restore it if users miss it.
- Subscribers are now editable.
- Form field order is a little goofy (this will be fixed in a future diff).
- Subscribers and projects are now race-resistant.
The race-resistance works like this: instead of submitting just the new value ("subscribers=apple, dog") and doing a set operation ("set subscribers = apple, dog"), we submit the old and new values ("original=apple" + "new=apple, dog") then apply the user's changes as an add + remove ("add=dog", "remove=<none>"). This means that two users who do "Edit Paste" at around the same time and each add or remove a couple of subscribers won't overwrite each other, unless they actually add or remove the exact same subscribers (in which case their edits legitimately conflict). Previously, the last user to save would win, and whatever was in their field would overwrite the prior state, potentially losing the first user's edits.
Test Plan:
- Created pastes.
- Created pastes via API.
- Edited pastes.
- Edited every field.
- Opened a paste in two windows and did project/subscriber edits in each, saved in arbitrary order, had edits respected.
Reviewers: chad
Reviewed By: chad
Maniphest Tasks: T4768, T9132
Differential Revision: https://secure.phabricator.com/D14390
2015-11-02 18:58:32 -08:00
|
|
|
$field->readValueFromSubmit($request);
|
|
|
|
}
|
|
|
|
|
|
|
|
$xactions = array();
|
|
|
|
foreach ($fields as $field) {
|
2015-11-18 10:50:09 -08:00
|
|
|
$xaction = $field->generateTransaction(clone $template);
|
|
|
|
|
|
|
|
if (!$xaction) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
$xactions[] = $xaction;
|
Implement a basic version of ApplicationEditor in Paste
Summary:
Ref T9132. Ref T4768. This is a rough v0 of ApplicationEditor, which replaces the edit workflow in Paste.
This mostly looks and works like ApplicationSearch, and is heavily modeled on it.
Roughly, we define a set of editable fields and the ApplicationEditor stuff builds everything else.
This has no functional changes, except:
- I removed "Fork Paste" since I don't think it's particularly useful now that pastes are editable. We could restore it if users miss it.
- Subscribers are now editable.
- Form field order is a little goofy (this will be fixed in a future diff).
- Subscribers and projects are now race-resistant.
The race-resistance works like this: instead of submitting just the new value ("subscribers=apple, dog") and doing a set operation ("set subscribers = apple, dog"), we submit the old and new values ("original=apple" + "new=apple, dog") then apply the user's changes as an add + remove ("add=dog", "remove=<none>"). This means that two users who do "Edit Paste" at around the same time and each add or remove a couple of subscribers won't overwrite each other, unless they actually add or remove the exact same subscribers (in which case their edits legitimately conflict). Previously, the last user to save would win, and whatever was in their field would overwrite the prior state, potentially losing the first user's edits.
Test Plan:
- Created pastes.
- Created pastes via API.
- Edited pastes.
- Edited every field.
- Opened a paste in two windows and did project/subscriber edits in each, saved in arbitrary order, had edits respected.
Reviewers: chad
Reviewed By: chad
Maniphest Tasks: T4768, T9132
Differential Revision: https://secure.phabricator.com/D14390
2015-11-02 18:58:32 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
$editor = $object->getApplicationTransactionEditor()
|
|
|
|
->setActor($viewer)
|
|
|
|
->setContentSourceFromRequest($request)
|
2015-11-03 15:59:23 -08:00
|
|
|
->setContinueOnNoEffect(true);
|
Implement a basic version of ApplicationEditor in Paste
Summary:
Ref T9132. Ref T4768. This is a rough v0 of ApplicationEditor, which replaces the edit workflow in Paste.
This mostly looks and works like ApplicationSearch, and is heavily modeled on it.
Roughly, we define a set of editable fields and the ApplicationEditor stuff builds everything else.
This has no functional changes, except:
- I removed "Fork Paste" since I don't think it's particularly useful now that pastes are editable. We could restore it if users miss it.
- Subscribers are now editable.
- Form field order is a little goofy (this will be fixed in a future diff).
- Subscribers and projects are now race-resistant.
The race-resistance works like this: instead of submitting just the new value ("subscribers=apple, dog") and doing a set operation ("set subscribers = apple, dog"), we submit the old and new values ("original=apple" + "new=apple, dog") then apply the user's changes as an add + remove ("add=dog", "remove=<none>"). This means that two users who do "Edit Paste" at around the same time and each add or remove a couple of subscribers won't overwrite each other, unless they actually add or remove the exact same subscribers (in which case their edits legitimately conflict). Previously, the last user to save would win, and whatever was in their field would overwrite the prior state, potentially losing the first user's edits.
Test Plan:
- Created pastes.
- Created pastes via API.
- Edited pastes.
- Edited every field.
- Opened a paste in two windows and did project/subscriber edits in each, saved in arbitrary order, had edits respected.
Reviewers: chad
Reviewed By: chad
Maniphest Tasks: T4768, T9132
Differential Revision: https://secure.phabricator.com/D14390
2015-11-02 18:58:32 -08:00
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
|
|
$editor->applyTransactions($object, $xactions);
|
|
|
|
|
|
|
|
return id(new AphrontRedirectResponse())
|
|
|
|
->setURI($this->getObjectViewURI($object));
|
|
|
|
} catch (PhabricatorApplicationTransactionValidationException $ex) {
|
|
|
|
$validation_exception = $ex;
|
|
|
|
}
|
|
|
|
} else {
|
2015-11-03 05:38:06 -08:00
|
|
|
if ($this->getIsCreate()) {
|
Implement a basic version of ApplicationEditor in Paste
Summary:
Ref T9132. Ref T4768. This is a rough v0 of ApplicationEditor, which replaces the edit workflow in Paste.
This mostly looks and works like ApplicationSearch, and is heavily modeled on it.
Roughly, we define a set of editable fields and the ApplicationEditor stuff builds everything else.
This has no functional changes, except:
- I removed "Fork Paste" since I don't think it's particularly useful now that pastes are editable. We could restore it if users miss it.
- Subscribers are now editable.
- Form field order is a little goofy (this will be fixed in a future diff).
- Subscribers and projects are now race-resistant.
The race-resistance works like this: instead of submitting just the new value ("subscribers=apple, dog") and doing a set operation ("set subscribers = apple, dog"), we submit the old and new values ("original=apple" + "new=apple, dog") then apply the user's changes as an add + remove ("add=dog", "remove=<none>"). This means that two users who do "Edit Paste" at around the same time and each add or remove a couple of subscribers won't overwrite each other, unless they actually add or remove the exact same subscribers (in which case their edits legitimately conflict). Previously, the last user to save would win, and whatever was in their field would overwrite the prior state, potentially losing the first user's edits.
Test Plan:
- Created pastes.
- Created pastes via API.
- Edited pastes.
- Edited every field.
- Opened a paste in two windows and did project/subscriber edits in each, saved in arbitrary order, had edits respected.
Reviewers: chad
Reviewed By: chad
Maniphest Tasks: T4768, T9132
Differential Revision: https://secure.phabricator.com/D14390
2015-11-02 18:58:32 -08:00
|
|
|
foreach ($fields as $field) {
|
2015-11-18 10:50:09 -08:00
|
|
|
if ($field->getIsLocked() || $field->getIsHidden()) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
Implement a basic version of ApplicationEditor in Paste
Summary:
Ref T9132. Ref T4768. This is a rough v0 of ApplicationEditor, which replaces the edit workflow in Paste.
This mostly looks and works like ApplicationSearch, and is heavily modeled on it.
Roughly, we define a set of editable fields and the ApplicationEditor stuff builds everything else.
This has no functional changes, except:
- I removed "Fork Paste" since I don't think it's particularly useful now that pastes are editable. We could restore it if users miss it.
- Subscribers are now editable.
- Form field order is a little goofy (this will be fixed in a future diff).
- Subscribers and projects are now race-resistant.
The race-resistance works like this: instead of submitting just the new value ("subscribers=apple, dog") and doing a set operation ("set subscribers = apple, dog"), we submit the old and new values ("original=apple" + "new=apple, dog") then apply the user's changes as an add + remove ("add=dog", "remove=<none>"). This means that two users who do "Edit Paste" at around the same time and each add or remove a couple of subscribers won't overwrite each other, unless they actually add or remove the exact same subscribers (in which case their edits legitimately conflict). Previously, the last user to save would win, and whatever was in their field would overwrite the prior state, potentially losing the first user's edits.
Test Plan:
- Created pastes.
- Created pastes via API.
- Edited pastes.
- Edited every field.
- Opened a paste in two windows and did project/subscriber edits in each, saved in arbitrary order, had edits respected.
Reviewers: chad
Reviewed By: chad
Maniphest Tasks: T4768, T9132
Differential Revision: https://secure.phabricator.com/D14390
2015-11-02 18:58:32 -08:00
|
|
|
$field->readValueFromRequest($request);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
foreach ($fields as $field) {
|
|
|
|
$field->readValueFromObject($object);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-11-03 15:59:23 -08:00
|
|
|
$action_button = $this->buildEditFormActionButton($object);
|
Implement a basic version of ApplicationEditor in Paste
Summary:
Ref T9132. Ref T4768. This is a rough v0 of ApplicationEditor, which replaces the edit workflow in Paste.
This mostly looks and works like ApplicationSearch, and is heavily modeled on it.
Roughly, we define a set of editable fields and the ApplicationEditor stuff builds everything else.
This has no functional changes, except:
- I removed "Fork Paste" since I don't think it's particularly useful now that pastes are editable. We could restore it if users miss it.
- Subscribers are now editable.
- Form field order is a little goofy (this will be fixed in a future diff).
- Subscribers and projects are now race-resistant.
The race-resistance works like this: instead of submitting just the new value ("subscribers=apple, dog") and doing a set operation ("set subscribers = apple, dog"), we submit the old and new values ("original=apple" + "new=apple, dog") then apply the user's changes as an add + remove ("add=dog", "remove=<none>"). This means that two users who do "Edit Paste" at around the same time and each add or remove a couple of subscribers won't overwrite each other, unless they actually add or remove the exact same subscribers (in which case their edits legitimately conflict). Previously, the last user to save would win, and whatever was in their field would overwrite the prior state, potentially losing the first user's edits.
Test Plan:
- Created pastes.
- Created pastes via API.
- Edited pastes.
- Edited every field.
- Opened a paste in two windows and did project/subscriber edits in each, saved in arbitrary order, had edits respected.
Reviewers: chad
Reviewed By: chad
Maniphest Tasks: T4768, T9132
Differential Revision: https://secure.phabricator.com/D14390
2015-11-02 18:58:32 -08:00
|
|
|
|
2015-11-03 05:38:06 -08:00
|
|
|
if ($this->getIsCreate()) {
|
2015-11-17 09:33:06 -08:00
|
|
|
$header_text = $this->getFormHeaderText($object);
|
Implement a basic version of ApplicationEditor in Paste
Summary:
Ref T9132. Ref T4768. This is a rough v0 of ApplicationEditor, which replaces the edit workflow in Paste.
This mostly looks and works like ApplicationSearch, and is heavily modeled on it.
Roughly, we define a set of editable fields and the ApplicationEditor stuff builds everything else.
This has no functional changes, except:
- I removed "Fork Paste" since I don't think it's particularly useful now that pastes are editable. We could restore it if users miss it.
- Subscribers are now editable.
- Form field order is a little goofy (this will be fixed in a future diff).
- Subscribers and projects are now race-resistant.
The race-resistance works like this: instead of submitting just the new value ("subscribers=apple, dog") and doing a set operation ("set subscribers = apple, dog"), we submit the old and new values ("original=apple" + "new=apple, dog") then apply the user's changes as an add + remove ("add=dog", "remove=<none>"). This means that two users who do "Edit Paste" at around the same time and each add or remove a couple of subscribers won't overwrite each other, unless they actually add or remove the exact same subscribers (in which case their edits legitimately conflict). Previously, the last user to save would win, and whatever was in their field would overwrite the prior state, potentially losing the first user's edits.
Test Plan:
- Created pastes.
- Created pastes via API.
- Edited pastes.
- Edited every field.
- Opened a paste in two windows and did project/subscriber edits in each, saved in arbitrary order, had edits respected.
Reviewers: chad
Reviewed By: chad
Maniphest Tasks: T4768, T9132
Differential Revision: https://secure.phabricator.com/D14390
2015-11-02 18:58:32 -08:00
|
|
|
} else {
|
|
|
|
$header_text = $this->getObjectEditTitleText($object);
|
|
|
|
}
|
|
|
|
|
2015-11-03 05:38:06 -08:00
|
|
|
$header = id(new PHUIHeaderView())
|
2015-11-03 15:59:23 -08:00
|
|
|
->setHeader($header_text)
|
|
|
|
->addActionLink($action_button);
|
Implement a basic version of ApplicationEditor in Paste
Summary:
Ref T9132. Ref T4768. This is a rough v0 of ApplicationEditor, which replaces the edit workflow in Paste.
This mostly looks and works like ApplicationSearch, and is heavily modeled on it.
Roughly, we define a set of editable fields and the ApplicationEditor stuff builds everything else.
This has no functional changes, except:
- I removed "Fork Paste" since I don't think it's particularly useful now that pastes are editable. We could restore it if users miss it.
- Subscribers are now editable.
- Form field order is a little goofy (this will be fixed in a future diff).
- Subscribers and projects are now race-resistant.
The race-resistance works like this: instead of submitting just the new value ("subscribers=apple, dog") and doing a set operation ("set subscribers = apple, dog"), we submit the old and new values ("original=apple" + "new=apple, dog") then apply the user's changes as an add + remove ("add=dog", "remove=<none>"). This means that two users who do "Edit Paste" at around the same time and each add or remove a couple of subscribers won't overwrite each other, unless they actually add or remove the exact same subscribers (in which case their edits legitimately conflict). Previously, the last user to save would win, and whatever was in their field would overwrite the prior state, potentially losing the first user's edits.
Test Plan:
- Created pastes.
- Created pastes via API.
- Edited pastes.
- Edited every field.
- Opened a paste in two windows and did project/subscriber edits in each, saved in arbitrary order, had edits respected.
Reviewers: chad
Reviewed By: chad
Maniphest Tasks: T4768, T9132
Differential Revision: https://secure.phabricator.com/D14390
2015-11-02 18:58:32 -08:00
|
|
|
|
2015-11-03 15:59:23 -08:00
|
|
|
$crumbs = $this->buildCrumbs($object, $final = true);
|
|
|
|
$form = $this->buildEditForm($object, $fields);
|
Implement a basic version of ApplicationEditor in Paste
Summary:
Ref T9132. Ref T4768. This is a rough v0 of ApplicationEditor, which replaces the edit workflow in Paste.
This mostly looks and works like ApplicationSearch, and is heavily modeled on it.
Roughly, we define a set of editable fields and the ApplicationEditor stuff builds everything else.
This has no functional changes, except:
- I removed "Fork Paste" since I don't think it's particularly useful now that pastes are editable. We could restore it if users miss it.
- Subscribers are now editable.
- Form field order is a little goofy (this will be fixed in a future diff).
- Subscribers and projects are now race-resistant.
The race-resistance works like this: instead of submitting just the new value ("subscribers=apple, dog") and doing a set operation ("set subscribers = apple, dog"), we submit the old and new values ("original=apple" + "new=apple, dog") then apply the user's changes as an add + remove ("add=dog", "remove=<none>"). This means that two users who do "Edit Paste" at around the same time and each add or remove a couple of subscribers won't overwrite each other, unless they actually add or remove the exact same subscribers (in which case their edits legitimately conflict). Previously, the last user to save would win, and whatever was in their field would overwrite the prior state, potentially losing the first user's edits.
Test Plan:
- Created pastes.
- Created pastes via API.
- Edited pastes.
- Edited every field.
- Opened a paste in two windows and did project/subscriber edits in each, saved in arbitrary order, had edits respected.
Reviewers: chad
Reviewed By: chad
Maniphest Tasks: T4768, T9132
Differential Revision: https://secure.phabricator.com/D14390
2015-11-02 18:58:32 -08:00
|
|
|
|
2015-11-03 15:59:23 -08:00
|
|
|
$box = id(new PHUIObjectBoxView())
|
|
|
|
->setUser($viewer)
|
|
|
|
->setHeader($header)
|
|
|
|
->setValidationException($validation_exception)
|
|
|
|
->appendChild($form);
|
Implement a basic version of ApplicationEditor in Paste
Summary:
Ref T9132. Ref T4768. This is a rough v0 of ApplicationEditor, which replaces the edit workflow in Paste.
This mostly looks and works like ApplicationSearch, and is heavily modeled on it.
Roughly, we define a set of editable fields and the ApplicationEditor stuff builds everything else.
This has no functional changes, except:
- I removed "Fork Paste" since I don't think it's particularly useful now that pastes are editable. We could restore it if users miss it.
- Subscribers are now editable.
- Form field order is a little goofy (this will be fixed in a future diff).
- Subscribers and projects are now race-resistant.
The race-resistance works like this: instead of submitting just the new value ("subscribers=apple, dog") and doing a set operation ("set subscribers = apple, dog"), we submit the old and new values ("original=apple" + "new=apple, dog") then apply the user's changes as an add + remove ("add=dog", "remove=<none>"). This means that two users who do "Edit Paste" at around the same time and each add or remove a couple of subscribers won't overwrite each other, unless they actually add or remove the exact same subscribers (in which case their edits legitimately conflict). Previously, the last user to save would win, and whatever was in their field would overwrite the prior state, potentially losing the first user's edits.
Test Plan:
- Created pastes.
- Created pastes via API.
- Edited pastes.
- Edited every field.
- Opened a paste in two windows and did project/subscriber edits in each, saved in arbitrary order, had edits respected.
Reviewers: chad
Reviewed By: chad
Maniphest Tasks: T4768, T9132
Differential Revision: https://secure.phabricator.com/D14390
2015-11-02 18:58:32 -08:00
|
|
|
|
|
|
|
return $controller->newPage()
|
|
|
|
->setTitle($header_text)
|
|
|
|
->setCrumbs($crumbs)
|
|
|
|
->appendChild($box);
|
|
|
|
}
|
|
|
|
|
2015-11-03 15:59:23 -08:00
|
|
|
private function buildEditForm($object, array $fields) {
|
2015-11-03 05:38:06 -08:00
|
|
|
$viewer = $this->getViewer();
|
|
|
|
|
2015-11-03 15:59:23 -08:00
|
|
|
$form = id(new AphrontFormView())
|
|
|
|
->setUser($viewer);
|
2015-11-03 05:38:06 -08:00
|
|
|
|
2015-11-03 15:59:23 -08:00
|
|
|
foreach ($fields as $field) {
|
|
|
|
$field->appendToForm($form);
|
|
|
|
}
|
2015-11-03 05:38:06 -08:00
|
|
|
|
|
|
|
if ($this->getIsCreate()) {
|
2015-11-03 15:59:23 -08:00
|
|
|
$cancel_uri = $this->getObjectCreateCancelURI($object);
|
|
|
|
$submit_button = $this->getObjectCreateButtonText($object);
|
2015-11-03 05:38:06 -08:00
|
|
|
} else {
|
2015-11-03 15:59:23 -08:00
|
|
|
$cancel_uri = $this->getObjectEditCancelURI($object);
|
|
|
|
$submit_button = $this->getObjectEditButtonText($object);
|
2015-11-03 05:38:06 -08:00
|
|
|
}
|
|
|
|
|
2015-11-03 15:59:23 -08:00
|
|
|
$form->appendControl(
|
|
|
|
id(new AphrontFormSubmitControl())
|
|
|
|
->addCancelButton($cancel_uri)
|
|
|
|
->setValue($submit_button));
|
|
|
|
|
|
|
|
return $form;
|
2015-11-03 05:38:06 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
private function buildEditFormActionButton($object) {
|
|
|
|
$viewer = $this->getViewer();
|
|
|
|
|
|
|
|
$action_view = id(new PhabricatorActionListView())
|
|
|
|
->setUser($viewer);
|
|
|
|
|
|
|
|
foreach ($this->buildEditFormActions($object) as $action) {
|
|
|
|
$action_view->addAction($action);
|
|
|
|
}
|
|
|
|
|
|
|
|
$action_button = id(new PHUIButtonView())
|
|
|
|
->setTag('a')
|
|
|
|
->setText(pht('Actions'))
|
|
|
|
->setHref('#')
|
|
|
|
->setIconFont('fa-bars')
|
|
|
|
->setDropdownMenu($action_view);
|
|
|
|
|
|
|
|
return $action_button;
|
|
|
|
}
|
|
|
|
|
|
|
|
private function buildEditFormActions($object) {
|
|
|
|
$actions = array();
|
|
|
|
|
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
|
|
|
if ($this->supportsEditEngineConfiguration()) {
|
|
|
|
$engine_key = $this->getEngineKey();
|
|
|
|
$config = $this->getEditEngineConfiguration();
|
|
|
|
|
|
|
|
$actions[] = id(new PhabricatorActionView())
|
|
|
|
->setName(pht('Manage Form Configurations'))
|
|
|
|
->setIcon('fa-list-ul')
|
|
|
|
->setHref("/transactions/editengine/{$engine_key}/");
|
|
|
|
$actions[] = id(new PhabricatorActionView())
|
|
|
|
->setName(pht('Edit Form Configuration'))
|
|
|
|
->setIcon('fa-pencil')
|
|
|
|
->setHref($config->getURI());
|
|
|
|
}
|
|
|
|
|
2015-11-03 05:38:06 -08:00
|
|
|
$actions[] = id(new PhabricatorActionView())
|
|
|
|
->setName(pht('Show HTTP Parameters'))
|
|
|
|
->setIcon('fa-crosshairs')
|
|
|
|
->setHref($this->getEditURI($object, 'parameters/'));
|
|
|
|
|
|
|
|
return $actions;
|
|
|
|
}
|
Implement a basic version of ApplicationEditor in Paste
Summary:
Ref T9132. Ref T4768. This is a rough v0 of ApplicationEditor, which replaces the edit workflow in Paste.
This mostly looks and works like ApplicationSearch, and is heavily modeled on it.
Roughly, we define a set of editable fields and the ApplicationEditor stuff builds everything else.
This has no functional changes, except:
- I removed "Fork Paste" since I don't think it's particularly useful now that pastes are editable. We could restore it if users miss it.
- Subscribers are now editable.
- Form field order is a little goofy (this will be fixed in a future diff).
- Subscribers and projects are now race-resistant.
The race-resistance works like this: instead of submitting just the new value ("subscribers=apple, dog") and doing a set operation ("set subscribers = apple, dog"), we submit the old and new values ("original=apple" + "new=apple, dog") then apply the user's changes as an add + remove ("add=dog", "remove=<none>"). This means that two users who do "Edit Paste" at around the same time and each add or remove a couple of subscribers won't overwrite each other, unless they actually add or remove the exact same subscribers (in which case their edits legitimately conflict). Previously, the last user to save would win, and whatever was in their field would overwrite the prior state, potentially losing the first user's edits.
Test Plan:
- Created pastes.
- Created pastes via API.
- Edited pastes.
- Edited every field.
- Opened a paste in two windows and did project/subscriber edits in each, saved in arbitrary order, had edits respected.
Reviewers: chad
Reviewed By: chad
Maniphest Tasks: T4768, T9132
Differential Revision: https://secure.phabricator.com/D14390
2015-11-02 18:58:32 -08:00
|
|
|
|
2015-11-03 08:45:00 -08:00
|
|
|
|
2015-11-03 15:59:23 -08:00
|
|
|
/* -( Responding to HTTP Parameter Requests )------------------------------ */
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Respond to a request for documentation on HTTP parameters.
|
|
|
|
*
|
|
|
|
* @param object Editable object.
|
|
|
|
* @return AphrontResponse Response object.
|
|
|
|
* @task http
|
|
|
|
*/
|
|
|
|
private function buildParametersResponse($object) {
|
|
|
|
$controller = $this->getController();
|
|
|
|
$viewer = $this->getViewer();
|
|
|
|
$request = $controller->getRequest();
|
|
|
|
$fields = $this->buildEditFields($object);
|
|
|
|
|
|
|
|
$crumbs = $this->buildCrumbs($object);
|
|
|
|
$crumbs->addTextCrumb(pht('HTTP Parameters'));
|
|
|
|
$crumbs->setBorder(true);
|
|
|
|
|
|
|
|
$header_text = pht(
|
|
|
|
'HTTP Parameters: %s',
|
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
|
|
|
$this->getObjectCreateShortText());
|
2015-11-03 15:59:23 -08:00
|
|
|
|
|
|
|
$header = id(new PHUIHeaderView())
|
|
|
|
->setHeader($header_text);
|
|
|
|
|
|
|
|
$help_view = id(new PhabricatorApplicationEditHTTPParameterHelpView())
|
|
|
|
->setUser($viewer)
|
|
|
|
->setFields($fields);
|
|
|
|
|
|
|
|
$document = id(new PHUIDocumentViewPro())
|
|
|
|
->setUser($viewer)
|
|
|
|
->setHeader($header)
|
|
|
|
->appendChild($help_view);
|
|
|
|
|
|
|
|
return $controller->newPage()
|
|
|
|
->setTitle(pht('HTTP Parameters'))
|
|
|
|
->setCrumbs($crumbs)
|
|
|
|
->appendChild($document);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-11-03 08:45:00 -08:00
|
|
|
/* -( Conduit )------------------------------------------------------------ */
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Respond to a Conduit edit request.
|
|
|
|
*
|
|
|
|
* This method accepts a list of transactions to apply to an object, and
|
|
|
|
* either edits an existing object or creates a new one.
|
|
|
|
*
|
|
|
|
* @task conduit
|
|
|
|
*/
|
|
|
|
final public function buildConduitResponse(ConduitAPIRequest $request) {
|
|
|
|
$viewer = $this->getViewer();
|
|
|
|
|
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
|
|
|
$config = $this->loadEditEngineConfiguration(null);
|
|
|
|
if (!$config) {
|
|
|
|
throw new Exception(
|
|
|
|
pht(
|
|
|
|
'Unable to load configuration for this EditEngine ("%s").',
|
|
|
|
get_class($this)));
|
|
|
|
}
|
|
|
|
|
2015-11-03 08:45:00 -08:00
|
|
|
$phid = $request->getValue('objectPHID');
|
|
|
|
if ($phid) {
|
2015-11-03 15:59:23 -08:00
|
|
|
$this->setIsCreate(false);
|
|
|
|
$object = $this->newObjectFromPHID($phid);
|
2015-11-03 08:45:00 -08:00
|
|
|
if (!$object) {
|
|
|
|
throw new Exception(pht('No such object with PHID "%s".', $phid));
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
$this->setIsCreate(true);
|
2015-11-03 15:59:23 -08:00
|
|
|
$object = $this->newEditableObject();
|
2015-11-03 08:45:00 -08:00
|
|
|
}
|
|
|
|
|
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
|
|
|
$this->validateObject($object);
|
|
|
|
|
2015-11-03 08:45:00 -08:00
|
|
|
$fields = $this->buildEditFields($object);
|
|
|
|
|
|
|
|
$types = $this->getAllEditTypesFromFields($fields);
|
|
|
|
$template = $object->getApplicationTransactionTemplate();
|
|
|
|
|
|
|
|
$xactions = $this->getConduitTransactions($request, $types, $template);
|
|
|
|
|
|
|
|
$editor = $object->getApplicationTransactionEditor()
|
|
|
|
->setActor($viewer)
|
|
|
|
->setContentSourceFromConduitRequest($request)
|
|
|
|
->setContinueOnNoEffect(true);
|
|
|
|
|
|
|
|
$xactions = $editor->applyTransactions($object, $xactions);
|
|
|
|
|
|
|
|
$xactions_struct = array();
|
|
|
|
foreach ($xactions as $xaction) {
|
|
|
|
$xactions_struct[] = array(
|
|
|
|
'phid' => $xaction->getPHID(),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
return array(
|
|
|
|
'object' => array(
|
|
|
|
'id' => $object->getID(),
|
|
|
|
'phid' => $object->getPHID(),
|
|
|
|
),
|
|
|
|
'transactions' => $xactions_struct,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Generate transactions which can be applied from edit actions in a Conduit
|
|
|
|
* request.
|
|
|
|
*
|
|
|
|
* @param ConduitAPIRequest The request.
|
|
|
|
* @param list<PhabricatorEditType> Supported edit types.
|
|
|
|
* @param PhabricatorApplicationTransaction Template transaction.
|
|
|
|
* @return list<PhabricatorApplicationTransaction> Generated transactions.
|
|
|
|
* @task conduit
|
|
|
|
*/
|
|
|
|
private function getConduitTransactions(
|
|
|
|
ConduitAPIRequest $request,
|
|
|
|
array $types,
|
|
|
|
PhabricatorApplicationTransaction $template) {
|
|
|
|
|
|
|
|
$transactions_key = 'transactions';
|
|
|
|
|
|
|
|
$xactions = $request->getValue($transactions_key);
|
|
|
|
if (!is_array($xactions)) {
|
|
|
|
throw new Exception(
|
|
|
|
pht(
|
|
|
|
'Parameter "%s" is not a list of transactions.',
|
|
|
|
$transactions_key));
|
|
|
|
}
|
|
|
|
|
|
|
|
foreach ($xactions as $key => $xaction) {
|
|
|
|
if (!is_array($xaction)) {
|
|
|
|
throw new Exception(
|
|
|
|
pht(
|
|
|
|
'Parameter "%s" must contain a list of transaction descriptions, '.
|
|
|
|
'but item with key "%s" is not a dictionary.',
|
|
|
|
$transactions_key,
|
|
|
|
$key));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!array_key_exists('type', $xaction)) {
|
|
|
|
throw new Exception(
|
|
|
|
pht(
|
|
|
|
'Parameter "%s" must contain a list of transaction descriptions, '.
|
|
|
|
'but item with key "%s" is missing a "type" field. Each '.
|
|
|
|
'transaction must have a type field.',
|
|
|
|
$transactions_key,
|
|
|
|
$key));
|
|
|
|
}
|
|
|
|
|
|
|
|
$type = $xaction['type'];
|
|
|
|
if (empty($types[$type])) {
|
|
|
|
throw new Exception(
|
|
|
|
pht(
|
|
|
|
'Transaction with key "%s" has invalid type "%s". This type is '.
|
|
|
|
'not recognized. Valid types are: %s.',
|
|
|
|
$key,
|
|
|
|
$type,
|
|
|
|
implode(', ', array_keys($types))));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
$results = array();
|
|
|
|
foreach ($xactions as $xaction) {
|
|
|
|
$type = $types[$xaction['type']];
|
|
|
|
|
|
|
|
$results[] = $type->generateTransaction(
|
|
|
|
clone $template,
|
|
|
|
$xaction);
|
|
|
|
}
|
|
|
|
|
|
|
|
return $results;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @return map<string, PhabricatorEditType>
|
|
|
|
* @task conduit
|
|
|
|
*/
|
|
|
|
private function getAllEditTypesFromFields(array $fields) {
|
|
|
|
$types = array();
|
|
|
|
foreach ($fields as $field) {
|
|
|
|
$field_types = $field->getEditTransactionTypes();
|
|
|
|
foreach ($field_types as $field_type) {
|
|
|
|
$field_type->setField($field);
|
|
|
|
$types[$field_type->getEditType()] = $field_type;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return $types;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getAllEditTypes() {
|
2015-11-12 10:49:39 -08:00
|
|
|
$config = $this->loadEditEngineConfiguration(null);
|
|
|
|
if (!$config) {
|
|
|
|
return array();
|
|
|
|
}
|
|
|
|
|
2015-11-03 08:45:00 -08:00
|
|
|
$object = $this->newEditableObject();
|
|
|
|
$fields = $this->buildEditFields($object);
|
|
|
|
return $this->getAllEditTypesFromFields($fields);
|
|
|
|
}
|
|
|
|
|
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
|
|
|
final public static function getAllEditEngines() {
|
|
|
|
return id(new PhutilClassMapQuery())
|
|
|
|
->setAncestorClass(__CLASS__)
|
|
|
|
->setUniqueMethod('getEngineKey')
|
|
|
|
->execute();
|
|
|
|
}
|
|
|
|
|
|
|
|
final public static function getByKey(PhabricatorUser $viewer, $key) {
|
|
|
|
return id(new PhabricatorEditEngineQuery())
|
|
|
|
->setViewer($viewer)
|
|
|
|
->withEngineKeys(array($key))
|
|
|
|
->executeOne();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* -( PhabricatorPolicyInterface )----------------------------------------- */
|
|
|
|
|
|
|
|
|
|
|
|
public function getPHID() {
|
|
|
|
return get_class($this);
|
|
|
|
}
|
|
|
|
|
|
|
|
public function getCapabilities() {
|
|
|
|
return array(
|
|
|
|
PhabricatorPolicyCapability::CAN_VIEW,
|
|
|
|
);
|
|
|
|
}
|
2015-11-03 08:45:00 -08:00
|
|
|
|
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
|
|
|
public function getPolicy($capability) {
|
|
|
|
switch ($capability) {
|
|
|
|
case PhabricatorPolicyCapability::CAN_VIEW:
|
|
|
|
return PhabricatorPolicies::getMostOpenPolicy();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public function hasAutomaticCapability($capability, PhabricatorUser $viewer) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
public function describeAutomaticCapability($capability) {
|
|
|
|
return null;
|
|
|
|
}
|
Implement a basic version of ApplicationEditor in Paste
Summary:
Ref T9132. Ref T4768. This is a rough v0 of ApplicationEditor, which replaces the edit workflow in Paste.
This mostly looks and works like ApplicationSearch, and is heavily modeled on it.
Roughly, we define a set of editable fields and the ApplicationEditor stuff builds everything else.
This has no functional changes, except:
- I removed "Fork Paste" since I don't think it's particularly useful now that pastes are editable. We could restore it if users miss it.
- Subscribers are now editable.
- Form field order is a little goofy (this will be fixed in a future diff).
- Subscribers and projects are now race-resistant.
The race-resistance works like this: instead of submitting just the new value ("subscribers=apple, dog") and doing a set operation ("set subscribers = apple, dog"), we submit the old and new values ("original=apple" + "new=apple, dog") then apply the user's changes as an add + remove ("add=dog", "remove=<none>"). This means that two users who do "Edit Paste" at around the same time and each add or remove a couple of subscribers won't overwrite each other, unless they actually add or remove the exact same subscribers (in which case their edits legitimately conflict). Previously, the last user to save would win, and whatever was in their field would overwrite the prior state, potentially losing the first user's edits.
Test Plan:
- Created pastes.
- Created pastes via API.
- Edited pastes.
- Edited every field.
- Opened a paste in two windows and did project/subscriber edits in each, saved in arbitrary order, had edits respected.
Reviewers: chad
Reviewed By: chad
Maniphest Tasks: T4768, T9132
Differential Revision: https://secure.phabricator.com/D14390
2015-11-02 18:58:32 -08:00
|
|
|
}
|