mirror of
https://we.phorge.it/source/phorge.git
synced 2024-12-28 08:20:57 +01:00
Nuance - federate out the design of NuanceSource via NuanceSourceDefinition
Summary: ...and get the basic edit flow "working" for a new NuanceSourceDefinition - the Phabricator Form. ...and fix a dumb bug in the query class so when you redirect to the view page / try to edit an existing NuanceSource you don't fatal. Test Plan: played around with the edit form and it worked! Reviewers: epriestley Reviewed By: epriestley CC: Korvin, epriestley, aran Differential Revision: https://secure.phabricator.com/D7585
This commit is contained in:
parent
a07f444f2a
commit
7b718bb033
13 changed files with 557 additions and 82 deletions
11
resources/sql/patches/20131120.nuancesourcetype.sql
Normal file
11
resources/sql/patches/20131120.nuancesourcetype.sql
Normal file
|
@ -0,0 +1,11 @@
|
|||
ALTER TABLE {$NAMESPACE}_nuance.nuance_source
|
||||
DROP KEY key_type;
|
||||
|
||||
ALTER TABLE {$NAMESPACE}_nuance.nuance_source
|
||||
DROP COLUMN type;
|
||||
|
||||
ALTER TABLE {$NAMESPACE}_nuance.nuance_source
|
||||
ADD type VARCHAR(32) NOT NULL COLLATE utf8_bin AFTER name;
|
||||
|
||||
ALTER TABLE {$NAMESPACE}_nuance.nuance_source
|
||||
ADD KEY `key_type` (type, dateModified);
|
|
@ -867,6 +867,7 @@ phutil_register_library_map(array(
|
|||
'NuancePHIDTypeQueue' => 'applications/nuance/phid/NuancePHIDTypeQueue.php',
|
||||
'NuancePHIDTypeRequestor' => 'applications/nuance/phid/NuancePHIDTypeRequestor.php',
|
||||
'NuancePHIDTypeSource' => 'applications/nuance/phid/NuancePHIDTypeSource.php',
|
||||
'NuancePhabricatorFormSourceDefinition' => 'applications/nuance/source/NuancePhabricatorFormSourceDefinition.php',
|
||||
'NuanceQuery' => 'applications/nuance/query/NuanceQuery.php',
|
||||
'NuanceQueue' => 'applications/nuance/storage/NuanceQueue.php',
|
||||
'NuanceQueueEditController' => 'applications/nuance/controller/NuanceQueueEditController.php',
|
||||
|
@ -887,13 +888,13 @@ phutil_register_library_map(array(
|
|||
'NuanceRequestorTransactionQuery' => 'applications/nuance/query/NuanceRequestorTransactionQuery.php',
|
||||
'NuanceRequestorViewController' => 'applications/nuance/controller/NuanceRequestorViewController.php',
|
||||
'NuanceSource' => 'applications/nuance/storage/NuanceSource.php',
|
||||
'NuanceSourceDefinition' => 'applications/nuance/source/NuanceSourceDefinition.php',
|
||||
'NuanceSourceEditController' => 'applications/nuance/controller/NuanceSourceEditController.php',
|
||||
'NuanceSourceEditor' => 'applications/nuance/editor/NuanceSourceEditor.php',
|
||||
'NuanceSourceQuery' => 'applications/nuance/query/NuanceSourceQuery.php',
|
||||
'NuanceSourceTransaction' => 'applications/nuance/storage/NuanceSourceTransaction.php',
|
||||
'NuanceSourceTransactionComment' => 'applications/nuance/storage/NuanceSourceTransactionComment.php',
|
||||
'NuanceSourceTransactionQuery' => 'applications/nuance/query/NuanceSourceTransactionQuery.php',
|
||||
'NuanceSourceType' => 'applications/nuance/constants/NuanceSourceType.php',
|
||||
'NuanceSourceViewController' => 'applications/nuance/controller/NuanceSourceViewController.php',
|
||||
'NuanceTransaction' => 'applications/nuance/storage/NuanceTransaction.php',
|
||||
'OwnersPackageReplyHandler' => 'applications/owners/mail/OwnersPackageReplyHandler.php',
|
||||
|
@ -3238,6 +3239,7 @@ phutil_register_library_map(array(
|
|||
'NuancePHIDTypeQueue' => 'PhabricatorPHIDType',
|
||||
'NuancePHIDTypeRequestor' => 'PhabricatorPHIDType',
|
||||
'NuancePHIDTypeSource' => 'PhabricatorPHIDType',
|
||||
'NuancePhabricatorFormSourceDefinition' => 'NuanceSourceDefinition',
|
||||
'NuanceQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
|
||||
'NuanceQueue' =>
|
||||
array(
|
||||
|
@ -3266,13 +3268,13 @@ phutil_register_library_map(array(
|
|||
0 => 'NuanceDAO',
|
||||
1 => 'PhabricatorPolicyInterface',
|
||||
),
|
||||
'NuanceSourceDefinition' => 'Phobject',
|
||||
'NuanceSourceEditController' => 'NuanceController',
|
||||
'NuanceSourceEditor' => 'PhabricatorApplicationTransactionEditor',
|
||||
'NuanceSourceQuery' => 'NuanceQuery',
|
||||
'NuanceSourceTransaction' => 'NuanceTransaction',
|
||||
'NuanceSourceTransactionComment' => 'PhabricatorApplicationTransactionComment',
|
||||
'NuanceSourceTransactionQuery' => 'PhabricatorApplicationTransactionQuery',
|
||||
'NuanceSourceType' => 'NuanceConstants',
|
||||
'NuanceSourceViewController' => 'NuanceController',
|
||||
'NuanceTransaction' => 'PhabricatorApplicationTransaction',
|
||||
'OwnersPackageReplyHandler' => 'PhabricatorMailReplyHandler',
|
||||
|
|
|
@ -23,6 +23,10 @@ final class PhabricatorApplicationNuance extends PhabricatorApplication {
|
|||
return true;
|
||||
}
|
||||
|
||||
public function getBaseURI() {
|
||||
return '/nuance/';
|
||||
}
|
||||
|
||||
public function getRoutes() {
|
||||
return array(
|
||||
'/nuance/' => array(
|
||||
|
|
|
@ -1,22 +0,0 @@
|
|||
<?php
|
||||
|
||||
final class NuanceSourceType extends NuanceConstants {
|
||||
|
||||
/* internal source types */
|
||||
const PHABRICATOR_FORM = 1;
|
||||
|
||||
/* social media source types */
|
||||
const TWITTER = 101;
|
||||
|
||||
/* engineering media source types */
|
||||
const GITHUB = 201;
|
||||
|
||||
|
||||
public static function getSelectOptions() {
|
||||
|
||||
return array(
|
||||
self::PHABRICATOR_FORM => pht('Phabricator Form'),
|
||||
);
|
||||
}
|
||||
|
||||
}
|
|
@ -28,7 +28,6 @@ final class NuanceSourceEditController extends NuanceController {
|
|||
|
||||
if ($is_new) {
|
||||
$source = NuanceSource::initializeNewSource($user);
|
||||
$title = pht('Create Source');
|
||||
} else {
|
||||
$source = id(new NuanceSourceQuery())
|
||||
->setViewer($user)
|
||||
|
@ -39,71 +38,29 @@ final class NuanceSourceEditController extends NuanceController {
|
|||
PhabricatorPolicyCapability::CAN_EDIT,
|
||||
))
|
||||
->executeOne();
|
||||
$title = pht('Edit Source');
|
||||
}
|
||||
|
||||
if (!$source) {
|
||||
return new Aphront404Response();
|
||||
}
|
||||
|
||||
$error_view = null;
|
||||
$e_name = null;
|
||||
if ($request->isFormPost()) {
|
||||
$error_view = id(new AphrontErrorView())
|
||||
->setTitle(pht('This does not work at all yet.'));
|
||||
}
|
||||
$definition = NuanceSourceDefinition::getDefinitionForSource($source);
|
||||
$definition->setActor($user);
|
||||
|
||||
$policies = id(new PhabricatorPolicyQuery())
|
||||
->setViewer($user)
|
||||
->setObject($source)
|
||||
->execute();
|
||||
$response = $definition->buildEditLayout($request);
|
||||
if ($response instanceof AphrontResponse) {
|
||||
return $response;
|
||||
}
|
||||
$layout = $response;
|
||||
|
||||
$crumbs = $this->buildApplicationCrumbs();
|
||||
|
||||
$form = id(new AphrontFormView())
|
||||
->setUser($user)
|
||||
->appendChild(
|
||||
id(new AphrontFormTextControl())
|
||||
->setLabel(pht('Name'))
|
||||
->setName('name')
|
||||
->setError($e_name)
|
||||
->setValue($source->getName()))
|
||||
->appendChild(
|
||||
id(new AphrontFormSelectControl())
|
||||
->setLabel(pht('Type'))
|
||||
->setName('type')
|
||||
->setOptions(NuanceSourceType::getSelectOptions())
|
||||
->setValue($source->getType()))
|
||||
->appendChild(
|
||||
id(new AphrontFormPolicyControl())
|
||||
->setUser($user)
|
||||
->setCapability(PhabricatorPolicyCapability::CAN_VIEW)
|
||||
->setPolicyObject($source)
|
||||
->setPolicies($policies)
|
||||
->setName('viewPolicy'))
|
||||
->appendChild(
|
||||
id(new AphrontFormPolicyControl())
|
||||
->setUser($user)
|
||||
->setCapability(PhabricatorPolicyCapability::CAN_EDIT)
|
||||
->setPolicyObject($source)
|
||||
->setPolicies($policies)
|
||||
->setName('editPolicy'))
|
||||
->appendChild(
|
||||
id(new AphrontFormSubmitControl())
|
||||
->setValue(pht('Save')));
|
||||
|
||||
$layout = id(new PHUIObjectBoxView())
|
||||
->setHeaderText($title)
|
||||
->setFormError($error_view)
|
||||
->setForm($form);
|
||||
|
||||
return $this->buildApplicationPage(
|
||||
array(
|
||||
$crumbs,
|
||||
$layout,
|
||||
),
|
||||
array(
|
||||
'title' => $title,
|
||||
'title' => $definition->getEditTitle(),
|
||||
'device' => true));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,11 +18,11 @@ final class NuanceSourceViewController extends NuanceController {
|
|||
|
||||
public function processRequest() {
|
||||
$request = $this->getRequest();
|
||||
$user = $request->getUser();
|
||||
$viewer = $request->getUser();
|
||||
|
||||
$source_id = $this->getSourceID();
|
||||
$source = id(new NuanceSourceQuery())
|
||||
->setViewer($user)
|
||||
->setViewer($viewer)
|
||||
->withIDs(array($source_id))
|
||||
->executeOne();
|
||||
|
||||
|
@ -30,13 +30,107 @@ final class NuanceSourceViewController extends NuanceController {
|
|||
return new Aphront404Response();
|
||||
}
|
||||
|
||||
$source_phid = $source->getPHID();
|
||||
$xactions = id(new NuanceSourceTransactionQuery())
|
||||
->setViewer($viewer)
|
||||
->withObjectPHIDs(array($source_phid))
|
||||
->execute();
|
||||
|
||||
$engine = id(new PhabricatorMarkupEngine())
|
||||
->setViewer($viewer);
|
||||
|
||||
$timeline = id(new PhabricatorApplicationTransactionView())
|
||||
->setUser($viewer)
|
||||
->setObjectPHID($source_phid)
|
||||
->setMarkupEngine($engine)
|
||||
->setTransactions($xactions);
|
||||
|
||||
$title = pht('%s', $source->getName());
|
||||
$crumbs = $this->buildApplicationCrumbs();
|
||||
$title = 'TODO';
|
||||
$crumbs->addCrumb(
|
||||
id(new PhabricatorCrumbView())
|
||||
->setName($title));
|
||||
|
||||
$header = $this->buildHeaderView($source);
|
||||
$actions = $this->buildActionView($source);
|
||||
$properties = $this->buildPropertyView($source, $actions);
|
||||
|
||||
$box = id(new PHUIObjectBoxView())
|
||||
->setHeader($header)
|
||||
->addPropertyList($properties);
|
||||
|
||||
return $this->buildApplicationPage(
|
||||
$crumbs,
|
||||
array(
|
||||
$crumbs,
|
||||
$box,
|
||||
$timeline,
|
||||
),
|
||||
array(
|
||||
'title' => $title,
|
||||
'device' => true));
|
||||
'device' => true,
|
||||
));
|
||||
|
||||
}
|
||||
|
||||
|
||||
private function buildHeaderView(NuanceSource $source) {
|
||||
$viewer = $this->getRequest()->getUser();
|
||||
|
||||
$header = id(new PHUIHeaderView())
|
||||
->setUser($viewer)
|
||||
->setHeader($source->getName())
|
||||
->setPolicyObject($source);
|
||||
|
||||
return $header;
|
||||
}
|
||||
|
||||
private function buildActionView(NuanceSource $source) {
|
||||
$viewer = $this->getRequest()->getUser();
|
||||
$id = $source->getID();
|
||||
|
||||
$actions = id(new PhabricatorActionListView())
|
||||
->setObjectURI($source->getURI())
|
||||
->setUser($viewer);
|
||||
|
||||
$can_edit = PhabricatorPolicyFilter::hasCapability(
|
||||
$viewer,
|
||||
$source,
|
||||
PhabricatorPolicyCapability::CAN_EDIT);
|
||||
|
||||
$actions->addAction(
|
||||
id(new PhabricatorActionView())
|
||||
->setName(pht('Edit Source'))
|
||||
->setIcon('edit')
|
||||
->setHref($this->getApplicationURI("source/edit/{$id}/"))
|
||||
->setDisabled(!$can_edit)
|
||||
->setWorkflow(!$can_edit));
|
||||
|
||||
return $actions;
|
||||
}
|
||||
|
||||
private function buildPropertyView(
|
||||
NuanceSource $source,
|
||||
PhabricatorActionListView $actions) {
|
||||
$viewer = $this->getRequest()->getUser();
|
||||
|
||||
$properties = id(new PHUIPropertyListView())
|
||||
->setUser($viewer)
|
||||
->setObject($source)
|
||||
->setActionList($actions);
|
||||
|
||||
$definition = NuanceSourceDefinition::getDefinitionForSource($source);
|
||||
$properties->addProperty(
|
||||
pht('Source Type'),
|
||||
$definition->getName());
|
||||
|
||||
$descriptions = PhabricatorPolicyQuery::renderPolicyDescriptions(
|
||||
$viewer,
|
||||
$source);
|
||||
|
||||
$properties->addProperty(
|
||||
pht('Editable By'),
|
||||
$descriptions[PhabricatorPolicyCapability::CAN_EDIT]);
|
||||
|
||||
return $properties;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,8 @@ final class NuanceSourceEditor
|
|||
public function getTransactionTypes() {
|
||||
$types = parent::getTransactionTypes();
|
||||
|
||||
$types[] = NuanceSourceTransaction::TYPE_NAME;
|
||||
|
||||
$types[] = PhabricatorTransactions::TYPE_EDGE;
|
||||
$types[] = PhabricatorTransactions::TYPE_COMMENT;
|
||||
$types[] = PhabricatorTransactions::TYPE_VIEW_POLICY;
|
||||
|
@ -14,4 +16,80 @@ final class NuanceSourceEditor
|
|||
return $types;
|
||||
}
|
||||
|
||||
protected function getCustomTransactionOldValue(
|
||||
PhabricatorLiskDAO $object,
|
||||
PhabricatorApplicationTransaction $xaction) {
|
||||
|
||||
switch ($xaction->getTransactionType()) {
|
||||
case NuanceSourceTransaction::TYPE_NAME:
|
||||
return $object->getName();
|
||||
}
|
||||
|
||||
return parent::getCustomTransactionOldValue($object, $xaction);
|
||||
}
|
||||
|
||||
protected function getCustomTransactionNewValue(
|
||||
PhabricatorLiskDAO $object,
|
||||
PhabricatorApplicationTransaction $xaction) {
|
||||
|
||||
switch ($xaction->getTransactionType()) {
|
||||
case NuanceSourceTransaction::TYPE_NAME:
|
||||
return $xaction->getNewValue();
|
||||
}
|
||||
|
||||
return parent::getCustomTransactionNewValue($object, $xaction);
|
||||
}
|
||||
|
||||
protected function applyCustomInternalTransaction(
|
||||
PhabricatorLiskDAO $object,
|
||||
PhabricatorApplicationTransaction $xaction) {
|
||||
|
||||
switch ($xaction->getTransactionType()) {
|
||||
case NuanceSourceTransaction::TYPE_NAME:
|
||||
$object->setName($xaction->getNewValue());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
protected function applyCustomExternalTransaction(
|
||||
PhabricatorLiskDAO $object,
|
||||
PhabricatorApplicationTransaction $xaction) {
|
||||
|
||||
switch ($xaction->getTransactionType()) {
|
||||
case NuanceSourceTransaction::TYPE_NAME:
|
||||
return;
|
||||
}
|
||||
|
||||
return parent::applyCustomExternalTransaction($object, $xaction);
|
||||
}
|
||||
|
||||
protected function validateTransaction(
|
||||
PhabricatorLiskDAO $object,
|
||||
$type,
|
||||
array $xactions) {
|
||||
|
||||
$errors = parent::validateTransaction($object, $type, $xactions);
|
||||
|
||||
switch ($type) {
|
||||
case NuanceSourceTransaction::TYPE_NAME:
|
||||
$missing = $this->validateIsEmptyTextField(
|
||||
$object->getName(),
|
||||
$xactions);
|
||||
|
||||
if ($missing) {
|
||||
$error = new PhabricatorApplicationTransactionValidationError(
|
||||
$type,
|
||||
pht('Required'),
|
||||
pht('Source name is required.'),
|
||||
nonempty(last($xactions), null));
|
||||
|
||||
$error->setIsMissingFieldError(true);
|
||||
$errors[] = $error;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return $errors;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -35,7 +35,7 @@ final class NuanceSourceQuery
|
|||
|
||||
$data = queryfx_all(
|
||||
$conn_r,
|
||||
'SELECT FROM %T %Q %Q %Q',
|
||||
'SELECT * FROM %T %Q %Q %Q',
|
||||
$table->getTableName(),
|
||||
$this->buildWhereClause($conn_r),
|
||||
$this->buildOrderClause($conn_r),
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
<?php
|
||||
|
||||
final class NuancePhabricatorFormSourceDefinition
|
||||
extends NuanceSourceDefinition {
|
||||
|
||||
public function getName() {
|
||||
return pht('Phabricator Form');
|
||||
}
|
||||
|
||||
public function getSourceTypeConstant() {
|
||||
return 'phabricator-form';
|
||||
}
|
||||
|
||||
public function updateItems() {
|
||||
return null;
|
||||
}
|
||||
|
||||
protected function augmentEditForm(
|
||||
AphrontFormView $form,
|
||||
PhabricatorApplicationTransactionValidationException $ex = null) {
|
||||
|
||||
/* TODO - add a box to allow for custom fields to be defined here, so that
|
||||
* these NuanceSource objects made from this defintion can be used to
|
||||
* capture arbitrary data */
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
protected function buildTransactions(AphrontRequest $request) {
|
||||
$transactions = parent::buildTransactions($request);
|
||||
|
||||
// TODO -- as above
|
||||
|
||||
return $transactions;
|
||||
}
|
||||
|
||||
public function renderView() {
|
||||
}
|
||||
|
||||
public function renderListView() {
|
||||
}
|
||||
|
||||
}
|
274
src/applications/nuance/source/NuanceSourceDefinition.php
Normal file
274
src/applications/nuance/source/NuanceSourceDefinition.php
Normal file
|
@ -0,0 +1,274 @@
|
|||
<?php
|
||||
|
||||
abstract class NuanceSourceDefinition extends Phobject {
|
||||
|
||||
private $actor;
|
||||
private $sourceObject;
|
||||
|
||||
public function setActor(PhabricatorUser $actor) {
|
||||
$this->actor = $actor;
|
||||
return $this;
|
||||
}
|
||||
public function getActor() {
|
||||
return $this->actor;
|
||||
}
|
||||
public function requireActor() {
|
||||
$actor = $this->getActor();
|
||||
if (!$actor) {
|
||||
throw new Exception('You must "setActor()" first!');
|
||||
}
|
||||
return $actor;
|
||||
}
|
||||
|
||||
public function setSourceObject(NuanceSource $source) {
|
||||
$source->setType($this->getSourceTypeConstant());
|
||||
$this->sourceObject = $source;
|
||||
return $this;
|
||||
}
|
||||
public function getSourceObject() {
|
||||
return $this->sourceObject;
|
||||
}
|
||||
public function requireSourceObject() {
|
||||
$source = $this->getSourceObject();
|
||||
if (!$source) {
|
||||
throw new Exception('You must "setSourceObject()" first!');
|
||||
}
|
||||
return $source;
|
||||
}
|
||||
|
||||
public static function getSelectOptions() {
|
||||
$definitions = self::getAllDefinitions();
|
||||
|
||||
$options = array();
|
||||
foreach ($definitions as $definition) {
|
||||
$key = $definition->getSourceTypeConstant();
|
||||
$name = $definition->getName();
|
||||
$options[$key] = $name;
|
||||
}
|
||||
|
||||
return $options;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gives a @{class:NuanceSourceDefinition} object for a given
|
||||
* @{class:NuanceSource}. Note you still need to @{method:setActor}
|
||||
* before the @{class:NuanceSourceDefinition} object will be useful.
|
||||
*/
|
||||
public static function getDefinitionForSource(NuanceSource $source) {
|
||||
$definitions = self::getAllDefinitions();
|
||||
$map = mpull($definitions, null, 'getSourceTypeConstant');
|
||||
$definition = $map[$source->getType()];
|
||||
$definition->setSourceObject($source);
|
||||
|
||||
return $definition;
|
||||
}
|
||||
|
||||
public static function getAllDefinitions() {
|
||||
static $definitions;
|
||||
|
||||
if ($definitions === null) {
|
||||
$objects = id(new PhutilSymbolLoader())
|
||||
->setAncestorClass(__CLASS__)
|
||||
->loadObjects();
|
||||
foreach ($objects as $definition) {
|
||||
$key = $definition->getSourceTypeConstant();
|
||||
$name = $definition->getName();
|
||||
if (isset($definitions[$key])) {
|
||||
$conflict = $definitions[$key];
|
||||
throw new Exception(sprintf(
|
||||
'Defintion %s conflicts with definition %s. This is a programming '.
|
||||
'error.',
|
||||
$conflict,
|
||||
$name));
|
||||
}
|
||||
}
|
||||
$definitions = $objects;
|
||||
}
|
||||
return $definitions;
|
||||
}
|
||||
|
||||
/**
|
||||
* A human readable string like "Twitter" or "Phabricator Form".
|
||||
*/
|
||||
abstract public function getName();
|
||||
|
||||
/**
|
||||
* This should be a any VARCHAR(32).
|
||||
*
|
||||
* @{method:getAllDefinitions} will throw if you choose a string that
|
||||
* collides with another @{class:NuanceSourceDefinition} class.
|
||||
*/
|
||||
abstract public function getSourceTypeConstant();
|
||||
|
||||
/**
|
||||
* Code to create and update @{class:NuanceItem}s and
|
||||
* @{class:NuanceRequestor}s via daemons goes here.
|
||||
*
|
||||
* If that does not make sense for the @{class:NuanceSource} you are
|
||||
* defining, simply return null. For example,
|
||||
* @{class:NuancePhabricatorFormSourceDefinition} since these are one-way
|
||||
* contact forms.
|
||||
*/
|
||||
abstract public function updateItems();
|
||||
|
||||
private function loadSourceObjectPolicies(
|
||||
PhabricatorUser $user,
|
||||
NuanceSource $source) {
|
||||
|
||||
$user = $this->requireActor();
|
||||
$source = $this->requireSourceObject();
|
||||
return id(new PhabricatorPolicyQuery())
|
||||
->setViewer($user)
|
||||
->setObject($source)
|
||||
->execute();
|
||||
}
|
||||
|
||||
final public function getEditTitle() {
|
||||
$source = $this->requireSourceObject();
|
||||
if ($source->getPHID()) {
|
||||
$title = pht('Edit "%s" source.', $source->getName());
|
||||
} else {
|
||||
$title = pht('Create a new "%s" source.', $this->getName());
|
||||
}
|
||||
|
||||
return $title;
|
||||
}
|
||||
|
||||
final public function buildEditLayout(AphrontRequest $request) {
|
||||
$actor = $this->requireActor();
|
||||
$source = $this->requireSourceObject();
|
||||
|
||||
$form_errors = array();
|
||||
$error_messages = array();
|
||||
$transactions = array();
|
||||
$validation_exception = null;
|
||||
if ($request->isFormPost()) {
|
||||
$transactions = $this->buildTransactions($request);
|
||||
try {
|
||||
$editor = id(new NuanceSourceEditor())
|
||||
->setActor($actor)
|
||||
->setContentSourceFromRequest($request)
|
||||
->setContinueOnNoEffect(true)
|
||||
->applyTransactions($source, $transactions);
|
||||
|
||||
return id(new AphrontRedirectResponse())
|
||||
->setURI($source->getURI());
|
||||
|
||||
} catch (PhabricatorApplicationTransactionValidationException $ex) {
|
||||
$validation_exception = $ex;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
$form = $this->renderEditForm($validation_exception);
|
||||
$layout = id(new PHUIObjectBoxView())
|
||||
->setHeaderText($this->getEditTitle())
|
||||
->setValidationException($validation_exception)
|
||||
->setForm($form);
|
||||
if ($error_messages) {
|
||||
$layout->setFormError($this->renderEditErrorView($error_messages));
|
||||
}
|
||||
|
||||
return $layout;
|
||||
}
|
||||
|
||||
/**
|
||||
* Code to create a form to edit the @{class:NuanceItem} you are defining.
|
||||
*
|
||||
* return @{class:AphrontFormView}
|
||||
*/
|
||||
private function renderEditForm(
|
||||
PhabricatorApplicationTransactionValidationException $ex = null) {
|
||||
$user = $this->requireActor();
|
||||
$source = $this->requireSourceObject();
|
||||
$policies = $this->loadSourceObjectPolicies($user, $source);
|
||||
$e_name = null;
|
||||
if ($ex) {
|
||||
$e_name = $ex->getShortMessage(NuanceSourceTransaction::TYPE_NAME);
|
||||
}
|
||||
|
||||
$form = id(new AphrontFormView())
|
||||
->setUser($user)
|
||||
->appendChild(
|
||||
id(new AphrontFormTextControl())
|
||||
->setLabel(pht('Name'))
|
||||
->setName('name')
|
||||
->setError($e_name)
|
||||
->setValue($source->getName()))
|
||||
->appendChild(
|
||||
id(new AphrontFormSelectControl())
|
||||
->setLabel(pht('Type'))
|
||||
->setName('type')
|
||||
->setOptions(self::getSelectOptions())
|
||||
->setValue($source->getType()));
|
||||
|
||||
$form = $this->augmentEditForm($form, $ex);
|
||||
|
||||
$form
|
||||
->appendChild(
|
||||
id(new AphrontFormPolicyControl())
|
||||
->setUser($user)
|
||||
->setCapability(PhabricatorPolicyCapability::CAN_VIEW)
|
||||
->setPolicyObject($source)
|
||||
->setPolicies($policies)
|
||||
->setName('viewPolicy'))
|
||||
->appendChild(
|
||||
id(new AphrontFormPolicyControl())
|
||||
->setUser($user)
|
||||
->setCapability(PhabricatorPolicyCapability::CAN_EDIT)
|
||||
->setPolicyObject($source)
|
||||
->setPolicies($policies)
|
||||
->setName('editPolicy'))
|
||||
->appendChild(
|
||||
id(new AphrontFormSubmitControl())
|
||||
->addCancelButton($source->getURI())
|
||||
->setValue(pht('Save')));
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* return @{class:AphrontFormView}
|
||||
*/
|
||||
protected function augmentEditForm(
|
||||
AphrontFormView $form,
|
||||
PhabricatorApplicationTransactionValidationException $ex = null) {
|
||||
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* return @{class:AphrontErrorView}
|
||||
*/
|
||||
public function renderEditErrorView(array $errors) {
|
||||
return id(new AphrontErrorView())
|
||||
->setTitle(pht('Error with submission.'))
|
||||
->setErrors($errors);
|
||||
}
|
||||
|
||||
/**
|
||||
* Hook to build up @{class:PhabricatorTransactions}.
|
||||
*
|
||||
* return array $transactions
|
||||
*/
|
||||
protected function buildTransactions(AphrontRequest $request) {
|
||||
$transactions = array();
|
||||
|
||||
$transactions[] = id(new NuanceSourceTransaction())
|
||||
->setTransactionType(PhabricatorTransactions::TYPE_EDIT_POLICY)
|
||||
->setNewValue($request->getStr('editPolicy'));
|
||||
$transactions[] = id(new NuanceSourceTransaction())
|
||||
->setTransactionType(PhabricatorTransactions::TYPE_VIEW_POLICY)
|
||||
->setNewValue($request->getStr('viewPolicy'));
|
||||
$transactions[] = id(new NuanceSourceTransaction())
|
||||
->setTransactionType(NuanceSourceTransaction::TYPE_NAME)
|
||||
->setNewvalue($request->getStr('name'));
|
||||
|
||||
return $transactions;
|
||||
}
|
||||
|
||||
abstract public function renderView();
|
||||
|
||||
abstract public function renderListView();
|
||||
}
|
||||
|
|
@ -47,9 +47,14 @@ final class NuanceSource
|
|||
$edit_policy = $app->getPolicy(
|
||||
NuanceCapabilitySourceDefaultEdit::CAPABILITY);
|
||||
|
||||
$definitions = NuanceSourceDefinition::getAllDefinitions();
|
||||
$lucky_definition = head($definitions);
|
||||
|
||||
return id(new NuanceSource())
|
||||
->setViewPolicy($view_policy)
|
||||
->setEditPolicy($edit_policy);
|
||||
->setEditPolicy($edit_policy)
|
||||
->setType($lucky_definition->getSourceTypeConstant());
|
||||
|
||||
}
|
||||
|
||||
public function getCapabilities() {
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
final class NuanceSourceTransaction
|
||||
extends NuanceTransaction {
|
||||
|
||||
const TYPE_NAME = 'name-source';
|
||||
|
||||
public function getApplicationTransactionType() {
|
||||
return NuancePHIDTypeSource::TYPECONST;
|
||||
}
|
||||
|
@ -11,4 +13,27 @@ final class NuanceSourceTransaction
|
|||
return new NuanceSourceTransactionComment();
|
||||
}
|
||||
|
||||
public function getTitle() {
|
||||
$old = $this->getOldValue();
|
||||
$new = $this->getNewValue();
|
||||
$author_phid = $this->getAuthorPHID();
|
||||
|
||||
switch ($this->getTransactionType()) {
|
||||
case self::TYPE_NAME:
|
||||
if ($old === null) {
|
||||
return pht(
|
||||
'%s created this source.',
|
||||
$this->renderHandleLink($author_phid));
|
||||
} else {
|
||||
return pht(
|
||||
'%s renamed this source from "%s" to "%s".',
|
||||
$this->renderHandleLink($author_phid),
|
||||
$old,
|
||||
$new);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1768,6 +1768,10 @@ final class PhabricatorBuiltinPatchList extends PhabricatorSQLPatchList {
|
|||
'type' => 'sql',
|
||||
'name' => $this->getPatchPath('20131119.passphrase.sql'),
|
||||
),
|
||||
'20131120.nuancesourcetype.sql' => array(
|
||||
'type' => 'sql',
|
||||
'name' => $this->getPatchPath('20131120.nuancesourcetype.sql'),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue