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 @@ -106,6 +106,7 @@ 'AlmanacServiceController' => 'applications/almanac/controller/AlmanacServiceController.php', 'AlmanacServiceDatasource' => 'applications/almanac/typeahead/AlmanacServiceDatasource.php', 'AlmanacServiceEditController' => 'applications/almanac/controller/AlmanacServiceEditController.php', + 'AlmanacServiceEditEngine' => 'applications/almanac/editor/AlmanacServiceEditEngine.php', 'AlmanacServiceEditor' => 'applications/almanac/editor/AlmanacServiceEditor.php', 'AlmanacServiceListController' => 'applications/almanac/controller/AlmanacServiceListController.php', 'AlmanacServiceNameNgrams' => 'applications/almanac/storage/AlmanacServiceNameNgrams.php', @@ -4145,6 +4146,7 @@ 'AlmanacServiceController' => 'AlmanacController', 'AlmanacServiceDatasource' => 'PhabricatorTypeaheadDatasource', 'AlmanacServiceEditController' => 'AlmanacServiceController', + 'AlmanacServiceEditEngine' => 'PhabricatorEditEngine', 'AlmanacServiceEditor' => 'AlmanacEditor', 'AlmanacServiceListController' => 'AlmanacServiceController', 'AlmanacServiceNameNgrams' => 'PhabricatorSearchNgrams', diff --git a/src/applications/almanac/application/PhabricatorAlmanacApplication.php b/src/applications/almanac/application/PhabricatorAlmanacApplication.php --- a/src/applications/almanac/application/PhabricatorAlmanacApplication.php +++ b/src/applications/almanac/application/PhabricatorAlmanacApplication.php @@ -45,7 +45,7 @@ '' => 'AlmanacConsoleController', '(?Pservice)/' => array( $this->getQueryRoutePattern() => 'AlmanacServiceListController', - 'edit/(?:(?P\d+)/)?' => 'AlmanacServiceEditController', + $this->getEditRoutePattern('edit/') => 'AlmanacServiceEditController', 'view/(?P[^/]+)/' => 'AlmanacServiceViewController', ), '(?Pdevice)/' => array( diff --git a/src/applications/almanac/controller/AlmanacServiceController.php b/src/applications/almanac/controller/AlmanacServiceController.php --- a/src/applications/almanac/controller/AlmanacServiceController.php +++ b/src/applications/almanac/controller/AlmanacServiceController.php @@ -11,6 +11,11 @@ return $crumbs; } + public function buildApplicationMenu() { + return $this->newApplicationMenu() + ->setSearchEngine(new AlmanacServiceSearchEngine()); + } + protected function getPropertyDeleteURI($object) { $id = $object->getID(); return "/almanac/service/delete/{$id}/"; diff --git a/src/applications/almanac/controller/AlmanacServiceEditController.php b/src/applications/almanac/controller/AlmanacServiceEditController.php --- a/src/applications/almanac/controller/AlmanacServiceEditController.php +++ b/src/applications/almanac/controller/AlmanacServiceEditController.php @@ -4,175 +4,28 @@ extends AlmanacServiceController { public function handleRequest(AphrontRequest $request) { - $viewer = $request->getViewer(); - - $list_uri = $this->getApplicationURI('service/'); + $engine = id(new AlmanacServiceEditEngine()) + ->setController($this); $id = $request->getURIData('id'); - if ($id) { - $service = id(new AlmanacServiceQuery()) - ->setViewer($viewer) - ->withIDs(array($id)) - ->requireCapabilities( - array( - PhabricatorPolicyCapability::CAN_VIEW, - PhabricatorPolicyCapability::CAN_EDIT, - )) - ->executeOne(); - if (!$service) { - return new Aphront404Response(); - } - - $is_new = false; - $service_uri = $service->getURI(); - $cancel_uri = $service_uri; - $title = pht('Edit Service'); - $save_button = pht('Save Changes'); - } else { - $cancel_uri = $list_uri; - + if (!$id) { $this->requireApplicationCapability( AlmanacCreateServicesCapability::CAPABILITY); - $service_type = $request->getStr('serviceType'); - - try { - $service = AlmanacService::initializeNewService($service_type); - } catch (Exception $ex) { - return $this->buildServiceTypeResponse($cancel_uri); - } - - if ($service->isClusterService()) { - $this->requireApplicationCapability( - AlmanacManageClusterServicesCapability::CAPABILITY); - } - - $is_new = true; - - $title = pht('Create Service'); - $save_button = pht('Create Service'); - } - - $v_name = $service->getName(); - $e_name = true; - $validation_exception = null; - - if ($is_new) { - $v_projects = array(); - } else { - $v_projects = PhabricatorEdgeQuery::loadDestinationPHIDs( - $service->getPHID(), - PhabricatorProjectObjectHasProjectEdgeType::EDGECONST); - $v_projects = array_reverse($v_projects); - } - - if ($request->isFormPost() && $request->getStr('edit')) { - $v_name = $request->getStr('name'); - $v_view = $request->getStr('viewPolicy'); - $v_edit = $request->getStr('editPolicy'); - $v_projects = $request->getArr('projects'); - - $type_name = AlmanacServiceTransaction::TYPE_NAME; - $type_view = PhabricatorTransactions::TYPE_VIEW_POLICY; - $type_edit = PhabricatorTransactions::TYPE_EDIT_POLICY; - - $xactions = array(); - - $xactions[] = id(new AlmanacServiceTransaction()) - ->setTransactionType($type_name) - ->setNewValue($v_name); - - $xactions[] = id(new AlmanacServiceTransaction()) - ->setTransactionType($type_view) - ->setNewValue($v_view); - - $xactions[] = id(new AlmanacServiceTransaction()) - ->setTransactionType($type_edit) - ->setNewValue($v_edit); - - $proj_edge_type = PhabricatorProjectObjectHasProjectEdgeType::EDGECONST; - $xactions[] = id(new AlmanacServiceTransaction()) - ->setTransactionType(PhabricatorTransactions::TYPE_EDGE) - ->setMetadataValue('edge:type', $proj_edge_type) - ->setNewValue(array('=' => array_fuse($v_projects))); - - $editor = id(new AlmanacServiceEditor()) - ->setActor($viewer) - ->setContentSourceFromRequest($request) - ->setContinueOnNoEffect(true); - - try { - $editor->applyTransactions($service, $xactions); - - $service_uri = $service->getURI(); - return id(new AphrontRedirectResponse())->setURI($service_uri); - } catch (PhabricatorApplicationTransactionValidationException $ex) { - $validation_exception = $ex; - $e_name = $ex->getShortMessage($type_name); + $list_uri = $this->getApplicationURI('service/'); - $service->setViewPolicy($v_view); - $service->setEditPolicy($v_edit); + $service_type = $request->getStr('serviceType'); + $service_types = AlmanacServiceType::getAllServiceTypes(); + if (empty($service_types[$service_type])) { + return $this->buildServiceTypeResponse($list_uri); } - } - - $policies = id(new PhabricatorPolicyQuery()) - ->setViewer($viewer) - ->setObject($service) - ->execute(); - - $form = id(new AphrontFormView()) - ->setUser($viewer) - ->addHiddenInput('edit', true) - ->addHiddenInput('serviceType', $service->getServiceType()) - ->appendChild( - id(new AphrontFormTextControl()) - ->setLabel(pht('Name')) - ->setName('name') - ->setValue($v_name) - ->setError($e_name)) - ->appendChild( - id(new AphrontFormPolicyControl()) - ->setName('viewPolicy') - ->setPolicyObject($service) - ->setCapability(PhabricatorPolicyCapability::CAN_VIEW) - ->setPolicies($policies)) - ->appendChild( - id(new AphrontFormPolicyControl()) - ->setName('editPolicy') - ->setPolicyObject($service) - ->setCapability(PhabricatorPolicyCapability::CAN_EDIT) - ->setPolicies($policies)) - ->appendControl( - id(new AphrontFormTokenizerControl()) - ->setLabel(pht('Projects')) - ->setName('projects') - ->setValue($v_projects) - ->setDatasource(new PhabricatorProjectDatasource())) - ->appendChild( - id(new AphrontFormSubmitControl()) - ->addCancelButton($cancel_uri) - ->setValue($save_button)); - $box = id(new PHUIObjectBoxView()) - ->setValidationException($validation_exception) - ->setHeaderText($title) - ->appendChild($form); - - $crumbs = $this->buildApplicationCrumbs(); - if ($is_new) { - $crumbs->addTextCrumb(pht('Create Service')); - } else { - $crumbs->addTextCrumb($service->getName(), $service_uri); - $crumbs->addTextCrumb(pht('Edit')); + $engine + ->addContextParameter('serviceType', $service_type) + ->setServiceType($service_type); } - return $this->newPage() - ->setTitle($title) - ->setCrumbs($crumbs) - ->appendChild( - array( - $box, - )); + return $engine->buildResponse(); } private function buildServiceTypeResponse($cancel_uri) { @@ -194,7 +47,6 @@ pht('You have permission to create cluster services.'), pht('You do not have permission to create new cluster services.')); - $type_control = id(new AphrontFormRadioButtonControl()) ->setLabel(pht('Service Type')) ->setName('serviceType') @@ -239,14 +91,10 @@ ->setHeaderText($title) ->setForm($form); - return $this->buildApplicationPage( - array( - $crumbs, - $box, - ), - array( - 'title' => $title, - )); + return $this->newPage() + ->setTitle($title) + ->setCrumbs($crumbs) + ->appendChild($box); } } diff --git a/src/applications/almanac/controller/AlmanacServiceListController.php b/src/applications/almanac/controller/AlmanacServiceListController.php --- a/src/applications/almanac/controller/AlmanacServiceListController.php +++ b/src/applications/almanac/controller/AlmanacServiceListController.php @@ -8,45 +8,19 @@ } public function handleRequest(AphrontRequest $request) { - $controller = id(new PhabricatorApplicationSearchController()) - ->setQueryKey($request->getURIData('queryKey')) - ->setSearchEngine(new AlmanacServiceSearchEngine()) - ->setNavigation($this->buildSideNavView()); - - return $this->delegateToController($controller); + return id(new AlmanacServiceSearchEngine()) + ->setController($this) + ->buildResponse(); } protected function buildApplicationCrumbs() { $crumbs = parent::buildApplicationCrumbs(); - $can_create = $this->hasApplicationCapability( - AlmanacCreateServicesCapability::CAPABILITY); - - $crumbs->addAction( - id(new PHUIListItemView()) - ->setName(pht('Create Service')) - ->setHref($this->getApplicationURI('service/edit/')) - ->setIcon('fa-plus-square') - ->setDisabled(!$can_create) - ->setWorkflow(!$can_create)); + id(new AlmanacServiceEditEngine()) + ->setViewer($this->getViewer()) + ->addActionToCrumbs($crumbs); return $crumbs; } - public function buildSideNavView() { - $viewer = $this->getViewer(); - - $nav = new AphrontSideNavFilterView(); - $nav->setBaseURI(new PhutilURI($this->getApplicationURI())); - - id(new AlmanacServiceSearchEngine()) - ->setViewer($viewer) - ->addNavigationItems($nav->getMenu()); - - $nav->selectFilter(null); - - return $nav; - } - - } diff --git a/src/applications/almanac/editor/AlmanacServiceEditEngine.php b/src/applications/almanac/editor/AlmanacServiceEditEngine.php new file mode 100644 --- /dev/null +++ b/src/applications/almanac/editor/AlmanacServiceEditEngine.php @@ -0,0 +1,97 @@ +serviceType = $service_type; + return $this; + } + + public function getServiceType() { + return $this->serviceType; + } + + public function isEngineConfigurable() { + return false; + } + + public function getEngineName() { + return pht('Almanac Services'); + } + + public function getSummaryHeader() { + return pht('Edit Almanac Service Configurations'); + } + + public function getSummaryText() { + return pht('This engine is used to edit Almanac services.'); + } + + public function getEngineApplicationClass() { + return 'PhabricatorAlmanacApplication'; + } + + protected function newEditableObject() { + $service_type = $this->getServiceType(); + return AlmanacService::initializeNewService($service_type); + } + + protected function newObjectQuery() { + return new AlmanacServiceQuery(); + } + + protected function getObjectCreateTitleText($object) { + return pht('Create Service'); + } + + protected function getObjectCreateButtonText($object) { + return pht('Create Service'); + } + + protected function getObjectEditTitleText($object) { + return pht('Edit Service: %s', $object->getName()); + } + + protected function getObjectEditShortText($object) { + return pht('Edit Service'); + } + + protected function getObjectCreateShortText() { + return pht('Create Service'); + } + + protected function getEditorURI() { + return '/almanac/service/edit/'; + } + + protected function getObjectCreateCancelURI($object) { + return '/almanac/service/'; + } + + protected function getObjectViewURI($object) { + return $object->getURI(); + } + + protected function getCreateNewObjectPolicy() { + return $this->getApplication()->getPolicy( + AlmanacCreateServicesCapability::CAPABILITY); + } + + protected function buildCustomEditFields($object) { + return array( + id(new PhabricatorTextEditField()) + ->setKey('name') + ->setLabel(pht('Name')) + ->setDescription(pht('Name of the service.')) + ->setTransactionType(AlmanacServiceTransaction::TYPE_NAME) + ->setIsRequired(true) + ->setValue($object->getName()), + ); + } + +} diff --git a/src/applications/almanac/editor/AlmanacServiceEditor.php b/src/applications/almanac/editor/AlmanacServiceEditor.php --- a/src/applications/almanac/editor/AlmanacServiceEditor.php +++ b/src/applications/almanac/editor/AlmanacServiceEditor.php @@ -152,4 +152,28 @@ return $errors; } + + protected function validateAllTransactions( + PhabricatorLiskDAO $object, + array $xactions) { + + $errors = parent::validateAllTransactions($object, $xactions); + + if ($object->isClusterService()) { + $can_manage = PhabricatorPolicyFilter::hasCapability( + $this->getActor(), + new PhabricatorAlmanacApplication(), + AlmanacManageClusterServicesCapability::CAPABILITY); + if (!$can_manage) { + $errors[] = new PhabricatorApplicationTransactionValidationError( + null, + pht('Restricted'), + pht('You do not have permission to manage cluster services.'), + null); + } + } + + return $errors; + } + }