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

Route task merges through new editor

Summary:
Ref T2217. Ship "Merge in Duplicates" through the new editor. The only notable thing here is `setContinueOnMissingFields()`.

The problem this solves is that if you add a custom field and mark it as required, all existing tasks are "invalid" since they don't have a value, and trying to edit them will raise an error like "Some Custom Field is required!". This is fine for normal edits via the UI, since the user can just select/provide a value, but surgical edits to specific fields should just ignore these errors. Add the ability to ignore these errors and use it on all the field-speific editors.

Test Plan: Merged duplicates, including "invalid" duplicates with missing fields.

Reviewers: btrahan

Reviewed By: btrahan

CC: aran

Maniphest Tasks: T2217

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

+89 -15
+4
src/applications/maniphest/conduit/ConduitAPI_maniphest_Method.php
··· 204 204 ->setContentSource($content_source) 205 205 ->setContinueOnNoEffect(true); 206 206 207 + if (!$is_new) { 208 + $editor->setContinueOnMissingFields(true); 209 + } 210 + 207 211 $editor->applyTransactions($task, $transactions); 208 212 209 213 $event = new PhabricatorEvent(
+1
src/applications/maniphest/controller/ManiphestBatchEditController.php
··· 35 35 ->setActor($user) 36 36 ->setContentSourceFromRequest($request) 37 37 ->setContinueOnNoEffect(true) 38 + ->setContinueOnMissingFields(true) 38 39 ->applyTransactions($task, $xactions); 39 40 } 40 41 }
+2 -1
src/applications/maniphest/controller/ManiphestSubpriorityController.php
··· 44 44 45 45 $editor = id(new ManiphestTransactionEditorPro()) 46 46 ->setActor($user) 47 - ->setContinueOnNoEffect($request->isContinueRequest()) 47 + ->setContinueOnMissingFields(true) 48 + ->setContinueOnNoEffect(true) 48 49 ->setContentSourceFromRequest($request); 49 50 50 51 $editor->applyTransactions($task, $xactions);
+29 -12
src/applications/search/controller/PhabricatorSearchAttachController.php
··· 157 157 return $response; 158 158 } 159 159 160 - $editor = new ManiphestTransactionEditor(); 161 - $editor->setActor($user); 160 + $editor = id(new ManiphestTransactionEditorPro()) 161 + ->setActor($user) 162 + ->setContentSourceFromRequest($this->getRequest()) 163 + ->setContinueOnNoEffect(true) 164 + ->setContinueOnMissingFields(true); 162 165 163 166 $task_names = array(); 164 167 ··· 172 175 $target->getAuthorPHID(), 173 176 $target->getOwnerPHID()); 174 177 175 - $close_task = id(new ManiphestTransaction()) 176 - ->setAuthorPHID($user->getPHID()) 178 + $close_task = id(new ManiphestTransactionPro()) 177 179 ->setTransactionType(ManiphestTransactionType::TYPE_STATUS) 178 - ->setNewValue(ManiphestTaskStatus::STATUS_CLOSED_DUPLICATE) 179 - ->setComments("\xE2\x9C\x98 Merged into {$merge_into_name}."); 180 + ->setNewValue(ManiphestTaskStatus::STATUS_CLOSED_DUPLICATE); 180 181 181 - $editor->applyTransactions($target, array($close_task)); 182 + $merge_comment = id(new ManiphestTransactionPro()) 183 + ->setTransactionType(PhabricatorTransactions::TYPE_COMMENT) 184 + ->attachComment( 185 + id(new ManiphestTransactionComment()) 186 + ->setContent("\xE2\x9C\x98 Merged into {$merge_into_name}.")); 187 + 188 + $editor->applyTransactions( 189 + $target, 190 + array( 191 + $close_task, 192 + $merge_comment, 193 + )); 182 194 183 195 $task_names[] = 'T'.$target->getID(); 184 196 } ··· 188 200 189 201 $task_names = implode(', ', $task_names); 190 202 191 - $add_ccs = id(new ManiphestTransaction()) 192 - ->setAuthorPHID($user->getPHID()) 203 + $add_ccs = id(new ManiphestTransactionPro()) 193 204 ->setTransactionType(ManiphestTransactionType::TYPE_CCS) 194 - ->setNewValue($all_ccs) 195 - ->setComments("\xE2\x97\x80 Merged tasks: {$task_names}."); 196 - $editor->applyTransactions($task, array($add_ccs)); 205 + ->setNewValue($all_ccs); 206 + 207 + $merged_comment = id(new ManiphestTransactionPro()) 208 + ->setTransactionType(PhabricatorTransactions::TYPE_COMMENT) 209 + ->attachComment( 210 + id(new ManiphestTransactionComment()) 211 + ->setContent("\xE2\x97\x80 Merged tasks: {$task_names}.")); 212 + 213 + $editor->applyTransactions($task, array($add_ccs, $merged_comment)); 197 214 198 215 return $response; 199 216 }
+39
src/applications/transactions/editor/PhabricatorApplicationTransactionEditor.php
··· 15 15 private $isNewObject; 16 16 private $mentionedPHIDs; 17 17 private $continueOnNoEffect; 18 + private $continueOnMissingFields; 18 19 private $parentMessageID; 19 20 private $heraldAdapter; 20 21 private $heraldTranscript; ··· 43 44 public function getContinueOnNoEffect() { 44 45 return $this->continueOnNoEffect; 45 46 } 47 + 48 + 49 + /** 50 + * When the editor tries to apply transactions which don't populate all of 51 + * an object's required fields, should it raise an exception (default) or 52 + * drop them and continue? 53 + * 54 + * For example, if a user adds a new required custom field (like "Severity") 55 + * to a task, all existing tasks won't have it populated. When users 56 + * manually edit existing tasks, it's usually desirable to have them provide 57 + * a severity. However, other operations (like batch editing just the 58 + * owner of a task) will fail by default. 59 + * 60 + * By setting this flag for edit operations which apply to specific fields 61 + * (like the priority, batch, and merge editors in Maniphest), these 62 + * operations can continue to function even if an object is outdated. 63 + * 64 + * @param bool True to continue when transactions don't completely satisfy 65 + * all required fields. 66 + * @return this 67 + */ 68 + public function setContinueOnMissingFields($continue_on_missing_fields) { 69 + $this->continueOnMissingFields = $continue_on_missing_fields; 70 + return $this; 71 + } 72 + 73 + public function getContinueOnMissingFields() { 74 + return $this->continueOnMissingFields; 75 + } 76 + 46 77 47 78 /** 48 79 * Not strictly necessary, but reply handlers ideally set this value to ··· 363 394 } 364 395 365 396 $errors = array_mergev($errors); 397 + 398 + $continue_on_missing = $this->getContinueOnMissingFields(); 399 + foreach ($errors as $key => $error) { 400 + if ($continue_on_missing && $error->getIsMissingFieldError()) { 401 + unset($errors[$key]); 402 + } 403 + } 404 + 366 405 if ($errors) { 367 406 throw new PhabricatorApplicationTransactionValidationException($errors); 368 407 }
+10
src/applications/transactions/error/PhabricatorApplicationTransactionValidationError.php
··· 7 7 private $transaction; 8 8 private $shortMessage; 9 9 private $message; 10 + private $isMissingFieldError; 10 11 11 12 public function __construct( 12 13 $type, ··· 34 35 35 36 public function getMessage() { 36 37 return $this->message; 38 + } 39 + 40 + public function setIsMissingFieldError($is_missing_field_error) { 41 + $this->isMissingFieldError = $is_missing_field_error; 42 + return $this; 43 + } 44 + 45 + public function getIsMissingFieldError() { 46 + return $this->isMissingFieldError; 37 47 } 38 48 39 49 }
+1 -1
src/applications/transactions/view/PhabricatorApplicationTransactionView.php
··· 281 281 $engine = $this->getOrBuildEngine(); 282 282 $comment = $xaction->getComment(); 283 283 284 - if ($comment) { 284 + if ($xaction->hasComment()) { 285 285 if ($comment->getIsDeleted()) { 286 286 return phutil_tag( 287 287 'em',
+3 -1
src/infrastructure/customfield/standard/PhabricatorStandardCustomField.php
··· 282 282 } 283 283 } 284 284 if ($this->isValueEmpty($value)) { 285 - $errors[] = new PhabricatorApplicationTransactionValidationError( 285 + $error = new PhabricatorApplicationTransactionValidationError( 286 286 $type, 287 287 pht('Required'), 288 288 pht('%s is required.', $this->getFieldName()), 289 289 $transaction); 290 + $error->setIsMissingFieldError(true); 291 + $errors[] = $error; 290 292 $this->setFieldError(pht('Required')); 291 293 } 292 294 }