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

Separate commit message parsing and validation from Conduit

Summary:
Ref T11114. I want to move this step away from custom fields. To start with, isolate all the parsing in one class with a clearer API boundary.

Next, I'll make this class use new field objects to perform parsing, without CustomField interactions.

Test Plan: Created and edited revisions from the CLI, using valid and invalid commit messages.

Reviewers: chad

Reviewed By: chad

Maniphest Tasks: T11114

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

+106 -61
+12 -60
src/applications/differential/conduit/DifferentialParseCommitMessageConduitAPIMethod.php
··· 3 3 final class DifferentialParseCommitMessageConduitAPIMethod 4 4 extends DifferentialConduitAPIMethod { 5 5 6 - private $errors; 7 - 8 6 public function getAPIMethodName() { 9 7 return 'differential.parsecommitmessage'; 10 8 } ··· 25 23 } 26 24 27 25 protected function execute(ConduitAPIRequest $request) { 28 - $viewer = $request->getUser(); 29 - $corpus = $request->getValue('corpus'); 30 - $is_partial = $request->getValue('partial'); 31 - 32 - $field_list = PhabricatorCustomField::getObjectFields( 33 - new DifferentialRevision(), 34 - DifferentialCustomField::ROLE_COMMITMESSAGE); 35 - $field_list->setViewer($viewer); 36 - $field_map = mpull($field_list->getFields(), null, 'getFieldKeyForConduit'); 37 - 38 - $corpus_map = $this->parseCommitMessage($corpus); 39 - 40 - $values = array(); 41 - foreach ($corpus_map as $field_key => $text_value) { 42 - $field = idx($field_map, $field_key); 26 + $viewer = $this->getViewer(); 43 27 44 - if (!$field) { 45 - throw new Exception( 46 - pht( 47 - 'Parser emitted text value for field key "%s", but no such '. 48 - 'field exists.', 49 - $field_key)); 50 - } 28 + $parser = DifferentialCommitMessageParser::newStandardParser($viewer); 51 29 52 - try { 53 - $values[$field_key] = $field->parseValueFromCommitMessage($text_value); 54 - } catch (DifferentialFieldParseException $ex) { 55 - $this->errors[] = pht( 56 - 'Error parsing field "%s": %s', 57 - $field->renderCommitMessageLabel(), 58 - $ex->getMessage()); 59 - } 30 + $is_partial = $request->getValue('partial'); 31 + if ($is_partial) { 32 + $parser->setRaiseMissingFieldErrors(false); 60 33 } 61 34 62 - if (!$is_partial) { 63 - foreach ($field_map as $key => $field) { 64 - try { 65 - $field->validateCommitMessageValue(idx($values, $key)); 66 - } catch (DifferentialFieldValidationException $ex) { 67 - $this->errors[] = pht( 68 - 'Invalid or missing field "%s": %s', 69 - $field->renderCommitMessageLabel(), 70 - $ex->getMessage()); 71 - } 72 - } 73 - } 35 + $corpus = $request->getValue('corpus'); 36 + $field_map = $parser->parseFields($corpus); 37 + 38 + $errors = $parser->getErrors(); 74 39 75 40 // grab some extra information about the Differential Revision: field... 76 41 $revision_id_field = new DifferentialRevisionIDField(); 77 42 $revision_id_value = idx( 78 - $corpus_map, 43 + $field_map, 79 44 $revision_id_field->getFieldKeyForConduit()); 80 45 $revision_id_valid_domain = PhabricatorEnv::getProductionURI(''); 81 46 82 47 return array( 83 - 'errors' => $this->errors, 84 - 'fields' => $values, 48 + 'errors' => $errors, 49 + 'fields' => $field_map, 85 50 'revisionIDFieldInfo' => array( 86 51 'value' => $revision_id_value, 87 52 'validDomain' => $revision_id_valid_domain, 88 53 ), 89 54 ); 90 - } 91 - 92 - private function parseCommitMessage($corpus) { 93 - $viewer = $this->getViewer(); 94 - $parser = DifferentialCommitMessageParser::newStandardParser($viewer); 95 - $result = $parser->parseCorpus($corpus); 96 - 97 - $this->errors = array(); 98 - foreach ($parser->getErrors() as $error) { 99 - $this->errors[] = $error; 100 - } 101 - 102 - return $result; 103 55 } 104 56 105 57 }
+94 -1
src/applications/differential/parser/DifferentialCommitMessageParser.php
··· 21 21 */ 22 22 final class DifferentialCommitMessageParser extends Phobject { 23 23 24 + private $viewer; 24 25 private $labelMap; 25 26 private $titleKey; 26 27 private $summaryKey; 27 28 private $errors; 28 - 29 + private $raiseMissingFieldErrors = true; 29 30 30 31 public static function newStandardParser(PhabricatorUser $viewer) { 31 32 ··· 60 61 } 61 62 62 63 return id(new self()) 64 + ->setViewer($viewer) 63 65 ->setLabelMap($label_map) 64 66 ->setTitleKey($key_title) 65 67 ->setSummaryKey($key_summary); ··· 67 69 68 70 69 71 /* -( Configuring the Parser )--------------------------------------------- */ 72 + 73 + 74 + /** 75 + * @task config 76 + */ 77 + public function setViewer(PhabricatorUser $viewer) { 78 + $this->viewer = $viewer; 79 + return $this; 80 + } 81 + 82 + 83 + /** 84 + * @task config 85 + */ 86 + public function getViewer() { 87 + return $this->viewer; 88 + } 89 + 90 + 91 + /** 92 + * @task config 93 + */ 94 + public function setRaiseMissingFieldErrors($raise) { 95 + $this->raiseMissingFieldErrors = $raise; 96 + return $this; 97 + } 98 + 99 + 100 + /** 101 + * @task config 102 + */ 103 + public function getRaiseMissingFieldErrors() { 104 + return $this->raiseMissingFieldErrors; 105 + } 70 106 71 107 72 108 /** ··· 212 248 } 213 249 214 250 return $fields; 251 + } 252 + 253 + 254 + /** 255 + * @task parse 256 + */ 257 + public function parseFields($corpus) { 258 + $viewer = $this->getViewer(); 259 + $text_map = $this->parseCorpus($corpus); 260 + 261 + $field_list = PhabricatorCustomField::getObjectFields( 262 + new DifferentialRevision(), 263 + DifferentialCustomField::ROLE_COMMITMESSAGE); 264 + $field_list->setViewer($viewer); 265 + 266 + $field_map = $field_list->getFields(); 267 + $field_map = mpull($field_map, null, 'getFieldKeyForConduit'); 268 + 269 + $result_map = array(); 270 + foreach ($text_map as $field_key => $text_value) { 271 + $field = idx($field_map, $field_key); 272 + if (!$field) { 273 + // This is a strict error, since we only parse fields which we have 274 + // been told are valid. The caller probably handed us an invalid label 275 + // map. 276 + throw new Exception( 277 + pht( 278 + 'Parser emitted a field with key "%s", but no corresponding '. 279 + 'field definition exists.', 280 + $field_key)); 281 + } 282 + 283 + try { 284 + $result = $field->parseValueFromCommitMessage($text_value); 285 + $result_map[$field_key] = $result; 286 + } catch (DifferentialFieldParseException $ex) { 287 + $this->errors[] = pht( 288 + 'Error parsing field "%s": %s', 289 + $field->renderCommitMessageLabel(), 290 + $ex->getMessage()); 291 + } 292 + } 293 + 294 + if ($this->getRaiseMissingFieldErrors()) { 295 + foreach ($field_map as $key => $field) { 296 + try { 297 + $field->validateCommitMessageValue(idx($result_map, $key)); 298 + } catch (DifferentialFieldValidationException $ex) { 299 + $this->errors[] = pht( 300 + 'Invalid or missing field "%s": %s', 301 + $field->renderCommitMessageLabel(), 302 + $ex->getMessage()); 303 + } 304 + } 305 + } 306 + 307 + return $result_map; 215 308 } 216 309 217 310