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 @@ -1141,6 +1141,7 @@ 'FundInitiativeCommentController' => 'applications/fund/controller/FundInitiativeCommentController.php', 'FundInitiativeDescriptionTransaction' => 'applications/fund/xaction/FundInitiativeDescriptionTransaction.php', 'FundInitiativeEditController' => 'applications/fund/controller/FundInitiativeEditController.php', + 'FundInitiativeEditEngine' => 'applications/fund/editor/FundInitiativeEditEngine.php', 'FundInitiativeEditor' => 'applications/fund/editor/FundInitiativeEditor.php', 'FundInitiativeFulltextEngine' => 'applications/fund/search/FundInitiativeFulltextEngine.php', 'FundInitiativeListController' => 'applications/fund/controller/FundInitiativeListController.php', @@ -6105,6 +6106,7 @@ 'FundInitiativeCommentController' => 'FundController', 'FundInitiativeDescriptionTransaction' => 'FundInitiativeTransactionType', 'FundInitiativeEditController' => 'FundController', + 'FundInitiativeEditEngine' => 'PhabricatorEditEngine', 'FundInitiativeEditor' => 'PhabricatorApplicationTransactionEditor', 'FundInitiativeFulltextEngine' => 'PhabricatorFulltextEngine', 'FundInitiativeListController' => 'FundController', diff --git a/src/applications/fund/application/PhabricatorFundApplication.php b/src/applications/fund/application/PhabricatorFundApplication.php --- a/src/applications/fund/application/PhabricatorFundApplication.php +++ b/src/applications/fund/application/PhabricatorFundApplication.php @@ -43,7 +43,8 @@ '(?:query/(?P[^/]+)/)?' => 'FundInitiativeListController', 'create/' => 'FundInitiativeEditController', 'comment/(?P[1-9]\d*)/' => 'FundInitiativeCommentController', - 'edit/(?:(?P\d+)/)?' => 'FundInitiativeEditController', + $this->getEditRoutePattern('edit/') + => 'FundInitiativeEditController', 'close/(?P\d+)/' => 'FundInitiativeCloseController', 'back/(?P\d+)/' => 'FundInitiativeBackController', 'backers/(?:(?P\d+)/)?(?:query/(?P[^/]+)/)?' diff --git a/src/applications/fund/controller/FundInitiativeEditController.php b/src/applications/fund/controller/FundInitiativeEditController.php --- a/src/applications/fund/controller/FundInitiativeEditController.php +++ b/src/applications/fund/controller/FundInitiativeEditController.php @@ -1,256 +1,11 @@ getViewer(); - $id = $request->getURIData('id'); - - if ($id) { - $initiative = id(new FundInitiativeQuery()) - ->setViewer($viewer) - ->withIDs(array($id)) - ->requireCapabilities( - array( - PhabricatorPolicyCapability::CAN_VIEW, - PhabricatorPolicyCapability::CAN_EDIT, - )) - ->executeOne(); - if (!$initiative) { - return new Aphront404Response(); - } - $is_new = false; - } else { - $initiative = FundInitiative::initializeNewInitiative($viewer); - $is_new = true; - } - - if ($is_new) { - $title = pht('Create Initiative'); - $button_text = pht('Create Initiative'); - $cancel_uri = $this->getApplicationURI(); - $header_icon = 'fa-plus-square'; - } else { - $title = pht( - 'Edit Initiative: %s', - $initiative->getName()); - $button_text = pht('Save Changes'); - $cancel_uri = '/'.$initiative->getMonogram(); - $header_icon = 'fa-pencil'; - } - - $e_name = true; - $v_name = $initiative->getName(); - - $e_merchant = null; - $v_merchant = $initiative->getMerchantPHID(); - - $v_desc = $initiative->getDescription(); - $v_risk = $initiative->getRisks(); - - if ($is_new) { - $v_projects = array(); - } else { - $v_projects = PhabricatorEdgeQuery::loadDestinationPHIDs( - $initiative->getPHID(), - PhabricatorProjectObjectHasProjectEdgeType::EDGECONST); - $v_projects = array_reverse($v_projects); - } - - $validation_exception = null; - if ($request->isFormPost()) { - $v_name = $request->getStr('name'); - $v_desc = $request->getStr('description'); - $v_risk = $request->getStr('risks'); - $v_view = $request->getStr('viewPolicy'); - $v_edit = $request->getStr('editPolicy'); - $v_merchant = $request->getStr('merchantPHID'); - $v_projects = $request->getArr('projects'); - - $type_name = FundInitiativeNameTransaction::TRANSACTIONTYPE; - $type_desc = FundInitiativeDescriptionTransaction::TRANSACTIONTYPE; - $type_risk = FundInitiativeRisksTransaction::TRANSACTIONTYPE; - $type_merchant = FundInitiativeMerchantTransaction::TRANSACTIONTYPE; - $type_view = PhabricatorTransactions::TYPE_VIEW_POLICY; - $type_edit = PhabricatorTransactions::TYPE_EDIT_POLICY; - - $xactions = array(); - - $xactions[] = id(new FundInitiativeTransaction()) - ->setTransactionType($type_name) - ->setNewValue($v_name); - - $xactions[] = id(new FundInitiativeTransaction()) - ->setTransactionType($type_desc) - ->setNewValue($v_desc); - - $xactions[] = id(new FundInitiativeTransaction()) - ->setTransactionType($type_risk) - ->setNewValue($v_risk); - - $xactions[] = id(new FundInitiativeTransaction()) - ->setTransactionType($type_merchant) - ->setNewValue($v_merchant); - - $xactions[] = id(new FundInitiativeTransaction()) - ->setTransactionType($type_view) - ->setNewValue($v_view); - - $xactions[] = id(new FundInitiativeTransaction()) - ->setTransactionType($type_edit) - ->setNewValue($v_edit); - - $proj_edge_type = PhabricatorProjectObjectHasProjectEdgeType::EDGECONST; - $xactions[] = id(new FundInitiativeTransaction()) - ->setTransactionType(PhabricatorTransactions::TYPE_EDGE) - ->setMetadataValue('edge:type', $proj_edge_type) - ->setNewValue(array('=' => array_fuse($v_projects))); - - $editor = id(new FundInitiativeEditor()) - ->setActor($viewer) - ->setContentSourceFromRequest($request) - ->setContinueOnNoEffect(true); - - try { - $editor->applyTransactions($initiative, $xactions); - - return id(new AphrontRedirectResponse()) - ->setURI('/'.$initiative->getMonogram()); - } catch (PhabricatorApplicationTransactionValidationException $ex) { - $validation_exception = $ex; - - $e_name = $ex->getShortMessage($type_name); - $e_merchant = $ex->getShortMessage($type_merchant); - - $initiative->setViewPolicy($v_view); - $initiative->setEditPolicy($v_edit); - } - } - - $policies = id(new PhabricatorPolicyQuery()) - ->setViewer($viewer) - ->setObject($initiative) - ->execute(); - - $merchants = id(new PhortuneMerchantQuery()) - ->setViewer($viewer) - ->requireCapabilities( - array( - PhabricatorPolicyCapability::CAN_VIEW, - PhabricatorPolicyCapability::CAN_EDIT, - )) - ->execute(); - - $merchant_options = array(); - foreach ($merchants as $merchant) { - $merchant_options[$merchant->getPHID()] = pht( - 'Merchant %d %s', - $merchant->getID(), - $merchant->getName()); - } - - if ($v_merchant && empty($merchant_options[$v_merchant])) { - $merchant_options = array( - $v_merchant => pht('(Restricted Merchant)'), - ) + $merchant_options; - } - - if (!$merchant_options) { - return $this->newDialog() - ->setTitle(pht('No Valid Phortune Merchant Accounts')) - ->appendParagraph( - pht( - 'You do not control any merchant accounts which can receive '. - 'payments from this initiative. When you create an initiative, '. - 'you need to specify a merchant account where funds will be paid '. - 'to.')) - ->appendParagraph( - pht( - 'Create a merchant account in the Phortune application before '. - 'creating an initiative in Fund.')) - ->addCancelButton($this->getApplicationURI()); - } - - $form = id(new AphrontFormView()) - ->setUser($viewer) - ->appendChild( - id(new AphrontFormTextControl()) - ->setName('name') - ->setLabel(pht('Name')) - ->setValue($v_name) - ->setError($e_name)) - ->appendChild( - id(new AphrontFormSelectControl()) - ->setName('merchantPHID') - ->setLabel(pht('Pay To Merchant')) - ->setValue($v_merchant) - ->setError($e_merchant) - ->setOptions($merchant_options)) - ->appendChild( - id(new PhabricatorRemarkupControl()) - ->setUser($viewer) - ->setName('description') - ->setLabel(pht('Description')) - ->setValue($v_desc)) - ->appendChild( - id(new PhabricatorRemarkupControl()) - ->setUser($viewer) - ->setName('risks') - ->setLabel(pht('Risks/Challenges')) - ->setValue($v_risk)) - ->appendControl( - id(new AphrontFormTokenizerControl()) - ->setLabel(pht('Tags')) - ->setName('projects') - ->setValue($v_projects) - ->setDatasource(new PhabricatorProjectDatasource())) - ->appendChild( - id(new AphrontFormPolicyControl()) - ->setName('viewPolicy') - ->setPolicyObject($initiative) - ->setCapability(PhabricatorPolicyCapability::CAN_VIEW) - ->setPolicies($policies)) - ->appendChild( - id(new AphrontFormPolicyControl()) - ->setName('editPolicy') - ->setPolicyObject($initiative) - ->setCapability(PhabricatorPolicyCapability::CAN_EDIT) - ->setPolicies($policies)) - ->appendChild( - id(new AphrontFormSubmitControl()) - ->setValue($button_text) - ->addCancelButton($cancel_uri)); - - $crumbs = $this->buildApplicationCrumbs(); - if ($is_new) { - $crumbs->addTextCrumb(pht('Create Initiative')); - } else { - $crumbs->addTextCrumb( - $initiative->getMonogram(), - '/'.$initiative->getMonogram()); - $crumbs->addTextCrumb(pht('Edit')); - } - $crumbs->setBorder(true); - - $box = id(new PHUIObjectBoxView()) - ->setValidationException($validation_exception) - ->setHeaderText(pht('Initiative')) - ->setBackground(PHUIObjectBoxView::BLUE_PROPERTY) - ->appendChild($form); - - $header = id(new PHUIHeaderView()) - ->setHeader($title) - ->setHeaderIcon($header_icon); - - $view = id(new PHUITwoColumnView()) - ->setHeader($header) - ->setFooter($box); - - return $this->newPage() - ->setTitle($title) - ->setCrumbs($crumbs) - ->appendChild($view); + return id(new FundInitiativeEditEngine()) + ->setController($this) + ->buildResponse(); } } diff --git a/src/applications/fund/editor/FundInitiativeEditEngine.php b/src/applications/fund/editor/FundInitiativeEditEngine.php new file mode 100644 --- /dev/null +++ b/src/applications/fund/editor/FundInitiativeEditEngine.php @@ -0,0 +1,152 @@ +getViewer()); + } + + protected function newObjectQuery() { + return new FundInitiativeQuery(); + } + + protected function getObjectCreateTitleText($object) { + return pht('Create New Initiative'); + } + + protected function getObjectEditTitleText($object) { + return pht('Edit Initiative: %s', $object->getName()); + } + + protected function getObjectEditShortText($object) { + return $object->getName(); + } + + protected function getObjectCreateShortText() { + return pht('Create Initiative'); + } + + protected function getObjectName() { + return pht('Initivative'); + } + + protected function getObjectCreateCancelURI($object) { + return $this->getApplication()->getApplicationURI('/'); + } + + protected function getEditorURI() { + return $this->getApplication()->getApplicationURI('edit/'); + } + + protected function getObjectViewURI($object) { + return $object->getViewURI(); + } + + protected function getCreateNewObjectPolicy() { + return $this->getApplication()->getPolicy( + FundCreateInitiativesCapability::CAPABILITY); + } + + protected function buildCustomEditFields($object) { + $viewer = $this->getViewer(); + $v_merchant = $object->getMerchantPHID(); + + $merchants = id(new PhortuneMerchantQuery()) + ->setViewer($viewer) + ->requireCapabilities( + array( + PhabricatorPolicyCapability::CAN_VIEW, + PhabricatorPolicyCapability::CAN_EDIT, + )) + ->execute(); + + $merchant_options = array(); + foreach ($merchants as $merchant) { + $merchant_options[$merchant->getPHID()] = pht( + 'Merchant %d %s', + $merchant->getID(), + $merchant->getName()); + } + + if ($v_merchant && empty($merchant_options[$v_merchant])) { + $merchant_options = array( + $v_merchant => pht('(Restricted Merchant)'), + ) + $merchant_options; + } + + $merchant_instructions = null; + if (!$merchant_options) { + $merchant_instructions = pht( + 'NOTE: You do not control any merchant accounts which can receive '. + 'payments from this initiative. When you create an initiative, '. + 'you need to specify a merchant account where funds will be paid '. + 'to. Create a merchant account in the Phortune application before '. + 'creating an initiative in Fund.'); + } + + return array( + id(new PhabricatorTextEditField()) + ->setKey('name') + ->setLabel(pht('Name')) + ->setDescription(pht('Initiative name.')) + ->setConduitTypeDescription(pht('New initiative name.')) + ->setTransactionType( + FundInitiativeNameTransaction::TRANSACTIONTYPE) + ->setValue($object->getName()) + ->setIsRequired(true), + id(new PhabricatorSelectEditField()) + ->setKey('merchantPHID') + ->setLabel(pht('Merchant')) + ->setDescription(pht('Merchant operating the initiative.')) + ->setConduitTypeDescription(pht('New initiative merchant.')) + ->setControlInstructions($merchant_instructions) + ->setValue($object->getMerchantPHID()) + ->setTransactionType( + FundInitiativeMerchantTransaction::TRANSACTIONTYPE) + ->setOptions($merchant_options) + ->setIsRequired(true), + id(new PhabricatorRemarkupEditField()) + ->setKey('description') + ->setLabel(pht('Description')) + ->setDescription(pht('Initiative long description.')) + ->setConduitTypeDescription(pht('New initiative description.')) + ->setTransactionType( + FundInitiativeDescriptionTransaction::TRANSACTIONTYPE) + ->setValue($object->getDescription()), + id(new PhabricatorRemarkupEditField()) + ->setKey('risks') + ->setLabel(pht('Risks/Challenges')) + ->setDescription(pht('Initiative risks and challenges.')) + ->setConduitTypeDescription(pht('Initiative risks and challenges.')) + ->setTransactionType( + FundInitiativeRisksTransaction::TRANSACTIONTYPE) + ->setValue($object->getRisks()), + + ); + + } + +} diff --git a/src/applications/fund/storage/FundInitiative.php b/src/applications/fund/storage/FundInitiative.php --- a/src/applications/fund/storage/FundInitiative.php +++ b/src/applications/fund/storage/FundInitiative.php @@ -85,6 +85,10 @@ return 'I'.$this->getID(); } + public function getViewURI() { + return '/'.$this->getMonogram(); + } + public function getProjectPHIDs() { return $this->assertAttached($this->projectPHIDs); }