@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Modernize Releeph project create controller

Summary:
Ref T3092.

- Check for a duplicate key error;
- do less single loading and use Query classes;
- use responsive UI elements;
- add crumbs.

Test Plan: Created a new project, and hit error cases.

Reviewers: btrahan

Reviewed By: btrahan

CC: aran

Maniphest Tasks: T3092

Differential Revision: https://secure.phabricator.com/D6629

+110 -51
+73 -51
src/applications/releeph/controller/project/ReleephProjectCreateController.php
··· 8 8 $trunk_branch = trim($request->getStr('trunkBranch')); 9 9 $arc_pr_id = $request->getInt('arcPrID'); 10 10 11 - 12 - // Only allow arc projects with repositories. Sort and re-key by ID. 13 - $arc_projects = id(new PhabricatorRepositoryArcanistProject())->loadAll(); 14 - $arc_projects = mpull( 15 - msort( 16 - mfilter($arc_projects, 'getRepositoryID'), 17 - 'getName'), 18 - null, 19 - 'getID'); 11 + $arc_projects = $this->loadArcProjects(); 20 12 21 13 $e_name = true; 22 14 $e_trunk_branch = true; ··· 25 17 if ($request->isFormPost()) { 26 18 if (!$name) { 27 19 $e_name = pht('Required'); 28 - $errors[] = 29 - pht('Your Releeph project should have a simple descriptive name.'); 20 + $errors[] = pht( 21 + 'Your Releeph project should have a simple descriptive name.'); 30 22 } 31 23 32 24 if (!$trunk_branch) { 33 25 $e_trunk_branch = pht('Required'); 34 - $errors[] = 35 - pht('You must specify which branch you will be picking from.'); 36 - } 37 - 38 - $all_names = mpull(id(new ReleephProject())->loadAll(), 'getName'); 39 - 40 - if (in_array($name, $all_names)) { 41 - $errors[] = pht('Releeph project name %s is already taken', $name); 26 + $errors[] = pht( 27 + 'You must specify which branch you will be picking from.'); 42 28 } 43 29 44 30 $arc_project = $arc_projects[$arc_pr_id]; ··· 52 38 ->setRepositoryPHID($pr_repository->getPHID()) 53 39 ->setArcanistProjectID($arc_project->getID()) 54 40 ->setCreatedByUserPHID($request->getUser()->getPHID()) 55 - ->setIsActive(1) 56 - ->save(); 41 + ->setIsActive(1); 42 + 43 + try { 44 + $releeph_project->save(); 57 45 58 - return id(new AphrontRedirectResponse())->setURI('/releeph/'); 46 + return id(new AphrontRedirectResponse()) 47 + ->setURI($releeph_project->getURI()); 48 + } catch (AphrontQueryDuplicateKeyException $ex) { 49 + $e_name = pht('Not Unique'); 50 + $errors[] = pht( 51 + 'Another project already uses this name.'); 52 + } 59 53 } 60 54 } 61 55 ··· 63 57 if ($errors) { 64 58 $error_view = new AphrontErrorView(); 65 59 $error_view->setErrors($errors); 66 - $error_view->setTitle(pht('Form Errors')); 67 60 } 68 61 69 - // Make our own optgroup select control 70 - $arc_project_choices = array(); 71 - $pr_repositories = mpull( 72 - msort( 73 - array_filter( 74 - // Some arc-projects don't have repositories 75 - mpull($arc_projects, 'loadRepository')), 76 - 'getName'), 77 - null, 78 - 'getID'); 79 - 80 - foreach ($pr_repositories as $pr_repo_id => $pr_repository) { 81 - $options = array(); 82 - foreach ($arc_projects as $arc_project) { 83 - if ($arc_project->getRepositoryID() == $pr_repo_id) { 84 - $options[$arc_project->getID()] = $arc_project->getName(); 85 - } 86 - } 87 - $arc_project_choices[$pr_repository->getName()] = $options; 88 - } 62 + $arc_project_options = $this->getArcProjectSelectOptions($arc_projects); 89 63 90 64 $project_name_input = id(new AphrontFormTextControl()) 91 65 ->setLabel(pht('Name')) ··· 108 82 'target' => '_blank', 109 83 ), 110 84 'here'))) 111 - ->setOptions($arc_project_choices); 85 + ->setOptions($arc_project_options); 112 86 113 87 $branch_name_preview = id(new ReleephBranchPreviewView()) 114 88 ->setLabel(pht('Example Branch')) ··· 119 93 120 94 $form = id(new AphrontFormView()) 121 95 ->setUser($request->getUser()) 96 + ->setFlexible(true) 122 97 ->appendChild($project_name_input) 123 98 ->appendChild($arc_project_input) 124 99 ->appendChild( ··· 135 110 ->addCancelButton('/releeph/project/') 136 111 ->setValue(pht('Create'))); 137 112 138 - $panel = id(new AphrontPanelView()) 139 - ->setHeader(pht('Create Releeph Project')) 140 - ->appendChild($form) 141 - ->setWidth(AphrontPanelView::WIDTH_FORM); 113 + $crumbs = $this->buildApplicationCrumbs(); 114 + $crumbs->addCrumb( 115 + id(new PhabricatorCrumbView()) 116 + ->setName(pht('New Project'))); 142 117 143 - return $this->buildStandardPageResponse( 144 - array($error_view, $panel), 118 + return $this->buildApplicationPage( 119 + array( 120 + $crumbs, 121 + $error_view, 122 + $form, 123 + ), 145 124 array( 146 - 'title' => pht('Create New Releeph Project') 125 + 'title' => pht('Create New Project'), 126 + 'dust' => true, 127 + 'device' => true, 147 128 )); 148 129 } 130 + 131 + private function loadArcProjects() { 132 + $viewer = $this->getRequest()->getUser(); 133 + 134 + $projects = id(new PhabricatorRepositoryArcanistProjectQuery()) 135 + ->setViewer($viewer) 136 + ->needRepositories(true) 137 + ->execute(); 138 + 139 + $projects = mfilter($projects, 'getRepository'); 140 + $projects = msort($projects, 'getName'); 141 + 142 + return $projects; 143 + } 144 + 145 + private function getArcProjectSelectOptions(array $arc_projects) { 146 + assert_instances_of($arc_projects, 'PhabricatorRepositoryArcanistProject'); 147 + 148 + $repos = mpull($arc_projects, 'getRepository'); 149 + $repos = mpull($repos, null, 'getID'); 150 + 151 + $groups = array(); 152 + foreach ($arc_projects as $arc_project) { 153 + $id = $arc_project->getID(); 154 + $repo_id = $arc_project->getRepository()->getID(); 155 + $groups[$repo_id][$id] = $arc_project->getName(); 156 + } 157 + 158 + $choices = array(); 159 + foreach ($groups as $repo_id => $group) { 160 + $repo_name = $repos[$repo_id]->getName(); 161 + $callsign = $repos[$repo_id]->getCallsign(); 162 + $name = "r{$callsign} ({$repo_name})"; 163 + $choices[$name] = $group; 164 + } 165 + 166 + ksort($choices); 167 + 168 + return $choices; 169 + } 170 + 149 171 }
+25
src/applications/repository/query/PhabricatorRepositoryArcanistProjectQuery.php
··· 9 9 private $ids; 10 10 private $phids; 11 11 12 + private $needRepositories; 13 + 12 14 public function withIDs(array $ids) { 13 15 $this->ids = $ids; 14 16 return $this; ··· 16 18 17 19 public function withPHIDs(array $phids) { 18 20 $this->phids = $phids; 21 + return $this; 22 + } 23 + 24 + public function needRepositories($need_repositories) { 25 + $this->needRepositories = $need_repositories; 19 26 return $this; 20 27 } 21 28 ··· 32 39 $this->buildLimitClause($conn_r)); 33 40 34 41 return $table->loadAllFromArray($data); 42 + } 43 + 44 + public function willFilterPage(array $projects) { 45 + assert_instances_of($projects, 'PhabricatorRepositoryArcanistProject'); 46 + 47 + if ($this->needRepositories) { 48 + $repository_ids = mpull($projects, 'getRepositoryID'); 49 + $repositories = id(new PhabricatorRepositoryQuery()) 50 + ->setViewer($this->getViewer()) 51 + ->withIDs($repository_ids) 52 + ->execute(); 53 + foreach ($projects as $project) { 54 + $repo = idx($repositories, $project->getRepositoryID()); 55 + $project->attachRepository($repo); 56 + } 57 + } 58 + 59 + return $projects; 35 60 } 36 61 37 62 private function buildWhereClause(AphrontDatabaseConnection $conn_r) {
+12
src/applications/repository/storage/PhabricatorRepositoryArcanistProject.php
··· 14 14 protected $symbolIndexLanguages = array(); 15 15 protected $symbolIndexProjects = array(); 16 16 17 + private $repository = self::ATTACHABLE; 18 + 17 19 public function getConfiguration() { 18 20 return array( 19 21 self::CONFIG_AUX_PHID => true, ··· 30 32 PhabricatorRepositoryPHIDTypeArcanistProject::TYPECONST); 31 33 } 32 34 35 + // TODO: Remove. 33 36 public function loadRepository() { 34 37 if (!$this->getRepositoryID()) { 35 38 return null; ··· 49 52 $result = parent::delete(); 50 53 $this->saveTransaction(); 51 54 return $result; 55 + } 56 + 57 + public function getRepository() { 58 + return $this->assertAttached($this->repository); 59 + } 60 + 61 + public function attachRepository(PhabricatorRepository $repository = null) { 62 + $this->repository = $repository; 63 + return $this; 52 64 } 53 65 54 66