1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2025-02-16 08:48:38 +01:00
phorge-phorge/src/applications/policy/editor/PhabricatorPolicyEditEngineExtension.php
epriestley af1fef242c Fix an issue with editing pre-space objects using a form with no visibility controls
Summary:
WMF ran into this after their update. Here's the setup:

  - When you enable Spaces, we leave all existing objects set to `null`, which means "these belong to the default space". This is so we don't have to go update a trillion objects.
  - New objects get set to the default space explicitly (`PHID-SPCE-...`) but older ones stay with `null`.
  - If you edit an older object (like a task) from the time before Spaces, //and// the form doesn't have a Visbility/Spaces control, we would incorrectly poplate the value with `null` when the effective value should be the default space PHID.
  - This caused a "You must choose a space." error in the UI.

Instead, populate the control with the effective value instead of the literal database value. This makes the edit go through cleanly.

Also add a note about this for future-me.

Test Plan:
  - Disabled "Visibility" control in task edit form.
  - Edited an old task which had `null` as a `spacePHID` in the database.
  - Before patch: UI error about selecting a Space.
  - After patch: edit goes through cleanly.

Reviewers: chad, 20after4

Reviewed By: chad, 20after4

Subscribers: 20after4, aklapper

Differential Revision: https://secure.phabricator.com/D15306
2016-02-18 11:15:40 -08:00

133 lines
4.3 KiB
PHP

<?php
final class PhabricatorPolicyEditEngineExtension
extends PhabricatorEditEngineExtension {
const EXTENSIONKEY = 'policy.policy';
public function getExtensionPriority() {
return 250;
}
public function isExtensionEnabled() {
return true;
}
public function getExtensionName() {
return pht('Policies');
}
public function supportsObject(
PhabricatorEditEngine $engine,
PhabricatorApplicationTransactionInterface $object) {
return ($object instanceof PhabricatorPolicyInterface);
}
public function buildCustomEditFields(
PhabricatorEditEngine $engine,
PhabricatorApplicationTransactionInterface $object) {
$viewer = $engine->getViewer();
$editor = $object->getApplicationTransactionEditor();
$types = $editor->getTransactionTypesForObject($object);
$types = array_fuse($types);
$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,
'label' => pht('View Policy'),
'description' => pht('Controls who can view the object.'),
'description.conduit' => pht('Change the view policy of the object.'),
'edit' => 'view',
),
PhabricatorTransactions::TYPE_EDIT_POLICY => array(
'key' => 'policy.edit',
'aliases' => array('edit'),
'capability' => PhabricatorPolicyCapability::CAN_EDIT,
'label' => pht('Edit Policy'),
'description' => pht('Controls who can edit the object.'),
'description.conduit' => pht('Change the edit policy of the object.'),
'edit' => 'edit',
),
PhabricatorTransactions::TYPE_JOIN_POLICY => array(
'key' => 'policy.join',
'aliases' => array('join'),
'capability' => PhabricatorPolicyCapability::CAN_JOIN,
'label' => pht('Join Policy'),
'description' => pht('Controls who can join the object.'),
'description.conduit' => pht('Change the join policy of the object.'),
'edit' => 'join',
),
);
$fields = array();
foreach ($map as $type => $spec) {
if (empty($types[$type])) {
continue;
}
$capability = $spec['capability'];
$key = $spec['key'];
$aliases = $spec['aliases'];
$label = $spec['label'];
$description = $spec['description'];
$conduit_description = $spec['description.conduit'];
$edit = $spec['edit'];
$policy_field = id(new PhabricatorPolicyEditField())
->setKey($key)
->setLabel($label)
->setAliases($aliases)
->setIsCopyable(true)
->setCapability($capability)
->setPolicies($policies)
->setTransactionType($type)
->setEditTypeKey($edit)
->setDescription($description)
->setConduitDescription($conduit_description)
->setConduitTypeDescription(pht('New policy PHID or constant.'))
->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_phid = PhabricatorSpacesNamespaceQuery::getObjectSpacePHID(
$object);
$space_field = id(new PhabricatorSpaceEditField())
->setKey('spacePHID')
->setLabel(pht('Space'))
->setEditTypeKey('space')
->setIsCopyable(true)
->setIsLockable(false)
->setIsReorderable(false)
->setAliases(array('space', 'policy.space'))
->setTransactionType($type_space)
->setDescription(pht('Select a space for the object.'))
->setConduitDescription(
pht('Shift the object between spaces.'))
->setConduitTypeDescription(pht('New space PHID.'))
->setValue($space_phid);
$fields[] = $space_field;
$space_field->setPolicyField($policy_field);
$policy_field->setSpaceField($space_field);
}
}
}
}
return $fields;
}
}