1
0
Fork 0
mirror of https://we.phorge.it/source/phorge.git synced 2024-11-10 08:52:39 +01:00

Move "Remote URI" to modern repository editor thing

Summary:
Ref T2231. Allows you to edit the remote URI and credentials.

This is a little bit funky because I'm reusing some of the pages on the new (not-yet-hooked-up) create form. Specifically, it had pages like this:

  - Repo Type
  - Name/Callsign/Remote
  - Auth
  - Done

I split "Name/Callsign/Remote" into "Name/Callsign" and "Remote", then when editing the remote I just take you through "Remote" and "Auth" and then back. This lets us reuse the giant pile of protocol/URI sanity checking logic and ends up being pretty clean, although it's a little weird that the "Create" controller does both full-create and edit-remote.

Test Plan: See screenshots.

Reviewers: btrahan, chad

Reviewed By: btrahan

CC: chad, aran

Maniphest Tasks: T2231

Differential Revision: https://secure.phabricator.com/D7405
This commit is contained in:
epriestley 2013-10-25 13:59:02 -07:00
parent 52d4e66883
commit b57b72368c
11 changed files with 432 additions and 113 deletions

View file

@ -3858,7 +3858,7 @@ celerity_register_resource_map(array(
),
'phui-form-view-css' =>
array(
'uri' => '/res/157ddd8b/rsrc/css/phui/phui-form-view.css',
'uri' => '/res/3621b05d/rsrc/css/phui/phui-form-view.css',
'type' => 'css',
'requires' =>
array(
@ -3885,7 +3885,7 @@ celerity_register_resource_map(array(
),
'phui-info-panel-css' =>
array(
'uri' => '/res/0a9c55c3/rsrc/css/phui/phui-info-panel.css',
'uri' => '/res/e0ba8d04/rsrc/css/phui/phui-info-panel.css',
'type' => 'css',
'requires' =>
array(
@ -4318,7 +4318,7 @@ celerity_register_resource_map(array(
), array(
'packages' =>
array(
'8486b05c' =>
'3b488eea' =>
array(
'name' => 'core.pkg.css',
'symbols' =>
@ -4367,7 +4367,7 @@ celerity_register_resource_map(array(
41 => 'phabricator-tag-view-css',
42 => 'phui-list-view-css',
),
'uri' => '/res/pkg/8486b05c/core.pkg.css',
'uri' => '/res/pkg/3b488eea/core.pkg.css',
'type' => 'css',
),
'2c1dba03' =>
@ -4559,15 +4559,15 @@ celerity_register_resource_map(array(
),
'reverse' =>
array(
'aphront-dialog-view-css' => '8486b05c',
'aphront-error-view-css' => '8486b05c',
'aphront-list-filter-view-css' => '8486b05c',
'aphront-pager-view-css' => '8486b05c',
'aphront-panel-view-css' => '8486b05c',
'aphront-table-view-css' => '8486b05c',
'aphront-tokenizer-control-css' => '8486b05c',
'aphront-tooltip-css' => '8486b05c',
'aphront-typeahead-control-css' => '8486b05c',
'aphront-dialog-view-css' => '3b488eea',
'aphront-error-view-css' => '3b488eea',
'aphront-list-filter-view-css' => '3b488eea',
'aphront-pager-view-css' => '3b488eea',
'aphront-panel-view-css' => '3b488eea',
'aphront-table-view-css' => '3b488eea',
'aphront-tokenizer-control-css' => '3b488eea',
'aphront-tooltip-css' => '3b488eea',
'aphront-typeahead-control-css' => '3b488eea',
'differential-changeset-view-css' => 'f87db3d0',
'differential-core-view-css' => 'f87db3d0',
'differential-inline-comment-editor' => '5e9e5c4e',
@ -4581,7 +4581,7 @@ celerity_register_resource_map(array(
'differential-table-of-contents-css' => 'f87db3d0',
'diffusion-commit-view-css' => '270f4eb4',
'diffusion-icons-css' => '270f4eb4',
'global-drag-and-drop-css' => '8486b05c',
'global-drag-and-drop-css' => '3b488eea',
'inline-comment-summary-css' => 'f87db3d0',
'javelin-aphlict' => '2c1dba03',
'javelin-behavior' => '3e3be199',
@ -4656,56 +4656,56 @@ celerity_register_resource_map(array(
'javelin-util' => '3e3be199',
'javelin-vector' => '3e3be199',
'javelin-workflow' => '3e3be199',
'lightbox-attachment-css' => '8486b05c',
'lightbox-attachment-css' => '3b488eea',
'maniphest-task-summary-css' => '49898640',
'phabricator-action-list-view-css' => '8486b05c',
'phabricator-application-launch-view-css' => '8486b05c',
'phabricator-action-list-view-css' => '3b488eea',
'phabricator-application-launch-view-css' => '3b488eea',
'phabricator-busy' => '2c1dba03',
'phabricator-content-source-view-css' => 'f87db3d0',
'phabricator-core-css' => '8486b05c',
'phabricator-crumbs-view-css' => '8486b05c',
'phabricator-core-css' => '3b488eea',
'phabricator-crumbs-view-css' => '3b488eea',
'phabricator-drag-and-drop-file-upload' => '5e9e5c4e',
'phabricator-dropdown-menu' => '2c1dba03',
'phabricator-file-upload' => '2c1dba03',
'phabricator-filetree-view-css' => '8486b05c',
'phabricator-flag-css' => '8486b05c',
'phabricator-filetree-view-css' => '3b488eea',
'phabricator-flag-css' => '3b488eea',
'phabricator-hovercard' => '2c1dba03',
'phabricator-jump-nav' => '8486b05c',
'phabricator-jump-nav' => '3b488eea',
'phabricator-keyboard-shortcut' => '2c1dba03',
'phabricator-keyboard-shortcut-manager' => '2c1dba03',
'phabricator-main-menu-view' => '8486b05c',
'phabricator-main-menu-view' => '3b488eea',
'phabricator-menu-item' => '2c1dba03',
'phabricator-nav-view-css' => '8486b05c',
'phabricator-nav-view-css' => '3b488eea',
'phabricator-notification' => '2c1dba03',
'phabricator-notification-css' => '8486b05c',
'phabricator-notification-menu-css' => '8486b05c',
'phabricator-notification-css' => '3b488eea',
'phabricator-notification-menu-css' => '3b488eea',
'phabricator-object-selector-css' => 'f87db3d0',
'phabricator-phtize' => '2c1dba03',
'phabricator-prefab' => '2c1dba03',
'phabricator-project-tag-css' => '49898640',
'phabricator-remarkup-css' => '8486b05c',
'phabricator-remarkup-css' => '3b488eea',
'phabricator-shaped-request' => '5e9e5c4e',
'phabricator-side-menu-view-css' => '8486b05c',
'phabricator-standard-page-view' => '8486b05c',
'phabricator-tag-view-css' => '8486b05c',
'phabricator-side-menu-view-css' => '3b488eea',
'phabricator-standard-page-view' => '3b488eea',
'phabricator-tag-view-css' => '3b488eea',
'phabricator-textareautils' => '2c1dba03',
'phabricator-tooltip' => '2c1dba03',
'phabricator-transaction-view-css' => '8486b05c',
'phabricator-zindex-css' => '8486b05c',
'phui-button-css' => '8486b05c',
'phui-form-css' => '8486b05c',
'phui-form-view-css' => '8486b05c',
'phui-header-view-css' => '8486b05c',
'phui-icon-view-css' => '8486b05c',
'phui-list-view-css' => '8486b05c',
'phui-object-item-list-view-css' => '8486b05c',
'phui-property-list-view-css' => '8486b05c',
'phui-spacing-css' => '8486b05c',
'sprite-apps-large-css' => '8486b05c',
'sprite-gradient-css' => '8486b05c',
'sprite-icons-css' => '8486b05c',
'sprite-menu-css' => '8486b05c',
'sprite-status-css' => '8486b05c',
'syntax-highlighting-css' => '8486b05c',
'phabricator-transaction-view-css' => '3b488eea',
'phabricator-zindex-css' => '3b488eea',
'phui-button-css' => '3b488eea',
'phui-form-css' => '3b488eea',
'phui-form-view-css' => '3b488eea',
'phui-header-view-css' => '3b488eea',
'phui-icon-view-css' => '3b488eea',
'phui-list-view-css' => '3b488eea',
'phui-object-item-list-view-css' => '3b488eea',
'phui-property-list-view-css' => '3b488eea',
'phui-spacing-css' => '3b488eea',
'sprite-apps-large-css' => '3b488eea',
'sprite-gradient-css' => '3b488eea',
'sprite-icons-css' => '3b488eea',
'sprite-menu-css' => '3b488eea',
'sprite-status-css' => '3b488eea',
'syntax-highlighting-css' => '3b488eea',
),
));

View file

@ -72,6 +72,7 @@ final class PhabricatorApplicationDiffusion extends PhabricatorApplication {
'branches/' => 'DiffusionRepositoryEditBranchesController',
'subversion/' => 'DiffusionRepositoryEditSubversionController',
'actions/' => 'DiffusionRepositoryEditActionsController',
'(?P<edit>remote)/' => 'DiffusionRepositoryCreateController',
),
),
'inline/' => array(

View file

@ -2,30 +2,140 @@
final class DiffusionRepositoryCreateController extends DiffusionController {
private $edit;
private $repository;
public function willProcessRequest(array $data) {
parent::willProcessRequest($data);
$this->edit = idx($data, 'edit');
}
public function processRequest() {
$request = $this->getRequest();
$viewer = $request->getUser();
// NOTE: We can end up here via either "Create Repository" or via
// "Edit Remote". In the latter case, we show only a few of the pages.
$repository = null;
if ($this->edit) {
$repository = $this->getDiffusionRequest()->getRepository();
// Make sure we have CAN_EDIT.
id(new PhabricatorRepositoryQuery())
->setViewer($viewer)
->withIDs(array($repository->getID()))
->requireCapabilities(
array(
PhabricatorPolicyCapability::CAN_VIEW,
PhabricatorPolicyCapability::CAN_EDIT,
))
->executeOne();
$this->setRepository($repository);
$cancel_uri = $this->getRepositoryControllerURI($repository, 'edit/');
} else {
$cancel_uri = $this->getApplicationURI();
}
$form = id(new PHUIPagedFormView())
->setUser($viewer)
->addPage('vcs', $this->buildVCSPage())
->addPage('name', $this->buildNamePage())
->addPage('auth', $this->buildAuthPage())
->addPage('done', $this->buildDonePage());
->setCancelURI($cancel_uri);
switch ($this->edit) {
case 'remote':
$title = pht('Edit Remote');
$form
->addPage('remote-uri', $this->buildRemoteURIPage())
->addPage('auth', $this->buildAuthPage());
break;
default:
$title = pht('Import Repository');
$form
->addPage('vcs', $this->buildVCSPage())
->addPage('name', $this->buildNamePage())
->addPage('remote-uri', $this->buildRemoteURIPage())
->addPage('auth', $this->buildAuthPage())
->addPage('done', $this->buildDonePage());
break;
}
if ($request->isFormPost()) {
$form->readFromRequest($request);
if ($form->isComplete()) {
// TODO: This exception is heartwarming but should probably take more
// substantive actions.
throw new Exception("GOOD JOB AT FORM");
if ($this->edit != 'remote') {
// TODO: This exception is heartwarming but should probably take more
// substantive actions.
throw new Exception("GOOD JOB AT FORM");
}
$template = id(new PhabricatorRepositoryTransaction());
$type_remote_uri = PhabricatorRepositoryTransaction::TYPE_REMOTE_URI;
$type_ssh_login = PhabricatorRepositoryTransaction::TYPE_SSH_LOGIN;
$type_ssh_key = PhabricatorRepositoryTransaction::TYPE_SSH_KEY;
$type_ssh_keyfile = PhabricatorRepositoryTransaction::TYPE_SSH_KEYFILE;
$type_http_login = PhabricatorRepositoryTransaction::TYPE_HTTP_LOGIN;
$type_http_pass = PhabricatorRepositoryTransaction::TYPE_HTTP_PASS;
$xactions = array();
$xactions[] = id(clone $template)
->setTransactionType($type_remote_uri)
->setNewValue(
$form->getPage('remote-uri')->getControl('remoteURI')->getValue());
$xactions[] = id(clone $template)
->setTransactionType($type_ssh_login)
->setNewValue(
$form->getPage('auth')->getControl('ssh-login')->getValue());
$xactions[] = id(clone $template)
->setTransactionType($type_ssh_key)
->setNewValue(
$form->getPage('auth')->getControl('ssh-key')->getValue());
$xactions[] = id(clone $template)
->setTransactionType($type_ssh_keyfile)
->setNewValue(
$form->getPage('auth')->getControl('ssh-keyfile')->getValue());
$xactions[] = id(clone $template)
->setTransactionType($type_http_login)
->setNewValue(
$form->getPage('auth')->getControl('http-login')->getValue());
$xactions[] = id(clone $template)
->setTransactionType($type_http_pass)
->setNewValue(
$form->getPage('auth')->getControl('http-pass')->getValue());
id(new PhabricatorRepositoryEditor())
->setContinueOnNoEffect(true)
->setContentSourceFromRequest($request)
->setActor($viewer)
->applyTransactions($repository, $xactions);
$repo_uri = $this->getRepositoryControllerURI($repository, 'edit/');
return id(new AphrontRedirectResponse())->setURI($repo_uri);
}
} else {
$form->readFromObject(null);
$dict = array();
if ($repository) {
$dict = array(
'remoteURI' => $repository->getRemoteURI(),
'ssh-login' => $repository->getDetail('ssh-login'),
'ssh-key' => $repository->getDetail('ssh-key'),
'ssh-keyfile' => $repository->getDetail('ssh-keyfile'),
'http-login' => $repository->getDetail('http-login'),
'http-pass' => $repository->getDetail('http-pass'),
);
}
$form->readFromObject($dict);
}
$title = pht('Import Repository');
$crumbs = $this->buildCrumbs();
$crumbs->addCrumb(
id(new PhabricatorCrumbView())
@ -120,7 +230,6 @@ final class DiffusionRepositoryCreateController extends DiffusionController {
->setUser($this->getRequest()->getUser())
->setPageName(pht('Repository Name and Location'))
->setValidateFormPageCallback(array($this, 'validateNamePage'))
->setAdjustFormPageCallback(array($this, 'adjustNamePage'))
->addRemarkupInstructions(
pht(
'**Choose a human-readable name for this repository**, like '.
@ -145,20 +254,81 @@ final class DiffusionRepositoryCreateController extends DiffusionController {
id(new AphrontFormTextControl())
->setName('callsign')
->setLabel(pht('Callsign'))
->setCaption(pht('Short UPPERCASE identifier.')))
->setCaption(pht('Short UPPERCASE identifier.')));
}
public function validateNamePage(PHUIFormPageView $page) {
$c_name = $page->getControl('name');
$v_name = $c_name->getValue();
if (!strlen($v_name)) {
$c_name->setError(pht('Required'));
$page->addPageError(
pht('You must choose a name for this repository.'));
}
$c_call = $page->getControl('callsign');
$v_call = $c_call->getValue();
if (!strlen($v_call)) {
$c_call->setError(pht('Required'));
$page->addPageError(
pht('You must choose a callsign for this repository.'));
} else if (!preg_match('/^[A-Z]+$/', $v_call)) {
$c_call->setError(pht('Invalid'));
$page->addPageError(
pht('The callsign must contain only UPPERCASE letters.'));
} else {
$exists = false;
try {
$repo = id(new PhabricatorRepositoryQuery())
->setViewer($this->getRequest()->getUser())
->withCallsigns(array($v_call))
->executeOne();
$exists = (bool)$repo;
} catch (PhabricatorPolicyException $ex) {
$exists = true;
}
if ($exists) {
$c_call->setError(pht('Not Unique'));
$page->addPageError(
pht(
'Another repository already uses that callsign. You must choose '.
'a unique callsign.'));
}
}
return $c_name->isValid() &&
$c_call->isValid();
}
/* -( Page: Remote URI )--------------------------------------------------- */
private function buildRemoteURIPage() {
return id(new PHUIFormPageView())
->setUser($this->getRequest()->getUser())
->setPageName(pht('Repository Remote URI'))
->setValidateFormPageCallback(array($this, 'validateRemoteURIPage'))
->setAdjustFormPageCallback(array($this, 'adjustRemoteURIPage'))
->addControl(
id(new AphrontFormTextControl())
->setName('remoteURI'));
}
public function adjustNamePage(PHUIFormPageView $page) {
public function adjustRemoteURIPage(PHUIFormPageView $page) {
$form = $page->getForm();
$is_git = false;
$is_svn = false;
$is_mercurial = false;
switch ($form->getPage('vcs')->getControl('vcs')->getValue()) {
if ($this->getRepository()) {
$vcs = $this->getRepository()->getVersionControlSystem();
} else {
$vcs = $form->getPage('vcs')->getControl('vcs')->getValue();
}
switch ($vcs) {
case PhabricatorRepositoryType::REPOSITORY_TYPE_GIT:
$is_git = true;
break;
@ -220,45 +390,7 @@ final class DiffusionRepositoryCreateController extends DiffusionController {
$page->getControl('remoteURI')->setLabel($uri_label);
}
public function validateNamePage(PHUIFormPageView $page) {
$c_name = $page->getControl('name');
$v_name = $c_name->getValue();
if (!strlen($v_name)) {
$c_name->setError(pht('Required'));
$page->addPageError(
pht('You must choose a name for this repository.'));
}
$c_call = $page->getControl('callsign');
$v_call = $c_call->getValue();
if (!strlen($v_call)) {
$c_call->setError(pht('Required'));
$page->addPageError(
pht('You must choose a callsign for this repository.'));
} else if (!preg_match('/^[A-Z]+$/', $v_call)) {
$c_call->setError(pht('Invalid'));
$page->addPageError(
pht('The callsign must contain only UPPERCASE letters.'));
} else {
$exists = false;
try {
$repo = id(new PhabricatorRepositoryQuery())
->setViewer($this->getRequest()->getUser())
->withCallsigns(array($v_call))
->executeOne();
$exists = (bool)$repo;
} catch (PhabricatorPolicyException $ex) {
$exists = true;
}
if ($exists) {
$c_call->setError(pht('Not Unique'));
$page->addPageError(
pht(
'Another repository already uses that callsign. You must choose '.
'a unique callsign.'));
}
}
public function validateRemoteURIPage(PHUIFormPageView $page) {
$c_remote = $page->getControl('remoteURI');
$v_remote = $c_remote->getValue();
@ -301,9 +433,7 @@ final class DiffusionRepositoryCreateController extends DiffusionController {
}
}
return $c_name->isValid() &&
$c_call->isValid() &&
$c_remote->isValid();
return $c_remote->isValid();
}
@ -346,8 +476,17 @@ final class DiffusionRepositoryCreateController extends DiffusionController {
public function adjustAuthPage($page) {
$form = $page->getForm();
$remote_uri = $form->getPage('name')->getControl('remoteURI')->getValue();
$vcs = $form->getPage('vcs')->getControl('vcs')->getValue();
$remote_uri = $form->getPage('remote-uri')
->getControl('remoteURI')
->getValue();
if ($this->getRepository()) {
$vcs = $this->getRepository()->getVersionControlSystem();
} else {
$vcs = $form->getPage('vcs')->getControl('vcs')->getValue();
}
$proto = $this->getRemoteURIProtocol($remote_uri);
$remote_user = $this->getRemoteURIUser($remote_uri);
@ -541,4 +680,14 @@ final class DiffusionRepositoryCreateController extends DiffusionController {
return ($proto == 'http' || $proto == 'https' || $proto == 'svn');
}
private function setRepository(PhabricatorRepository $repository) {
$this->repository = $repository;
return $this;
}
private function getRepository() {
return $this->repository;
}
}

View file

@ -50,6 +50,10 @@ final class DiffusionRepositoryEditController extends DiffusionController {
$policy_properties =
$this->buildPolicyProperties($repository, $policy_actions);
$remote_properties = $this->buildRemoteProperties(
$repository,
$this->buildRemoteActions($repository));
$encoding_actions = $this->buildEncodingActions($repository);
$encoding_properties =
$this->buildEncodingProperties($repository, $encoding_actions);
@ -98,6 +102,7 @@ final class DiffusionRepositoryEditController extends DiffusionController {
->setHeader($header)
->addPropertyList($basic_properties)
->addPropertyList($policy_properties)
->addPropertyList($remote_properties)
->addPropertyList($encoding_properties);
if ($branches_properties) {
@ -445,4 +450,46 @@ final class DiffusionRepositoryEditController extends DiffusionController {
return $view;
}
private function buildRemoteActions(PhabricatorRepository $repository) {
$viewer = $this->getRequest()->getUser();
$view = id(new PhabricatorActionListView())
->setObjectURI($this->getRequest()->getRequestURI())
->setUser($viewer);
$can_edit = PhabricatorPolicyFilter::hasCapability(
$viewer,
$repository,
PhabricatorPolicyCapability::CAN_EDIT);
$edit = id(new PhabricatorActionView())
->setIcon('edit')
->setName(pht('Edit Remote'))
->setHref(
$this->getRepositoryControllerURI($repository, 'edit/remote/'))
->setWorkflow(!$can_edit)
->setDisabled(!$can_edit);
$view->addAction($edit);
return $view;
}
private function buildRemoteProperties(
PhabricatorRepository $repository,
PhabricatorActionListView $actions) {
$viewer = $this->getRequest()->getUser();
$view = id(new PHUIPropertyListView())
->setUser($viewer)
->setActionList($actions)
->addSectionHeader(pht('Remote'));
$view->addProperty(
pht('Remote URI'),
$repository->getDetail('remote-uri'));
return $view;
}
}

View file

@ -17,6 +17,13 @@ final class PhabricatorRepositoryEditor
$types[] = PhabricatorRepositoryTransaction::TYPE_SVN_SUBPATH;
$types[] = PhabricatorRepositoryTransaction::TYPE_NOTIFY;
$types[] = PhabricatorRepositoryTransaction::TYPE_AUTOCLOSE;
$types[] = PhabricatorRepositoryTransaction::TYPE_REMOTE_URI;
$types[] = PhabricatorRepositoryTransaction::TYPE_SSH_LOGIN;
$types[] = PhabricatorRepositoryTransaction::TYPE_SSH_KEY;
$types[] = PhabricatorRepositoryTransaction::TYPE_SSH_KEYFILE;
$types[] = PhabricatorRepositoryTransaction::TYPE_HTTP_LOGIN;
$types[] = PhabricatorRepositoryTransaction::TYPE_HTTP_PASS;
$types[] = PhabricatorTransactions::TYPE_VIEW_POLICY;
$types[] = PhabricatorTransactions::TYPE_EDIT_POLICY;
@ -50,6 +57,18 @@ final class PhabricatorRepositoryEditor
return (int)!$object->getDetail('herald-disabled');
case PhabricatorRepositoryTransaction::TYPE_AUTOCLOSE:
return (int)!$object->getDetail('disable-autoclose');
case PhabricatorRepositoryTransaction::TYPE_REMOTE_URI:
return $object->getDetail('remote-uri');
case PhabricatorRepositoryTransaction::TYPE_SSH_LOGIN:
return $object->getDetail('ssh-login');
case PhabricatorRepositoryTransaction::TYPE_SSH_KEY:
return $object->getDetail('ssh-key');
case PhabricatorRepositoryTransaction::TYPE_SSH_KEYFILE:
return $object->getDetail('ssh-keyfile');
case PhabricatorRepositoryTransaction::TYPE_HTTP_LOGIN:
return $object->getDetail('http-login');
case PhabricatorRepositoryTransaction::TYPE_HTTP_PASS:
return $object->getDetail('http-pass');
}
}
@ -67,6 +86,12 @@ final class PhabricatorRepositoryEditor
case PhabricatorRepositoryTransaction::TYPE_AUTOCLOSE_ONLY:
case PhabricatorRepositoryTransaction::TYPE_UUID:
case PhabricatorRepositoryTransaction::TYPE_SVN_SUBPATH:
case PhabricatorRepositoryTransaction::TYPE_REMOTE_URI:
case PhabricatorRepositoryTransaction::TYPE_SSH_LOGIN:
case PhabricatorRepositoryTransaction::TYPE_SSH_KEY:
case PhabricatorRepositoryTransaction::TYPE_SSH_KEYFILE:
case PhabricatorRepositoryTransaction::TYPE_HTTP_LOGIN:
case PhabricatorRepositoryTransaction::TYPE_HTTP_PASS:
return $xaction->getNewValue();
case PhabricatorRepositoryTransaction::TYPE_NOTIFY:
case PhabricatorRepositoryTransaction::TYPE_AUTOCLOSE:
@ -113,6 +138,24 @@ final class PhabricatorRepositoryEditor
case PhabricatorRepositoryTransaction::TYPE_AUTOCLOSE:
$object->setDetail('disable-autoclose', (int)!$xaction->getNewValue());
break;
case PhabricatorRepositoryTransaction::TYPE_REMOTE_URI:
$object->setDetail('remote-uri', $xaction->getNewValue());
break;
case PhabricatorRepositoryTransaction::TYPE_SSH_LOGIN:
$object->setDetail('ssh-login', $xaction->getNewValue());
break;
case PhabricatorRepositoryTransaction::TYPE_SSH_KEY:
$object->setDetail('ssh-key', $xaction->getNewValue());
break;
case PhabricatorRepositoryTransaction::TYPE_SSH_KEYFILE:
$object->setDetail('ssh-keyfile', $xaction->getNewValue());
break;
case PhabricatorRepositoryTransaction::TYPE_HTTP_LOGIN:
$object->setDetail('http-login', $xaction->getNewValue());
break;
case PhabricatorRepositoryTransaction::TYPE_HTTP_PASS:
$object->setDetail('http-pass', $xaction->getNewValue());
break;
case PhabricatorRepositoryTransaction::TYPE_ENCODING:
// Make sure the encoding is valid by converting to UTF-8. This tests
// that the user has mbstring installed, and also that they didn't type

View file

@ -14,6 +14,12 @@ final class PhabricatorRepositoryTransaction
const TYPE_UUID = 'repo:uuid';
const TYPE_NOTIFY = 'repo:notify';
const TYPE_AUTOCLOSE = 'repo:autoclose';
const TYPE_REMOTE_URI = 'repo:remote-uri';
const TYPE_SSH_LOGIN = 'repo:ssh-login';
const TYPE_SSH_KEY = 'repo:ssh-key';
const TYPE_SSH_KEYFILE = 'repo:ssh-keyfile';
const TYPE_HTTP_LOGIN = 'repo:http-login';
const TYPE_HTTP_PASS = 'repo:http-pass';
public function getApplicationName() {
return 'repository';
@ -187,7 +193,44 @@ final class PhabricatorRepositoryTransaction
$this->renderHandleLink($author_phid));
}
break;
case self::TYPE_REMOTE_URI:
if (!strlen($old)) {
return pht(
'%s set the remote URI for this repository to "%s".',
$this->renderHandleLink($author_phid),
$new);
} else if (!strlen($new)) {
return pht(
'%s removed the remote URI for this repository.',
$this->renderHandleLink($author_phid));
} else {
return pht(
'%s changed the remote URI for this repository from "%s" to "%s".',
$this->renderHandleLink($author_phid),
$old,
$new);
}
break;
case self::TYPE_SSH_LOGIN:
return pht(
'%s updated the SSH login for this repository.',
$this->renderHandleLink($author_phid));
case self::TYPE_SSH_KEY:
return pht(
'%s updated the SSH key for this repository.',
$this->renderHandleLink($author_phid));
case self::TYPE_SSH_KEYFILE:
return pht(
'%s updated the SSH keyfile for this repository.',
$this->renderHandleLink($author_phid));
case self::TYPE_HTTP_LOGIN:
return pht(
'%s updated the HTTP login for this repository.',
$this->renderHandleLink($author_phid));
case self::TYPE_HTTP_PASS:
return pht(
'%s updated the HTTP password for this repository.',
$this->renderHandleLink($author_phid));
}
return parent::getTitle();

View file

@ -190,6 +190,10 @@ class PHUIFormPageView extends AphrontView {
}
public function readFromObject($object) {
foreach ($this->getControls() as $name => $control) {
$control->readValueFromDictionary($object);
}
return $this;
}

View file

@ -1,7 +1,6 @@
<?php
/**
*
* @task page Managing Pages
*/
final class PHUIPagedFormView extends AphrontTagView {
@ -13,6 +12,7 @@ final class PHUIPagedFormView extends AphrontTagView {
private $nextPage;
private $prevPage;
private $complete;
private $cancelURI;
protected function canAppendChild() {
return false;
@ -211,6 +211,15 @@ final class PHUIPagedFormView extends AphrontTagView {
return $this->name.':'.$key;
}
public function setCancelURI($cancel_uri) {
$this->cancelURI = $cancel_uri;
return $this;
}
public function getCancelURI() {
return $this->cancelURI;
}
public function getTagContent() {
$form = id(new AphrontFormView())
->setUser($this->getUser());
@ -240,6 +249,8 @@ final class PHUIPagedFormView extends AphrontTagView {
if (!$this->isFirstPage($selected_page)) {
$submit->addBackButton();
} else if ($this->getCancelURI()) {
$submit->addCancelButton($this->getCancelURI());
}
if ($this->isLastPage($selected_page)) {
@ -261,11 +272,10 @@ final class PHUIPagedFormView extends AphrontTagView {
->setHeader($selected_page->getPageName());
}
return array(
$header,
$errors,
$form,
);
return id(new PHUIObjectBoxView())
->setHeader($header)
->setFormError($errors)
->setForm($form);
}
}

View file

@ -126,6 +126,11 @@ abstract class AphrontFormControl extends AphrontView {
return $this;
}
public function readValueFromDictionary(array $dictionary) {
$this->setValue(idx($dictionary, $this->getName()));
return $this;
}
public function setFormPage(PHUIFormPageView $page) {
if ($this->formPage) {
throw new Exception("This control is already a member of a page!");

View file

@ -15,6 +15,22 @@ final class PHUIFormMultiSubmitControl extends AphrontFormControl {
return $this->addButton('__submit__', $label);
}
public function addCancelButton($uri, $label = null) {
if ($label === null) {
$label = pht('Cancel');
}
$this->buttons[] = phutil_tag(
'a',
array(
'class' => 'grey button',
'href' => $uri,
),
$label);
return $this;
}
public function addButton($name, $label, $class = null) {
$this->buttons[] = phutil_tag(
'input',

View file

@ -108,7 +108,8 @@
margin: 4px 0 0 8px;
}
.phui-form-control-multi-submit input {
.phui-form-control-multi-submit input,
.phui-form-control-multi-submit a {
float: right;
margin: 0.5em 0 0em 2%;
width: auto;