diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -4322,13 +4322,16 @@ 'PhortuneAccount' => 'applications/phortune/storage/PhortuneAccount.php', 'PhortuneAccountChargeListController' => 'applications/phortune/controller/account/PhortuneAccountChargeListController.php', 'PhortuneAccountEditController' => 'applications/phortune/controller/account/PhortuneAccountEditController.php', + 'PhortuneAccountEditEngine' => 'applications/phortune/editor/PhortuneAccountEditEngine.php', 'PhortuneAccountEditor' => 'applications/phortune/editor/PhortuneAccountEditor.php', 'PhortuneAccountHasMemberEdgeType' => 'applications/phortune/edge/PhortuneAccountHasMemberEdgeType.php', 'PhortuneAccountListController' => 'applications/phortune/controller/account/PhortuneAccountListController.php', + 'PhortuneAccountNameTransaction' => 'applications/phortune/xaction/PhortuneAccountNameTransaction.php', 'PhortuneAccountPHIDType' => 'applications/phortune/phid/PhortuneAccountPHIDType.php', 'PhortuneAccountQuery' => 'applications/phortune/query/PhortuneAccountQuery.php', 'PhortuneAccountTransaction' => 'applications/phortune/storage/PhortuneAccountTransaction.php', 'PhortuneAccountTransactionQuery' => 'applications/phortune/query/PhortuneAccountTransactionQuery.php', + 'PhortuneAccountTransactionType' => 'applications/phortune/xaction/PhortuneAccountTransactionType.php', 'PhortuneAccountViewController' => 'applications/phortune/controller/account/PhortuneAccountViewController.php', 'PhortuneAdHocCart' => 'applications/phortune/cart/PhortuneAdHocCart.php', 'PhortuneAdHocProduct' => 'applications/phortune/product/PhortuneAdHocProduct.php', @@ -9771,13 +9774,16 @@ ), 'PhortuneAccountChargeListController' => 'PhortuneController', 'PhortuneAccountEditController' => 'PhortuneController', + 'PhortuneAccountEditEngine' => 'PhabricatorEditEngine', 'PhortuneAccountEditor' => 'PhabricatorApplicationTransactionEditor', 'PhortuneAccountHasMemberEdgeType' => 'PhabricatorEdgeType', 'PhortuneAccountListController' => 'PhortuneController', + 'PhortuneAccountNameTransaction' => 'PhortuneAccountTransactionType', 'PhortuneAccountPHIDType' => 'PhabricatorPHIDType', 'PhortuneAccountQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', - 'PhortuneAccountTransaction' => 'PhabricatorApplicationTransaction', + 'PhortuneAccountTransaction' => 'PhabricatorModularTransaction', 'PhortuneAccountTransactionQuery' => 'PhabricatorApplicationTransactionQuery', + 'PhortuneAccountTransactionType' => 'PhabricatorModularTransactionType', 'PhortuneAccountViewController' => 'PhortuneController', 'PhortuneAdHocCart' => 'PhortuneCartImplementation', 'PhortuneAdHocProduct' => 'PhortuneProductImplementation', diff --git a/src/applications/phortune/application/PhabricatorPhortuneApplication.php b/src/applications/phortune/application/PhabricatorPhortuneApplication.php --- a/src/applications/phortune/application/PhabricatorPhortuneApplication.php +++ b/src/applications/phortune/application/PhabricatorPhortuneApplication.php @@ -67,7 +67,8 @@ ), 'account/' => array( '' => 'PhortuneAccountListController', - 'edit/(?:(?P\d+)/)?' => 'PhortuneAccountEditController', + $this->getEditRoutePattern('edit/') + => 'PhortuneAccountEditController', ), 'product/' => array( '' => 'PhortuneProductListController', diff --git a/src/applications/phortune/controller/account/PhortuneAccountEditController.php b/src/applications/phortune/controller/account/PhortuneAccountEditController.php --- a/src/applications/phortune/controller/account/PhortuneAccountEditController.php +++ b/src/applications/phortune/controller/account/PhortuneAccountEditController.php @@ -1,137 +1,11 @@ getViewer(); - $id = $request->getURIData('id'); - - if ($id) { - $account = id(new PhortuneAccountQuery()) - ->setViewer($viewer) - ->withIDs(array($id)) - ->requireCapabilities( - array( - PhabricatorPolicyCapability::CAN_VIEW, - PhabricatorPolicyCapability::CAN_EDIT, - )) - ->executeOne(); - if (!$account) { - return new Aphront404Response(); - } - $is_new = false; - } else { - $account = PhortuneAccount::initializeNewAccount($viewer); - $account->attachMemberPHIDs(array($viewer->getPHID())); - $is_new = true; - } - - $v_name = $account->getName(); - $e_name = true; - - $v_members = $account->getMemberPHIDs(); - $e_members = null; - - $validation_exception = null; - - if ($request->isFormPost()) { - $v_name = $request->getStr('name'); - $v_members = $request->getArr('memberPHIDs'); - - $type_name = PhortuneAccountTransaction::TYPE_NAME; - $type_edge = PhabricatorTransactions::TYPE_EDGE; - - $xactions = array(); - $xactions[] = id(new PhortuneAccountTransaction()) - ->setTransactionType($type_name) - ->setNewValue($v_name); - - $xactions[] = id(new PhortuneAccountTransaction()) - ->setTransactionType($type_edge) - ->setMetadataValue( - 'edge:type', - PhortuneAccountHasMemberEdgeType::EDGECONST) - ->setNewValue( - array( - '=' => array_fuse($v_members), - )); - - $editor = id(new PhortuneAccountEditor()) - ->setActor($viewer) - ->setContentSourceFromRequest($request) - ->setContinueOnNoEffect(true); - - try { - $editor->applyTransactions($account, $xactions); - - $account_uri = $this->getApplicationURI($account->getID().'/'); - return id(new AphrontRedirectResponse())->setURI($account_uri); - } catch (PhabricatorApplicationTransactionValidationException $ex) { - $validation_exception = $ex; - $e_name = $ex->getShortMessage($type_name); - $e_members = $ex->getShortMessage($type_edge); - } - } - - $crumbs = $this->buildApplicationCrumbs(); - $crumbs->setBorder(true); - - if ($is_new) { - $cancel_uri = $this->getApplicationURI('account/'); - $crumbs->addTextCrumb(pht('Accounts'), $cancel_uri); - $crumbs->addTextCrumb(pht('Create Account')); - - $title = pht('Create Payment Account'); - $submit_button = pht('Create Account'); - } else { - $cancel_uri = $this->getApplicationURI($account->getID().'/'); - $crumbs->addTextCrumb($account->getName(), $cancel_uri); - $crumbs->addTextCrumb(pht('Edit')); - - $title = pht('Edit %s', $account->getName()); - $submit_button = pht('Save Changes'); - } - - $form = id(new AphrontFormView()) - ->setUser($viewer) - ->appendChild( - id(new AphrontFormTextControl()) - ->setName('name') - ->setLabel(pht('Name')) - ->setValue($v_name) - ->setError($e_name)) - ->appendControl( - id(new AphrontFormTokenizerControl()) - ->setDatasource(new PhabricatorPeopleDatasource()) - ->setLabel(pht('Members')) - ->setName('memberPHIDs') - ->setValue($v_members) - ->setError($e_members)) - ->appendChild( - id(new AphrontFormSubmitControl()) - ->setValue($submit_button) - ->addCancelButton($cancel_uri)); - - $box = id(new PHUIObjectBoxView()) - ->setHeaderText(pht('Account')) - ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY) - ->setValidationException($validation_exception) - ->setForm($form); - - $header = id(new PHUIHeaderView()) - ->setHeader($title) - ->setHeaderIcon('fa-pencil'); - - $view = id(new PHUITwoColumnView()) - ->setHeader($header) - ->setFooter(array( - $box, - )); - - return $this->newPage() - ->setTitle($title) - ->setCrumbs($crumbs) - ->appendChild($view); + return id(new PhortuneAccountEditEngine()) + ->setController($this) + ->buildResponse(); } - } diff --git a/src/applications/phortune/controller/account/PhortuneAccountViewController.php b/src/applications/phortune/controller/account/PhortuneAccountViewController.php --- a/src/applications/phortune/controller/account/PhortuneAccountViewController.php +++ b/src/applications/phortune/controller/account/PhortuneAccountViewController.php @@ -129,7 +129,7 @@ ->appendChild($status_view); $curtain->newPanel() - ->setHeaderText(pht('Members')) + ->setHeaderText(pht('Managers')) ->appendChild($member_list); return $curtain; diff --git a/src/applications/phortune/controller/merchant/PhortuneMerchantPictureController.php b/src/applications/phortune/controller/merchant/PhortuneMerchantPictureController.php --- a/src/applications/phortune/controller/merchant/PhortuneMerchantPictureController.php +++ b/src/applications/phortune/controller/merchant/PhortuneMerchantPictureController.php @@ -21,7 +21,7 @@ return new Aphront404Response(); } - $uri = $merchant->getViewURI(); + $uri = $merchant->getURI(); $supported_formats = PhabricatorFile::getTransformableImageFormats(); $e_file = true; diff --git a/src/applications/phortune/edge/PhortuneAccountHasMemberEdgeType.php b/src/applications/phortune/edge/PhortuneAccountHasMemberEdgeType.php --- a/src/applications/phortune/edge/PhortuneAccountHasMemberEdgeType.php +++ b/src/applications/phortune/edge/PhortuneAccountHasMemberEdgeType.php @@ -14,7 +14,7 @@ $add_edges) { return pht( - '%s added %s account member(s): %s.', + '%s added %s account manager(s): %s.', $actor, $add_count, $add_edges); @@ -26,7 +26,7 @@ $rem_edges) { return pht( - '%s removed %s account member(s): %s.', + '%s removed %s account manager(s): %s.', $actor, $rem_count, $rem_edges); @@ -41,7 +41,7 @@ $rem_edges) { return pht( - '%s edited %s account member(s), added %s: %s; removed %s: %s.', + '%s edited %s account manager(s), added %s: %s; removed %s: %s.', $actor, $total_count, $add_count, @@ -57,7 +57,7 @@ $add_edges) { return pht( - '%s added %s account member(s) to %s: %s.', + '%s added %s account manager(s) to %s: %s.', $actor, $add_count, $object, @@ -71,7 +71,7 @@ $rem_edges) { return pht( - '%s removed %s account member(s) from %s: %s.', + '%s removed %s account manager(s) from %s: %s.', $actor, $rem_count, $object, @@ -88,7 +88,7 @@ $rem_edges) { return pht( - '%s edited %s account member(s) for %s, added %s: %s; removed %s: %s.', + '%s edited %s account manager(s) for %s, added %s: %s; removed %s: %s.', $actor, $total_count, $object, diff --git a/src/applications/phortune/editor/PhortuneAccountEditEngine.php b/src/applications/phortune/editor/PhortuneAccountEditEngine.php new file mode 100644 --- /dev/null +++ b/src/applications/phortune/editor/PhortuneAccountEditEngine.php @@ -0,0 +1,108 @@ +getViewer()); + } + + protected function newObjectQuery() { + return new PhortuneAccountQuery(); + } + + protected function getObjectCreateTitleText($object) { + return pht('Create Payment Account'); + } + + protected function getObjectEditTitleText($object) { + return pht('Edit Account: %s', $object->getName()); + } + + protected function getObjectEditShortText($object) { + return $object->getName(); + } + + protected function getObjectCreateShortText() { + return pht('Create Account'); + } + + protected function getObjectName() { + return pht('Account'); + } + + protected function getObjectCreateCancelURI($object) { + return $this->getApplication()->getApplicationURI('/'); + } + + protected function getEditorURI() { + return $this->getApplication()->getApplicationURI('edit/'); + } + + protected function getObjectViewURI($object) { + return $object->getURI(); + } + + protected function buildCustomEditFields($object) { + $viewer = $this->getViewer(); + + if ($this->getIsCreate()) { + $member_phids = array($viewer->getPHID()); + } else { + $member_phids = $object->getMemberPHIDs(); + } + + $fields = array( + id(new PhabricatorTextEditField()) + ->setKey('name') + ->setLabel(pht('Name')) + ->setDescription(pht('Account name.')) + ->setConduitTypeDescription(pht('New account name.')) + ->setTransactionType( + PhortuneAccountNameTransaction::TRANSACTIONTYPE) + ->setValue($object->getName()) + ->setIsRequired(true), + + id(new PhabricatorUsersEditField()) + ->setKey('managers') + ->setAliases(array('memberPHIDs', 'managerPHIDs')) + ->setLabel(pht('Managers')) + ->setUseEdgeTransactions(true) + ->setTransactionType(PhabricatorTransactions::TYPE_EDGE) + ->setMetadataValue( + 'edge:type', + PhortuneAccountHasMemberEdgeType::EDGECONST) + ->setDescription(pht('Initial account managers.')) + ->setConduitDescription(pht('Set account managers.')) + ->setConduitTypeDescription(pht('New list of managers.')) + ->setInitialValue($object->getMemberPHIDs()) + ->setValue($member_phids), + ); + + return $fields; + + } + +} diff --git a/src/applications/phortune/editor/PhortuneAccountEditor.php b/src/applications/phortune/editor/PhortuneAccountEditor.php --- a/src/applications/phortune/editor/PhortuneAccountEditor.php +++ b/src/applications/phortune/editor/PhortuneAccountEditor.php @@ -1,6 +1,5 @@ getTransactionType()) { - case PhortuneAccountTransaction::TYPE_NAME: - return $object->getName(); - } - return parent::getCustomTransactionOldValue($object, $xaction); - } - - protected function getCustomTransactionNewValue( - PhabricatorLiskDAO $object, - PhabricatorApplicationTransaction $xaction) { - switch ($xaction->getTransactionType()) { - case PhortuneAccountTransaction::TYPE_NAME: - return $xaction->getNewValue(); - } - return parent::getCustomTransactionNewValue($object, $xaction); - } - - protected function applyCustomInternalTransaction( - PhabricatorLiskDAO $object, - PhabricatorApplicationTransaction $xaction) { - switch ($xaction->getTransactionType()) { - case PhortuneAccountTransaction::TYPE_NAME: - $object->setName($xaction->getNewValue()); - return; - } - return parent::applyCustomInternalTransaction($object, $xaction); - } - - protected function applyCustomExternalTransaction( - PhabricatorLiskDAO $object, - PhabricatorApplicationTransaction $xaction) { - switch ($xaction->getTransactionType()) { - case PhortuneAccountTransaction::TYPE_NAME: - return; - } - return parent::applyCustomExternalTransaction($object, $xaction); - } - protected function validateTransaction( PhabricatorLiskDAO $object, $type, @@ -71,47 +29,53 @@ $errors = parent::validateTransaction($object, $type, $xactions); switch ($type) { - case PhortuneAccountTransaction::TYPE_NAME: - $missing = $this->validateIsEmptyTextField( - $object->getName(), - $xactions); - - if ($missing) { - $error = new PhabricatorApplicationTransactionValidationError( - $type, - pht('Required'), - pht('Account name is required.'), - nonempty(last($xactions), null)); - - $error->setIsMissingFieldError(true); - $errors[] = $error; - } - break; case PhabricatorTransactions::TYPE_EDGE: foreach ($xactions as $xaction) { switch ($xaction->getMetadataValue('edge:type')) { case PhortuneAccountHasMemberEdgeType::EDGECONST: - // TODO: This is a bit cumbersome, but validation happens before - // transaction normalization. Maybe provide a cleaner attack on - // this eventually? There's no way to generate "+" or "-" - // transactions right now. + $actor_phid = $this->requireActor()->getPHID(); $new = $xaction->getNewValue(); - $set = idx($new, '=', array()); + $old = $object->getMemberPHIDs(); + + // Check if user is trying to not set themselves on creation + if (!$old) { + $set = idx($new, '+', array()); + $actor_set = false; + foreach ($set as $phid) { + if ($actor_phid == $phid) { + $actor_set = true; + } + } + if (!$actor_set) { + $error = new PhabricatorApplicationTransactionValidationError( + $type, + pht('Invalid'), + pht('You can not remove yourself as an account manager.'), + $xaction); + $errors[] = $error; + + } + } - if (empty($set[$this->requireActor()->getPHID()])) { - $error = new PhabricatorApplicationTransactionValidationError( - $type, - pht('Invalid'), - pht('You can not remove yourself as an account member.'), - $xaction); - $errors[] = $error; + // Check if user is trying to remove themselves on edit + $set = idx($new, '-', array()); + foreach ($set as $phid) { + if ($actor_phid == $phid) { + $error = new PhabricatorApplicationTransactionValidationError( + $type, + pht('Invalid'), + pht('You can not remove yourself as an account manager.'), + $xaction); + $errors[] = $error; + + } } - break; + break; } } break; } - return $errors; } + } diff --git a/src/applications/phortune/editor/PhortuneMerchantEditEngine.php b/src/applications/phortune/editor/PhortuneMerchantEditEngine.php --- a/src/applications/phortune/editor/PhortuneMerchantEditEngine.php +++ b/src/applications/phortune/editor/PhortuneMerchantEditEngine.php @@ -58,7 +58,7 @@ } protected function getObjectViewURI($object) { - return $object->getViewURI(); + return $object->getURI(); } public function isEngineConfigurable() { diff --git a/src/applications/phortune/storage/PhortuneAccount.php b/src/applications/phortune/storage/PhortuneAccount.php --- a/src/applications/phortune/storage/PhortuneAccount.php +++ b/src/applications/phortune/storage/PhortuneAccount.php @@ -17,7 +17,6 @@ public static function initializeNewAccount(PhabricatorUser $actor) { $account = id(new PhortuneAccount()); - $account->memberPHIDs = array(); return $account; @@ -31,7 +30,7 @@ $xactions = array(); $xactions[] = id(new PhortuneAccountTransaction()) - ->setTransactionType(PhortuneAccountTransaction::TYPE_NAME) + ->setTransactionType(PhortuneAccountNameTransaction::TRANSACTIONTYPE) ->setNewValue(pht('Default Account')); $xactions[] = id(new PhortuneAccountTransaction()) @@ -96,6 +95,10 @@ return $this; } + public function getURI() { + return '/phortune/'.$this->getID().'/'; + } + /* -( PhabricatorApplicationTransactionInterface )------------------------- */ diff --git a/src/applications/phortune/storage/PhortuneAccountTransaction.php b/src/applications/phortune/storage/PhortuneAccountTransaction.php --- a/src/applications/phortune/storage/PhortuneAccountTransaction.php +++ b/src/applications/phortune/storage/PhortuneAccountTransaction.php @@ -1,9 +1,7 @@ getAuthorPHID(); - - $old = $this->getOldValue(); - $new = $this->getNewValue(); - - switch ($this->getTransactionType()) { - case self::TYPE_NAME: - if ($old === null) { - return pht( - '%s created this account.', - $this->renderHandleLink($author_phid)); - } else { - return pht( - '%s renamed this account from "%s" to "%s".', - $this->renderHandleLink($author_phid), - $old, - $new); - } - break; - } - - return parent::getTitle(); + public function getBaseTransactionClass() { + return 'PhortuneAccountTransactionType'; } } diff --git a/src/applications/phortune/storage/PhortuneMerchant.php b/src/applications/phortune/storage/PhortuneMerchant.php --- a/src/applications/phortune/storage/PhortuneMerchant.php +++ b/src/applications/phortune/storage/PhortuneMerchant.php @@ -53,7 +53,7 @@ return $this; } - public function getViewURI() { + public function getURI() { return '/phortune/merchant/'.$this->getID().'/'; } @@ -70,6 +70,7 @@ return $this->assertAttached($this->profileImageFile); } + /* -( PhabricatorApplicationTransactionInterface )------------------------- */ diff --git a/src/applications/phortune/xaction/PhortuneAccountNameTransaction.php b/src/applications/phortune/xaction/PhortuneAccountNameTransaction.php new file mode 100644 --- /dev/null +++ b/src/applications/phortune/xaction/PhortuneAccountNameTransaction.php @@ -0,0 +1,55 @@ +getName(); + } + + public function applyInternalEffects($object, $value) { + $object->setName($value); + } + + public function getTitle() { + $old = $this->getOldValue(); + $new = $this->getNewValue(); + + if (strlen($old) && strlen($new)) { + return pht( + '%s renamed this account from %s to %s.', + $this->renderAuthor(), + $this->renderOldValue(), + $this->renderNewValue()); + } else { + return pht( + '%s created this account.', + $this->renderAuthor()); + } + } + + public function validateTransactions($object, array $xactions) { + $errors = array(); + + if ($this->isEmptyTextTransaction($object->getName(), $xactions)) { + $errors[] = $this->newRequiredError( + pht('Accounts must have a name.')); + } + + $max_length = $object->getColumnMaximumByteLength('name'); + foreach ($xactions as $xaction) { + $new_value = $xaction->getNewValue(); + $new_length = strlen($new_value); + if ($new_length > $max_length) { + $errors[] = $this->newRequiredError( + pht('The name can be no longer than %s characters.', + new PhutilNumber($max_length))); + } + } + + return $errors; + } + +} diff --git a/src/applications/phortune/xaction/PhortuneAccountTransactionType.php b/src/applications/phortune/xaction/PhortuneAccountTransactionType.php new file mode 100644 --- /dev/null +++ b/src/applications/phortune/xaction/PhortuneAccountTransactionType.php @@ -0,0 +1,4 @@ + array( + array( + '%s added an account manager: %3$s.', + '%s added account managers: %3$s.', + ), + ), + + '%s removed %s account manager(s): %s.' => array( + array( + '%s removed an account manager: %3$s.', + '%s removed account managers: %3$s.', + ), + ), + ); }