mirror of
https://we.phorge.it/source/phorge.git
synced 2024-11-27 01:02:42 +01:00
Implement modular transactions for application policy changes
Summary: Still needs some cleanup, but ready for review in broad outline form. Test Plan: Made lots of policy changes to the Badges application and confirmed expected rows in `application_xactions`, confirmed expected changes to `phabricator.application-settings`. See example output (not quite working for custom policy objects) here: {F4922240} Reviewers: epriestley Reviewed By: epriestley Subscribers: Korvin, chad, epriestley Maniphest Tasks: T11476 Differential Revision: https://secure.phabricator.com/D17757
This commit is contained in:
parent
5307f51170
commit
d34b338f3f
11 changed files with 371 additions and 61 deletions
|
@ -1849,9 +1849,12 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorApplicationDatasource' => 'applications/meta/typeahead/PhabricatorApplicationDatasource.php',
|
'PhabricatorApplicationDatasource' => 'applications/meta/typeahead/PhabricatorApplicationDatasource.php',
|
||||||
'PhabricatorApplicationDetailViewController' => 'applications/meta/controller/PhabricatorApplicationDetailViewController.php',
|
'PhabricatorApplicationDetailViewController' => 'applications/meta/controller/PhabricatorApplicationDetailViewController.php',
|
||||||
'PhabricatorApplicationEditController' => 'applications/meta/controller/PhabricatorApplicationEditController.php',
|
'PhabricatorApplicationEditController' => 'applications/meta/controller/PhabricatorApplicationEditController.php',
|
||||||
|
'PhabricatorApplicationEditEngine' => 'applications/meta/editor/PhabricatorApplicationEditEngine.php',
|
||||||
'PhabricatorApplicationEditHTTPParameterHelpView' => 'applications/transactions/view/PhabricatorApplicationEditHTTPParameterHelpView.php',
|
'PhabricatorApplicationEditHTTPParameterHelpView' => 'applications/transactions/view/PhabricatorApplicationEditHTTPParameterHelpView.php',
|
||||||
|
'PhabricatorApplicationEditor' => 'applications/meta/editor/PhabricatorApplicationEditor.php',
|
||||||
'PhabricatorApplicationEmailCommandsController' => 'applications/meta/controller/PhabricatorApplicationEmailCommandsController.php',
|
'PhabricatorApplicationEmailCommandsController' => 'applications/meta/controller/PhabricatorApplicationEmailCommandsController.php',
|
||||||
'PhabricatorApplicationPanelController' => 'applications/meta/controller/PhabricatorApplicationPanelController.php',
|
'PhabricatorApplicationPanelController' => 'applications/meta/controller/PhabricatorApplicationPanelController.php',
|
||||||
|
'PhabricatorApplicationPolicyChangeTransaction' => 'applications/meta/xactions/PhabricatorApplicationPolicyChangeTransaction.php',
|
||||||
'PhabricatorApplicationProfileMenuItem' => 'applications/search/menuitem/PhabricatorApplicationProfileMenuItem.php',
|
'PhabricatorApplicationProfileMenuItem' => 'applications/search/menuitem/PhabricatorApplicationProfileMenuItem.php',
|
||||||
'PhabricatorApplicationQuery' => 'applications/meta/query/PhabricatorApplicationQuery.php',
|
'PhabricatorApplicationQuery' => 'applications/meta/query/PhabricatorApplicationQuery.php',
|
||||||
'PhabricatorApplicationSchemaSpec' => 'applications/meta/storage/PhabricatorApplicationSchemaSpec.php',
|
'PhabricatorApplicationSchemaSpec' => 'applications/meta/storage/PhabricatorApplicationSchemaSpec.php',
|
||||||
|
@ -6889,9 +6892,12 @@ phutil_register_library_map(array(
|
||||||
'PhabricatorApplicationDatasource' => 'PhabricatorTypeaheadDatasource',
|
'PhabricatorApplicationDatasource' => 'PhabricatorTypeaheadDatasource',
|
||||||
'PhabricatorApplicationDetailViewController' => 'PhabricatorApplicationsController',
|
'PhabricatorApplicationDetailViewController' => 'PhabricatorApplicationsController',
|
||||||
'PhabricatorApplicationEditController' => 'PhabricatorApplicationsController',
|
'PhabricatorApplicationEditController' => 'PhabricatorApplicationsController',
|
||||||
|
'PhabricatorApplicationEditEngine' => 'PhabricatorEditEngine',
|
||||||
'PhabricatorApplicationEditHTTPParameterHelpView' => 'AphrontView',
|
'PhabricatorApplicationEditHTTPParameterHelpView' => 'AphrontView',
|
||||||
|
'PhabricatorApplicationEditor' => 'PhabricatorApplicationTransactionEditor',
|
||||||
'PhabricatorApplicationEmailCommandsController' => 'PhabricatorApplicationsController',
|
'PhabricatorApplicationEmailCommandsController' => 'PhabricatorApplicationsController',
|
||||||
'PhabricatorApplicationPanelController' => 'PhabricatorApplicationsController',
|
'PhabricatorApplicationPanelController' => 'PhabricatorApplicationsController',
|
||||||
|
'PhabricatorApplicationPolicyChangeTransaction' => 'PhabricatorApplicationTransactionType',
|
||||||
'PhabricatorApplicationProfileMenuItem' => 'PhabricatorProfileMenuItem',
|
'PhabricatorApplicationProfileMenuItem' => 'PhabricatorProfileMenuItem',
|
||||||
'PhabricatorApplicationQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
|
'PhabricatorApplicationQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
|
||||||
'PhabricatorApplicationSchemaSpec' => 'PhabricatorConfigSchemaSpec',
|
'PhabricatorApplicationSchemaSpec' => 'PhabricatorConfigSchemaSpec',
|
||||||
|
|
|
@ -284,7 +284,6 @@ abstract class PhabricatorApplication
|
||||||
throw new PhutilMethodNotImplementedException();
|
throw new PhutilMethodNotImplementedException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* -( Fact Integration )--------------------------------------------------- */
|
/* -( Fact Integration )--------------------------------------------------- */
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -38,6 +38,11 @@ final class PhabricatorApplicationDetailViewController
|
||||||
$header->setStatus('fa-ban', 'dark', pht('Uninstalled'));
|
$header->setStatus('fa-ban', 'dark', pht('Uninstalled'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$timeline = $this->buildTransactionTimeline(
|
||||||
|
$selected,
|
||||||
|
new PhabricatorApplicationApplicationTransactionQuery());
|
||||||
|
$timeline->setShouldTerminate(true);
|
||||||
|
|
||||||
$curtain = $this->buildCurtain($selected);
|
$curtain = $this->buildCurtain($selected);
|
||||||
$details = $this->buildPropertySectionView($selected);
|
$details = $this->buildPropertySectionView($selected);
|
||||||
$policies = $this->buildPolicyView($selected);
|
$policies = $this->buildPolicyView($selected);
|
||||||
|
@ -61,6 +66,7 @@ final class PhabricatorApplicationDetailViewController
|
||||||
->setMainColumn(array(
|
->setMainColumn(array(
|
||||||
$policies,
|
$policies,
|
||||||
$panels,
|
$panels,
|
||||||
|
$timeline,
|
||||||
))
|
))
|
||||||
->addPropertySection(pht('Details'), $details);
|
->addPropertySection(pht('Details'), $details);
|
||||||
|
|
||||||
|
|
|
@ -30,8 +30,15 @@ final class PhabricatorApplicationEditController
|
||||||
->execute();
|
->execute();
|
||||||
|
|
||||||
if ($request->isFormPost()) {
|
if ($request->isFormPost()) {
|
||||||
|
$xactions = array();
|
||||||
|
|
||||||
$result = array();
|
$result = array();
|
||||||
|
$template = $application->getApplicationTransactionTemplate();
|
||||||
foreach ($application->getCapabilities() as $capability) {
|
foreach ($application->getCapabilities() as $capability) {
|
||||||
|
if (!$application->isCapabilityEditable($capability)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
$old = $application->getPolicy($capability);
|
$old = $application->getPolicy($capability);
|
||||||
$new = $request->getStr('policy:'.$capability);
|
$new = $request->getStr('policy:'.$capability);
|
||||||
|
|
||||||
|
@ -40,67 +47,36 @@ final class PhabricatorApplicationEditController
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (empty($policies[$new])) {
|
|
||||||
// Not a standard policy, check for a custom policy.
|
|
||||||
$policy = id(new PhabricatorPolicyQuery())
|
|
||||||
->setViewer($user)
|
|
||||||
->withPHIDs(array($new))
|
|
||||||
->executeOne();
|
|
||||||
if (!$policy) {
|
|
||||||
// Not a custom policy either. Can't set the policy to something
|
|
||||||
// invalid, so skip this.
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($new == PhabricatorPolicies::POLICY_PUBLIC) {
|
|
||||||
$capobj = PhabricatorPolicyCapability::getCapabilityByKey(
|
|
||||||
$capability);
|
|
||||||
if (!$capobj || !$capobj->shouldAllowPublicPolicySetting()) {
|
|
||||||
// Can't set non-public policies to public.
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$result[$capability] = $new;
|
$result[$capability] = $new;
|
||||||
|
|
||||||
|
$xactions[] = id(clone $template)
|
||||||
|
->setTransactionType(
|
||||||
|
PhabricatorApplicationPolicyChangeTransaction::TRANSACTIONTYPE)
|
||||||
|
->setMetadataValue(
|
||||||
|
PhabricatorApplicationPolicyChangeTransaction::METADATA_ATTRIBUTE,
|
||||||
|
$capability)
|
||||||
|
->setNewValue($new);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($result) {
|
if ($result) {
|
||||||
$key = 'phabricator.application-settings';
|
$editor = id(new PhabricatorApplicationEditor())
|
||||||
$config_entry = PhabricatorConfigEntry::loadConfigEntry($key);
|
->setActor($user)
|
||||||
$value = $config_entry->getValue();
|
->setContentSourceFromRequest($request)
|
||||||
|
->setContinueOnNoEffect(true)
|
||||||
|
->setContinueOnMissingFields(true);
|
||||||
|
|
||||||
$phid = $application->getPHID();
|
try {
|
||||||
if (empty($value[$phid])) {
|
$editor->applyTransactions($application, $xactions);
|
||||||
$value[$application->getPHID()] = array();
|
return id(new AphrontRedirectResponse())->setURI($view_uri);
|
||||||
}
|
} catch (PhabricatorApplicationTransactionValidationException $ex) {
|
||||||
if (empty($value[$phid]['policy'])) {
|
$validation_exception = $ex;
|
||||||
$value[$phid]['policy'] = array();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$value[$phid]['policy'] = $result + $value[$phid]['policy'];
|
return $this->newDialog()
|
||||||
|
->setTitle('Validation Failed')
|
||||||
// Don't allow users to make policy edits which would lock them out of
|
->setValidationException($validation_exception)
|
||||||
// applications, since they would be unable to undo those actions.
|
->addCancelButton($view_uri);
|
||||||
PhabricatorEnv::overrideConfig($key, $value);
|
|
||||||
PhabricatorPolicyFilter::mustRetainCapability(
|
|
||||||
$user,
|
|
||||||
$application,
|
|
||||||
PhabricatorPolicyCapability::CAN_VIEW);
|
|
||||||
|
|
||||||
PhabricatorPolicyFilter::mustRetainCapability(
|
|
||||||
$user,
|
|
||||||
$application,
|
|
||||||
PhabricatorPolicyCapability::CAN_EDIT);
|
|
||||||
|
|
||||||
PhabricatorConfigEditor::storeNewValue(
|
|
||||||
$user,
|
|
||||||
$config_entry,
|
|
||||||
$value,
|
|
||||||
PhabricatorContentSource::newFromRequest($request));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return id(new AphrontRedirectResponse())->setURI($view_uri);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$descriptions = PhabricatorPolicyQuery::renderPolicyDescriptions(
|
$descriptions = PhabricatorPolicyQuery::renderPolicyDescriptions(
|
||||||
|
|
|
@ -0,0 +1,64 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class PhabricatorApplicationEditEngine
|
||||||
|
extends PhabricatorEditEngine {
|
||||||
|
|
||||||
|
const ENGINECONST = 'application.application';
|
||||||
|
|
||||||
|
public function getEngineApplicationClass() {
|
||||||
|
return 'PhabricatorApplicationsApplication';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getEngineName() {
|
||||||
|
return pht('Applications');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getSummaryHeader() {
|
||||||
|
return pht('Configure Application Forms');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getSummaryText() {
|
||||||
|
return pht('Configure creation and editing forms in Applications.');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function isEngineConfigurable() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function newEditableObject() {
|
||||||
|
throw new PhutilMethodNotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function newObjectQuery() {
|
||||||
|
return new PhabricatorApplicationQuery();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getObjectCreateTitleText($object) {
|
||||||
|
return pht('Create New Application');
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getObjectEditTitleText($object) {
|
||||||
|
return pht('Edit Application: %s', $object->getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getObjectEditShortText($object) {
|
||||||
|
return $object->getName();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getObjectCreateShortText() {
|
||||||
|
return pht('Create Application');
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getObjectName() {
|
||||||
|
return pht('Application');
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getObjectViewURI($object) {
|
||||||
|
return $object->getViewURI();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function buildCustomEditFields($object) {
|
||||||
|
return array();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,46 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class PhabricatorApplicationEditor
|
||||||
|
extends PhabricatorApplicationTransactionEditor {
|
||||||
|
|
||||||
|
public function getEditorApplicationClass() {
|
||||||
|
return 'PhabricatorApplicationsApplication';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getEditorObjectsDescription() {
|
||||||
|
return pht('Application');
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function supportsSearch() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getTransactionTypes() {
|
||||||
|
$types = parent::getTransactionTypes();
|
||||||
|
$types[] = PhabricatorTransactions::TYPE_VIEW_POLICY;
|
||||||
|
$types[] = PhabricatorTransactions::TYPE_EDIT_POLICY;
|
||||||
|
|
||||||
|
return $types;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function shouldSendMail(
|
||||||
|
PhabricatorLiskDAO $object,
|
||||||
|
array $xactions) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function shouldPublishFeedStory(
|
||||||
|
PhabricatorLiskDAO $object,
|
||||||
|
array $xactions) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getMailTo(PhabricatorLiskDAO $object) {
|
||||||
|
return array();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getMailCC(PhabricatorLiskDAO $object) {
|
||||||
|
return array();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -11,10 +11,6 @@ final class PhabricatorApplicationApplicationTransaction
|
||||||
return PhabricatorApplicationApplicationPHIDType::TYPECONST;
|
return PhabricatorApplicationApplicationPHIDType::TYPECONST;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getApplicationTransactionCommentObject() {
|
|
||||||
return new PhabricatorApplicationTransactionComment();
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getBaseTransactionClass() {
|
public function getBaseTransactionClass() {
|
||||||
return 'PhabricatorApplicationTransactionType';
|
return 'PhabricatorApplicationTransactionType';
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,197 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
final class PhabricatorApplicationPolicyChangeTransaction
|
||||||
|
extends PhabricatorApplicationTransactionType {
|
||||||
|
|
||||||
|
const TRANSACTIONTYPE = 'application.policy';
|
||||||
|
const METADATA_ATTRIBUTE = 'capability.name';
|
||||||
|
|
||||||
|
private $policies;
|
||||||
|
|
||||||
|
public function generateOldValue($object) {
|
||||||
|
$application = $object;
|
||||||
|
$capability = $this->getCapabilityName();
|
||||||
|
return $application->getPolicy($capability);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function applyInternalEffects($object, $value) {
|
||||||
|
$application = $object;
|
||||||
|
$user = $this->getActor();
|
||||||
|
|
||||||
|
$key = 'phabricator.application-settings';
|
||||||
|
$config_entry = PhabricatorConfigEntry::loadConfigEntry($key);
|
||||||
|
$current_value = $config_entry->getValue();
|
||||||
|
|
||||||
|
$phid = $application->getPHID();
|
||||||
|
if (empty($current_value[$phid])) {
|
||||||
|
$current_value[$application->getPHID()] = array();
|
||||||
|
}
|
||||||
|
if (empty($current_value[$phid]['policy'])) {
|
||||||
|
$current_value[$phid]['policy'] = array();
|
||||||
|
}
|
||||||
|
|
||||||
|
$new = array($this->getCapabilityName() => $value);
|
||||||
|
$current_value[$phid]['policy'] = $new + $current_value[$phid]['policy'];
|
||||||
|
|
||||||
|
$editor = $this->getEditor();
|
||||||
|
$content_source = $editor->getContentSource();
|
||||||
|
PhabricatorConfigEditor::storeNewValue(
|
||||||
|
$user,
|
||||||
|
$config_entry,
|
||||||
|
$current_value,
|
||||||
|
$content_source);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getTitle() {
|
||||||
|
$old = $this->renderPolicy($this->getOldValue());
|
||||||
|
$new = $this->renderPolicy($this->getNewValue());
|
||||||
|
|
||||||
|
return pht(
|
||||||
|
'%s changed the "%s" policy from "%s" to "%s".',
|
||||||
|
$this->renderAuthor(),
|
||||||
|
$this->renderCapability(),
|
||||||
|
$old,
|
||||||
|
$new);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getTitleForFeed() {
|
||||||
|
$old = $this->renderPolicy($this->getOldValue());
|
||||||
|
$new = $this->renderPolicy($this->getNewValue());
|
||||||
|
|
||||||
|
return pht(
|
||||||
|
'%s changed the "%s" policy for application %s from "%s" to "%s".',
|
||||||
|
$this->renderAuthor(),
|
||||||
|
$this->renderCapability(),
|
||||||
|
$this->renderObject(),
|
||||||
|
$old,
|
||||||
|
$new);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function validateTransactions($object, array $xactions) {
|
||||||
|
$user = $this->getActor();
|
||||||
|
$application = $object;
|
||||||
|
$policies = id(new PhabricatorPolicyQuery())
|
||||||
|
->setViewer($user)
|
||||||
|
->setObject($application)
|
||||||
|
->execute();
|
||||||
|
|
||||||
|
$errors = array();
|
||||||
|
foreach ($xactions as $xaction) {
|
||||||
|
$new = $xaction->getNewValue();
|
||||||
|
$capability = $xaction->getMetadataValue(self::METADATA_ATTRIBUTE);
|
||||||
|
|
||||||
|
if (empty($policies[$new])) {
|
||||||
|
// Not a standard policy, check for a custom policy.
|
||||||
|
$policy = id(new PhabricatorPolicyQuery())
|
||||||
|
->setViewer($user)
|
||||||
|
->withPHIDs(array($new))
|
||||||
|
->executeOne();
|
||||||
|
if (!$policy) {
|
||||||
|
$errors[] = $this->newInvalidError(
|
||||||
|
pht('Policy does not exist.'));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$policy = idx($policies, $new);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$policy->isValidPolicyForEdit()) {
|
||||||
|
$errors[] = $this->newInvalidError(
|
||||||
|
pht('Can\'t set the policy to a policy you can\'t view!'));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($new == PhabricatorPolicies::POLICY_PUBLIC) {
|
||||||
|
$capobj = PhabricatorPolicyCapability::getCapabilityByKey(
|
||||||
|
$capability);
|
||||||
|
if (!$capobj || !$capobj->shouldAllowPublicPolicySetting()) {
|
||||||
|
$errors[] = $this->newInvalidError(
|
||||||
|
pht('Can\'t set non-public policies to public.'));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$application->isCapabilityEditable($capability)) {
|
||||||
|
$errors[] = $this->newInvalidError(
|
||||||
|
pht('Capability "%s" is not editable for this application.',
|
||||||
|
$capability));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we're changing these policies, the viewer needs to still be able to
|
||||||
|
// view or edit the application under the new policy.
|
||||||
|
$validate_map = array(
|
||||||
|
PhabricatorPolicyCapability::CAN_VIEW,
|
||||||
|
PhabricatorPolicyCapability::CAN_EDIT,
|
||||||
|
);
|
||||||
|
$validate_map = array_fill_keys($validate_map, array());
|
||||||
|
|
||||||
|
foreach ($xactions as $xaction) {
|
||||||
|
$capability = $xaction->getMetadataValue(self::METADATA_ATTRIBUTE);
|
||||||
|
if (!isset($validate_map[$capability])) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$validate_map[$capability][] = $xaction;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($validate_map as $capability => $cap_xactions) {
|
||||||
|
if (!$cap_xactions) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$editor = $this->getEditor();
|
||||||
|
$policy_errors = $editor->validatePolicyTransaction(
|
||||||
|
$object,
|
||||||
|
$cap_xactions,
|
||||||
|
self::TRANSACTIONTYPE,
|
||||||
|
$capability);
|
||||||
|
|
||||||
|
foreach ($policy_errors as $error) {
|
||||||
|
$errors[] = $error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $errors;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function renderPolicy($name) {
|
||||||
|
$policies = $this->getAllPolicies();
|
||||||
|
if (empty($policies[$name])) {
|
||||||
|
// Not a standard policy, check for a custom policy.
|
||||||
|
$policy = id(new PhabricatorPolicyQuery())
|
||||||
|
->setViewer($this->getViewer())
|
||||||
|
->withPHIDs(array($name))
|
||||||
|
->executeOne();
|
||||||
|
$policies[$name] = $policy;
|
||||||
|
}
|
||||||
|
|
||||||
|
$policy = idx($policies, $name);
|
||||||
|
return $this->renderValue($policy->getFullName());
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getAllPolicies() {
|
||||||
|
if (!$this->policies) {
|
||||||
|
$viewer = $this->getViewer();
|
||||||
|
$application = $this->getObject();
|
||||||
|
$this->policies = id(new PhabricatorPolicyQuery())
|
||||||
|
->setViewer($viewer)
|
||||||
|
->setObject($application)
|
||||||
|
->execute();
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->policies;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function renderCapability() {
|
||||||
|
$application = $this->getObject();
|
||||||
|
$capability = $this->getCapabilityName();
|
||||||
|
return $application->getCapabilityLabel($capability);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getCapabilityName() {
|
||||||
|
return $this->getMetadataValue(self::METADATA_ATTRIBUTE);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -264,9 +264,11 @@ final class PhabricatorPolicy
|
||||||
public function getFullName() {
|
public function getFullName() {
|
||||||
switch ($this->getType()) {
|
switch ($this->getType()) {
|
||||||
case PhabricatorPolicyType::TYPE_PROJECT:
|
case PhabricatorPolicyType::TYPE_PROJECT:
|
||||||
return pht('Project: %s', $this->getName());
|
return pht('Members of Project: %s', $this->getName());
|
||||||
case PhabricatorPolicyType::TYPE_MASKED:
|
case PhabricatorPolicyType::TYPE_MASKED:
|
||||||
return pht('Other: %s', $this->getName());
|
return pht('Other: %s', $this->getName());
|
||||||
|
case PhabricatorPolicyType::TYPE_USER:
|
||||||
|
return pht('Only User: %s', $this->getName());
|
||||||
default:
|
default:
|
||||||
return $this->getName();
|
return $this->getName();
|
||||||
}
|
}
|
||||||
|
@ -422,6 +424,10 @@ final class PhabricatorPolicy
|
||||||
return ($this_strength > $other_strength);
|
return ($this_strength > $other_strength);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function isValidPolicyForEdit() {
|
||||||
|
return $this->getType() !== PhabricatorPolicyType::TYPE_MASKED;
|
||||||
|
}
|
||||||
|
|
||||||
public static function getSpecialRules(
|
public static function getSpecialRules(
|
||||||
PhabricatorPolicyInterface $object,
|
PhabricatorPolicyInterface $object,
|
||||||
PhabricatorUser $viewer,
|
PhabricatorUser $viewer,
|
||||||
|
|
|
@ -334,6 +334,8 @@ abstract class PhabricatorApplicationTransactionEditor
|
||||||
|
|
||||||
$xtype = $this->getModularTransactionType($type);
|
$xtype = $this->getModularTransactionType($type);
|
||||||
if ($xtype) {
|
if ($xtype) {
|
||||||
|
$xtype = clone $xtype;
|
||||||
|
$xtype->setStorage($xaction);
|
||||||
return $xtype->generateOldValue($object);
|
return $xtype->generateOldValue($object);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -414,6 +416,8 @@ abstract class PhabricatorApplicationTransactionEditor
|
||||||
|
|
||||||
$xtype = $this->getModularTransactionType($type);
|
$xtype = $this->getModularTransactionType($type);
|
||||||
if ($xtype) {
|
if ($xtype) {
|
||||||
|
$xtype = clone $xtype;
|
||||||
|
$xtype->setStorage($xaction);
|
||||||
return $xtype->generateNewValue($object, $xaction->getNewValue());
|
return $xtype->generateNewValue($object, $xaction->getNewValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -553,6 +557,8 @@ abstract class PhabricatorApplicationTransactionEditor
|
||||||
|
|
||||||
$xtype = $this->getModularTransactionType($type);
|
$xtype = $this->getModularTransactionType($type);
|
||||||
if ($xtype) {
|
if ($xtype) {
|
||||||
|
$xtype = clone $xtype;
|
||||||
|
$xtype->setStorage($xaction);
|
||||||
return $xtype->applyInternalEffects($object, $xaction->getNewValue());
|
return $xtype->applyInternalEffects($object, $xaction->getNewValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2163,7 +2169,7 @@ abstract class PhabricatorApplicationTransactionEditor
|
||||||
return array_mergev($errors);
|
return array_mergev($errors);
|
||||||
}
|
}
|
||||||
|
|
||||||
private function validatePolicyTransaction(
|
public function validatePolicyTransaction(
|
||||||
PhabricatorLiskDAO $object,
|
PhabricatorLiskDAO $object,
|
||||||
array $xactions,
|
array $xactions,
|
||||||
$transaction_type,
|
$transaction_type,
|
||||||
|
@ -2772,7 +2778,11 @@ abstract class PhabricatorApplicationTransactionEditor
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!$has_support) {
|
if (!$has_support) {
|
||||||
throw new Exception(pht('Capability not supported.'));
|
throw new Exception(
|
||||||
|
pht('The object being edited does not implement any standard '.
|
||||||
|
'interfaces (like PhabricatorSubscribableInterface) which allow '.
|
||||||
|
'CCs to be generated automatically. Override the "getMailCC()" '.
|
||||||
|
'method and generate CCs explicitly.'));
|
||||||
}
|
}
|
||||||
|
|
||||||
return array_mergev($phids);
|
return array_mergev($phids);
|
||||||
|
|
|
@ -315,4 +315,8 @@ abstract class PhabricatorModularTransactionType
|
||||||
return $editor->getPHIDList($old, $new);
|
return $editor->getPHIDList($old, $new);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getMetadataValue($key, $default = null) {
|
||||||
|
return $this->getStorage()->getMetadataValue($key, $default);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue