@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.

Split "Edit Blocking Tasks" into "Edit Parent Tasks" and "Edit Subtasks"

Summary:
Ref T11179. This splits "Edit Blocking Tasks" into two options now that we have more room ("Edit Parent Tasks", "Edit Subtasks").

This also renames "Blocking" tasks to "Subtasks", and "Blocked" tasks to "Parent" tasks. My goals here are:

- Make the relationship direction more clear: it's more clear which way is up with "parent" and "subtask" at a glance than with "blocking" and "blocked" or "dependent" and "dependency".
- Align language with "Create Subtask".
- To some small degree, use more flexible/general-purpose language, although I haven't seen any real confusion here.

Fixes T6815. I think I narrowed this down to two issues:

- Just throwing a bare exeception (we now return a dialog explicitly).
- Not killing open transactions when the cyclec check fails (we now kill them).

Test Plan:
- Edited parent tasks.
- Edited subtasks.
- Tried to introduce graph cycles, got a nice error dialog.

{F1697087}

{F1697088}

Reviewers: chad

Reviewed By: chad

Maniphest Tasks: T6815, T11179

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

+166 -74
+4
src/__phutil_library_map__.php
··· 1422 1422 'ManiphestTaskHasCommitRelationship' => 'applications/maniphest/relationship/ManiphestTaskHasCommitRelationship.php', 1423 1423 'ManiphestTaskHasMockEdgeType' => 'applications/maniphest/edge/ManiphestTaskHasMockEdgeType.php', 1424 1424 'ManiphestTaskHasMockRelationship' => 'applications/maniphest/relationship/ManiphestTaskHasMockRelationship.php', 1425 + 'ManiphestTaskHasParentRelationship' => 'applications/maniphest/relationship/ManiphestTaskHasParentRelationship.php', 1425 1426 'ManiphestTaskHasRevisionEdgeType' => 'applications/maniphest/edge/ManiphestTaskHasRevisionEdgeType.php', 1426 1427 'ManiphestTaskHasRevisionRelationship' => 'applications/maniphest/relationship/ManiphestTaskHasRevisionRelationship.php', 1428 + 'ManiphestTaskHasSubtaskRelationship' => 'applications/maniphest/relationship/ManiphestTaskHasSubtaskRelationship.php', 1427 1429 'ManiphestTaskHeraldField' => 'applications/maniphest/herald/ManiphestTaskHeraldField.php', 1428 1430 'ManiphestTaskHeraldFieldGroup' => 'applications/maniphest/herald/ManiphestTaskHeraldFieldGroup.php', 1429 1431 'ManiphestTaskListController' => 'applications/maniphest/controller/ManiphestTaskListController.php', ··· 5913 5915 'ManiphestTaskHasCommitRelationship' => 'ManiphestTaskRelationship', 5914 5916 'ManiphestTaskHasMockEdgeType' => 'PhabricatorEdgeType', 5915 5917 'ManiphestTaskHasMockRelationship' => 'ManiphestTaskRelationship', 5918 + 'ManiphestTaskHasParentRelationship' => 'ManiphestTaskRelationship', 5916 5919 'ManiphestTaskHasRevisionEdgeType' => 'PhabricatorEdgeType', 5917 5920 'ManiphestTaskHasRevisionRelationship' => 'ManiphestTaskRelationship', 5921 + 'ManiphestTaskHasSubtaskRelationship' => 'ManiphestTaskRelationship', 5918 5922 'ManiphestTaskHeraldField' => 'HeraldField', 5919 5923 'ManiphestTaskHeraldFieldGroup' => 'HeraldFieldGroup', 5920 5924 'ManiphestTaskListController' => 'ManiphestController',
+4 -4
src/applications/auth/controller/PhabricatorAuthStartController.php
··· 225 225 } 226 226 227 227 // Often, users end up here by clicking a disabled action link in the UI 228 - // (for example, they might click "Edit Blocking Tasks" on a Maniphest 229 - // task page). After they log in we want to send them back to that main 230 - // object page if we can, since it's confusing to end up on a standalone 231 - // page with only a dialog (particularly if that dialog is another error, 228 + // (for example, they might click "Edit Subtasks" on a Maniphest task 229 + // page). After they log in we want to send them back to that main object 230 + // page if we can, since it's confusing to end up on a standalone page with 231 + // only a dialog (particularly if that dialog is another error, 232 232 // like a policy exception). 233 233 234 234 $via_header = AphrontRequest::getViaHeaderName();
+14 -12
src/applications/maniphest/controller/ManiphestTaskDetailController.php
··· 195 195 ->setDisabled(!$can_create) 196 196 ->setWorkflow(!$can_create); 197 197 198 - $task_submenu[] = id(new PhabricatorActionView()) 199 - ->setName(pht('Edit Blocking Tasks')) 200 - ->setHref("/search/attach/{$phid}/TASK/blocks/") 201 - ->setIcon('fa-link') 202 - ->setDisabled(!$can_edit) 203 - ->setWorkflow(true); 198 + $relationship_list = PhabricatorObjectRelationshipList::newForObject( 199 + $viewer, 200 + $task); 201 + 202 + $parent_key = ManiphestTaskHasParentRelationship::RELATIONSHIPKEY; 203 + $subtask_key = ManiphestTaskHasSubtaskRelationship::RELATIONSHIPKEY; 204 + 205 + $task_submenu[] = $relationship_list->getRelationship($parent_key) 206 + ->newAction($task); 207 + 208 + $task_submenu[] = $relationship_list->getRelationship($subtask_key) 209 + ->newAction($task); 204 210 205 211 $task_submenu[] = id(new PhabricatorActionView()) 206 212 ->setName(pht('Merge Duplicates In')) ··· 214 220 ->setName(pht('Edit Related Tasks...')) 215 221 ->setIcon('fa-anchor') 216 222 ->setSubmenu($task_submenu)); 217 - 218 - $relationship_list = PhabricatorObjectRelationshipList::newForObject( 219 - $viewer, 220 - $task); 221 223 222 224 $relationship_submenu = $relationship_list->newActionMenu(); 223 225 if ($relationship_submenu) { ··· 288 290 289 291 $edge_types = array( 290 292 ManiphestTaskDependedOnByTaskEdgeType::EDGECONST 291 - => pht('Blocks'), 293 + => pht('Parent Tasks'), 292 294 ManiphestTaskDependsOnTaskEdgeType::EDGECONST 293 - => pht('Blocked By'), 295 + => pht('Subtasks'), 294 296 ManiphestTaskHasRevisionEdgeType::EDGECONST 295 297 => pht('Differential Revisions'), 296 298 ManiphestTaskHasMockEdgeType::EDGECONST
+6 -6
src/applications/maniphest/edge/ManiphestTaskDependedOnByTaskEdgeType.php
··· 17 17 $add_edges) { 18 18 19 19 return pht( 20 - '%s added %s blocked task(s): %s.', 20 + '%s added %s parent task(s): %s.', 21 21 $actor, 22 22 $add_count, 23 23 $add_edges); ··· 29 29 $rem_edges) { 30 30 31 31 return pht( 32 - '%s removed %s blocked task(s): %s.', 32 + '%s removed %s parent task(s): %s.', 33 33 $actor, 34 34 $rem_count, 35 35 $rem_edges); ··· 44 44 $rem_edges) { 45 45 46 46 return pht( 47 - '%s edited blocked task(s), added %s: %s; removed %s: %s.', 47 + '%s edited parent task(s), added %s: %s; removed %s: %s.', 48 48 $actor, 49 49 $add_count, 50 50 $add_edges, ··· 59 59 $add_edges) { 60 60 61 61 return pht( 62 - '%s added %s blocked task(s) for %s: %s.', 62 + '%s added %s parent task(s) for %s: %s.', 63 63 $actor, 64 64 $add_count, 65 65 $object, ··· 73 73 $rem_edges) { 74 74 75 75 return pht( 76 - '%s removed %s blocked task(s) for %s: %s.', 76 + '%s removed %s parent task(s) for %s: %s.', 77 77 $actor, 78 78 $rem_count, 79 79 $object, ··· 90 90 $rem_edges) { 91 91 92 92 return pht( 93 - '%s edited blocked task(s) for %s, added %s: %s; removed %s: %s.', 93 + '%s edited parent task(s) for %s, added %s: %s; removed %s: %s.', 94 94 $actor, 95 95 $object, 96 96 $add_count,
+6 -6
src/applications/maniphest/edge/ManiphestTaskDependsOnTaskEdgeType.php
··· 22 22 $add_edges) { 23 23 24 24 return pht( 25 - '%s added %s blocking task(s): %s.', 25 + '%s added %s subtask(s): %s.', 26 26 $actor, 27 27 $add_count, 28 28 $add_edges); ··· 34 34 $rem_edges) { 35 35 36 36 return pht( 37 - '%s removed %s blocking task(s): %s.', 37 + '%s removed %s subtask(s): %s.', 38 38 $actor, 39 39 $rem_count, 40 40 $rem_edges); ··· 49 49 $rem_edges) { 50 50 51 51 return pht( 52 - '%s edited blocking task(s), added %s: %s; removed %s: %s.', 52 + '%s edited subtask(s), added %s: %s; removed %s: %s.', 53 53 $actor, 54 54 $add_count, 55 55 $add_edges, ··· 64 64 $add_edges) { 65 65 66 66 return pht( 67 - '%s added %s blocking task(s) for %s: %s.', 67 + '%s added %s subtask(s) for %s: %s.', 68 68 $actor, 69 69 $add_count, 70 70 $object, ··· 78 78 $rem_edges) { 79 79 80 80 return pht( 81 - '%s removed %s blocking task(s) for %s: %s.', 81 + '%s removed %s subtask(s) for %s: %s.', 82 82 $actor, 83 83 $rem_count, 84 84 $object, ··· 95 95 $rem_edges) { 96 96 97 97 return pht( 98 - '%s edited blocking task(s) for %s, added %s: %s; removed %s: %s.', 98 + '%s edited subtask(s) for %s, added %s: %s; removed %s: %s.', 99 99 $actor, 100 100 $object, 101 101 $add_count,
+1 -1
src/applications/maniphest/editor/ManiphestTransactionEditor.php
··· 325 325 ManiphestTransaction::MAILTAG_PROJECTS => 326 326 pht("A task's associated projects change."), 327 327 ManiphestTransaction::MAILTAG_UNBLOCK => 328 - pht('One of the tasks a task is blocked by changes status.'), 328 + pht("One of a task's subtasks changes status."), 329 329 ManiphestTransaction::MAILTAG_COLUMN => 330 330 pht('A task is moved between columns on a workboard.'), 331 331 ManiphestTransaction::MAILTAG_COMMENT =>
+40
src/applications/maniphest/relationship/ManiphestTaskHasParentRelationship.php
··· 1 + <?php 2 + 3 + final class ManiphestTaskHasParentRelationship 4 + extends ManiphestTaskRelationship { 5 + 6 + const RELATIONSHIPKEY = 'task.has-parent'; 7 + 8 + public function getEdgeConstant() { 9 + return ManiphestTaskDependedOnByTaskEdgeType::EDGECONST; 10 + } 11 + 12 + protected function getActionName() { 13 + return pht('Edit Parent Tasks'); 14 + } 15 + 16 + protected function getActionIcon() { 17 + return 'fa-chevron-circle-up'; 18 + } 19 + 20 + public function canRelateObjects($src, $dst) { 21 + return ($dst instanceof ManiphestTask); 22 + } 23 + 24 + public function shouldAppearInActionMenu() { 25 + return false; 26 + } 27 + 28 + public function getDialogTitleText() { 29 + return pht('Edit Parent Tasks'); 30 + } 31 + 32 + public function getDialogHeaderText() { 33 + return pht('Current Parent Tasks'); 34 + } 35 + 36 + public function getDialogButtonText() { 37 + return pht('Save Parent Tasks'); 38 + } 39 + 40 + }
+40
src/applications/maniphest/relationship/ManiphestTaskHasSubtaskRelationship.php
··· 1 + <?php 2 + 3 + final class ManiphestTaskHasSubtaskRelationship 4 + extends ManiphestTaskRelationship { 5 + 6 + const RELATIONSHIPKEY = 'task.has-subtask'; 7 + 8 + public function getEdgeConstant() { 9 + return ManiphestTaskDependsOnTaskEdgeType::EDGECONST; 10 + } 11 + 12 + protected function getActionName() { 13 + return pht('Edit Subtasks'); 14 + } 15 + 16 + protected function getActionIcon() { 17 + return 'fa-chevron-circle-down'; 18 + } 19 + 20 + public function canRelateObjects($src, $dst) { 21 + return ($dst instanceof ManiphestTask); 22 + } 23 + 24 + public function shouldAppearInActionMenu() { 25 + return false; 26 + } 27 + 28 + public function getDialogTitleText() { 29 + return pht('Edit Subtasks'); 30 + } 31 + 32 + public function getDialogHeaderText() { 33 + return pht('Current Subtasks'); 34 + } 35 + 36 + public function getDialogButtonText() { 37 + return pht('Save Subtasks'); 38 + } 39 + 40 + }
+7 -7
src/applications/maniphest/storage/ManiphestTransaction.php
··· 500 500 501 501 if ($this->getMetadataValue('blocker.new')) { 502 502 return pht( 503 - '%s created blocking task %s.', 503 + '%s created subtask %s.', 504 504 $this->renderHandleLink($author_phid), 505 505 $this->renderHandleLink($blocker_phid)); 506 506 } else if ($old_closed && !$new_closed) { 507 507 return pht( 508 - '%s reopened blocking task %s as "%s".', 508 + '%s reopened subtask %s as "%s".', 509 509 $this->renderHandleLink($author_phid), 510 510 $this->renderHandleLink($blocker_phid), 511 511 $new_name); 512 512 } else if (!$old_closed && $new_closed) { 513 513 return pht( 514 - '%s closed blocking task %s as "%s".', 514 + '%s closed subtask %s as "%s".', 515 515 $this->renderHandleLink($author_phid), 516 516 $this->renderHandleLink($blocker_phid), 517 517 $new_name); 518 518 } else { 519 519 return pht( 520 - '%s changed the status of blocking task %s from "%s" to "%s".', 520 + '%s changed the status of subtask %s from "%s" to "%s".', 521 521 $this->renderHandleLink($author_phid), 522 522 $this->renderHandleLink($blocker_phid), 523 523 $old_name, ··· 753 753 754 754 if ($old_closed && !$new_closed) { 755 755 return pht( 756 - '%s reopened %s, a task blocking %s, as "%s".', 756 + '%s reopened %s, a subtask of %s, as "%s".', 757 757 $this->renderHandleLink($author_phid), 758 758 $this->renderHandleLink($blocker_phid), 759 759 $this->renderHandleLink($object_phid), 760 760 $new_name); 761 761 } else if (!$old_closed && $new_closed) { 762 762 return pht( 763 - '%s closed %s, a task blocking %s, as "%s".', 763 + '%s closed %s, a subtask of %s, as "%s".', 764 764 $this->renderHandleLink($author_phid), 765 765 $this->renderHandleLink($blocker_phid), 766 766 $this->renderHandleLink($object_phid), 767 767 $new_name); 768 768 } else { 769 769 return pht( 770 - '%s changed the status of %s, a task blocking %s, '. 770 + '%s changed the status of %s, a subtasktask of %s, '. 771 771 'from "%s" to "%s".', 772 772 $this->renderHandleLink($author_phid), 773 773 $this->renderHandleLink($blocker_phid),
+6 -2
src/applications/search/controller/PhabricatorSearchRelationshipController.php
··· 140 140 ManiphestTaskHasCommitEdgeType::EDGECONST => 'CMIT', 141 141 ManiphestTaskHasMockEdgeType::EDGECONST => 'MOCK', 142 142 ManiphestTaskHasRevisionEdgeType::EDGECONST => 'DREV', 143 + ManiphestTaskDependsOnTaskEdgeType::EDGECONST => 'TASK', 144 + ManiphestTaskDependedOnByTaskEdgeType::EDGECONST => 'TASK', 143 145 ); 144 146 145 147 $edge_type = $relationship->getEdgeConstant(); ··· 180 182 181 183 $message = pht( 182 184 'You can not create that relationship because it would create a '. 183 - 'circular dependency: %s.', 184 - implode(" \xE2\x86\x92 ", $names)); 185 + 'circular dependency:'); 186 + 187 + $list = implode(" \xE2\x86\x92 ", $names); 185 188 186 189 return $this->newDialog() 187 190 ->setTitle(pht('Circular Dependency')) 188 191 ->appendParagraph($message) 192 + ->appendParagraph($list) 189 193 ->addCancelButton($done_uri); 190 194 } 191 195
+6 -3
src/applications/transactions/editor/PhabricatorApplicationTransactionEditor.php
··· 931 931 $object->openTransaction(); 932 932 } 933 933 934 + try { 934 935 foreach ($xactions as $xaction) { 935 936 $this->applyInternalEffects($object, $xaction); 936 937 } ··· 940 941 try { 941 942 $object->save(); 942 943 } catch (AphrontDuplicateKeyQueryException $ex) { 943 - $object->killTransaction(); 944 - 945 944 // This callback has an opportunity to throw a better exception, 946 945 // so execution may end here. 947 946 $this->didCatchDuplicateKeyException($object, $xactions, $ex); ··· 973 972 $read_locking = false; 974 973 } 975 974 976 - $object->saveTransaction(); 975 + $object->saveTransaction(); 976 + } catch (Exception $ex) { 977 + $object->killTransaction(); 978 + throw $ex; 979 + } 977 980 978 981 // Now that we've completely applied the core transaction set, try to apply 979 982 // Herald rules. Herald rules are allowed to either take direct actions on
-1
src/infrastructure/edges/editor/PhabricatorEdgeEditor.php
··· 134 134 $caught = $ex; 135 135 } 136 136 137 - 138 137 if ($caught) { 139 138 $this->killTransactions(); 140 139 }
+32 -32
src/infrastructure/internationalization/translation/PhabricatorUSEnglishTranslation.php
··· 206 206 ), 207 207 ), 208 208 209 - '%s added %s blocking task(s): %s.' => array( 209 + '%s added %s subtask(s): %s.' => array( 210 210 array( 211 - '%s added a blocking task: %3$s.', 212 - '%s added blocking tasks: %3$s.', 211 + '%s added a subtask: %3$s.', 212 + '%s added subtasks: %3$s.', 213 213 ), 214 214 ), 215 215 216 - '%s added %s blocked task(s): %s.' => array( 216 + '%s added %s parent task(s): %s.' => array( 217 217 array( 218 - '%s added a blocked task: %3$s.', 219 - '%s added blocked tasks: %3$s.', 218 + '%s added a parent task: %3$s.', 219 + '%s added parent tasks: %3$s.', 220 220 ), 221 221 ), 222 222 223 - '%s removed %s blocking task(s): %s.' => array( 223 + '%s removed %s subtask(s): %s.' => array( 224 224 array( 225 - '%s removed a blocking task: %3$s.', 226 - '%s removed blocking tasks: %3$s.', 225 + '%s removed a subtask: %3$s.', 226 + '%s removed subtasks: %3$s.', 227 227 ), 228 228 ), 229 229 230 - '%s removed %s blocked task(s): %s.' => array( 230 + '%s removed %s parent task(s): %s.' => array( 231 231 array( 232 - '%s removed a blocked task: %3$s.', 233 - '%s removed blocked tasks: %3$s.', 232 + '%s removed a parent task: %3$s.', 233 + '%s removed parent tasks: %3$s.', 234 234 ), 235 235 ), 236 236 237 - '%s added %s blocking task(s) for %s: %s.' => array( 237 + '%s added %s subtask(s) for %s: %s.' => array( 238 238 array( 239 - '%s added a blocking task for %3$s: %4$s.', 240 - '%s added blocking tasks for %3$s: %4$s.', 239 + '%s added a subtask for %3$s: %4$s.', 240 + '%s added subtasks for %3$s: %4$s.', 241 241 ), 242 242 ), 243 243 244 - '%s added %s blocked task(s) for %s: %s.' => array( 244 + '%s added %s parent task(s) for %s: %s.' => array( 245 245 array( 246 - '%s added a blocked task for %3$s: %4$s.', 247 - '%s added blocked tasks for %3$s: %4$s.', 246 + '%s added a parent task for %3$s: %4$s.', 247 + '%s added parent tasks for %3$s: %4$s.', 248 248 ), 249 249 ), 250 250 251 - '%s removed %s blocking task(s) for %s: %s.' => array( 251 + '%s removed %s subtask(s) for %s: %s.' => array( 252 252 array( 253 - '%s removed a blocking task for %3$s: %4$s.', 254 - '%s removed blocking tasks for %3$s: %4$s.', 253 + '%s removed a subtask for %3$s: %4$s.', 254 + '%s removed subtasks for %3$s: %4$s.', 255 255 ), 256 256 ), 257 257 258 - '%s removed %s blocked task(s) for %s: %s.' => array( 258 + '%s removed %s parent task(s) for %s: %s.' => array( 259 259 array( 260 - '%s removed a blocked task for %3$s: %4$s.', 261 - '%s removed blocked tasks for %3$s: %4$s.', 260 + '%s removed a parent task for %3$s: %4$s.', 261 + '%s removed parent tasks for %3$s: %4$s.', 262 262 ), 263 263 ), 264 264 265 - '%s edited blocking task(s), added %s: %s; removed %s: %s.' => 266 - '%s edited blocking tasks, added: %3$s; removed: %5$s.', 265 + '%s edited subtask(s), added %s: %s; removed %s: %s.' => 266 + '%s edited subtasks, added: %3$s; removed: %5$s.', 267 267 268 - '%s edited blocking task(s) for %s, added %s: %s; removed %s: %s.' => 269 - '%s edited blocking tasks for %s, added: %4$s; removed: %6$s.', 268 + '%s edited subtask(s) for %s, added %s: %s; removed %s: %s.' => 269 + '%s edited subtasks for %s, added: %4$s; removed: %6$s.', 270 270 271 - '%s edited blocked task(s), added %s: %s; removed %s: %s.' => 272 - '%s edited blocked tasks, added: %3$s; removed: %5$s.', 271 + '%s edited parent task(s), added %s: %s; removed %s: %s.' => 272 + '%s edited parent tasks, added: %3$s; removed: %5$s.', 273 273 274 - '%s edited blocked task(s) for %s, added %s: %s; removed %s: %s.' => 275 - '%s edited blocked tasks for %s, added: %4$s; removed: %6$s.', 274 + '%s edited parent task(s) for %s, added %s: %s; removed %s: %s.' => 275 + '%s edited parent tasks for %s, added: %4$s; removed: %6$s.', 276 276 277 277 '%s edited answer(s), added %s: %s; removed %d: %s.' => 278 278 '%s edited answers, added: %3$s; removed: %5$s.',