From 7b718bb033a3556f547e591817f2eff4528f14cc Mon Sep 17 00:00:00 2001 From: Bob Trahan Date: Wed, 20 Nov 2013 13:41:19 -0800 Subject: [PATCH] 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 --- .../sql/patches/20131120.nuancesourcetype.sql | 11 + src/__phutil_library_map__.php | 6 +- .../PhabricatorApplicationNuance.php | 4 + .../nuance/constants/NuanceSourceType.php | 22 -- .../controller/NuanceSourceEditController.php | 59 +--- .../controller/NuanceSourceViewController.php | 104 ++++++- .../nuance/editor/NuanceSourceEditor.php | 78 +++++ .../nuance/query/NuanceSourceQuery.php | 2 +- .../NuancePhabricatorFormSourceDefinition.php | 43 +++ .../nuance/source/NuanceSourceDefinition.php | 274 ++++++++++++++++++ .../nuance/storage/NuanceSource.php | 7 +- .../storage/NuanceSourceTransaction.php | 25 ++ .../patch/PhabricatorBuiltinPatchList.php | 4 + 13 files changed, 557 insertions(+), 82 deletions(-) create mode 100644 resources/sql/patches/20131120.nuancesourcetype.sql delete mode 100644 src/applications/nuance/constants/NuanceSourceType.php create mode 100644 src/applications/nuance/source/NuancePhabricatorFormSourceDefinition.php create mode 100644 src/applications/nuance/source/NuanceSourceDefinition.php diff --git a/resources/sql/patches/20131120.nuancesourcetype.sql b/resources/sql/patches/20131120.nuancesourcetype.sql new file mode 100644 index 0000000000..14133e605e --- /dev/null +++ b/resources/sql/patches/20131120.nuancesourcetype.sql @@ -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); diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index fcb1ae4d1a..b73bc4e28e 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -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', diff --git a/src/applications/nuance/application/PhabricatorApplicationNuance.php b/src/applications/nuance/application/PhabricatorApplicationNuance.php index c085e69a0e..b2d123ee2e 100644 --- a/src/applications/nuance/application/PhabricatorApplicationNuance.php +++ b/src/applications/nuance/application/PhabricatorApplicationNuance.php @@ -23,6 +23,10 @@ final class PhabricatorApplicationNuance extends PhabricatorApplication { return true; } + public function getBaseURI() { + return '/nuance/'; + } + public function getRoutes() { return array( '/nuance/' => array( diff --git a/src/applications/nuance/constants/NuanceSourceType.php b/src/applications/nuance/constants/NuanceSourceType.php deleted file mode 100644 index 9bc341ae1f..0000000000 --- a/src/applications/nuance/constants/NuanceSourceType.php +++ /dev/null @@ -1,22 +0,0 @@ - pht('Phabricator Form'), - ); - } - -} diff --git a/src/applications/nuance/controller/NuanceSourceEditController.php b/src/applications/nuance/controller/NuanceSourceEditController.php index b71ace7d73..b0c73c77b9 100644 --- a/src/applications/nuance/controller/NuanceSourceEditController.php +++ b/src/applications/nuance/controller/NuanceSourceEditController.php @@ -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)); } } diff --git a/src/applications/nuance/controller/NuanceSourceViewController.php b/src/applications/nuance/controller/NuanceSourceViewController.php index 254ca59f1e..2f2c4037d7 100644 --- a/src/applications/nuance/controller/NuanceSourceViewController.php +++ b/src/applications/nuance/controller/NuanceSourceViewController.php @@ -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; } } diff --git a/src/applications/nuance/editor/NuanceSourceEditor.php b/src/applications/nuance/editor/NuanceSourceEditor.php index b470265974..0d17ba00f3 100644 --- a/src/applications/nuance/editor/NuanceSourceEditor.php +++ b/src/applications/nuance/editor/NuanceSourceEditor.php @@ -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; + } + } diff --git a/src/applications/nuance/query/NuanceSourceQuery.php b/src/applications/nuance/query/NuanceSourceQuery.php index a8d71ff35a..d56dbe0eda 100644 --- a/src/applications/nuance/query/NuanceSourceQuery.php +++ b/src/applications/nuance/query/NuanceSourceQuery.php @@ -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), diff --git a/src/applications/nuance/source/NuancePhabricatorFormSourceDefinition.php b/src/applications/nuance/source/NuancePhabricatorFormSourceDefinition.php new file mode 100644 index 0000000000..aa1befd917 --- /dev/null +++ b/src/applications/nuance/source/NuancePhabricatorFormSourceDefinition.php @@ -0,0 +1,43 @@ +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(); +} + diff --git a/src/applications/nuance/storage/NuanceSource.php b/src/applications/nuance/storage/NuanceSource.php index 7d371ef8e7..e7984b6397 100644 --- a/src/applications/nuance/storage/NuanceSource.php +++ b/src/applications/nuance/storage/NuanceSource.php @@ -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() { diff --git a/src/applications/nuance/storage/NuanceSourceTransaction.php b/src/applications/nuance/storage/NuanceSourceTransaction.php index 1c06508b40..ba7d8e8f03 100644 --- a/src/applications/nuance/storage/NuanceSourceTransaction.php +++ b/src/applications/nuance/storage/NuanceSourceTransaction.php @@ -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; + } + + } + } diff --git a/src/infrastructure/storage/patch/PhabricatorBuiltinPatchList.php b/src/infrastructure/storage/patch/PhabricatorBuiltinPatchList.php index 2506aea071..a8cdf2bc53 100644 --- a/src/infrastructure/storage/patch/PhabricatorBuiltinPatchList.php +++ b/src/infrastructure/storage/patch/PhabricatorBuiltinPatchList.php @@ -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'), + ), ); } }