Differential D14392 Diff 34773 src/applications/transactions/editengine/PhabricatorApplicationEditEngine.php
Changeset View
Changeset View
Standalone View
Standalone View
src/applications/transactions/editengine/PhabricatorApplicationEditEngine.php
| <?php | <?php | ||||
| abstract class PhabricatorApplicationEditEngine extends Phobject { | abstract class PhabricatorApplicationEditEngine extends Phobject { | ||||
| private $viewer; | private $viewer; | ||||
| private $controller; | private $controller; | ||||
| private $isCreate; | |||||
| final public function setViewer(PhabricatorUser $viewer) { | final public function setViewer(PhabricatorUser $viewer) { | ||||
| $this->viewer = $viewer; | $this->viewer = $viewer; | ||||
| return $this; | return $this; | ||||
| } | } | ||||
| final public function getViewer() { | final public function getViewer() { | ||||
| return $this->viewer; | return $this->viewer; | ||||
| Show All 24 Lines | if ($object instanceof PhabricatorPolicyInterface) { | ||||
| ->setObject($object) | ->setObject($object) | ||||
| ->execute(); | ->execute(); | ||||
| $map = array( | $map = array( | ||||
| PhabricatorTransactions::TYPE_VIEW_POLICY => array( | PhabricatorTransactions::TYPE_VIEW_POLICY => array( | ||||
| 'key' => 'policy.view', | 'key' => 'policy.view', | ||||
| 'aliases' => array('view'), | 'aliases' => array('view'), | ||||
| 'capability' => PhabricatorPolicyCapability::CAN_VIEW, | 'capability' => PhabricatorPolicyCapability::CAN_VIEW, | ||||
| 'label' => pht('View Policy'), | |||||
| 'description' => pht('Controls who can view the object.'), | |||||
| ), | ), | ||||
| PhabricatorTransactions::TYPE_EDIT_POLICY => array( | PhabricatorTransactions::TYPE_EDIT_POLICY => array( | ||||
| 'key' => 'policy.edit', | 'key' => 'policy.edit', | ||||
| 'aliases' => array('edit'), | 'aliases' => array('edit'), | ||||
| 'capability' => PhabricatorPolicyCapability::CAN_EDIT, | 'capability' => PhabricatorPolicyCapability::CAN_EDIT, | ||||
| 'label' => pht('Edit Policy'), | |||||
| 'description' => pht('Controls who can edit the object.'), | |||||
| ), | ), | ||||
| PhabricatorTransactions::TYPE_JOIN_POLICY => array( | PhabricatorTransactions::TYPE_JOIN_POLICY => array( | ||||
| 'key' => 'policy.join', | 'key' => 'policy.join', | ||||
| 'aliases' => array('join'), | 'aliases' => array('join'), | ||||
| 'capability' => PhabricatorPolicyCapability::CAN_JOIN, | 'capability' => PhabricatorPolicyCapability::CAN_JOIN, | ||||
| 'label' => pht('Join Policy'), | |||||
| 'description' => pht('Controls who can join the object.'), | |||||
| ), | ), | ||||
| ); | ); | ||||
| foreach ($map as $type => $spec) { | foreach ($map as $type => $spec) { | ||||
| if (empty($types[$type])) { | if (empty($types[$type])) { | ||||
| continue; | continue; | ||||
| } | } | ||||
| $capability = $spec['capability']; | $capability = $spec['capability']; | ||||
| $key = $spec['key']; | $key = $spec['key']; | ||||
| $aliases = $spec['aliases']; | $aliases = $spec['aliases']; | ||||
| $label = $spec['label']; | |||||
| $description = $spec['description']; | |||||
| $policy_field = id(new PhabricatorPolicyEditField()) | $policy_field = id(new PhabricatorPolicyEditField()) | ||||
| ->setKey($key) | ->setKey($key) | ||||
| ->setLabel($label) | |||||
| ->setDescription($description) | |||||
| ->setAliases($aliases) | ->setAliases($aliases) | ||||
| ->setCapability($capability) | ->setCapability($capability) | ||||
| ->setPolicies($policies) | ->setPolicies($policies) | ||||
| ->setTransactionType($type) | ->setTransactionType($type) | ||||
| ->setValue($object->getPolicy($capability)); | ->setValue($object->getPolicy($capability)); | ||||
| $fields[] = $policy_field; | $fields[] = $policy_field; | ||||
| if ($object instanceof PhabricatorSpacesInterface) { | if ($object instanceof PhabricatorSpacesInterface) { | ||||
| if ($capability == PhabricatorPolicyCapability::CAN_VIEW) { | if ($capability == PhabricatorPolicyCapability::CAN_VIEW) { | ||||
| $type_space = PhabricatorTransactions::TYPE_SPACE; | $type_space = PhabricatorTransactions::TYPE_SPACE; | ||||
| if (isset($types[$type_space])) { | if (isset($types[$type_space])) { | ||||
| $space_field = id(new PhabricatorSpaceEditField()) | $space_field = id(new PhabricatorSpaceEditField()) | ||||
| ->setKey('spacePHID') | ->setKey('spacePHID') | ||||
| ->setLabel(pht('Space')) | |||||
| ->setDescription( | |||||
| pht('Shifts the object in the Spaces application.')) | |||||
| ->setAliases(array('space', 'policy.space')) | ->setAliases(array('space', 'policy.space')) | ||||
| ->setTransactionType($type_space) | ->setTransactionType($type_space) | ||||
| ->setValue($object->getSpacePHID()); | ->setValue($object->getSpacePHID()); | ||||
| $fields[] = $space_field; | $fields[] = $space_field; | ||||
| $policy_field->setSpaceField($space_field); | $policy_field->setSpaceField($space_field); | ||||
| } | } | ||||
| } | } | ||||
| Show All 15 Lines | if ($object instanceof PhabricatorProjectInterface) { | ||||
| $project_phids = array_reverse($project_phids); | $project_phids = array_reverse($project_phids); | ||||
| } else { | } else { | ||||
| $project_phids = array(); | $project_phids = array(); | ||||
| } | } | ||||
| $edge_field = id(new PhabricatorDatasourceEditField()) | $edge_field = id(new PhabricatorDatasourceEditField()) | ||||
| ->setKey('projectPHIDs') | ->setKey('projectPHIDs') | ||||
| ->setLabel(pht('Projects')) | ->setLabel(pht('Projects')) | ||||
| ->setDescription( | |||||
| pht( | |||||
| 'Add or remove associated projects.')) | |||||
| ->setDatasource(new PhabricatorProjectDatasource()) | ->setDatasource(new PhabricatorProjectDatasource()) | ||||
| ->setAliases(array('project', 'projects')) | ->setAliases(array('project', 'projects')) | ||||
| ->setTransactionType($edge_type) | ->setTransactionType($edge_type) | ||||
| ->setMetadataValue('edge:type', $project_edge_type) | ->setMetadataValue('edge:type', $project_edge_type) | ||||
| ->setValue($project_phids); | ->setValue($project_phids); | ||||
| $fields[] = $edge_field; | $fields[] = $edge_field; | ||||
| } | } | ||||
| } | } | ||||
| Show All 9 Lines | if ($object instanceof PhabricatorSubscribableInterface) { | ||||
| // TODO: Allow applications to provide default subscribers; Maniphest | // TODO: Allow applications to provide default subscribers; Maniphest | ||||
| // does this at a minimum. | // does this at a minimum. | ||||
| $sub_phids = array(); | $sub_phids = array(); | ||||
| } | } | ||||
| $subscribers_field = id(new PhabricatorDatasourceEditField()) | $subscribers_field = id(new PhabricatorDatasourceEditField()) | ||||
| ->setKey('subscriberPHIDs') | ->setKey('subscriberPHIDs') | ||||
| ->setLabel(pht('Subscribers')) | ->setLabel(pht('Subscribers')) | ||||
| ->setDescription(pht('Manage subscribers.')) | |||||
| ->setDatasource(new PhabricatorMetaMTAMailableDatasource()) | ->setDatasource(new PhabricatorMetaMTAMailableDatasource()) | ||||
| ->setAliases(array('subscriber', 'subscribers')) | ->setAliases(array('subscriber', 'subscribers')) | ||||
| ->setTransactionType($subscribers_type) | ->setTransactionType($subscribers_type) | ||||
| ->setValue($sub_phids); | ->setValue($sub_phids); | ||||
| $fields[] = $subscribers_field; | $fields[] = $subscribers_field; | ||||
| } | } | ||||
| } | } | ||||
| return $fields; | return $fields; | ||||
| } | } | ||||
| abstract protected function newEditableObject(); | abstract protected function newEditableObject(); | ||||
| abstract protected function newObjectQuery(); | abstract protected function newObjectQuery(); | ||||
| abstract protected function buildCustomEditFields($object); | abstract protected function buildCustomEditFields($object); | ||||
| abstract protected function getObjectCreateTitleText($object); | abstract protected function getObjectCreateTitleText($object); | ||||
| abstract protected function getObjectEditTitleText($object); | abstract protected function getObjectEditTitleText($object); | ||||
| abstract protected function getObjectCreateShortText($object); | abstract protected function getObjectCreateShortText($object); | ||||
| abstract protected function getObjectEditShortText($object); | abstract protected function getObjectEditShortText($object); | ||||
| abstract protected function getObjectViewURI($object); | abstract protected function getObjectViewURI($object); | ||||
| protected function getObjectEditURI($object) { | |||||
| return $this->getController()->getApplicationURI('edit/'); | |||||
| } | |||||
| protected function getObjectCreateCancelURI($object) { | protected function getObjectCreateCancelURI($object) { | ||||
| return $this->getController()->getApplicationURI(); | return $this->getController()->getApplicationURI(); | ||||
| } | } | ||||
| protected function getObjectEditCancelURI($object) { | protected function getObjectEditCancelURI($object) { | ||||
| return $this->getObjectViewURI($object); | return $this->getObjectViewURI($object); | ||||
| } | } | ||||
| protected function getObjectCreateButtonText($object) { | protected function getObjectCreateButtonText($object) { | ||||
| return $this->getObjectCreateTitleText($object); | return $this->getObjectCreateTitleText($object); | ||||
| } | } | ||||
| protected function getObjectEditButtonText($object) { | protected function getObjectEditButtonText($object) { | ||||
| return pht('Save Changes'); | return pht('Save Changes'); | ||||
| } | } | ||||
| protected function getEditURI($object, $path = null) { | |||||
| $parts = array( | |||||
| $this->getObjectEditURI($object), | |||||
| ); | |||||
| if (!$this->getIsCreate()) { | |||||
| $parts[] = $object->getID().'/'; | |||||
| } | |||||
| if ($path !== null) { | |||||
| $parts[] = $path; | |||||
| } | |||||
| return implode('', $parts); | |||||
| } | |||||
| final protected function setIsCreate($is_create) { | |||||
| $this->isCreate = $is_create; | |||||
| return $this; | |||||
| } | |||||
| final protected function getIsCreate() { | |||||
| return $this->isCreate; | |||||
| } | |||||
| final public function buildResponse() { | final public function buildResponse() { | ||||
| $controller = $this->getController(); | $controller = $this->getController(); | ||||
| $viewer = $this->getViewer(); | $viewer = $this->getViewer(); | ||||
| $request = $controller->getRequest(); | $request = $controller->getRequest(); | ||||
| $id = $request->getURIData('id'); | $id = $request->getURIData('id'); | ||||
| if ($id) { | if ($id) { | ||||
| $object = $this->newObjectQuery() | $object = $this->newObjectQuery() | ||||
| ->setViewer($viewer) | ->setViewer($viewer) | ||||
| ->withIDs(array($id)) | ->withIDs(array($id)) | ||||
| ->requireCapabilities( | ->requireCapabilities( | ||||
| array( | array( | ||||
| PhabricatorPolicyCapability::CAN_VIEW, | PhabricatorPolicyCapability::CAN_VIEW, | ||||
| PhabricatorPolicyCapability::CAN_EDIT, | PhabricatorPolicyCapability::CAN_EDIT, | ||||
| )) | )) | ||||
| ->executeOne(); | ->executeOne(); | ||||
| if (!$object) { | if (!$object) { | ||||
| return new Aphront404Response(); | return new Aphront404Response(); | ||||
| } | } | ||||
| $is_create = false; | $this->setIsCreate(false); | ||||
| } else { | } else { | ||||
| $object = $this->newEditableObject(); | $object = $this->newEditableObject(); | ||||
| $is_create = true; | $this->setIsCreate(true); | ||||
| } | } | ||||
| $fields = $this->buildEditFields($object); | $fields = $this->buildEditFields($object); | ||||
| foreach ($fields as $field) { | foreach ($fields as $field) { | ||||
| $field | $field | ||||
| ->setViewer($viewer) | ->setViewer($viewer) | ||||
| ->setObject($object); | ->setObject($object); | ||||
| } | } | ||||
| $action = $request->getURIData('editAction'); | |||||
| switch ($action) { | |||||
| case 'parameters': | |||||
| return $this->buildParametersResponse($object, $fields); | |||||
| } | |||||
| $validation_exception = null; | $validation_exception = null; | ||||
| if ($request->isFormPost()) { | if ($request->isFormPost()) { | ||||
| foreach ($fields as $field) { | foreach ($fields as $field) { | ||||
| $field->readValueFromSubmit($request); | $field->readValueFromSubmit($request); | ||||
| } | } | ||||
| $template = $object->getApplicationTransactionTemplate(); | $template = $object->getApplicationTransactionTemplate(); | ||||
| Show All 13 Lines | if ($request->isFormPost()) { | ||||
| $editor->applyTransactions($object, $xactions); | $editor->applyTransactions($object, $xactions); | ||||
| return id(new AphrontRedirectResponse()) | return id(new AphrontRedirectResponse()) | ||||
| ->setURI($this->getObjectViewURI($object)); | ->setURI($this->getObjectViewURI($object)); | ||||
| } catch (PhabricatorApplicationTransactionValidationException $ex) { | } catch (PhabricatorApplicationTransactionValidationException $ex) { | ||||
| $validation_exception = $ex; | $validation_exception = $ex; | ||||
| } | } | ||||
| } else { | } else { | ||||
| if ($is_create) { | if ($this->getIsCreate()) { | ||||
| foreach ($fields as $field) { | foreach ($fields as $field) { | ||||
| $field->readValueFromRequest($request); | $field->readValueFromRequest($request); | ||||
| } | } | ||||
| } else { | } else { | ||||
| foreach ($fields as $field) { | foreach ($fields as $field) { | ||||
| $field->readValueFromObject($object); | $field->readValueFromObject($object); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| $box = id(new PHUIObjectBoxView()) | $box = id(new PHUIObjectBoxView()) | ||||
| ->setUser($viewer); | ->setUser($viewer); | ||||
| $crumbs = $controller->buildApplicationCrumbsForEditEngine(); | $crumbs = $this->buildCrumbs($object, $final = true); | ||||
| if ($is_create) { | if ($this->getIsCreate()) { | ||||
| $header_text = $this->getObjectCreateTitleText($object); | $header_text = $this->getObjectCreateTitleText($object); | ||||
| $crumbs->addTextCrumb( | |||||
| $this->getObjectCreateShortText($object)); | |||||
| $cancel_uri = $this->getObjectCreateCancelURI($object); | $cancel_uri = $this->getObjectCreateCancelURI($object); | ||||
| $submit_button = $this->getObjectCreateButtonText($object); | $submit_button = $this->getObjectCreateButtonText($object); | ||||
| } else { | } else { | ||||
| $header_text = $this->getObjectEditTitleText($object); | $header_text = $this->getObjectEditTitleText($object); | ||||
| $crumbs->addTextCrumb( | |||||
| $this->getObjectEditShortText($object), | |||||
| $this->getObjectViewURI($object)); | |||||
| $cancel_uri = $this->getObjectEditCancelURI($object); | $cancel_uri = $this->getObjectEditCancelURI($object); | ||||
| $submit_button = $this->getObjectEditButtonText($object); | $submit_button = $this->getObjectEditButtonText($object); | ||||
| } | } | ||||
| $box->setHeaderText($header_text); | $header = id(new PHUIHeaderView()) | ||||
| ->setHeader($header_text); | |||||
| $action_button = $this->buildEditFormActionButton($object); | |||||
| $header->addActionLink($action_button); | |||||
| $box->setHeader($header); | |||||
| $form = id(new AphrontFormView()) | $form = id(new AphrontFormView()) | ||||
| ->setUser($viewer); | ->setUser($viewer); | ||||
| foreach ($fields as $field) { | foreach ($fields as $field) { | ||||
| $field->appendToForm($form); | $field->appendToForm($form); | ||||
| } | } | ||||
| Show All 9 Lines | final public function buildResponse() { | ||||
| } | } | ||||
| return $controller->newPage() | return $controller->newPage() | ||||
| ->setTitle($header_text) | ->setTitle($header_text) | ||||
| ->setCrumbs($crumbs) | ->setCrumbs($crumbs) | ||||
| ->appendChild($box); | ->appendChild($box); | ||||
| } | } | ||||
| private function buildParametersResponse($object, array $fields) { | |||||
| $controller = $this->getController(); | |||||
| $viewer = $this->getViewer(); | |||||
| $request = $controller->getRequest(); | |||||
| $crumbs = $this->buildCrumbs($object); | |||||
| $crumbs->addTextCrumb(pht('HTTP Parameters')); | |||||
| $header = id(new PHUIHeaderView()) | |||||
| ->setHeader( | |||||
| pht( | |||||
| 'HTTP Parameters: %s', | |||||
| $this->getObjectCreateShortText($object))); | |||||
| // TODO: Upgrade to DocumentViewPro. | |||||
| $document = id(new PHUIDocumentView()) | |||||
| ->setUser($viewer) | |||||
| ->setHeader($header); | |||||
| $document->appendChild( | |||||
| id(new PhabricatorApplicationEditHTTPParameterHelpView()) | |||||
| ->setUser($viewer) | |||||
| ->setFields($fields)); | |||||
| return $controller->newPage() | |||||
| ->setTitle(pht('HTTP Parameters')) | |||||
| ->setCrumbs($crumbs) | |||||
| ->appendChild($document); | |||||
| } | |||||
| private function buildCrumbs($object, $final = false) { | |||||
| $controller = $this->getcontroller(); | |||||
| $crumbs = $controller->buildApplicationCrumbsForEditEngine(); | |||||
| if ($this->getIsCreate()) { | |||||
| $create_text = $this->getObjectCreateShortText($object); | |||||
| if ($final) { | |||||
| $crumbs->addTextCrumb($create_text); | |||||
| } else { | |||||
| $edit_uri = $this->getEditURI($object); | |||||
| $crumbs->addTextCrumb($create_text, $edit_uri); | |||||
| } | |||||
| } else { | |||||
| $crumbs->addTextCrumb( | |||||
| $this->getObjectEditShortText($object), | |||||
| $this->getObjectViewURI($object)); | |||||
| $edit_text = pht('Edit'); | |||||
| if ($final) { | |||||
| $crumbs->addTextCrumb($edit_text); | |||||
| } else { | |||||
| $edit_uri = $this->getEditURI($object); | |||||
| $crumbs->addTextCrumb($edit_text, $edit_uri); | |||||
| } | |||||
| } | |||||
| return $crumbs; | |||||
| } | |||||
| private function buildEditFormActionButton($object) { | |||||
| $viewer = $this->getViewer(); | |||||
| $action_view = id(new PhabricatorActionListView()) | |||||
| ->setUser($viewer); | |||||
| foreach ($this->buildEditFormActions($object) as $action) { | |||||
| $action_view->addAction($action); | |||||
| } | |||||
| $action_button = id(new PHUIButtonView()) | |||||
| ->setTag('a') | |||||
| ->setText(pht('Actions')) | |||||
| ->setHref('#') | |||||
| ->setIconFont('fa-bars') | |||||
| ->setDropdownMenu($action_view); | |||||
| return $action_button; | |||||
| } | |||||
| private function buildEditFormActions($object) { | |||||
| $actions = array(); | |||||
| $actions[] = id(new PhabricatorActionView()) | |||||
| ->setName(pht('Show HTTP Parameters')) | |||||
| ->setIcon('fa-crosshairs') | |||||
| ->setHref($this->getEditURI($object, 'parameters/')); | |||||
| return $actions; | |||||
| } | |||||
| } | } | ||||